diff --git a/go.mod b/go.mod index 2b99dcc2e..5240dd072 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/kakao/varlog go 1.21 require ( - github.com/cockroachdb/pebble v0.0.0-20230724234444-7ef7553fd9e1 + github.com/cockroachdb/pebble v0.0.0-20231114155657-6682fd5e8763 github.com/docker/go-units v0.5.0 github.com/gogo/protobuf v1.3.2 github.com/gogo/status v1.1.1 @@ -30,7 +30,7 @@ require ( go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.26.0 - golang.org/x/exp v0.0.0-20221114191408-850992195362 + golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 golang.org/x/sync v0.5.0 golang.org/x/sys v0.15.0 @@ -48,11 +48,10 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/cockroachdb/errors v1.8.1 // indirect - github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f // indirect - github.com/cockroachdb/redact v1.0.8 // indirect - github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 // indirect - github.com/cockroachdb/tokenbucket v0.0.0-20230613231145-182959a1fad6 // indirect + github.com/cockroachdb/errors v1.11.1 // indirect + github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect + github.com/cockroachdb/redact v1.1.5 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/coreos/go-semver v0.2.0 // indirect github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 // indirect github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf // indirect @@ -60,13 +59,14 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.3 // indirect - github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a // indirect + github.com/gogo/googleapis v1.4.1 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/gofuzz v1.2.0 // indirect diff --git a/go.sum b/go.sum index 9599f6712..58dbf1e27 100644 --- a/go.sum +++ b/go.sum @@ -31,24 +31,15 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EFZQ978U7x8IRnstaskI3IysnWY5Ao3QgZUKOXlsAdw= -github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w= github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= -github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= -github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7/go.mod h1:6E6s8o2AE4KhCrqr6GRJjdC/gNfTdxkIXvuGZZda2VM= -github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= -github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -65,64 +56,44 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cockroachdb/datadriven v1.0.0/go.mod h1:5Ib8Meh+jk1RlHIXej6Pzevx/NLlNvQB9pmSBZErGA4= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= -github.com/cockroachdb/errors v1.6.1/go.mod h1:tm6FTP5G81vwJ5lC0SizQo374JNCOPrHyXGitRJoDqM= -github.com/cockroachdb/errors v1.8.1 h1:A5+txlVZfOqFBDa4mGz2bUWSp0aHElvHX2bKkdbQu+Y= -github.com/cockroachdb/errors v1.8.1/go.mod h1:qGwQn6JmZ+oMjuLwjWzUNqblqk0xl4CVV3SQbGwK7Ac= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/cockroachdb/pebble v0.0.0-20230724234444-7ef7553fd9e1 h1:aBPW14kJEdbuzyryv+8u1wxY6k8bu7uNVEuifOZxjRg= -github.com/cockroachdb/pebble v0.0.0-20230724234444-7ef7553fd9e1/go.mod h1:FN5O47SBEz5+kO9fG8UTR64g2WS1u5ZFCgTvxGjoSks= -github.com/cockroachdb/redact v1.0.8 h1:8QG/764wK+vmEYoOlfobpe12EQcS81ukx/a4hdVMxNw= -github.com/cockroachdb/redact v1.0.8/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= -github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 h1:IKgmqgMQlVJIZj19CdocBeSfSaiCbEBZGKODaixqtHM= -github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk0R8eg+OTkcqI6baNH4xAkpiYVvQ= -github.com/cockroachdb/tokenbucket v0.0.0-20230613231145-182959a1fad6 h1:DJK8W/iB+s/qkTtmXSrHA49lp5O3OsR7E6z4byOLy34= -github.com/cockroachdb/tokenbucket v0.0.0-20230613231145-182959a1fad6/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= -github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZazG8= +github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v0.0.0-20231114155657-6682fd5e8763 h1:OlEHusxVbWrQ2hVIHczmPaMksNKGcTgOPSrE6+gt8mk= +github.com/cockroachdb/pebble v0.0.0-20231114155657-6682fd5e8763/go.mod h1:acMRUGd/BK8AUmQNK3spUCCGzFLZU2bSST3NMXSq2Kc= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 h1:u9SHYsPQNyt5tgDm3YN7+9dYrpK96E5wFilTFWIDZOM= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf h1:CAKfRE2YtTUIjjh1bkBtyYFaUT/WmOqsJjgtihT0vMI= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= -github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= -github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= -github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= -github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= -github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= -github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= +github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -137,7 +108,6 @@ github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= github.com/go-logr/logr v1.3.0/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-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= @@ -149,17 +119,12 @@ github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a h1:dR8+Q0uO5S2ZBcs2IH6VBKYwSxPo2vYCYq0ot0mu7xA= github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= +github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= github.com/gogo/status v1.1.1 h1:DuHXlSFHNKqTQ+/ACf5Vs6r4X/dH2EgIzR9Vr+H65kg= github.com/gogo/status v1.1.1/go.mod h1:jpG3dM5QPcqu19Hg8lkUhBFBa3TcLs1DG7+2Jqci7oU= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -197,7 +162,6 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= @@ -215,7 +179,6 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -235,27 +198,15 @@ github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/hydrogen18/memlistener v0.0.0-20141126152155-54553eb933fb/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= -github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= -github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62A0xJL6I+umB2YTlFRwWXaDFA0jy+5HzGiJjqI= -github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= @@ -268,24 +219,12 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= -github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= -github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= -github.com/kataras/golog v0.0.9/go.mod h1:12HJgwBIZFNGL0EJnMRhmvGA0PQGx8VFwrZtM4CqbAk= -github.com/kataras/iris/v12 v12.0.1/go.mod h1:udK4vLQKkdDqMGJJVd/msuMtN6hpYJhg/lSzuxjhO+U= -github.com/kataras/neffos v0.0.10/go.mod h1:ZYmJC07hQPW67eKuzlfY7SO3bC0mw83A3j6im82hfqw= -github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d/go.mod h1:NV88laa9UiiDuX9AhMbDPkGYSPugBOV6yTZB1l2K9Z0= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= 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.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= -github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -297,28 +236,15 @@ 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/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= -github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/mediocregopher/mediocre-go-lib v0.0.0-20181029021733-cb65787f37ed/go.mod h1:dSsfyI2zABAdhcbvkXqgxOxrCsbYeHCPgrZkku60dSg= -github.com/mediocregopher/radix/v3 v3.3.0/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQGvsUt6O3Pj+LDCQ= -github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -326,26 +252,14 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= 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-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= -github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.13.0 h1:M76yO2HkZASFjXL0HSoZJ1AYEmQxNJmY41Jx1zNUq1Y= -github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -388,40 +302,27 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= 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/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shirou/gopsutil/v3 v3.23.10 h1:/N42opWlYzegYaVkWejXWJpbzKv2JDy3mrgGzKsh9hM= github.com/shirou/gopsutil/v3 v3.23.10/go.mod h1:JIE26kpucQi+innVlAUnIEOSBhBUkirr5b44yr55+WE= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY= github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.13.1 h1:Ef7KhSmjZcK6AVf9YbJdvPYG9avaF0ZxudX+ThRdWfU= github.com/smartystreets/assertions v1.13.1/go.mod h1:cXr/IwVfSo/RbCSPhoAPv73p3hlSdrBH/b3SdnW/LMY= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY= github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -438,27 +339,12 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli/v2 v2.26.0 h1:3f3AMg3HpThFNT4I++TKOejZO8yU55t3JnnSr4S4QEI= github.com/urfave/cli/v2 v2.26.0/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= -github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= -github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= -github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= -github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= -github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -503,11 +389,9 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8 go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= @@ -521,8 +405,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20221114191408-850992195362 h1:NoHlPRbyl1VFI6FjwHtPQCN7wAMXI6cKcqrmXhOOfBQ= -golang.org/x/exp v0.0.0-20221114191408-850992195362/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= +golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -551,13 +435,10 @@ golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -566,7 +447,6 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -577,7 +457,6 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= @@ -614,11 +493,8 @@ golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -626,14 +502,9 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -648,7 +519,6 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -690,15 +560,11 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -839,15 +705,10 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= -gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/internal/storage/logger.go b/internal/storage/logger.go index f3fd95432..156daef34 100644 --- a/internal/storage/logger.go +++ b/internal/storage/logger.go @@ -21,6 +21,10 @@ func (l *logAdaptor) Infof(format string, args ...interface{}) { l.logger.Infof(format, args...) } +func (l *logAdaptor) Errorf(format string, args ...interface{}) { + l.logger.Errorf(format, args...) +} + func (l *logAdaptor) Fatalf(format string, args ...interface{}) { l.logger.Fatalf(format, args...) } diff --git a/internal/storage/recovery_points.go b/internal/storage/recovery_points.go index 6d1f65a2b..ad6e2636f 100644 --- a/internal/storage/recovery_points.go +++ b/internal/storage/recovery_points.go @@ -35,7 +35,10 @@ func (s *Storage) ReadRecoveryPoints() (rp RecoveryPoints, err error) { if err != nil { return } - rp.CommittedLogEntry.First, rp.CommittedLogEntry.Last = s.readLogEntryBoundaries() + rp.CommittedLogEntry.First, rp.CommittedLogEntry.Last, err = s.readLogEntryBoundaries() + if err != nil { + return + } uncommittedBegin := types.MinLLSN if cc := rp.LastCommitContext; cc != nil { @@ -62,31 +65,39 @@ func (s *Storage) readLastCommitContext() (*CommitContext, error) { return &cc, nil } -func (s *Storage) readLogEntryBoundaries() (first, last *varlogpb.LogSequenceNumber) { - dit := s.dataDB.NewIter(&pebble.IterOptions{ +func (s *Storage) readLogEntryBoundaries() (first, last *varlogpb.LogSequenceNumber, err error) { + dit, err := s.dataDB.NewIter(&pebble.IterOptions{ LowerBound: []byte{dataKeyPrefix}, UpperBound: []byte{dataKeySentinelPrefix}, }) - cit := s.commitDB.NewIter(&pebble.IterOptions{ + if err != nil { + return + } + defer func() { + _ = dit.Close() + }() + cit, err := s.commitDB.NewIter(&pebble.IterOptions{ LowerBound: []byte{commitKeyPrefix}, UpperBound: []byte{commitKeySentinelPrefix}, }) + if err != nil { + return + } defer func() { - _ = dit.Close() _ = cit.Close() }() first = s.getFirstLogSequenceNumber(cit, dit) if first == nil { - return nil, nil + return nil, nil, nil } last = s.getLastLogSequenceNumber(cit, dit, first) if last == nil { s.logger.Warn("the last must exist but could not be found.", zap.Stringer("first", first)) - return nil, nil + return nil, nil, nil } - return first, last + return first, last, nil } func (s *Storage) getFirstLogSequenceNumber(cit, dit *pebble.Iterator) *varlogpb.LogSequenceNumber { @@ -173,10 +184,13 @@ func (s *Storage) getLastLogSequenceNumber(cit, dit *pebble.Iterator, first *var func (s *Storage) readUncommittedLogEntryBoundaries(uncommittedBegin types.LLSN) (begin, end types.LLSN, err error) { dk := make([]byte, dataKeyLength) dk = encodeDataKeyInternal(uncommittedBegin, dk) - it := s.dataDB.NewIter(&pebble.IterOptions{ + it, err := s.dataDB.NewIter(&pebble.IterOptions{ LowerBound: dk, UpperBound: []byte{dataKeySentinelPrefix}, }) + if err != nil { + return types.InvalidLLSN, types.InvalidLLSN, err + } defer func() { _ = it.Close() }() diff --git a/internal/storage/scanner.go b/internal/storage/scanner.go index 1652bc2bd..90f6d4bfc 100644 --- a/internal/storage/scanner.go +++ b/internal/storage/scanner.go @@ -59,8 +59,10 @@ func (s *Scanner) Next() bool { return s.it.Next() } -func (s *Scanner) Close() error { - err := s.it.Close() +func (s *Scanner) Close() (err error) { + if s.it != nil { + err = s.it.Close() + } s.release() return err } diff --git a/internal/storage/storage.go b/internal/storage/storage.go index 626ac625c..a7660e82e 100644 --- a/internal/storage/storage.go +++ b/internal/storage/storage.go @@ -107,7 +107,7 @@ func (s *Storage) newDB(path string, cfg *dbConfig) (*pebble.DB, error) { L0StopWritesThreshold: cfg.l0StopWritesThreshold, LBaseMaxBytes: cfg.lbaseMaxBytes, MaxOpenFiles: cfg.maxOpenFiles, - MemTableSize: cfg.memTableSize, + MemTableSize: uint64(cfg.memTableSize), MemTableStopWritesThreshold: cfg.memTableStopWritesThreshold, MaxConcurrentCompactions: func() int { return cfg.maxConcurrentCompaction }, Levels: make([]pebble.LevelOptions, 7), @@ -181,22 +181,26 @@ func (s *Storage) NewAppendBatch() *AppendBatch { } // NewScanner creates a scanner for the given key range. -func (s *Storage) NewScanner(opts ...ScanOption) *Scanner { - scanner := newScanner() +func (s *Storage) NewScanner(opts ...ScanOption) (scanner *Scanner, err error) { + scanner = newScanner() scanner.scanConfig = newScanConfig(opts) scanner.stg = s itOpt := &pebble.IterOptions{} if scanner.withGLSN { itOpt.LowerBound = encodeCommitKeyInternal(scanner.begin.GLSN, scanner.cks.lower) itOpt.UpperBound = encodeCommitKeyInternal(scanner.end.GLSN, scanner.cks.upper) - scanner.it = s.commitDB.NewIter(itOpt) + scanner.it, err = s.commitDB.NewIter(itOpt) } else { itOpt.LowerBound = encodeDataKeyInternal(scanner.begin.LLSN, scanner.dks.lower) itOpt.UpperBound = encodeDataKeyInternal(scanner.end.LLSN, scanner.dks.upper) - scanner.it = s.dataDB.NewIter(itOpt) + scanner.it, err = s.dataDB.NewIter(itOpt) + } + if err != nil { + _ = scanner.Close() + return nil, err } _ = scanner.it.First() - return scanner + return scanner, nil } // Read reads the log entry at the glsn. @@ -209,7 +213,10 @@ func (s *Storage) Read(opts ...ReadOption) (le varlogpb.LogEntry, err error) { } func (s *Storage) readGLSN(glsn types.GLSN) (le varlogpb.LogEntry, err error) { - scanner := s.NewScanner(WithGLSN(glsn, glsn+1)) + scanner, err := s.NewScanner(WithGLSN(glsn, glsn+1)) + if err != nil { + return + } defer func() { _ = scanner.Close() }() @@ -220,10 +227,13 @@ func (s *Storage) readGLSN(glsn types.GLSN) (le varlogpb.LogEntry, err error) { } func (s *Storage) readLLSN(llsn types.LLSN) (le varlogpb.LogEntry, err error) { - it := s.commitDB.NewIter(&pebble.IterOptions{ + it, err := s.commitDB.NewIter(&pebble.IterOptions{ LowerBound: []byte{commitKeyPrefix}, UpperBound: []byte{commitKeySentinelPrefix}, }) + if err != nil { + return + } defer func() { _ = it.Close() }() @@ -307,10 +317,13 @@ func (s *Storage) findLTE(glsn types.GLSN) (lem varlogpb.LogEntryMeta, err error upper = []byte{commitKeySentinelPrefix} } - it := s.commitDB.NewIter(&pebble.IterOptions{ + it, err := s.commitDB.NewIter(&pebble.IterOptions{ LowerBound: []byte{commitKeyPrefix}, UpperBound: upper, }) + if err != nil { + return + } defer func() { _ = it.Close() }() diff --git a/internal/storage/storage_test.go b/internal/storage/storage_test.go index 02de67fb2..4582338b4 100644 --- a/internal/storage/storage_test.go +++ b/internal/storage/storage_test.go @@ -216,7 +216,8 @@ func TestStorage_WriteBatch(t *testing.T) { _, err = stg.Read(AtLLSN(2)) assert.Error(t, err) - scanner := stg.NewScanner(WithLLSN(1, 3)) + scanner, err := stg.NewScanner(WithLLSN(1, 3)) + require.NoError(t, err) assert.True(t, scanner.Valid()) le, err := scanner.Value() assert.NoError(t, err) @@ -251,9 +252,10 @@ func TestStorage_EmptyWriteBatch(t *testing.T) { assert.NoError(t, wb.Apply()) assert.NoError(t, wb.Close()) - scanner := stg.NewScanner(WithLLSN(types.InvalidLLSN, types.MaxLLSN)) + scanner, err := stg.NewScanner(WithLLSN(types.InvalidLLSN, types.MaxLLSN)) + require.NoError(t, err) assert.False(t, scanner.Valid()) - _, err := scanner.Value() + _, err = scanner.Value() assert.ErrorIs(t, err, io.EOF) assert.NoError(t, scanner.Close()) }) @@ -346,7 +348,8 @@ func TestStorage_InconsistentWriteCommit(t *testing.T) { assert.NoError(t, cb.Apply()) assert.NoError(t, cb.Close()) - scanner := stg.NewScanner(WithGLSN(11, 13)) + scanner, err := stg.NewScanner(WithGLSN(11, 13)) + require.NoError(t, err) assert.True(t, scanner.Valid()) _, err = scanner.Value() assert.Error(t, err) @@ -417,7 +420,8 @@ func TestStorage_WriteCommit(t *testing.T) { }, le) // scan - scanner := stg.NewScanner(WithGLSN(11, 13)) + scanner, err := stg.NewScanner(WithGLSN(11, 13)) + require.NoError(t, err) assert.True(t, scanner.Valid()) le, err = scanner.Value() assert.NoError(t, err) @@ -622,7 +626,8 @@ func TestStorageReadLogEntryBoundaries(t *testing.T) { { name: "NoLogEntry", testf: func(t *testing.T, stg *Storage) { - first, last := stg.readLogEntryBoundaries() + first, last, err := stg.readLogEntryBoundaries() + require.NoError(t, err) require.Nil(t, first) require.Nil(t, last) }, @@ -641,7 +646,8 @@ func TestStorageReadLogEntryBoundaries(t *testing.T) { require.NoError(t, cb.Set(1, 1)) require.NoError(t, cb.Apply()) - first, last := stg.readLogEntryBoundaries() + first, last, err := stg.readLogEntryBoundaries() + require.NoError(t, err) require.Nil(t, first) require.Nil(t, last) }, @@ -666,7 +672,8 @@ func TestStorageReadLogEntryBoundaries(t *testing.T) { require.NoError(t, wb.Close()) want := &varlogpb.LogSequenceNumber{LLSN: 1, GLSN: 1} - first, last := stg.readLogEntryBoundaries() + first, last, err := stg.readLogEntryBoundaries() + require.NoError(t, err) require.Equal(t, want, first) require.Equal(t, want, last) }, @@ -692,7 +699,8 @@ func TestStorageReadLogEntryBoundaries(t *testing.T) { require.NoError(t, wb.Apply()) require.NoError(t, wb.Close()) - first, last := stg.readLogEntryBoundaries() + first, last, err := stg.readLogEntryBoundaries() + require.NoError(t, err) require.Equal(t, &varlogpb.LogSequenceNumber{GLSN: 1, LLSN: 1}, first) require.Equal(t, &varlogpb.LogSequenceNumber{GLSN: 2, LLSN: 2}, last) }, @@ -721,7 +729,8 @@ func TestStorageReadLogEntryBoundaries(t *testing.T) { require.NoError(t, wb.Apply()) require.NoError(t, wb.Close()) - first, last := stg.readLogEntryBoundaries() + first, last, err := stg.readLogEntryBoundaries() + require.NoError(t, err) require.Equal(t, &varlogpb.LogSequenceNumber{GLSN: 2, LLSN: 2}, first) require.Equal(t, &varlogpb.LogSequenceNumber{GLSN: 3, LLSN: 3}, last) }, @@ -750,7 +759,8 @@ func TestStorageReadLogEntryBoundaries(t *testing.T) { require.NoError(t, wb.Apply()) require.NoError(t, wb.Close()) - first, last := stg.readLogEntryBoundaries() + first, last, err := stg.readLogEntryBoundaries() + require.NoError(t, err) require.Equal(t, &varlogpb.LogSequenceNumber{GLSN: 2, LLSN: 2}, first) require.Equal(t, &varlogpb.LogSequenceNumber{GLSN: 3, LLSN: 3}, last) }, @@ -779,7 +789,8 @@ func TestStorageReadLogEntryBoundaries(t *testing.T) { require.NoError(t, wb.Apply()) require.NoError(t, wb.Close()) - first, last := stg.readLogEntryBoundaries() + first, last, err := stg.readLogEntryBoundaries() + require.NoError(t, err) require.Equal(t, &varlogpb.LogSequenceNumber{GLSN: 1, LLSN: 1}, first) require.Equal(t, &varlogpb.LogSequenceNumber{GLSN: 2, LLSN: 2}, last) }, @@ -808,7 +819,8 @@ func TestStorageReadLogEntryBoundaries(t *testing.T) { require.NoError(t, wb.Apply()) require.NoError(t, wb.Close()) - first, last := stg.readLogEntryBoundaries() + first, last, err := stg.readLogEntryBoundaries() + require.NoError(t, err) require.Equal(t, &varlogpb.LogSequenceNumber{GLSN: 1, LLSN: 1}, first) require.Equal(t, &varlogpb.LogSequenceNumber{GLSN: 2, LLSN: 2}, last) }, @@ -837,7 +849,8 @@ func TestStorageReadLogEntryBoundaries(t *testing.T) { require.NoError(t, wb.Close()) want := &varlogpb.LogSequenceNumber{LLSN: 2, GLSN: 2} - first, last := stg.readLogEntryBoundaries() + first, last, err := stg.readLogEntryBoundaries() + require.NoError(t, err) require.Equal(t, want, first) require.Equal(t, want, last) }, @@ -867,7 +880,8 @@ func TestStorageReadLogEntryBoundaries(t *testing.T) { require.NoError(t, wb.Apply()) require.NoError(t, wb.Close()) - first, last := stg.readLogEntryBoundaries() + first, last, err := stg.readLogEntryBoundaries() + require.NoError(t, err) require.Equal(t, &varlogpb.LogSequenceNumber{GLSN: 2, LLSN: 2}, first) require.Equal(t, &varlogpb.LogSequenceNumber{GLSN: 3, LLSN: 3}, last) }, @@ -894,7 +908,8 @@ func TestStorageReadLogEntryBoundaries(t *testing.T) { require.NoError(t, wb.Apply()) require.NoError(t, wb.Close()) - first, last := stg.readLogEntryBoundaries() + first, last, err := stg.readLogEntryBoundaries() + require.NoError(t, err) require.Nil(t, first) require.Nil(t, last) }, @@ -921,7 +936,8 @@ func TestStorageReadLogEntryBoundaries(t *testing.T) { require.NoError(t, wb.Apply()) require.NoError(t, wb.Close()) - first, last := stg.readLogEntryBoundaries() + first, last, err := stg.readLogEntryBoundaries() + require.NoError(t, err) require.Nil(t, first) require.Nil(t, last) }, @@ -1101,20 +1117,22 @@ func TestStorage_Trim(t *testing.T) { err := stg.Trim(types.MinGLSN) assert.NoError(t, err) - it := stg.dataDB.NewIter(&pebble.IterOptions{ + it, err := stg.dataDB.NewIter(&pebble.IterOptions{ LowerBound: []byte{dataKeyPrefix}, UpperBound: []byte{dataKeySentinelPrefix}, }) + require.NoError(t, err) assert.True(t, it.First()) assert.Equal(t, types.LLSN(2), decodeDataKey(it.Key())) assert.True(t, it.Next()) assert.Equal(t, types.LLSN(3), decodeDataKey(it.Key())) assert.NoError(t, it.Close()) - it = stg.commitDB.NewIter(&pebble.IterOptions{ + it, err = stg.commitDB.NewIter(&pebble.IterOptions{ LowerBound: []byte{commitKeyPrefix}, UpperBound: []byte{commitKeySentinelPrefix}, }) + require.NoError(t, err) assert.True(t, it.First()) assert.Equal(t, types.GLSN(2), decodeCommitKey(it.Key())) assert.True(t, it.Next()) @@ -1133,17 +1151,19 @@ func TestStorage_Trim(t *testing.T) { assert.NoError(t, err) assert.NoError(t, err) - it := stg.dataDB.NewIter(&pebble.IterOptions{ + it, err := stg.dataDB.NewIter(&pebble.IterOptions{ LowerBound: []byte{dataKeyPrefix}, UpperBound: []byte{dataKeySentinelPrefix}, }) + require.NoError(t, err) assert.False(t, it.First()) assert.NoError(t, it.Close()) - it = stg.commitDB.NewIter(&pebble.IterOptions{ + it, err = stg.commitDB.NewIter(&pebble.IterOptions{ LowerBound: []byte{commitKeyPrefix}, UpperBound: []byte{commitKeySentinelPrefix}, }) + require.NoError(t, err) assert.False(t, it.First()) assert.NoError(t, it.Close()) @@ -1158,17 +1178,19 @@ func TestStorage_Trim(t *testing.T) { err := stg.Trim(types.MaxGLSN) assert.NoError(t, err) - it := stg.dataDB.NewIter(&pebble.IterOptions{ + it, err := stg.dataDB.NewIter(&pebble.IterOptions{ LowerBound: []byte{dataKeyPrefix}, UpperBound: []byte{dataKeySentinelPrefix}, }) + require.NoError(t, err) assert.False(t, it.First()) assert.NoError(t, it.Close()) - it = stg.commitDB.NewIter(&pebble.IterOptions{ + it, err = stg.commitDB.NewIter(&pebble.IterOptions{ LowerBound: []byte{commitKeyPrefix}, UpperBound: []byte{commitKeySentinelPrefix}, }) + require.NoError(t, err) assert.False(t, it.First()) assert.NoError(t, it.Close()) diff --git a/internal/storagenode/logstream/executor_test.go b/internal/storagenode/logstream/executor_test.go index 3fec0130d..3384ce885 100644 --- a/internal/storagenode/logstream/executor_test.go +++ b/internal/storagenode/logstream/executor_test.go @@ -2866,7 +2866,8 @@ func TestExecutorSyncInit(t *testing.T) { LLSN: 5, GLSN: 5, }, localLWM) - scanner := dst.stg.NewScanner(storage.WithLLSN(types.LLSN(1), types.LLSN(5))) + scanner, err := dst.stg.NewScanner(storage.WithLLSN(types.LLSN(1), types.LLSN(5))) + require.NoError(t, err) defer func() { require.NoError(t, scanner.Close()) }() @@ -3004,7 +3005,8 @@ func TestExecutorSyncInit(t *testing.T) { localLWM, localHWM, _ := dst.lsc.localWatermarks() require.True(t, localHWM.Invalid()) require.True(t, localLWM.Invalid()) - scanner := dst.stg.NewScanner(storage.WithLLSN(types.MinLLSN, types.MaxLLSN)) + scanner, err := dst.stg.NewScanner(storage.WithLLSN(types.MinLLSN, types.MaxLLSN)) + require.NoError(t, err) defer func() { require.NoError(t, scanner.Close()) }() diff --git a/internal/storagenode/logstream/subscribe.go b/internal/storagenode/logstream/subscribe.go index 6caf32f14..8e639be7e 100644 --- a/internal/storagenode/logstream/subscribe.go +++ b/internal/storagenode/logstream/subscribe.go @@ -161,7 +161,10 @@ func (lse *Executor) scanWithGLSN(ctx context.Context, begin, end types.GLSN, sr } lastGLSN := types.InvalidGLSN - scanner := lse.stg.NewScanner(storage.WithGLSN(scanBegin, scanEnd)) + scanner, err := lse.stg.NewScanner(storage.WithGLSN(scanBegin, scanEnd)) + if err != nil { + return err + } for scanner.Valid() { le, err := scanner.Value() if err != nil { @@ -211,7 +214,10 @@ func (lse *Executor) scanWithLLSN(ctx context.Context, begin, end types.LLSN, sr } lastLLSN := types.InvalidLLSN - scanner := lse.stg.NewScanner(storage.WithLLSN(scanBegin, scanEnd)) + scanner, err := lse.stg.NewScanner(storage.WithLLSN(scanBegin, scanEnd)) + if err != nil { + return err + } for scanner.Valid() { le, err := scanner.Value() if err != nil { diff --git a/vendor/github.com/cockroachdb/errors/.travis.yml b/vendor/github.com/cockroachdb/errors/.travis.yml deleted file mode 100644 index 2c90cf7d7..000000000 --- a/vendor/github.com/cockroachdb/errors/.travis.yml +++ /dev/null @@ -1,6 +0,0 @@ -language: go - -go: -- 1.13.x -- 1.14.x -- 1.15.x diff --git a/vendor/github.com/cockroachdb/errors/Makefile.update-protos b/vendor/github.com/cockroachdb/errors/Makefile.update-protos index 44277542a..bcf9045bb 100644 --- a/vendor/github.com/cockroachdb/errors/Makefile.update-protos +++ b/vendor/github.com/cockroachdb/errors/Makefile.update-protos @@ -6,13 +6,16 @@ # go get github.com/gogo/protobuf/types # go get github.com/gogo/protobuf/protoc-gen-gogo # -# Note: as of 2020-11-01, it is not (yet) possible to use gogoproto -# v1.3.x to generate .pb.go files so that they are compatible with -# CockroachDB. This is because CockroachDB hardcodes gogoproto at -# version v1.2, and thus does not provide v1.3's -# proto.GoGoProtoPackageIsVersion3. +# Note: as of 2021-04-13, we like to use a custom protoc-gen-gogo +# with additional options, to stabilize the marshalled +# encoding of objects (so that they are deterministic +# across marshal/unmarshal cycles) and reduce the memory footprint +# of objects: # -# For details, see https://github.com/cockroachdb/cockroach/issues/56378 +# vanity.TurnOnStable_MarshalerAll, +# vanity.TurnOffGoUnrecognizedAll, +# vanity.TurnOffGoUnkeyedAll, +# vanity.TurnOffGoSizecacheAll, # # Until this is resolved, the "go get" commands above are not # adequate; instead: @@ -23,21 +26,33 @@ # # 2. run `make -f Makefile.update-protos` with this PATH active. -PROTOS := $(wildcard errorspb/*.proto) +export SHELL := env PWD=$(CURDIR) bash + +PROTOS := $(wildcard \ + errbase/internal/*.proto \ + errorspb/*.proto \ + extgrpc/*.proto \ + exthttp/*.proto \ + grpc/*.proto \ + markers/internal/*.proto \ +) GO_SOURCES = $(PROTOS:.proto=.pb.go) SED = sed SED_INPLACE := $(shell $(SED) --version 2>&1 | grep -q GNU && echo -i || echo "-i ''") all: $(PROTOS) - protoc \ - -I$$GOPATH/src/ \ - -I$$GOPATH/src/github.com \ - -I$$GOPATH/src/github.com/gogo/protobuf \ - -I$$GOPATH/src/github.com/gogo/protobuf/protobuf \ - --gogoroach_out=Mgoogle/protobuf/any.proto=github.com/gogo/protobuf/types,plugins=grpc,import_prefix=:. \ - $(PROTOS:%=$(GOPATH)/src/github.com/cockroachdb/errors/%) - mv -f github.com/cockroachdb/errors/errorspb/*.pb.go errorspb/ + set -e; for dir in $(sort $(dir $(PROTOS))); do \ + protoc \ + -I. \ + -I$$GOPATH/src/ \ + -I$$GOPATH/src/github.com \ + -I$$GOPATH/src/github.com/cockroachdb/errors \ + -I$$GOPATH/src/github.com/gogo/protobuf \ + -I$$GOPATH/src/github.com/gogo/protobuf/protobuf \ + --gogoroach_out=Mgoogle/protobuf/any.proto=github.com/gogo/protobuf/types,plugins=grpc,import_prefix=:. \ + $$dir/*.proto; \ + done $(SED) $(SED_INPLACE) -E \ -e '/import _ /d' \ -e 's!import (fmt|math) "github.com/(fmt|math)"! !g' \ diff --git a/vendor/github.com/cockroachdb/errors/README.md b/vendor/github.com/cockroachdb/errors/README.md index 7522923d1..db53c7013 100644 --- a/vendor/github.com/cockroachdb/errors/README.md +++ b/vendor/github.com/cockroachdb/errors/README.md @@ -11,7 +11,8 @@ automatically formats error details and strips them of PII. See also [the design RFC](https://github.com/cockroachdb/cockroach/blob/master/docs/RFCS/20190318_error_handling.md). -[![Build Status](https://travis-ci.org/cockroachdb/errors.svg?branch=master)](https://travis-ci.org/cockroachdb/errors) +![Build Status](https://github.com/cockroachdb/errors/actions/workflows/ci.yaml/badge.svg?branch=master) +[![Go Reference](https://pkg.go.dev/badge/github.com/cockroachdb/errors.svg)](https://pkg.go.dev/github.com/cockroachdb/errors) Table of contents: @@ -208,12 +209,12 @@ return errors.Wrap(foo(), "foo") - how to access the detail: `Error()`, regular Go formatting, Sentry Report. - `WithDetail(error, string) error`, `WithDetailf(error, string, ...interface{}) error`, user-facing detail with contextual information. - - **when to use: need to embark a message string to output when the error is presented to a human.** + - **when to use: need to embark a message string to output when the error is presented to a developer.** - what it does: captures detail strings. - how to access the detail: `errors.GetAllDetails()`, `errors.FlattenDetails()` (all details are preserved), format with `%+v`. Not included in Sentry reports. - `WithHint(error, string) error`, `WithHintf(error, string, ...interface{}) error`: user-facing detail with suggestion for action to take. - - **when to use: need to embark a message string to output when the error is presented to a human.** + - **when to use: need to embark a message string to output when the error is presented to an end user.** - what it does: captures hint strings. - how to access the detail: `errors.GetAllHints()`, `errors.FlattenHints()` (hints are de-duplicated), format with `%+v`. Not included in Sentry reports. @@ -422,10 +423,10 @@ func myLeafDecoder(_ string, details []string, _ proto.Message) error { (For an example, see the `withTelemetry` type in [`telemetry/with_telemetry.go`](telemetry/with_telemetry.go).) -**The only case where you need a custom encoder is when your error +__The only case where you need a custom encoder is when your error type contains some fields that are not reflected in the error message (so you can't extract them back from there), and are not PII-free and -thus cannot be reported as "safe details".** +thus cannot be reported as "safe details".__ To take inspiration from examples, see the following types in the library that need a custom encoder: @@ -535,9 +536,13 @@ Example use: | `WrapWithDepthf` | `WithMessagef` + `WithStackDepth` | | `AssertionFailedWithDepthf` | `NewWithDepthf` + `WithAssertionFailure` | | `NewAssertionErrorWithWrappedErrf` | `HandledWithMessagef` (barrier) + `WrapWithDepthf` + `WithAssertionFailure` | - +| `Join` | `JoinWithDepth` (see below) | +| `JoinWithDepth` | multi-cause wrapper + `WithStackDepth` | ## API (not constructing error objects) +The following is a summary of the non-constructor API functions, grouped by category. +Detailed documentation can be found at: https://pkg.go.dev/github.com/cockroachdb/errors + ```go // Access causes. func UnwrapAll(err error) error @@ -569,10 +574,16 @@ func RegisterLeafDecoder(typeName TypeKey, decoder LeafDecoder) func RegisterLeafEncoder(typeName TypeKey, encoder LeafEncoder) func RegisterWrapperDecoder(typeName TypeKey, decoder WrapperDecoder) func RegisterWrapperEncoder(typeName TypeKey, encoder WrapperEncoder) +func RegisterWrapperEncoderWithMessageOverride (typeName TypeKey, encoder WrapperEncoderWithMessageOverride) +func RegisterMultiCauseEncoder(theType TypeKey, encoder MultiCauseEncoder) +func RegisterMultiCauseDecoder(theType TypeKey, decoder MultiCauseDecoder) type LeafEncoder = func(ctx context.Context, err error) (msg string, safeDetails []string, payload proto.Message) type LeafDecoder = func(ctx context.Context, msg string, safeDetails []string, payload proto.Message) error type WrapperEncoder = func(ctx context.Context, err error) (msgPrefix string, safeDetails []string, payload proto.Message) +type WrapperEncoderWithMessageOverride = func(ctx context.Context, err error) (msgPrefix string, safeDetails []string, payload proto.Message, overrideError bool) type WrapperDecoder = func(ctx context.Context, cause error, msgPrefix string, safeDetails []string, payload proto.Message) error +type MultiCauseEncoder = func(ctx context.Context, err error) (msg string, safeDetails []string, payload proto.Message) +type MultiCauseDecoder = func(ctx context.Context, causes []error, msgPrefix string, safeDetails []string, payload proto.Message) error // Registering package renames for custom error types. func RegisterTypeMigration(previousPkgPath, previousTypeName string, newType error) diff --git a/vendor/github.com/cockroachdb/errors/barriers/barriers.go b/vendor/github.com/cockroachdb/errors/barriers/barriers.go index fa4f43118..54df8f3a7 100644 --- a/vendor/github.com/cockroachdb/errors/barriers/barriers.go +++ b/vendor/github.com/cockroachdb/errors/barriers/barriers.go @@ -19,6 +19,7 @@ import ( "fmt" "github.com/cockroachdb/errors/errbase" + "github.com/cockroachdb/redact" "github.com/gogo/protobuf/proto" ) @@ -36,7 +37,7 @@ func Handled(err error) error { if err == nil { return nil } - return HandledWithMessage(err, err.Error()) + return HandledWithSafeMessage(err, redact.Sprint(err)) } // HandledWithMessage is like Handled except the message is overridden. @@ -46,7 +47,14 @@ func HandledWithMessage(err error, msg string) error { if err == nil { return nil } - return &barrierError{maskedErr: err, msg: msg} + return HandledWithSafeMessage(err, redact.Sprint(msg)) +} + +// HandledWithSafeMessage is like Handled except the message is overridden. +// This can be used e.g. to hide message details or to prevent +// downstream code to make assertions on the message's contents. +func HandledWithSafeMessage(err error, msg redact.RedactableString) error { + return &barrierErr{maskedErr: err, smsg: msg} } // HandledWithMessagef is like HandledWithMessagef except the message @@ -55,47 +63,48 @@ func HandledWithMessagef(err error, format string, args ...interface{}) error { if err == nil { return nil } - return &barrierError{maskedErr: err, msg: fmt.Sprintf(format, args...)} + return &barrierErr{maskedErr: err, smsg: redact.Sprintf(format, args...)} } -// barrierError is a leaf error type. It encapsulates a chain of +// barrierErr is a leaf error type. It encapsulates a chain of // original causes, but these causes are hidden so that they inhibit // matching via Is() and the Cause()/Unwrap() recursions. -type barrierError struct { +type barrierErr struct { // Message for the barrier itself. // In the common case, the message from the masked error // is used as-is (see Handled() above) however it is // useful to cache it here since the masked error may // have a long chain of wrappers and its Error() call // may be expensive. - msg string + smsg redact.RedactableString // Masked error chain. maskedErr error } -var _ error = (*barrierError)(nil) -var _ errbase.SafeDetailer = (*barrierError)(nil) -var _ errbase.SafeFormatter = (*barrierError)(nil) -var _ fmt.Formatter = (*barrierError)(nil) +var _ error = (*barrierErr)(nil) +var _ errbase.SafeDetailer = (*barrierErr)(nil) +var _ errbase.SafeFormatter = (*barrierErr)(nil) +var _ fmt.Formatter = (*barrierErr)(nil) -// barrierError is an error. -func (e *barrierError) Error() string { return e.msg } +// barrierErr is an error. +func (e *barrierErr) Error() string { return e.smsg.StripMarkers() } // SafeDetails reports the PII-free details from the masked error. -func (e *barrierError) SafeDetails() []string { +func (e *barrierErr) SafeDetails() []string { var details []string for err := e.maskedErr; err != nil; err = errbase.UnwrapOnce(err) { sd := errbase.GetSafeDetails(err) details = sd.Fill(details) } + details = append(details, redact.Sprintf("masked error: %+v", e.maskedErr).Redact().StripMarkers()) return details } // Printing a barrier reveals the details. -func (e *barrierError) Format(s fmt.State, verb rune) { errbase.FormatError(e, s, verb) } +func (e *barrierErr) Format(s fmt.State, verb rune) { errbase.FormatError(e, s, verb) } -func (e *barrierError) SafeFormatError(p errbase.Printer) (next error) { - p.Print(e.msg) +func (e *barrierErr) SafeFormatError(p errbase.Printer) (next error) { + p.Print(e.smsg) if p.Detail() { p.Printf("-- cause hidden behind barrier\n%+v", e.maskedErr) } @@ -106,19 +115,37 @@ func (e *barrierError) SafeFormatError(p errbase.Printer) (next error) { func encodeBarrier( ctx context.Context, err error, ) (msg string, details []string, payload proto.Message) { - e := err.(*barrierError) + e := err.(*barrierErr) enc := errbase.EncodeError(ctx, e.maskedErr) - return e.msg, e.SafeDetails(), &enc + return string(e.smsg), e.SafeDetails(), &enc } // A barrier error is decoded exactly. func decodeBarrier(ctx context.Context, msg string, _ []string, payload proto.Message) error { enc := payload.(*errbase.EncodedError) - return &barrierError{msg: msg, maskedErr: errbase.DecodeError(ctx, *enc)} + return &barrierErr{smsg: redact.RedactableString(msg), maskedErr: errbase.DecodeError(ctx, *enc)} } +// Previous versions of barrier errors. +func decodeBarrierPrev(ctx context.Context, msg string, _ []string, payload proto.Message) error { + enc := payload.(*errbase.EncodedError) + return &barrierErr{smsg: redact.Sprint(msg), maskedErr: errbase.DecodeError(ctx, *enc)} +} + +// barrierError is the "old" type name of barrierErr. We use a new +// name now to ensure a different decode function is used when +// importing barriers from the previous structure, where the +// message is not redactable. +type barrierError struct { + msg string + maskedErr error +} + +func (b *barrierError) Error() string { return "" } + func init() { - tn := errbase.GetTypeKey((*barrierError)(nil)) + errbase.RegisterLeafDecoder(errbase.GetTypeKey((*barrierError)(nil)), decodeBarrierPrev) + tn := errbase.GetTypeKey((*barrierErr)(nil)) errbase.RegisterLeafDecoder(tn, decodeBarrier) errbase.RegisterLeafEncoder(tn, encodeBarrier) } diff --git a/vendor/github.com/cockroachdb/errors/contexttags_api.go b/vendor/github.com/cockroachdb/errors/contexttags_api.go index 3f77960e8..44f6fa457 100644 --- a/vendor/github.com/cockroachdb/errors/contexttags_api.go +++ b/vendor/github.com/cockroachdb/errors/contexttags_api.go @@ -24,7 +24,7 @@ import ( // WithContextTags captures the k/v pairs stored in the context via the // `logtags` package and annotates them on the error. // -// Only the stromg representation of values remains available. This is +// Only the strong representation of values remains available. This is // because the library cannot guarantee that the underlying value is // preserved across the network. To avoid creating a stateful interface // (where the user code needs to know whether an error has traveled diff --git a/vendor/github.com/cockroachdb/errors/errbase/adapters.go b/vendor/github.com/cockroachdb/errors/errbase/adapters.go index f7b1d2616..8ad5c93a5 100644 --- a/vendor/github.com/cockroachdb/errors/errbase/adapters.go +++ b/vendor/github.com/cockroachdb/errors/errbase/adapters.go @@ -37,6 +37,11 @@ func decodeErrorString(_ context.Context, msg string, _ []string, _ proto.Messag return goErr.New(msg) } +// context.DeadlineExceeded uses a custom type. +func decodeDeadlineExceeded(_ context.Context, _ string, _ []string, _ proto.Message) error { + return context.DeadlineExceeded +} + // errors.fundamental from github.com/pkg/errors cannot be encoded // exactly because it includes a non-serializable stack trace // object. In order to work with it, we encode it by dumping @@ -183,6 +188,8 @@ func init() { baseErr := goErr.New("") RegisterLeafDecoder(GetTypeKey(baseErr), decodeErrorString) + RegisterLeafDecoder(GetTypeKey(context.DeadlineExceeded), decodeDeadlineExceeded) + pkgE := pkgErr.New("") RegisterLeafEncoder(GetTypeKey(pkgE), encodePkgFundamental) @@ -191,9 +198,11 @@ func init() { ws := pkgErr.WithStack(baseErr) RegisterWrapperEncoder(GetTypeKey(ws), encodePkgWithStack) + registerOsPathErrorMigration() // Needed for Go 1.16. pKey := GetTypeKey(&os.PathError{}) RegisterWrapperEncoder(pKey, encodePathError) RegisterWrapperDecoder(pKey, decodePathError) + pKey = GetTypeKey(&os.LinkError{}) RegisterWrapperEncoder(pKey, encodeLinkError) RegisterWrapperDecoder(pKey, decodeLinkError) diff --git a/vendor/github.com/cockroachdb/errors/errbase/decode.go b/vendor/github.com/cockroachdb/errors/errbase/decode.go index 832c3b6c7..59af23057 100644 --- a/vendor/github.com/cockroachdb/errors/errbase/decode.go +++ b/vendor/github.com/cockroachdb/errors/errbase/decode.go @@ -23,6 +23,8 @@ import ( ) // DecodeError decodes an error. +// +// Can only be called if the EncodedError is set (see IsSet()). func DecodeError(ctx context.Context, enc EncodedError) error { if w := enc.GetWrapper(); w != nil { return decodeWrapper(ctx, w) @@ -55,6 +57,15 @@ func decodeLeaf(ctx context.Context, enc *errorspb.EncodedErrorLeaf) error { return genErr } // Decoding failed, we'll drop through to opaqueLeaf{} below. + } else if decoder, ok := multiCauseDecoders[typeKey]; ok { + causes := make([]error, len(enc.MultierrorCauses)) + for i, e := range enc.MultierrorCauses { + causes[i] = DecodeError(ctx, *e) + } + genErr := decoder(ctx, causes, enc.Message, enc.Details.ReportablePayload, payload) + if genErr != nil { + return genErr + } } else { // Shortcut for non-registered proto-encodable error types: // if it already implements `error`, it's good to go. @@ -64,6 +75,19 @@ func decodeLeaf(ctx context.Context, enc *errorspb.EncodedErrorLeaf) error { } } + if len(enc.MultierrorCauses) > 0 { + causes := make([]error, len(enc.MultierrorCauses)) + for i, e := range enc.MultierrorCauses { + causes[i] = DecodeError(ctx, *e) + } + leaf := &opaqueLeafCauses{ + causes: causes, + } + leaf.msg = enc.Message + leaf.details = enc.Details + return leaf + } + // No decoder and no error type: we'll keep what we received and // make it ready to re-encode exactly (if the error leaves over the // network again). @@ -95,7 +119,7 @@ func decodeWrapper(ctx context.Context, enc *errorspb.EncodedWrapper) error { typeKey := TypeKey(enc.Details.ErrorTypeMark.FamilyName) if decoder, ok := decoders[typeKey]; ok { // Yes, use it. - genErr := decoder(ctx, cause, enc.MessagePrefix, enc.Details.ReportablePayload, payload) + genErr := decoder(ctx, cause, enc.Message, enc.Details.ReportablePayload, payload) if genErr != nil { // Decoding succeeded. Use this. return genErr @@ -105,9 +129,10 @@ func decodeWrapper(ctx context.Context, enc *errorspb.EncodedWrapper) error { // Otherwise, preserve all details about the original object. return &opaqueWrapper{ - cause: cause, - prefix: enc.MessagePrefix, - details: enc.Details, + cause: cause, + prefix: enc.Message, + details: enc.Details, + messageType: MessageType(enc.MessageType), } } @@ -158,3 +183,24 @@ type WrapperDecoder = func(ctx context.Context, cause error, msgPrefix string, s // registry for RegisterWrapperType. var decoders = map[TypeKey]WrapperDecoder{} + +// MultiCauseDecoder is to be provided (via RegisterMultiCauseDecoder +// above) by additional multi-cause wrapper types not yet known by the +// library. A nil return indicates that decoding was not successful. +type MultiCauseDecoder = func(ctx context.Context, causes []error, msgPrefix string, safeDetails []string, payload proto.Message) error + +// registry for RegisterMultiCauseDecoder. +var multiCauseDecoders = map[TypeKey]MultiCauseDecoder{} + +// RegisterMultiCauseDecoder can be used to register new multi-cause +// wrapper types to the library. Registered wrappers will be decoded +// using their own Go type when an error is decoded. Multi-cause +// wrappers that have not been registered will be decoded using the +// opaqueWrapper type. +func RegisterMultiCauseDecoder(theType TypeKey, decoder MultiCauseDecoder) { + if decoder == nil { + delete(multiCauseDecoders, theType) + } else { + multiCauseDecoders[theType] = decoder + } +} diff --git a/vendor/github.com/cockroachdb/errors/errbase/encode.go b/vendor/github.com/cockroachdb/errors/errbase/encode.go index a4857632e..418cc50e8 100644 --- a/vendor/github.com/cockroachdb/errors/errbase/encode.go +++ b/vendor/github.com/cockroachdb/errors/errbase/encode.go @@ -33,18 +33,24 @@ func EncodeError(ctx context.Context, err error) EncodedError { if cause := UnwrapOnce(err); cause != nil { return encodeWrapper(ctx, err, cause) } - // Not a causer. - return encodeLeaf(ctx, err) + return encodeLeaf(ctx, err, UnwrapMulti(err)) } -// encodeLeaf encodes a leaf error. -func encodeLeaf(ctx context.Context, err error) EncodedError { +// encodeLeaf encodes a leaf error. This function accepts a `causes` +// argument because we encode multi-cause errors using the Leaf +// protobuf. This was done to enable backwards compatibility when +// introducing this functionality since the Wrapper type already has a +// required single `cause` field. +func encodeLeaf(ctx context.Context, err error, causes []error) EncodedError { var msg string var details errorspb.EncodedErrorDetails if e, ok := err.(*opaqueLeaf); ok { msg = e.msg details = e.details + } else if e, ok := err.(*opaqueLeafCauses); ok { + msg = e.msg + details = e.details } else { details.OriginalTypeName, details.ErrorTypeMark.FamilyName, details.ErrorTypeMark.Extension = getTypeDetails(err, false /*onlyFamily*/) @@ -74,11 +80,21 @@ func encodeLeaf(ctx context.Context, err error) EncodedError { details.FullDetails = encodeAsAny(ctx, err, payload) } + var cs []*EncodedError + if len(causes) > 0 { + cs = make([]*EncodedError, len(causes)) + for i, ee := range causes { + ee := EncodeError(ctx, ee) + cs[i] = &ee + } + } + return EncodedError{ Error: &errorspb.EncodedError_Leaf{ Leaf: &errorspb.EncodedErrorLeaf{ - Message: msg, - Details: details, + Message: msg, + Details: details, + MultierrorCauses: cs, }, }, } @@ -115,10 +131,18 @@ func encodeAsAny(ctx context.Context, err error, payload proto.Message) *types.A func encodeWrapper(ctx context.Context, err, cause error) EncodedError { var msg string var details errorspb.EncodedErrorDetails + messageType := Prefix if e, ok := err.(*opaqueWrapper); ok { + // We delegate all knowledge of the error string + // to the original encoder and do not try to re-engineer + // the prefix out of the error. This helps maintain + // backward compatibility with earlier versions of the + // encoder which don't have any understanding of + // error string ownership by the wrapper. msg = e.prefix details = e.details + messageType = e.messageType } else { details.OriginalTypeName, details.ErrorTypeMark.FamilyName, details.ErrorTypeMark.Extension = getTypeDetails(err, false /*onlyFamily*/) @@ -127,12 +151,12 @@ func encodeWrapper(ctx context.Context, err, cause error) EncodedError { // If we have a manually registered encoder, use that. typeKey := TypeKey(details.ErrorTypeMark.FamilyName) if enc, ok := encoders[typeKey]; ok { - msg, details.ReportablePayload, payload = enc(ctx, err) + msg, details.ReportablePayload, payload, messageType = enc(ctx, err) } else { // No encoder. // In that case, we'll try to compute a message prefix // manually. - msg = extractPrefix(err, cause) + msg, messageType = extractPrefix(err, cause) // If there are known safe details, use them. if s, ok := err.(SafeDetailer); ok { @@ -148,9 +172,10 @@ func encodeWrapper(ctx context.Context, err, cause error) EncodedError { return EncodedError{ Error: &errorspb.EncodedError_Wrapper{ Wrapper: &errorspb.EncodedWrapper{ - Cause: EncodeError(ctx, cause), - MessagePrefix: msg, - Details: details, + Cause: EncodeError(ctx, cause), + Message: msg, + Details: details, + MessageType: errorspb.MessageType(messageType), }, }, } @@ -158,21 +183,36 @@ func encodeWrapper(ctx context.Context, err, cause error) EncodedError { // extractPrefix extracts the prefix from a wrapper's error message. // For example, -// err := errors.New("bar") -// err = errors.Wrap(err, "foo") -// extractPrefix(err) +// +// err := errors.New("bar") +// err = errors.Wrap(err, "foo") +// extractPrefix(err) +// // returns "foo". -func extractPrefix(err, cause error) string { +// +// If a presumed wrapper does not have a message prefix, it is assumed +// to override the entire error message and `extractPrefix` returns +// the entire message and the boolean `true` to signify that the causes +// should not be appended to it. +func extractPrefix(err, cause error) (string, MessageType) { causeSuffix := cause.Error() errMsg := err.Error() if strings.HasSuffix(errMsg, causeSuffix) { prefix := errMsg[:len(errMsg)-len(causeSuffix)] + // If error msg matches exactly then this is a wrapper + // with no message of its own. + if len(prefix) == 0 { + return "", Prefix + } if strings.HasSuffix(prefix, ": ") { - return prefix[:len(prefix)-2] + return prefix[:len(prefix)-2], Prefix } } - return "" + // If we don't have the cause as a suffix, then we have + // some other string as our error msg, preserve that and + // mark as override + return errMsg, FullMessage } func getTypeDetails( @@ -183,6 +223,8 @@ func getTypeDetails( switch t := err.(type) { case *opaqueLeaf: return t.details.OriginalTypeName, t.details.ErrorTypeMark.FamilyName, t.details.ErrorTypeMark.Extension + case *opaqueLeafCauses: + return t.details.OriginalTypeName, t.details.ErrorTypeMark.FamilyName, t.details.ErrorTypeMark.Extension case *opaqueWrapper: return t.details.OriginalTypeName, t.details.ErrorTypeMark.FamilyName, t.details.ErrorTypeMark.Extension } @@ -286,6 +328,28 @@ type LeafEncoder = func(ctx context.Context, err error) (msg string, safeDetails // registry for RegisterLeafEncoder. var leafEncoders = map[TypeKey]LeafEncoder{} +// RegisterMultiCauseEncoder can be used to register new multi-cause +// error types to the library. Registered types will be encoded using +// their own Go type when an error is encoded. Multi-cause wrappers +// that have not been registered will be encoded using the +// opaqueWrapper type. +func RegisterMultiCauseEncoder(theType TypeKey, encoder MultiCauseEncoder) { + // This implementation is a simple wrapper around `LeafEncoder` + // because we implemented multi-cause error wrapper encoding into a + // `Leaf` instead of a `Wrapper` for smoother backwards + // compatibility support. Exposing this detail to consumers of the + // API is confusing and hence avoided. The causes of the error are + // encoded separately regardless of this encoder's implementation. + RegisterLeafEncoder(theType, encoder) +} + +// MultiCauseEncoder is to be provided (via RegisterMultiCauseEncoder +// above) by additional multi-cause wrapper types not yet known to this +// library. The encoder will automatically extract and encode the +// causes of this error by calling `Unwrap()` and expecting a slice of +// errors. +type MultiCauseEncoder = func(ctx context.Context, err error) (msg string, safeDetails []string, payload proto.Message) + // RegisterWrapperEncoder can be used to register new wrapper types to // the library. Registered wrappers will be encoded using their own // Go type when an error is encoded. Wrappers that have not been @@ -295,6 +359,35 @@ var leafEncoders = map[TypeKey]LeafEncoder{} // or a different type, ensure that RegisterTypeMigration() was called // prior to RegisterWrapperEncoder(). func RegisterWrapperEncoder(theType TypeKey, encoder WrapperEncoder) { + RegisterWrapperEncoderWithMessageType( + theType, + func(ctx context.Context, err error) ( + msgPrefix string, + safeDetails []string, + payload proto.Message, + messageType MessageType, + ) { + prefix, details, payload := encoder(ctx, err) + return prefix, details, payload, messageType + }) +} + +// RegisterWrapperEncoderWithMessageType can be used to register +// new wrapper types to the library. Registered wrappers will be +// encoded using their own Go type when an error is encoded. Wrappers +// that have not been registered will be encoded using the +// opaqueWrapper type. +// +// This function differs from RegisterWrapperEncoder by allowing the +// caller to explicitly decide whether the wrapper owns the entire +// error message or not. Otherwise, the relationship is inferred. +// +// Note: if the error type has been migrated from a previous location +// or a different type, ensure that RegisterTypeMigration() was called +// prior to RegisterWrapperEncoder(). +func RegisterWrapperEncoderWithMessageType( + theType TypeKey, encoder WrapperEncoderWithMessageType, +) { if encoder == nil { delete(encoders, theType) } else { @@ -304,7 +397,42 @@ func RegisterWrapperEncoder(theType TypeKey, encoder WrapperEncoder) { // WrapperEncoder is to be provided (via RegisterWrapperEncoder above) // by additional wrapper types not yet known to this library. -type WrapperEncoder = func(ctx context.Context, err error) (msgPrefix string, safeDetails []string, payload proto.Message) +type WrapperEncoder func(ctx context.Context, err error) ( + msgPrefix string, + safeDetails []string, + payload proto.Message, +) + +// MessageType is used to encode information about an error message +// within a wrapper error type. This information is used to affect +// display logic. +type MessageType errorspb.MessageType + +// Values below should match the ones in errorspb.MessageType for +// direct conversion. +const ( + // Prefix denotes an error message that should be prepended to the + // message of its cause. + Prefix MessageType = MessageType(errorspb.MessageType_PREFIX) + // FullMessage denotes an error message that contains the text of its + // causes and can be displayed standalone. + FullMessage = MessageType(errorspb.MessageType_FULL_MESSAGE) +) + +// WrapperEncoderWithMessageType is to be provided (via +// RegisterWrapperEncoderWithMessageType above) by additional wrapper +// types not yet known to this library. This encoder returns an +// additional enum which indicates whether the wrapper owns the error +// message completely instead of simply being a prefix with the error +// message of its causes appended to it. This information is encoded +// along with the prefix in order to provide context during error +// display. +type WrapperEncoderWithMessageType func(ctx context.Context, err error) ( + msgPrefix string, + safeDetails []string, + payload proto.Message, + messageType MessageType, +) // registry for RegisterWrapperType. -var encoders = map[TypeKey]WrapperEncoder{} +var encoders = map[TypeKey]WrapperEncoderWithMessageType{} diff --git a/vendor/github.com/cockroachdb/errors/errbase/format_error.go b/vendor/github.com/cockroachdb/errors/errbase/format_error.go index 534db0809..4b4602c85 100644 --- a/vendor/github.com/cockroachdb/errors/errbase/format_error.go +++ b/vendor/github.com/cockroachdb/errors/errbase/format_error.go @@ -102,7 +102,13 @@ func formatErrorInternal(err error, s fmt.State, verb rune, redactableOutput boo // to enable stack trace de-duplication. This requires a // post-order traversal. Since we have a linked list, the best we // can do is a recursion. - p.formatRecursive(err, true /* isOutermost */, true /* withDetail */) + p.formatRecursive( + err, + true, /* isOutermost */ + true, /* withDetail */ + false, /* withDepth */ + 0, /* depth */ + ) // We now have all the data, we can render the result. p.formatEntries(err) @@ -146,7 +152,13 @@ func formatErrorInternal(err error, s fmt.State, verb rune, redactableOutput boo // by calling FormatError(), in which case we'd get an infinite // recursion. So we have no choice but to peel the data // and then assemble the pieces ourselves. - p.formatRecursive(err, true /* isOutermost */, false /* withDetail */) + p.formatRecursive( + err, + true, /* isOutermost */ + false, /* withDetail */ + false, /* withDepth */ + 0, /* depth */ + ) p.formatSingleLineOutput() p.finishDisplay(verb) @@ -195,7 +207,19 @@ func (s *state) formatEntries(err error) { // Wraps: (N)
// for i, j := len(s.entries)-2, 2; i >= 0; i, j = i-1, j+1 { - fmt.Fprintf(&s.finalBuf, "\nWraps: (%d)", j) + s.finalBuf.WriteByte('\n') + // Extra indentation starts at depth==2 because the direct + // children of the root error area already printed on separate + // newlines. + for m := 0; m < s.entries[i].depth-1; m += 1 { + if m == s.entries[i].depth-2 { + s.finalBuf.WriteString("└─ ") + } else { + s.finalBuf.WriteByte(' ') + s.finalBuf.WriteByte(' ') + } + } + fmt.Fprintf(&s.finalBuf, "Wraps: (%d)", j) entry := s.entries[i] s.printEntry(entry) } @@ -278,8 +302,9 @@ func (s *state) printEntry(entry formatEntry) { // // This function is used both when FormatError() is called indirectly // from .Error(), e.g. in: -// (e *myType) Error() { return fmt.Sprintf("%v", e) } -// (e *myType) Format(s fmt.State, verb rune) { errors.FormatError(s, verb, e) } +// +// (e *myType) Error() { return fmt.Sprintf("%v", e) } +// (e *myType) Format(s fmt.State, verb rune) { errors.FormatError(s, verb, e) } // // and also to print the first line in the output of a %+v format. // @@ -329,12 +354,34 @@ func (s *state) formatSingleLineOutput() { // s.finalBuf is untouched. The conversion of s.entries // to s.finalBuf is done by formatSingleLineOutput() and/or // formatEntries(). -func (s *state) formatRecursive(err error, isOutermost, withDetail bool) { +// +// `withDepth` and `depth` are used to tag subtrees of multi-cause +// errors for added indentation during printing. Once a multi-cause +// error is encountered, all subsequent calls with set `withDepth` to +// true, and increment `depth` during recursion. This information is +// persisted into the generated entries and used later to display the +// error with increased indentation based in the depth. +func (s *state) formatRecursive(err error, isOutermost, withDetail, withDepth bool, depth int) int { cause := UnwrapOnce(err) + numChildren := 0 if cause != nil { - // Recurse first. - s.formatRecursive(cause, false /*isOutermost*/, withDetail) + // Recurse first, which populates entries list starting from innermost + // entry. If we've previously seen a multi-cause wrapper, `withDepth` + // will be true, and we'll record the depth below ensuring that extra + // indentation is applied to this inner cause during printing. + // Otherwise, we maintain "straight" vertical formatting by keeping the + // parent callers `withDepth` value of `false` by default. + numChildren += s.formatRecursive(cause, false, withDetail, withDepth, depth+1) + } + + causes := UnwrapMulti(err) + for _, c := range causes { + // Override `withDepth` to true for all child entries ensuring they have + // indentation applied during formatting to distinguish them from + // parents. + numChildren += s.formatRecursive(c, false, withDetail, true, depth+1) } + // inserted := len(s.entries) - 1 - startChildren // Reinitialize the state for this stage of wrapping. s.wantDetail = withDetail @@ -349,75 +396,94 @@ func (s *state) formatRecursive(err error, isOutermost, withDetail bool) { bufIsRedactable := false - printDone := false - for _, fn := range specialCases { - if handled, desiredShortening := fn(err, (*safePrinter)(s), cause == nil /* leaf */); handled { - printDone = true - bufIsRedactable = true - if desiredShortening == nil { - // The error wants to elide the short messages from inner - // causes. Do it. - for i := range s.entries { - s.entries[i].elideShort = true - } - } - break + switch v := err.(type) { + case SafeFormatter: + bufIsRedactable = true + desiredShortening := v.SafeFormatError((*safePrinter)(s)) + if desiredShortening == nil { + // The error wants to elide the short messages from inner causes. + // Read backwards through list of entries up to the number of new + // entries created "under" this one amount and mark `elideShort` + // true. + s.elideShortChildren(numChildren) } - } - if !printDone { - switch v := err.(type) { - case SafeFormatter: - bufIsRedactable = true - desiredShortening := v.SafeFormatError((*safePrinter)(s)) - if desiredShortening == nil { - // The error wants to elide the short messages from inner - // causes. Do it. - for i := range s.entries { - s.entries[i].elideShort = true - } - } - case Formatter: - desiredShortening := v.FormatError((*printer)(s)) - if desiredShortening == nil { + case Formatter: + desiredShortening := v.FormatError((*printer)(s)) + if desiredShortening == nil { + // The error wants to elide the short messages from inner + // causes. Do it. + s.elideShortChildren(numChildren) + } + + case fmt.Formatter: + // We can only use a fmt.Formatter when both the following + // conditions are true: + // - when it is the leaf error, because a fmt.Formatter + // on a wrapper also recurses. + // - when it is not the outermost wrapper, because + // the Format() method is likely to be calling FormatError() + // to do its job and we want to avoid an infinite recursion. + if !isOutermost && cause == nil { + v.Format(s, 'v') + if st, ok := err.(StackTraceProvider); ok { + // This is likely a leaf error from github/pkg/errors. + // The thing probably printed its stack trace on its own. + seenTrace = true + // We'll subsequently simplify stack traces in wrappers. + s.lastStack = st.StackTrace() + } + } else { + if elideCauseMsg := s.formatSimple(err, cause); elideCauseMsg { // The error wants to elide the short messages from inner // causes. Do it. - for i := range s.entries { - s.entries[i].elideShort = true - } + s.elideShortChildren(numChildren) } + } - case fmt.Formatter: - // We can only use a fmt.Formatter when both the following - // conditions are true: - // - when it is the leaf error, because a fmt.Formatter - // on a wrapper also recurses. - // - when it is not the outermost wrapper, because - // the Format() method is likely to be calling FormatError() - // to do its job and we want to avoid an infinite recursion. - if !isOutermost && cause == nil { - v.Format(s, 'v') - if st, ok := err.(StackTraceProvider); ok { - // This is likely a leaf error from github/pkg/errors. - // The thing probably printed its stack trace on its own. - seenTrace = true - // We'll subsequently simplify stack traces in wrappers. - s.lastStack = st.StackTrace() + default: + // Handle the special case overrides for context.Canceled, + // os.PathError, etc for which we know how to extract some safe + // strings. + // + // We need to do this in the `default` branch, instead of doing + // this above the switch, because the special handler could call a + // .Error() that delegates its implementation to fmt.Formatter, + // errors.Safeformatter or errors.Formattable, which brings us + // back to this method in a call cycle. So we need to handle the + // various interfaces first. + printDone := false + for _, fn := range specialCases { + if handled, desiredShortening := fn(err, (*safePrinter)(s), cause == nil /* leaf */); handled { + printDone = true + bufIsRedactable = true + if desiredShortening == nil { + // The error wants to elide the short messages from inner + // causes. Do it. + s.elideShortChildren(numChildren) } - } else { - s.formatSimple(err, cause) + break } - - default: + } + if !printDone { // If the error did not implement errors.Formatter nor // fmt.Formatter, but it is a wrapper, still attempt best effort: // print what we can at this level. - s.formatSimple(err, cause) + elideChildren := s.formatSimple(err, cause) + // always elideChildren when dealing with multi-cause errors. + if len(causes) > 0 { + elideChildren = true + } + if elideChildren { + // The error wants to elide the short messages from inner + // causes. Do it. + s.elideShortChildren(numChildren) + } } } // Collect the result. - entry := s.collectEntry(err, bufIsRedactable) + entry := s.collectEntry(err, bufIsRedactable, withDepth, depth) // If there's an embedded stack trace, also collect it. // This will get either a stack from pkg/errors, or ours. @@ -431,9 +497,22 @@ func (s *state) formatRecursive(err error, isOutermost, withDetail bool) { // Remember the entry for later rendering. s.entries = append(s.entries, entry) s.buf = bytes.Buffer{} + + return numChildren + 1 +} + +// elideShortChildren takes a number of entries to set `elideShort` to +// false. The reason a number of entries is needed is that we may be +// eliding a subtree of causes in the case of a multi-cause error. In +// the multi-cause case, we need to know how many of the prior errors +// in the list of entries is a child of this subtree. +func (s *state) elideShortChildren(newEntries int) { + for i := 0; i < newEntries; i++ { + s.entries[len(s.entries)-1-i].elideShort = true + } } -func (s *state) collectEntry(err error, bufIsRedactable bool) formatEntry { +func (s *state) collectEntry(err error, bufIsRedactable bool, withDepth bool, depth int) formatEntry { entry := formatEntry{err: err} if s.wantDetail { // The buffer has been populated as a result of formatting with @@ -470,6 +549,10 @@ func (s *state) collectEntry(err error, bufIsRedactable bool) formatEntry { } } + if withDepth { + entry.depth = depth + } + return entry } @@ -490,16 +573,23 @@ func RegisterSpecialCasePrinter(fn safeErrorPrinterFn) { // formatSimple performs a best effort at extracting the details at a // given level of wrapping when the error object does not implement // the Formatter interface. -func (s *state) formatSimple(err, cause error) { +// Returns true if we want to elide errors from causal chain. +func (s *state) formatSimple(err, cause error) bool { var pref string + elideCauses := false if cause != nil { - pref = extractPrefix(err, cause) + var messageType MessageType + pref, messageType = extractPrefix(err, cause) + if messageType == FullMessage { + elideCauses = true + } } else { pref = err.Error() } if len(pref) > 0 { s.Write([]byte(pref)) } + return elideCauses } // finishDisplay renders s.finalBuf into s.State. @@ -558,7 +648,7 @@ type state struct { // entries collect the result of formatRecursive(). They are // consumed by formatSingleLineOutput() and formatEntries() to - // procude the contents of finalBuf. + // produce the contents of finalBuf. entries []formatEntry // buf collects the details of the current error object at a given @@ -680,6 +770,11 @@ type formatEntry struct { // truncated to avoid duplication of entries. This is used to // display a truncation indicator during verbose rendering. elidedStackTrace bool + + // depth, if positive, represents a nesting depth of this error as + // a causer of others. This is used with verbose printing to + // illustrate the nesting depth for multi-cause error wrappers. + depth int } // String is used for debugging only. @@ -701,6 +796,12 @@ func (s *state) Write(b []byte) (n int, err error) { for i, c := range b { if c == '\n' { + //if s.needNewline > 0 { + // for i := 0; i < s.needNewline-1; i++ { + // s.buf.Write(detailSep[:len(sep)-1]) + // } + // s.needNewline = 0 + //} // Flush all the bytes seen so far. s.buf.Write(b[k:i]) // Don't print the newline itself; instead, prepare the state so @@ -730,6 +831,11 @@ func (s *state) Write(b []byte) (n int, err error) { s.notEmpty = true } } + //if s.needNewline > 0 { + // for i := 0; i < s.needNewline-1; i++ { + // s.buf.Write(detailSep[:len(sep)-1]) + // } + //} s.buf.Write(b[k:]) return len(b), nil } @@ -756,6 +862,9 @@ func (p *state) switchOver() { p.buf = bytes.Buffer{} p.notEmpty = false p.hasDetail = true + + // One of the newlines is accounted for in the switch over. + // p.needNewline -= 1 } func (s *printer) Detail() bool { @@ -819,7 +928,7 @@ func (s *safePrinter) enhanceArgs(args []interface{}) { args[i] = redact.Safe(thisStack) lastSeen = st } - // In contrast with (*printer).enhanceArgs(), we dont use a + // In contrast with (*printer).enhanceArgs(), we don't use a // special case for `error` here, because the redact package // already helps us recursing into a safe print for // error objects. diff --git a/vendor/github.com/cockroachdb/errors/errbase/opaque.go b/vendor/github.com/cockroachdb/errors/errbase/opaque.go index 81ca03295..cd9b38aaa 100644 --- a/vendor/github.com/cockroachdb/errors/errbase/opaque.go +++ b/vendor/github.com/cockroachdb/errors/errbase/opaque.go @@ -30,19 +30,39 @@ type opaqueLeaf struct { details errorspb.EncodedErrorDetails } +// opaqueLeafCauses is used when receiving an unknown multi-cause +// wrapper type. Its important property is that if it is communicated +// back to some network system that _does_ know about the type, the +// original object can be restored. We encode multi-cause errors as +// leaf nodes over the network, in order to support backwards +// compatibility with existing single-cause wrapper messages. +// +// This struct *must* be initialized with a non-nil causes value in +// order to comply with go stdlib expectations for `Unwrap()`. +type opaqueLeafCauses struct { + opaqueLeaf + causes []error +} + var _ error = (*opaqueLeaf)(nil) var _ SafeDetailer = (*opaqueLeaf)(nil) var _ fmt.Formatter = (*opaqueLeaf)(nil) var _ SafeFormatter = (*opaqueLeaf)(nil) +var _ error = (*opaqueLeafCauses)(nil) +var _ SafeDetailer = (*opaqueLeafCauses)(nil) +var _ fmt.Formatter = (*opaqueLeafCauses)(nil) +var _ SafeFormatter = (*opaqueLeafCauses)(nil) + // opaqueWrapper is used when receiving an unknown wrapper type. // Its important property is that if it is communicated // back to some network system that _does_ know about // the type, the original object can be restored. type opaqueWrapper struct { - cause error - prefix string - details errorspb.EncodedErrorDetails + cause error + prefix string + details errorspb.EncodedErrorDetails + messageType MessageType } var _ error = (*opaqueWrapper)(nil) @@ -53,6 +73,9 @@ var _ SafeFormatter = (*opaqueWrapper)(nil) func (e *opaqueLeaf) Error() string { return e.msg } func (e *opaqueWrapper) Error() string { + if e.messageType == FullMessage { + return e.prefix + } if e.prefix == "" { return e.cause.Error() } @@ -66,8 +89,12 @@ func (e *opaqueWrapper) Unwrap() error { return e.cause } func (e *opaqueLeaf) SafeDetails() []string { return e.details.ReportablePayload } func (e *opaqueWrapper) SafeDetails() []string { return e.details.ReportablePayload } -func (e *opaqueLeaf) Format(s fmt.State, verb rune) { FormatError(e, s, verb) } -func (e *opaqueWrapper) Format(s fmt.State, verb rune) { FormatError(e, s, verb) } +func (e *opaqueLeaf) Format(s fmt.State, verb rune) { FormatError(e, s, verb) } +func (e *opaqueLeafCauses) Format(s fmt.State, verb rune) { FormatError(e, s, verb) } +func (e *opaqueWrapper) Format(s fmt.State, verb rune) { FormatError(e, s, verb) } + +// opaqueLeafCauses is a multi-cause wrapper +func (e *opaqueLeafCauses) Unwrap() []error { return e.causes } func (e *opaqueLeaf) SafeFormatError(p Printer) (next error) { p.Print(e.msg) @@ -103,5 +130,8 @@ func (e *opaqueWrapper) SafeFormatError(p Printer) (next error) { p.Printf("\npayload type: %s", redact.Safe(e.details.FullDetails.TypeUrl)) } } + if e.messageType == FullMessage { + return nil + } return e.cause } diff --git a/vendor/github.com/cockroachdb/errors/errbase/format_simple.go b/vendor/github.com/cockroachdb/errors/errbase/oserror_go116.go similarity index 51% rename from vendor/github.com/cockroachdb/errors/errbase/format_simple.go rename to vendor/github.com/cockroachdb/errors/errbase/oserror_go116.go index 31b85f91c..00fa11a16 100644 --- a/vendor/github.com/cockroachdb/errors/errbase/format_simple.go +++ b/vendor/github.com/cockroachdb/errors/errbase/oserror_go116.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Cockroach Authors. +// Copyright 2021 The Cockroach Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,25 +12,13 @@ // implied. See the License for the specific language governing // permissions and limitations under the License. +// +build go1.16 + package errbase -import "io" +import "io/fs" -// formatSimpleError is a helper used by FormatError() for the top -// level error/wrapper argument, if it does not implement the -// errors.Formatter interface. -func formatSimpleError(err error, p *state, sep string) error { - if cause := UnwrapOnce(err); cause != nil { - pref := extractPrefix(err, cause) - p.buf.WriteString(pref) - if pref != "" { - p.buf.WriteByte(':') - p.buf.WriteString(sep) - } - err = cause - } else { - io.WriteString(&p.buf, err.Error()) - err = nil - } - return err +func registerOsPathErrorMigration() { + // The os.PathError type was migrated to io.fs.PathError in Go 1.16. + RegisterTypeMigration("os", "*os.PathError", &fs.PathError{}) } diff --git a/vendor/github.com/cockroachdb/errors/errbase/oserror_pre116.go b/vendor/github.com/cockroachdb/errors/errbase/oserror_pre116.go new file mode 100644 index 000000000..62eeb7d22 --- /dev/null +++ b/vendor/github.com/cockroachdb/errors/errbase/oserror_pre116.go @@ -0,0 +1,19 @@ +// Copyright 2021 The Cockroach 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. + +// +build !go1.16 + +package errbase + +func registerOsPathErrorMigration() {} diff --git a/vendor/github.com/cockroachdb/errors/errbase/unwrap.go b/vendor/github.com/cockroachdb/errors/errbase/unwrap.go index 031cf7f83..bed4c9aac 100644 --- a/vendor/github.com/cockroachdb/errors/errbase/unwrap.go +++ b/vendor/github.com/cockroachdb/errors/errbase/unwrap.go @@ -27,6 +27,16 @@ package errbase // It supports both errors implementing causer (`Cause()` method, from // github.com/pkg/errors) and `Wrapper` (`Unwrap()` method, from the // Go 2 error proposal). +// +// UnwrapOnce treats multi-errors (those implementing the +// `Unwrap() []error` interface as leaf-nodes since they cannot +// reasonably be iterated through to a single cause. These errors +// are typically constructed as a result of `fmt.Errorf` which results +// in a `wrapErrors` instance that contains an interpolated error +// string along with a list of causes. +// +// The go stdlib does not define output on `Unwrap()` for a multi-cause +// error, so we default to nil here. func UnwrapOnce(err error) (cause error) { switch e := err.(type) { case interface{ Cause() error }: @@ -39,6 +49,7 @@ func UnwrapOnce(err error) (cause error) { // UnwrapAll accesses the root cause object of the error. // If the error has no cause (leaf error), it is returned directly. +// UnwrapAll treats multi-errors as leaf nodes. func UnwrapAll(err error) error { for { if cause := UnwrapOnce(err); cause != nil { @@ -49,3 +60,12 @@ func UnwrapAll(err error) error { } return err } + +// UnwrapMulti access the slice of causes that an error contains, if it is a +// multi-error. +func UnwrapMulti(err error) []error { + if me, ok := err.(interface{ Unwrap() []error }); ok { + return me.Unwrap() + } + return nil +} diff --git a/vendor/github.com/cockroachdb/errors/errbase_api.go b/vendor/github.com/cockroachdb/errors/errbase_api.go index 3f647e03c..da410f922 100644 --- a/vendor/github.com/cockroachdb/errors/errbase_api.go +++ b/vendor/github.com/cockroachdb/errors/errbase_api.go @@ -86,6 +86,20 @@ func GetTypeKey(err error) TypeKey { return errbase.GetTypeKey(err) } // A nil return indicates that decoding was not successful. type LeafDecoder = errbase.LeafDecoder +// MultiCauseDecoder is to be provided (via RegisterMultiCauseDecoder +// above) by additional multi-cause wrapper types not yet known by the +// library. A nil return indicates that decoding was not successful. +type MultiCauseDecoder = errbase.MultiCauseDecoder + +// RegisterMultiCauseDecoder can be used to register new multi-cause +// wrapper types to the library. Registered wrappers will be decoded +// using their own Go type when an error is decoded. Multi-cause +// wrappers that have not been registered will be decoded using the +// opaqueWrapper type. +func RegisterMultiCauseDecoder(theType TypeKey, decoder MultiCauseDecoder) { + errbase.RegisterMultiCauseDecoder(theType, decoder) +} + // RegisterWrapperDecoder can be used to register new wrapper types to // the library. Registered wrappers will be decoded using their own // Go type when an error is decoded. Wrappers that have not been @@ -135,6 +149,41 @@ func RegisterWrapperEncoder(typeName TypeKey, encoder WrapperEncoder) { // by additional wrapper types not yet known to this library. type WrapperEncoder = errbase.WrapperEncoder +// RegisterWrapperEncoderWithMessageType can be used to register new wrapper +// types to the library. These wrappers can optionally override the child error +// messages with their own error string instead of relying on iterative +// concatenation. Registered wrappers will be encoded using their own Go type +// when an error is encoded. Wrappers that have not been registered will be +// encoded using the opaqueWrapper type. +// +// Note: if the error type has been migrated from a previous location +// or a different type, ensure that RegisterTypeMigration() was called +// prior to RegisterWrapperEncoder(). +func RegisterWrapperEncoderWithMessageType(typeName TypeKey, encoder WrapperEncoderWithMessageType) { + errbase.RegisterWrapperEncoderWithMessageType(typeName, encoder) +} + +// WrapperEncoderWithMessageType is to be provided (via +// RegisterWrapperEncoderWithMessageType) by additional wrapper +// types not yet known to this library. +type WrapperEncoderWithMessageType = errbase.WrapperEncoderWithMessageType + +// RegisterMultiCauseEncoder can be used to register new multi-cause +// error types to the library. Registered types will be encoded using +// their own Go type when an error is encoded. Multi-cause wrappers +// that have not been registered will be encoded using the +// opaqueWrapper type. +func RegisterMultiCauseEncoder(typeName TypeKey, encoder MultiCauseEncoder) { + errbase.RegisterMultiCauseEncoder(typeName, encoder) +} + +// MultiCauseEncoder is to be provided (via RegisterMultiCauseEncoder +// above) by additional multi-cause wrapper types not yet known to this +// library. The encoder will automatically extract and encode the +// causes of this error by calling `Unwrap()` and expecting a slice of +// errors. +type MultiCauseEncoder = errbase.MultiCauseEncoder + // SetWarningFn enables configuration of the warning function. func SetWarningFn(fn func(context.Context, string, ...interface{})) { errbase.SetWarningFn(fn) } @@ -185,7 +234,8 @@ func Formattable(err error) fmt.Formatter { return errbase.Formattable(err) } // The value of previousTypeName must be the result of calling // reflect.TypeOf(err).String() on the original error object. // This is usually composed as follows: -// [*]. +// +// [*]. // // For example, Go's standard error type has name "*errors.errorString". // The asterisk indicates that `errorString` implements the `error` diff --git a/vendor/github.com/cockroachdb/errors/errorspb/errors.go b/vendor/github.com/cockroachdb/errors/errorspb/errors.go new file mode 100644 index 000000000..5cfc5ebf2 --- /dev/null +++ b/vendor/github.com/cockroachdb/errors/errorspb/errors.go @@ -0,0 +1,21 @@ +// Copyright 2021 The Cockroach 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 errorspb + +// IsSet returns true if the EncodedError contains an error, or false if it is +// empty. +func (m *EncodedError) IsSet() bool { + return m.Error != nil +} diff --git a/vendor/github.com/cockroachdb/errors/errorspb/errors.pb.go b/vendor/github.com/cockroachdb/errors/errorspb/errors.pb.go index c6f04f5e0..3ec6bfe22 100644 --- a/vendor/github.com/cockroachdb/errors/errorspb/errors.pb.go +++ b/vendor/github.com/cockroachdb/errors/errorspb/errors.pb.go @@ -1,14 +1,17 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: github.com/cockroachdb/errors/errorspb/errors.proto +// source: errorspb/errors.proto package errorspb -import proto "github.com/gogo/protobuf/proto" -import fmt "fmt" -import math "math" -import types "github.com/gogo/protobuf/types" - -import io "io" +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + types "github.com/gogo/protobuf/types" + io "io" + math "math" + math_bits "math/bits" +) // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal @@ -19,12 +22,44 @@ var _ = math.Inf // is compatible with the proto package it is being compiled against. // A compilation error at this line likely means your copy of the // proto package needs to be updated. -const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// MessageType encodes information regarding the interpretation of an +// error's message string. +type MessageType int32 + +const ( + // Keeping zero value as default for backwards compatibility. + // PREFIX is a message that should be prepended to its cause. + MessageType_PREFIX MessageType = 0 + // FULL_MESSAGE is a complete error message that can be displayed + // without its cause. + MessageType_FULL_MESSAGE MessageType = 1 +) + +var MessageType_name = map[int32]string{ + 0: "PREFIX", + 1: "FULL_MESSAGE", +} + +var MessageType_value = map[string]int32{ + "PREFIX": 0, + "FULL_MESSAGE": 1, +} + +func (x MessageType) String() string { + return proto.EnumName(MessageType_name, int32(x)) +} + +func (MessageType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_ddc818d0729874b8, []int{0} +} // EncodedError is the wire-encodable representation // of an error (or error cause chain). type EncodedError struct { // Types that are valid to be assigned to Error: + // // *EncodedError_Leaf // *EncodedError_Wrapper Error isEncodedError_Error `protobuf_oneof:"error"` @@ -34,21 +69,21 @@ func (m *EncodedError) Reset() { *m = EncodedError{} } func (m *EncodedError) String() string { return proto.CompactTextString(m) } func (*EncodedError) ProtoMessage() {} func (*EncodedError) Descriptor() ([]byte, []int) { - return fileDescriptor_errors_aa0d2b9df74f046a, []int{0} + return fileDescriptor_ddc818d0729874b8, []int{0} } func (m *EncodedError) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } func (m *EncodedError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { b = b[:cap(b)] - n, err := m.MarshalTo(b) + n, err := m.MarshalToSizedBuffer(b) if err != nil { return nil, err } return b[:n], nil } -func (dst *EncodedError) XXX_Merge(src proto.Message) { - xxx_messageInfo_EncodedError.Merge(dst, src) +func (m *EncodedError) XXX_Merge(src proto.Message) { + xxx_messageInfo_EncodedError.Merge(m, src) } func (m *EncodedError) XXX_Size() int { return m.Size() @@ -66,10 +101,10 @@ type isEncodedError_Error interface { } type EncodedError_Leaf struct { - Leaf *EncodedErrorLeaf `protobuf:"bytes,1,opt,name=leaf,proto3,oneof"` + Leaf *EncodedErrorLeaf `protobuf:"bytes,1,opt,name=leaf,proto3,oneof" json:"leaf,omitempty"` } type EncodedError_Wrapper struct { - Wrapper *EncodedWrapper `protobuf:"bytes,2,opt,name=wrapper,proto3,oneof"` + Wrapper *EncodedWrapper `protobuf:"bytes,2,opt,name=wrapper,proto3,oneof" json:"wrapper,omitempty"` } func (*EncodedError_Leaf) isEncodedError_Error() {} @@ -96,82 +131,16 @@ func (m *EncodedError) GetWrapper() *EncodedWrapper { return nil } -// XXX_OneofFuncs is for the internal use of the proto package. -func (*EncodedError) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { - return _EncodedError_OneofMarshaler, _EncodedError_OneofUnmarshaler, _EncodedError_OneofSizer, []interface{}{ +// XXX_OneofWrappers is for the internal use of the proto package. +func (*EncodedError) XXX_OneofWrappers() []interface{} { + return []interface{}{ (*EncodedError_Leaf)(nil), (*EncodedError_Wrapper)(nil), } } -func _EncodedError_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { - m := msg.(*EncodedError) - // error - switch x := m.Error.(type) { - case *EncodedError_Leaf: - _ = b.EncodeVarint(1<<3 | proto.WireBytes) - if err := b.EncodeMessage(x.Leaf); err != nil { - return err - } - case *EncodedError_Wrapper: - _ = b.EncodeVarint(2<<3 | proto.WireBytes) - if err := b.EncodeMessage(x.Wrapper); err != nil { - return err - } - case nil: - default: - return fmt.Errorf("EncodedError.Error has unexpected type %T", x) - } - return nil -} - -func _EncodedError_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { - m := msg.(*EncodedError) - switch tag { - case 1: // error.leaf - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - msg := new(EncodedErrorLeaf) - err := b.DecodeMessage(msg) - m.Error = &EncodedError_Leaf{msg} - return true, err - case 2: // error.wrapper - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - msg := new(EncodedWrapper) - err := b.DecodeMessage(msg) - m.Error = &EncodedError_Wrapper{msg} - return true, err - default: - return false, nil - } -} - -func _EncodedError_OneofSizer(msg proto.Message) (n int) { - m := msg.(*EncodedError) - // error - switch x := m.Error.(type) { - case *EncodedError_Leaf: - s := proto.Size(x.Leaf) - n += 1 // tag and wire - n += proto.SizeVarint(uint64(s)) - n += s - case *EncodedError_Wrapper: - s := proto.Size(x.Wrapper) - n += 1 // tag and wire - n += proto.SizeVarint(uint64(s)) - n += s - case nil: - default: - panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) - } - return n -} - // EncodedErrorLeaf is the wire-encodable representation -// of an error leaf. +// of an error leaf or a multi-cause wrapper from go 1.20+ type EncodedErrorLeaf struct { // The main error message (mandatory), that can be printed to human // users and may contain PII. This contains the value of the leaf @@ -179,27 +148,32 @@ type EncodedErrorLeaf struct { Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` // The error details. Details EncodedErrorDetails `protobuf:"bytes,2,opt,name=details,proto3" json:"details"` + // multierror_causes is a list of errors that contain the causal tree + // of this leaf. If this field is not empty, then this leaf encodes + // an error from go 1.20 or later that encodes multiple causes in its + // chain. + MultierrorCauses []*EncodedError `protobuf:"bytes,3,rep,name=multierror_causes,json=multierrorCauses,proto3" json:"multierror_causes,omitempty"` } func (m *EncodedErrorLeaf) Reset() { *m = EncodedErrorLeaf{} } func (m *EncodedErrorLeaf) String() string { return proto.CompactTextString(m) } func (*EncodedErrorLeaf) ProtoMessage() {} func (*EncodedErrorLeaf) Descriptor() ([]byte, []int) { - return fileDescriptor_errors_aa0d2b9df74f046a, []int{1} + return fileDescriptor_ddc818d0729874b8, []int{1} } func (m *EncodedErrorLeaf) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } func (m *EncodedErrorLeaf) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { b = b[:cap(b)] - n, err := m.MarshalTo(b) + n, err := m.MarshalToSizedBuffer(b) if err != nil { return nil, err } return b[:n], nil } -func (dst *EncodedErrorLeaf) XXX_Merge(src proto.Message) { - xxx_messageInfo_EncodedErrorLeaf.Merge(dst, src) +func (m *EncodedErrorLeaf) XXX_Merge(src proto.Message) { + xxx_messageInfo_EncodedErrorLeaf.Merge(m, src) } func (m *EncodedErrorLeaf) XXX_Size() int { return m.Size() @@ -243,21 +217,21 @@ func (m *EncodedErrorDetails) Reset() { *m = EncodedErrorDetails{} } func (m *EncodedErrorDetails) String() string { return proto.CompactTextString(m) } func (*EncodedErrorDetails) ProtoMessage() {} func (*EncodedErrorDetails) Descriptor() ([]byte, []int) { - return fileDescriptor_errors_aa0d2b9df74f046a, []int{2} + return fileDescriptor_ddc818d0729874b8, []int{2} } func (m *EncodedErrorDetails) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } func (m *EncodedErrorDetails) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { b = b[:cap(b)] - n, err := m.MarshalTo(b) + n, err := m.MarshalToSizedBuffer(b) if err != nil { return nil, err } return b[:n], nil } -func (dst *EncodedErrorDetails) XXX_Merge(src proto.Message) { - xxx_messageInfo_EncodedErrorDetails.Merge(dst, src) +func (m *EncodedErrorDetails) XXX_Merge(src proto.Message) { + xxx_messageInfo_EncodedErrorDetails.Merge(m, src) } func (m *EncodedErrorDetails) XXX_Size() int { return m.Size() @@ -273,38 +247,44 @@ var xxx_messageInfo_EncodedErrorDetails proto.InternalMessageInfo type EncodedWrapper struct { // The cause error. Mandatory. Cause EncodedError `protobuf:"bytes,1,opt,name=cause,proto3" json:"cause"` - // The wrapper message prefix (which may be empty). This - // isbprinted before the cause's own message when - // constructing a full message. This may contain PII. + // The wrapper message. This could either be a full error message + // that can be printed independently, or a (potentially empty) prefix + // which is printed before the cause's own message to construct the + // full message. This may contain PII. // // This is extracted automatically: // // - for wrappers that have a registered encoder, // - otherwise, when the wrapper's Error() has its cause's Error() as suffix. - MessagePrefix string `protobuf:"bytes,2,opt,name=message_prefix,json=messagePrefix,proto3" json:"message_prefix,omitempty"` + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` // The error details. Details EncodedErrorDetails `protobuf:"bytes,3,opt,name=details,proto3" json:"details"` + // message_type encodes the interpretation of `message`. Prior + // versions will not set this field and it will be left as `PREFIX`. + // This retains backwards compatibility since the new behavior is + // only enabled when this enum is set to `FULL_MESSAGE`. + MessageType MessageType `protobuf:"varint,4,opt,name=message_type,json=messageType,proto3,enum=cockroach.errorspb.MessageType" json:"message_type,omitempty"` } func (m *EncodedWrapper) Reset() { *m = EncodedWrapper{} } func (m *EncodedWrapper) String() string { return proto.CompactTextString(m) } func (*EncodedWrapper) ProtoMessage() {} func (*EncodedWrapper) Descriptor() ([]byte, []int) { - return fileDescriptor_errors_aa0d2b9df74f046a, []int{3} + return fileDescriptor_ddc818d0729874b8, []int{3} } func (m *EncodedWrapper) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } func (m *EncodedWrapper) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { b = b[:cap(b)] - n, err := m.MarshalTo(b) + n, err := m.MarshalToSizedBuffer(b) if err != nil { return nil, err } return b[:n], nil } -func (dst *EncodedWrapper) XXX_Merge(src proto.Message) { - xxx_messageInfo_EncodedWrapper.Merge(dst, src) +func (m *EncodedWrapper) XXX_Merge(src proto.Message) { + xxx_messageInfo_EncodedWrapper.Merge(m, src) } func (m *EncodedWrapper) XXX_Size() int { return m.Size() @@ -337,21 +317,21 @@ func (m *ErrorTypeMark) Reset() { *m = ErrorTypeMark{} } func (m *ErrorTypeMark) String() string { return proto.CompactTextString(m) } func (*ErrorTypeMark) ProtoMessage() {} func (*ErrorTypeMark) Descriptor() ([]byte, []int) { - return fileDescriptor_errors_aa0d2b9df74f046a, []int{4} + return fileDescriptor_ddc818d0729874b8, []int{4} } func (m *ErrorTypeMark) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } func (m *ErrorTypeMark) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { b = b[:cap(b)] - n, err := m.MarshalTo(b) + n, err := m.MarshalToSizedBuffer(b) if err != nil { return nil, err } return b[:n], nil } -func (dst *ErrorTypeMark) XXX_Merge(src proto.Message) { - xxx_messageInfo_ErrorTypeMark.Merge(dst, src) +func (m *ErrorTypeMark) XXX_Merge(src proto.Message) { + xxx_messageInfo_ErrorTypeMark.Merge(m, src) } func (m *ErrorTypeMark) XXX_Size() int { return m.Size() @@ -372,21 +352,21 @@ func (m *StringsPayload) Reset() { *m = StringsPayload{} } func (m *StringsPayload) String() string { return proto.CompactTextString(m) } func (*StringsPayload) ProtoMessage() {} func (*StringsPayload) Descriptor() ([]byte, []int) { - return fileDescriptor_errors_aa0d2b9df74f046a, []int{5} + return fileDescriptor_ddc818d0729874b8, []int{5} } func (m *StringsPayload) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } func (m *StringsPayload) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { b = b[:cap(b)] - n, err := m.MarshalTo(b) + n, err := m.MarshalToSizedBuffer(b) if err != nil { return nil, err } return b[:n], nil } -func (dst *StringsPayload) XXX_Merge(src proto.Message) { - xxx_messageInfo_StringsPayload.Merge(dst, src) +func (m *StringsPayload) XXX_Merge(src proto.Message) { + xxx_messageInfo_StringsPayload.Merge(m, src) } func (m *StringsPayload) XXX_Size() int { return m.Size() @@ -419,21 +399,21 @@ func (m *ErrnoPayload) Reset() { *m = ErrnoPayload{} } func (m *ErrnoPayload) String() string { return proto.CompactTextString(m) } func (*ErrnoPayload) ProtoMessage() {} func (*ErrnoPayload) Descriptor() ([]byte, []int) { - return fileDescriptor_errors_aa0d2b9df74f046a, []int{6} + return fileDescriptor_ddc818d0729874b8, []int{6} } func (m *ErrnoPayload) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } func (m *ErrnoPayload) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { b = b[:cap(b)] - n, err := m.MarshalTo(b) + n, err := m.MarshalToSizedBuffer(b) if err != nil { return nil, err } return b[:n], nil } -func (dst *ErrnoPayload) XXX_Merge(src proto.Message) { - xxx_messageInfo_ErrnoPayload.Merge(dst, src) +func (m *ErrnoPayload) XXX_Merge(src proto.Message) { + xxx_messageInfo_ErrnoPayload.Merge(m, src) } func (m *ErrnoPayload) XXX_Size() int { return m.Size() @@ -445,6 +425,7 @@ func (m *ErrnoPayload) XXX_DiscardUnknown() { var xxx_messageInfo_ErrnoPayload proto.InternalMessageInfo func init() { + proto.RegisterEnum("cockroach.errorspb.MessageType", MessageType_name, MessageType_value) proto.RegisterType((*EncodedError)(nil), "cockroach.errorspb.EncodedError") proto.RegisterType((*EncodedErrorLeaf)(nil), "cockroach.errorspb.EncodedErrorLeaf") proto.RegisterType((*EncodedErrorDetails)(nil), "cockroach.errorspb.EncodedErrorDetails") @@ -453,10 +434,61 @@ func init() { proto.RegisterType((*StringsPayload)(nil), "cockroach.errorspb.StringsPayload") proto.RegisterType((*ErrnoPayload)(nil), "cockroach.errorspb.ErrnoPayload") } + +func init() { proto.RegisterFile("errorspb/errors.proto", fileDescriptor_ddc818d0729874b8) } + +var fileDescriptor_ddc818d0729874b8 = []byte{ + // 693 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x53, 0x41, 0x4f, 0x13, 0x41, + 0x14, 0xde, 0xa5, 0x85, 0xb6, 0xaf, 0x05, 0xcb, 0x88, 0xc9, 0x42, 0x64, 0x29, 0xab, 0x89, 0x04, + 0x75, 0x9b, 0xe0, 0xc1, 0xc4, 0x18, 0x13, 0xaa, 0x05, 0x4c, 0x28, 0x92, 0x05, 0xa3, 0xf1, 0xb2, + 0x99, 0xb6, 0xd3, 0x65, 0xc2, 0xee, 0xce, 0x66, 0x66, 0x1b, 0xd9, 0x7f, 0x61, 0xe2, 0x5f, 0xf2, + 0xc0, 0x91, 0x23, 0x27, 0xa3, 0x25, 0xfe, 0x04, 0x6f, 0x1e, 0xcc, 0xce, 0xee, 0xd8, 0xa2, 0x28, + 0x07, 0x6f, 0x6f, 0xde, 0xfb, 0xbe, 0xf7, 0xde, 0xf7, 0xde, 0x1b, 0xb8, 0x45, 0x38, 0x67, 0x5c, + 0x44, 0xdd, 0x66, 0x66, 0xd8, 0x11, 0x67, 0x31, 0x43, 0xa8, 0xc7, 0x7a, 0xc7, 0x9c, 0xe1, 0xde, + 0x91, 0xad, 0x00, 0x4b, 0x8b, 0x1e, 0x63, 0x9e, 0x4f, 0x9a, 0x12, 0xd1, 0x1d, 0x0e, 0x9a, 0x38, + 0x4c, 0x32, 0xf8, 0xd2, 0x82, 0xc7, 0x3c, 0x26, 0xcd, 0x66, 0x6a, 0x65, 0x5e, 0xeb, 0xa3, 0x0e, + 0xb5, 0x76, 0xd8, 0x63, 0x7d, 0xd2, 0x6f, 0xa7, 0x49, 0xd0, 0x13, 0x28, 0xfa, 0x04, 0x0f, 0x0c, + 0xbd, 0xa1, 0xaf, 0x55, 0x37, 0xee, 0xda, 0x7f, 0x16, 0xb1, 0x27, 0xf1, 0xbb, 0x04, 0x0f, 0x76, + 0x34, 0x47, 0x72, 0xd0, 0x33, 0x28, 0xbd, 0xe7, 0x38, 0x8a, 0x08, 0x37, 0xa6, 0x24, 0xdd, 0xfa, + 0x07, 0xfd, 0x4d, 0x86, 0xdc, 0xd1, 0x1c, 0x45, 0x6a, 0x95, 0x60, 0x5a, 0xa2, 0xac, 0x4f, 0x3a, + 0xd4, 0x7f, 0xaf, 0x82, 0x0c, 0x28, 0x05, 0x44, 0x08, 0xec, 0x11, 0xd9, 0x5c, 0xc5, 0x51, 0x4f, + 0xb4, 0x0d, 0xa5, 0x3e, 0x89, 0x31, 0xf5, 0x45, 0x5e, 0xf7, 0xde, 0x75, 0x6d, 0xbf, 0xc8, 0xe0, + 0xad, 0xe2, 0xe9, 0xe7, 0x15, 0xcd, 0x51, 0x6c, 0xd4, 0x81, 0xf9, 0x60, 0xe8, 0xc7, 0x54, 0x72, + 0xdc, 0x1e, 0x1e, 0x0a, 0x22, 0x8c, 0x42, 0xa3, 0xb0, 0x56, 0xdd, 0x68, 0x5c, 0x97, 0xd2, 0xa9, + 0x8f, 0xa9, 0xcf, 0x25, 0xd3, 0xfa, 0xa1, 0xc3, 0xcd, 0x2b, 0xaa, 0xa2, 0x07, 0x80, 0x18, 0xa7, + 0x1e, 0x0d, 0xb1, 0xef, 0xc6, 0x49, 0x44, 0xdc, 0x10, 0x07, 0x4a, 0x54, 0x5d, 0x45, 0x0e, 0x93, + 0x88, 0xec, 0xe1, 0x80, 0xa0, 0x57, 0x70, 0x23, 0xeb, 0x47, 0x42, 0x03, 0xcc, 0x8f, 0x73, 0x95, + 0xab, 0x57, 0xb6, 0x94, 0x1a, 0x29, 0xb7, 0x83, 0xf9, 0x71, 0xae, 0x6f, 0x96, 0x4c, 0x3a, 0xd1, + 0x43, 0x40, 0x9c, 0x44, 0x8c, 0xc7, 0xb8, 0xeb, 0x13, 0x37, 0xc2, 0x89, 0xcf, 0x70, 0x5f, 0xca, + 0xac, 0x38, 0xf3, 0xe3, 0xc8, 0x7e, 0x16, 0x40, 0x8f, 0xa1, 0x36, 0x18, 0xfa, 0xbe, 0xab, 0x46, + 0x5c, 0x94, 0xc5, 0x17, 0xec, 0xec, 0xd4, 0x6c, 0x75, 0x6a, 0xf6, 0x66, 0x98, 0x38, 0xd5, 0x14, + 0x99, 0xcb, 0xb4, 0xbe, 0xeb, 0x30, 0x77, 0x79, 0xd9, 0xe8, 0x29, 0x4c, 0xcb, 0xa9, 0xe6, 0xe7, + 0x75, 0xed, 0x50, 0x73, 0x01, 0x19, 0x69, 0xf2, 0x02, 0xa6, 0xfe, 0x7a, 0x01, 0x85, 0xff, 0xba, + 0x80, 0x16, 0xd4, 0xf2, 0x9c, 0x72, 0xdc, 0x52, 0xec, 0xdc, 0xc6, 0xca, 0x55, 0xd9, 0x3a, 0x19, + 0x2e, 0x1d, 0xab, 0x53, 0x0d, 0xc6, 0x0f, 0x6b, 0x0f, 0x66, 0x2f, 0x6d, 0x01, 0xad, 0x40, 0x75, + 0x80, 0x03, 0xea, 0x27, 0x93, 0x8b, 0x86, 0xcc, 0x25, 0x57, 0x7c, 0x1b, 0x2a, 0xe4, 0x24, 0x26, + 0xa1, 0xa0, 0x2c, 0xcc, 0xa5, 0x8d, 0x1d, 0xd6, 0x3a, 0xcc, 0x1d, 0xc4, 0x9c, 0x86, 0x9e, 0x50, + 0x2b, 0x31, 0xc6, 0x72, 0x75, 0xb9, 0x36, 0xf5, 0xb4, 0xbe, 0xa5, 0xff, 0x99, 0xf3, 0x90, 0x29, + 0xe8, 0x32, 0x40, 0x7a, 0x51, 0x2e, 0x49, 0x9d, 0xb2, 0x74, 0xc1, 0xa9, 0xa4, 0x1e, 0x89, 0x42, + 0x08, 0x8a, 0x98, 0xf7, 0x8e, 0xf2, 0xa2, 0xd2, 0x46, 0x77, 0x60, 0x96, 0x0a, 0x37, 0x22, 0x3c, + 0xa0, 0x42, 0x76, 0x94, 0x8e, 0xb4, 0xec, 0xd4, 0xa8, 0xd8, 0xff, 0xe5, 0x43, 0x8b, 0x50, 0xa6, + 0xc2, 0x25, 0x27, 0x54, 0xc4, 0x72, 0x48, 0x65, 0xa7, 0x44, 0x45, 0x3b, 0x7d, 0xa2, 0x06, 0xd4, + 0xa8, 0x70, 0x43, 0x16, 0xe7, 0xe1, 0x69, 0x19, 0x06, 0x2a, 0xf6, 0x58, 0x9c, 0x21, 0x96, 0x01, + 0xa8, 0x70, 0x63, 0x1a, 0x10, 0x36, 0x8c, 0x8d, 0x19, 0x19, 0xaf, 0x50, 0x71, 0x98, 0x39, 0xd0, + 0xaa, 0x4c, 0x10, 0x93, 0x20, 0x62, 0x1c, 0xf3, 0xc4, 0x28, 0x49, 0x40, 0x95, 0x8a, 0x43, 0xe5, + 0x5a, 0xbf, 0x0f, 0xd5, 0x89, 0xf9, 0x23, 0x80, 0x99, 0x7d, 0xa7, 0xbd, 0xf5, 0xf2, 0x6d, 0x5d, + 0x43, 0x75, 0xa8, 0x6d, 0xbd, 0xde, 0xdd, 0x75, 0x3b, 0xed, 0x83, 0x83, 0xcd, 0xed, 0x76, 0x5d, + 0x6f, 0xad, 0x9f, 0x7e, 0x35, 0xb5, 0xd3, 0x91, 0xa9, 0x9f, 0x8d, 0x4c, 0xfd, 0x7c, 0x64, 0xea, + 0x5f, 0x46, 0xa6, 0xfe, 0xe1, 0xc2, 0xd4, 0xce, 0x2e, 0x4c, 0xed, 0xfc, 0xc2, 0xd4, 0xde, 0x95, + 0xd5, 0x56, 0xbb, 0x33, 0xf2, 0x9e, 0x1f, 0xfd, 0x0c, 0x00, 0x00, 0xff, 0xff, 0xd7, 0x2c, 0x21, + 0xe3, 0x75, 0x05, 0x00, 0x00, +} + func (m *EncodedError) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -464,52 +496,73 @@ func (m *EncodedError) Marshal() (dAtA []byte, err error) { } func (m *EncodedError) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EncodedError) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l if m.Error != nil { - nn1, err := m.Error.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err + { + size := m.Error.Size() + i -= size + if _, err := m.Error.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } } - i += nn1 } - return i, nil + return len(dAtA) - i, nil } func (m *EncodedError_Leaf) MarshalTo(dAtA []byte) (int, error) { - i := 0 + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EncodedError_Leaf) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) if m.Leaf != nil { - dAtA[i] = 0xa - i++ - i = encodeVarintErrors(dAtA, i, uint64(m.Leaf.Size())) - n2, err := m.Leaf.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err + { + size, err := m.Leaf.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintErrors(dAtA, i, uint64(size)) } - i += n2 + i-- + dAtA[i] = 0xa } - return i, nil + return len(dAtA) - i, nil } func (m *EncodedError_Wrapper) MarshalTo(dAtA []byte) (int, error) { - i := 0 + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EncodedError_Wrapper) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) if m.Wrapper != nil { - dAtA[i] = 0x12 - i++ - i = encodeVarintErrors(dAtA, i, uint64(m.Wrapper.Size())) - n3, err := m.Wrapper.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err + { + size, err := m.Wrapper.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintErrors(dAtA, i, uint64(size)) } - i += n3 + i-- + dAtA[i] = 0x12 } - return i, nil + return len(dAtA) - i, nil } func (m *EncodedErrorLeaf) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -517,31 +570,53 @@ func (m *EncodedErrorLeaf) Marshal() (dAtA []byte, err error) { } func (m *EncodedErrorLeaf) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EncodedErrorLeaf) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l - if len(m.Message) > 0 { - dAtA[i] = 0xa - i++ - i = encodeVarintErrors(dAtA, i, uint64(len(m.Message))) - i += copy(dAtA[i:], m.Message) + if len(m.MultierrorCauses) > 0 { + for iNdEx := len(m.MultierrorCauses) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.MultierrorCauses[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintErrors(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + { + size, err := m.Details.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintErrors(dAtA, i, uint64(size)) } + i-- dAtA[i] = 0x12 - i++ - i = encodeVarintErrors(dAtA, i, uint64(m.Details.Size())) - n4, err := m.Details.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err + if len(m.Message) > 0 { + i -= len(m.Message) + copy(dAtA[i:], m.Message) + i = encodeVarintErrors(dAtA, i, uint64(len(m.Message))) + i-- + dAtA[i] = 0xa } - i += n4 - return i, nil + return len(dAtA) - i, nil } func (m *EncodedErrorDetails) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -549,56 +624,60 @@ func (m *EncodedErrorDetails) Marshal() (dAtA []byte, err error) { } func (m *EncodedErrorDetails) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EncodedErrorDetails) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l - if len(m.OriginalTypeName) > 0 { - dAtA[i] = 0xa - i++ - i = encodeVarintErrors(dAtA, i, uint64(len(m.OriginalTypeName))) - i += copy(dAtA[i:], m.OriginalTypeName) - } - dAtA[i] = 0x12 - i++ - i = encodeVarintErrors(dAtA, i, uint64(m.ErrorTypeMark.Size())) - n5, err := m.ErrorTypeMark.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err + if m.FullDetails != nil { + { + size, err := m.FullDetails.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintErrors(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 } - i += n5 if len(m.ReportablePayload) > 0 { - for _, s := range m.ReportablePayload { + for iNdEx := len(m.ReportablePayload) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.ReportablePayload[iNdEx]) + copy(dAtA[i:], m.ReportablePayload[iNdEx]) + i = encodeVarintErrors(dAtA, i, uint64(len(m.ReportablePayload[iNdEx]))) + i-- dAtA[i] = 0x1a - i++ - l = len(s) - for l >= 1<<7 { - dAtA[i] = uint8(uint64(l)&0x7f | 0x80) - l >>= 7 - i++ - } - dAtA[i] = uint8(l) - i++ - i += copy(dAtA[i:], s) } } - if m.FullDetails != nil { - dAtA[i] = 0x22 - i++ - i = encodeVarintErrors(dAtA, i, uint64(m.FullDetails.Size())) - n6, err := m.FullDetails.MarshalTo(dAtA[i:]) + { + size, err := m.ErrorTypeMark.MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } - i += n6 + i -= size + i = encodeVarintErrors(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.OriginalTypeName) > 0 { + i -= len(m.OriginalTypeName) + copy(dAtA[i:], m.OriginalTypeName) + i = encodeVarintErrors(dAtA, i, uint64(len(m.OriginalTypeName))) + i-- + dAtA[i] = 0xa } - return i, nil + return len(dAtA) - i, nil } func (m *EncodedWrapper) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -606,39 +685,54 @@ func (m *EncodedWrapper) Marshal() (dAtA []byte, err error) { } func (m *EncodedWrapper) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EncodedWrapper) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l - dAtA[i] = 0xa - i++ - i = encodeVarintErrors(dAtA, i, uint64(m.Cause.Size())) - n7, err := m.Cause.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err + if m.MessageType != 0 { + i = encodeVarintErrors(dAtA, i, uint64(m.MessageType)) + i-- + dAtA[i] = 0x20 } - i += n7 - if len(m.MessagePrefix) > 0 { - dAtA[i] = 0x12 - i++ - i = encodeVarintErrors(dAtA, i, uint64(len(m.MessagePrefix))) - i += copy(dAtA[i:], m.MessagePrefix) + { + size, err := m.Details.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintErrors(dAtA, i, uint64(size)) } + i-- dAtA[i] = 0x1a - i++ - i = encodeVarintErrors(dAtA, i, uint64(m.Details.Size())) - n8, err := m.Details.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err + if len(m.Message) > 0 { + i -= len(m.Message) + copy(dAtA[i:], m.Message) + i = encodeVarintErrors(dAtA, i, uint64(len(m.Message))) + i-- + dAtA[i] = 0x12 + } + { + size, err := m.Cause.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintErrors(dAtA, i, uint64(size)) } - i += n8 - return i, nil + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil } func (m *ErrorTypeMark) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -646,29 +740,36 @@ func (m *ErrorTypeMark) Marshal() (dAtA []byte, err error) { } func (m *ErrorTypeMark) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ErrorTypeMark) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l - if len(m.FamilyName) > 0 { - dAtA[i] = 0xa - i++ - i = encodeVarintErrors(dAtA, i, uint64(len(m.FamilyName))) - i += copy(dAtA[i:], m.FamilyName) - } if len(m.Extension) > 0 { - dAtA[i] = 0x12 - i++ + i -= len(m.Extension) + copy(dAtA[i:], m.Extension) i = encodeVarintErrors(dAtA, i, uint64(len(m.Extension))) - i += copy(dAtA[i:], m.Extension) + i-- + dAtA[i] = 0x12 } - return i, nil + if len(m.FamilyName) > 0 { + i -= len(m.FamilyName) + copy(dAtA[i:], m.FamilyName) + i = encodeVarintErrors(dAtA, i, uint64(len(m.FamilyName))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil } func (m *StringsPayload) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -676,32 +777,31 @@ func (m *StringsPayload) Marshal() (dAtA []byte, err error) { } func (m *StringsPayload) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *StringsPayload) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l if len(m.Details) > 0 { - for _, s := range m.Details { + for iNdEx := len(m.Details) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Details[iNdEx]) + copy(dAtA[i:], m.Details[iNdEx]) + i = encodeVarintErrors(dAtA, i, uint64(len(m.Details[iNdEx]))) + i-- dAtA[i] = 0xa - i++ - l = len(s) - for l >= 1<<7 { - dAtA[i] = uint8(uint64(l)&0x7f | 0x80) - l >>= 7 - i++ - } - dAtA[i] = uint8(l) - i++ - i += copy(dAtA[i:], s) } } - return i, nil + return len(dAtA) - i, nil } func (m *ErrnoPayload) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -709,82 +809,90 @@ func (m *ErrnoPayload) Marshal() (dAtA []byte, err error) { } func (m *ErrnoPayload) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ErrnoPayload) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l - if m.OrigErrno != 0 { - dAtA[i] = 0x8 - i++ - i = encodeVarintErrors(dAtA, i, uint64(m.OrigErrno)) - } - if len(m.Arch) > 0 { - dAtA[i] = 0x12 - i++ - i = encodeVarintErrors(dAtA, i, uint64(len(m.Arch))) - i += copy(dAtA[i:], m.Arch) - } - if m.IsPermission { - dAtA[i] = 0x18 - i++ - if m.IsPermission { + if m.IsTemporary { + i-- + if m.IsTemporary { dAtA[i] = 1 } else { dAtA[i] = 0 } - i++ + i-- + dAtA[i] = 0x38 } - if m.IsExist { - dAtA[i] = 0x20 - i++ - if m.IsExist { + if m.IsTimeout { + i-- + if m.IsTimeout { dAtA[i] = 1 } else { dAtA[i] = 0 } - i++ + i-- + dAtA[i] = 0x30 } if m.IsNotExist { - dAtA[i] = 0x28 - i++ + i-- if m.IsNotExist { dAtA[i] = 1 } else { dAtA[i] = 0 } - i++ + i-- + dAtA[i] = 0x28 } - if m.IsTimeout { - dAtA[i] = 0x30 - i++ - if m.IsTimeout { + if m.IsExist { + i-- + if m.IsExist { dAtA[i] = 1 } else { dAtA[i] = 0 } - i++ + i-- + dAtA[i] = 0x20 } - if m.IsTemporary { - dAtA[i] = 0x38 - i++ - if m.IsTemporary { + if m.IsPermission { + i-- + if m.IsPermission { dAtA[i] = 1 } else { dAtA[i] = 0 } - i++ + i-- + dAtA[i] = 0x18 + } + if len(m.Arch) > 0 { + i -= len(m.Arch) + copy(dAtA[i:], m.Arch) + i = encodeVarintErrors(dAtA, i, uint64(len(m.Arch))) + i-- + dAtA[i] = 0x12 } - return i, nil + if m.OrigErrno != 0 { + i = encodeVarintErrors(dAtA, i, uint64(m.OrigErrno)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil } func encodeVarintErrors(dAtA []byte, offset int, v uint64) int { + offset -= sovErrors(v) + base := offset for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) v >>= 7 offset++ } dAtA[offset] = uint8(v) - return offset + 1 + return base } func (m *EncodedError) Size() (n int) { if m == nil { @@ -834,6 +942,12 @@ func (m *EncodedErrorLeaf) Size() (n int) { } l = m.Details.Size() n += 1 + l + sovErrors(uint64(l)) + if len(m.MultierrorCauses) > 0 { + for _, e := range m.MultierrorCauses { + l = e.Size() + n += 1 + l + sovErrors(uint64(l)) + } + } return n } @@ -870,12 +984,15 @@ func (m *EncodedWrapper) Size() (n int) { _ = l l = m.Cause.Size() n += 1 + l + sovErrors(uint64(l)) - l = len(m.MessagePrefix) + l = len(m.Message) if l > 0 { n += 1 + l + sovErrors(uint64(l)) } l = m.Details.Size() n += 1 + l + sovErrors(uint64(l)) + if m.MessageType != 0 { + n += 1 + sovErrors(uint64(m.MessageType)) + } return n } @@ -943,14 +1060,7 @@ func (m *ErrnoPayload) Size() (n int) { } func sovErrors(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } - } - return n + return (math_bits.Len64(x|1) + 6) / 7 } func sozErrors(x uint64) (n int) { return sovErrors(uint64((x << 1) ^ uint64((int64(x) >> 63)))) @@ -970,7 +1080,7 @@ func (m *EncodedError) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -998,7 +1108,7 @@ func (m *EncodedError) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } @@ -1007,6 +1117,9 @@ func (m *EncodedError) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrors } postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthErrors + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -1030,7 +1143,7 @@ func (m *EncodedError) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } @@ -1039,6 +1152,9 @@ func (m *EncodedError) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrors } postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthErrors + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -1054,7 +1170,7 @@ func (m *EncodedError) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthErrors } if (iNdEx + skippy) > l { @@ -1084,7 +1200,7 @@ func (m *EncodedErrorLeaf) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -1112,7 +1228,7 @@ func (m *EncodedErrorLeaf) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -1122,6 +1238,9 @@ func (m *EncodedErrorLeaf) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrors } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrors + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -1141,7 +1260,7 @@ func (m *EncodedErrorLeaf) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } @@ -1150,6 +1269,9 @@ func (m *EncodedErrorLeaf) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrors } postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthErrors + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -1157,13 +1279,47 @@ func (m *EncodedErrorLeaf) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MultierrorCauses", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowErrors + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthErrors + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthErrors + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MultierrorCauses = append(m.MultierrorCauses, &EncodedError{}) + if err := m.MultierrorCauses[len(m.MultierrorCauses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipErrors(dAtA[iNdEx:]) if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthErrors } if (iNdEx + skippy) > l { @@ -1193,7 +1349,7 @@ func (m *EncodedErrorDetails) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -1221,7 +1377,7 @@ func (m *EncodedErrorDetails) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -1231,6 +1387,9 @@ func (m *EncodedErrorDetails) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrors } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrors + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -1250,7 +1409,7 @@ func (m *EncodedErrorDetails) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } @@ -1259,6 +1418,9 @@ func (m *EncodedErrorDetails) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrors } postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthErrors + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -1280,7 +1442,7 @@ func (m *EncodedErrorDetails) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -1290,6 +1452,9 @@ func (m *EncodedErrorDetails) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrors } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrors + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -1309,7 +1474,7 @@ func (m *EncodedErrorDetails) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } @@ -1318,6 +1483,9 @@ func (m *EncodedErrorDetails) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrors } postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthErrors + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -1334,7 +1502,7 @@ func (m *EncodedErrorDetails) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthErrors } if (iNdEx + skippy) > l { @@ -1364,7 +1532,7 @@ func (m *EncodedWrapper) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -1392,7 +1560,7 @@ func (m *EncodedWrapper) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } @@ -1401,6 +1569,9 @@ func (m *EncodedWrapper) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrors } postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthErrors + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -1410,7 +1581,7 @@ func (m *EncodedWrapper) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field MessagePrefix", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Message", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1422,7 +1593,7 @@ func (m *EncodedWrapper) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -1432,10 +1603,13 @@ func (m *EncodedWrapper) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrors } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrors + } if postIndex > l { return io.ErrUnexpectedEOF } - m.MessagePrefix = string(dAtA[iNdEx:postIndex]) + m.Message = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: if wireType != 2 { @@ -1451,7 +1625,7 @@ func (m *EncodedWrapper) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } @@ -1460,6 +1634,9 @@ func (m *EncodedWrapper) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrors } postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthErrors + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -1467,13 +1644,32 @@ func (m *EncodedWrapper) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MessageType", wireType) + } + m.MessageType = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowErrors + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MessageType |= MessageType(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipErrors(dAtA[iNdEx:]) if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthErrors } if (iNdEx + skippy) > l { @@ -1503,7 +1699,7 @@ func (m *ErrorTypeMark) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -1531,7 +1727,7 @@ func (m *ErrorTypeMark) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -1541,6 +1737,9 @@ func (m *ErrorTypeMark) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrors } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrors + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -1560,7 +1759,7 @@ func (m *ErrorTypeMark) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -1570,6 +1769,9 @@ func (m *ErrorTypeMark) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrors } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrors + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -1581,7 +1783,7 @@ func (m *ErrorTypeMark) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthErrors } if (iNdEx + skippy) > l { @@ -1611,7 +1813,7 @@ func (m *StringsPayload) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -1639,7 +1841,7 @@ func (m *StringsPayload) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -1649,6 +1851,9 @@ func (m *StringsPayload) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrors } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrors + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -1660,7 +1865,7 @@ func (m *StringsPayload) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthErrors } if (iNdEx + skippy) > l { @@ -1690,7 +1895,7 @@ func (m *ErrnoPayload) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -1718,7 +1923,7 @@ func (m *ErrnoPayload) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.OrigErrno |= (int64(b) & 0x7F) << shift + m.OrigErrno |= int64(b&0x7F) << shift if b < 0x80 { break } @@ -1737,7 +1942,7 @@ func (m *ErrnoPayload) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -1747,6 +1952,9 @@ func (m *ErrnoPayload) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrors } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrors + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -1766,7 +1974,7 @@ func (m *ErrnoPayload) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= (int(b) & 0x7F) << shift + v |= int(b&0x7F) << shift if b < 0x80 { break } @@ -1786,7 +1994,7 @@ func (m *ErrnoPayload) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= (int(b) & 0x7F) << shift + v |= int(b&0x7F) << shift if b < 0x80 { break } @@ -1806,7 +2014,7 @@ func (m *ErrnoPayload) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= (int(b) & 0x7F) << shift + v |= int(b&0x7F) << shift if b < 0x80 { break } @@ -1826,7 +2034,7 @@ func (m *ErrnoPayload) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= (int(b) & 0x7F) << shift + v |= int(b&0x7F) << shift if b < 0x80 { break } @@ -1846,7 +2054,7 @@ func (m *ErrnoPayload) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= (int(b) & 0x7F) << shift + v |= int(b&0x7F) << shift if b < 0x80 { break } @@ -1858,7 +2066,7 @@ func (m *ErrnoPayload) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthErrors } if (iNdEx + skippy) > l { @@ -1876,6 +2084,7 @@ func (m *ErrnoPayload) Unmarshal(dAtA []byte) error { func skipErrors(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 + depth := 0 for iNdEx < l { var wire uint64 for shift := uint(0); ; shift += 7 { @@ -1907,10 +2116,8 @@ func skipErrors(dAtA []byte) (n int, err error) { break } } - return iNdEx, nil case 1: iNdEx += 8 - return iNdEx, nil case 2: var length int for shift := uint(0); ; shift += 7 { @@ -1927,101 +2134,34 @@ func skipErrors(dAtA []byte) (n int, err error) { break } } - iNdEx += length if length < 0 { return 0, ErrInvalidLengthErrors } - return iNdEx, nil + iNdEx += length case 3: - for { - var innerWire uint64 - var start int = iNdEx - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowErrors - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - innerWire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - innerWireType := int(innerWire & 0x7) - if innerWireType == 4 { - break - } - next, err := skipErrors(dAtA[start:]) - if err != nil { - return 0, err - } - iNdEx = start + next - } - return iNdEx, nil + depth++ case 4: - return iNdEx, nil + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupErrors + } + depth-- case 5: iNdEx += 4 - return iNdEx, nil default: return 0, fmt.Errorf("proto: illegal wireType %d", wireType) } + if iNdEx < 0 { + return 0, ErrInvalidLengthErrors + } + if depth == 0 { + return iNdEx, nil + } } - panic("unreachable") + return 0, io.ErrUnexpectedEOF } var ( - ErrInvalidLengthErrors = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowErrors = fmt.Errorf("proto: integer overflow") + ErrInvalidLengthErrors = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowErrors = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupErrors = fmt.Errorf("proto: unexpected end of group") ) - -func init() { - proto.RegisterFile("github.com/cockroachdb/errors/errorspb/errors.proto", fileDescriptor_errors_aa0d2b9df74f046a) -} - -var fileDescriptor_errors_aa0d2b9df74f046a = []byte{ - // 638 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x53, 0x41, 0x6f, 0xd3, 0x4c, - 0x10, 0xb5, 0xbf, 0xa4, 0x4d, 0x32, 0x49, 0xfa, 0x95, 0xa5, 0x07, 0xb7, 0xa2, 0x6e, 0x1a, 0x40, - 0x54, 0x15, 0x38, 0x12, 0x3d, 0x20, 0x21, 0x84, 0x44, 0x45, 0x45, 0x0f, 0x50, 0x2a, 0x53, 0x09, - 0x89, 0x8b, 0xb5, 0x71, 0x26, 0xee, 0xaa, 0xb6, 0xd7, 0xda, 0xdd, 0x88, 0xfa, 0x5f, 0x20, 0xf1, - 0x7f, 0x38, 0xf7, 0xd8, 0x63, 0x4f, 0x08, 0x52, 0xf1, 0x2f, 0x38, 0x20, 0xaf, 0xbd, 0x6d, 0x0a, - 0x15, 0x3d, 0x70, 0xca, 0xee, 0x9b, 0x37, 0x7e, 0x6f, 0xe7, 0x4d, 0x60, 0x2b, 0x62, 0xea, 0x70, - 0x32, 0xf4, 0x42, 0x9e, 0x0c, 0x42, 0x1e, 0x1e, 0x09, 0x4e, 0xc3, 0xc3, 0xd1, 0x70, 0x80, 0x42, - 0x70, 0x21, 0xab, 0x9f, 0xcc, 0xdc, 0xbd, 0x4c, 0x70, 0xc5, 0x09, 0xb9, 0x60, 0x7a, 0x86, 0xb0, - 0xb2, 0x1c, 0x71, 0x1e, 0xc5, 0x38, 0xd0, 0x8c, 0xe1, 0x64, 0x3c, 0xa0, 0x69, 0x5e, 0xd2, 0x57, - 0x96, 0x22, 0x1e, 0x71, 0x7d, 0x1c, 0x14, 0xa7, 0x12, 0xed, 0x7f, 0xb6, 0xa1, 0xb3, 0x93, 0x86, - 0x7c, 0x84, 0xa3, 0x9d, 0xe2, 0x23, 0xe4, 0x29, 0xd4, 0x63, 0xa4, 0x63, 0xc7, 0xee, 0xd9, 0x1b, - 0xed, 0xc7, 0xf7, 0xbc, 0x3f, 0x45, 0xbc, 0x59, 0xfe, 0x6b, 0xa4, 0xe3, 0x5d, 0xcb, 0xd7, 0x3d, - 0xe4, 0x39, 0x34, 0x3e, 0x0a, 0x9a, 0x65, 0x28, 0x9c, 0xff, 0x74, 0x7b, 0xff, 0x2f, 0xed, 0xef, - 0x4b, 0xe6, 0xae, 0xe5, 0x9b, 0xa6, 0xed, 0x06, 0xcc, 0x69, 0x56, 0x7f, 0x02, 0x8b, 0xbf, 0x8b, - 0x10, 0x07, 0x1a, 0x09, 0x4a, 0x49, 0x23, 0xd4, 0xde, 0x5a, 0xbe, 0xb9, 0x92, 0x57, 0xd0, 0x18, - 0xa1, 0xa2, 0x2c, 0x96, 0x95, 0xec, 0x83, 0x9b, 0x5c, 0xbf, 0x2c, 0xe9, 0xdb, 0xf5, 0x93, 0xaf, - 0x6b, 0x96, 0x6f, 0xba, 0xfb, 0x3f, 0x6d, 0xb8, 0x7d, 0x0d, 0x8d, 0x3c, 0x04, 0xc2, 0x05, 0x8b, - 0x58, 0x4a, 0xe3, 0x40, 0xe5, 0x19, 0x06, 0x29, 0x4d, 0x8c, 0x8b, 0x45, 0x53, 0x39, 0xc8, 0x33, - 0xdc, 0xa3, 0x09, 0x92, 0xb7, 0xf0, 0xbf, 0x16, 0x2d, 0xa9, 0x09, 0x15, 0x47, 0x95, 0xad, 0xf5, - 0x6b, 0x6d, 0x15, 0x87, 0xa2, 0xf7, 0x0d, 0x15, 0x47, 0x95, 0xa1, 0x2e, 0xce, 0x82, 0xe4, 0x11, - 0x10, 0x81, 0x19, 0x17, 0x8a, 0x0e, 0x63, 0x0c, 0x32, 0x9a, 0xc7, 0x9c, 0x8e, 0x9c, 0x5a, 0xaf, - 0xb6, 0xd1, 0xf2, 0x6f, 0x5d, 0x56, 0xf6, 0xcb, 0x02, 0x79, 0x02, 0x9d, 0xf1, 0x24, 0x8e, 0x03, - 0x33, 0x93, 0xba, 0x16, 0x5f, 0xf2, 0xca, 0xd5, 0xf0, 0xcc, 0x6a, 0x78, 0x2f, 0xd2, 0xdc, 0x6f, - 0x17, 0xcc, 0xea, 0x99, 0xfd, 0x2f, 0x36, 0x2c, 0x5c, 0x0d, 0x87, 0x3c, 0x83, 0xb9, 0x90, 0x4e, - 0x24, 0x56, 0xeb, 0xd0, 0xbb, 0x69, 0xb0, 0xd5, 0x03, 0xca, 0x26, 0x72, 0x1f, 0x16, 0xaa, 0x8c, - 0x82, 0x4c, 0xe0, 0x98, 0x1d, 0xeb, 0x41, 0xb4, 0xfc, 0x6e, 0x85, 0xee, 0x6b, 0x70, 0x36, 0xbf, - 0xda, 0x3f, 0xe5, 0xb7, 0x07, 0xdd, 0x2b, 0xe3, 0x24, 0x6b, 0xd0, 0x1e, 0xd3, 0x84, 0xc5, 0xf9, - 0x6c, 0x62, 0x50, 0x42, 0x3a, 0xab, 0x3b, 0xd0, 0xc2, 0x63, 0x85, 0xa9, 0x64, 0x3c, 0xad, 0xcc, - 0x5d, 0x02, 0xfd, 0x4d, 0x58, 0x78, 0xa7, 0x04, 0x4b, 0x23, 0x69, 0x66, 0xeb, 0x5c, 0x5a, 0xb5, - 0xf5, 0xfc, 0x2f, 0xb4, 0x7f, 0x14, 0x7f, 0x24, 0x21, 0x52, 0x6e, 0xa8, 0xab, 0x00, 0xc5, 0x6a, - 0x04, 0x58, 0x80, 0x5a, 0xba, 0xe6, 0xb7, 0x0a, 0x44, 0xb3, 0x08, 0x81, 0x3a, 0x15, 0xe1, 0x61, - 0x25, 0xaa, 0xcf, 0xe4, 0x2e, 0x74, 0x99, 0x0c, 0x32, 0x14, 0x09, 0x93, 0xda, 0x51, 0x31, 0x8e, - 0xa6, 0xdf, 0x61, 0x72, 0xff, 0x02, 0x23, 0xcb, 0xd0, 0x64, 0x32, 0xc0, 0x63, 0x26, 0x95, 0x8e, - 0xb6, 0xe9, 0x37, 0x98, 0xdc, 0x29, 0xae, 0xa4, 0x07, 0x1d, 0x26, 0x83, 0x94, 0xab, 0xaa, 0x3c, - 0xa7, 0xcb, 0xc0, 0xe4, 0x1e, 0x57, 0x25, 0x63, 0x15, 0x80, 0xc9, 0x40, 0xb1, 0x04, 0xf9, 0x44, - 0x39, 0xf3, 0xba, 0xde, 0x62, 0xf2, 0xa0, 0x04, 0xc8, 0xba, 0xfe, 0x80, 0xc2, 0x24, 0xe3, 0x82, - 0x8a, 0xdc, 0x69, 0x68, 0x42, 0x9b, 0xc9, 0x03, 0x03, 0x6d, 0x6f, 0x9e, 0x7c, 0x77, 0xad, 0x93, - 0xa9, 0x6b, 0x9f, 0x4e, 0x5d, 0xfb, 0x6c, 0xea, 0xda, 0xdf, 0xa6, 0xae, 0xfd, 0xe9, 0xdc, 0xb5, - 0x4e, 0xcf, 0x5d, 0xeb, 0xec, 0xdc, 0xb5, 0x3e, 0x34, 0x4d, 0x64, 0xc3, 0x79, 0xbd, 0x6b, 0x5b, - 0xbf, 0x02, 0x00, 0x00, 0xff, 0xff, 0xb9, 0xfc, 0x57, 0x8a, 0xdf, 0x04, 0x00, 0x00, -} diff --git a/vendor/github.com/cockroachdb/errors/errorspb/errors.proto b/vendor/github.com/cockroachdb/errors/errorspb/errors.proto index 3fe195db5..aba161df6 100644 --- a/vendor/github.com/cockroachdb/errors/errorspb/errors.proto +++ b/vendor/github.com/cockroachdb/errors/errorspb/errors.proto @@ -17,7 +17,7 @@ message EncodedError { } // EncodedErrorLeaf is the wire-encodable representation -// of an error leaf. +// of an error leaf or a multi-cause wrapper from go 1.20+ message EncodedErrorLeaf { // The main error message (mandatory), that can be printed to human // users and may contain PII. This contains the value of the leaf @@ -26,6 +26,12 @@ message EncodedErrorLeaf { // The error details. EncodedErrorDetails details = 2 [(gogoproto.nullable) = false]; + + // multierror_causes is a list of errors that contain the causal tree + // of this leaf. If this field is not empty, then this leaf encodes + // an error from go 1.20 or later that encodes multiple causes in its + // chain. + repeated EncodedError multierror_causes = 3; } message EncodedErrorDetails { @@ -60,24 +66,42 @@ message EncodedErrorDetails { google.protobuf.Any full_details = 4; } +// MessageType encodes information regarding the interpretation of an +// error's message string. +enum MessageType { + // Keeping zero value as default for backwards compatibility. + // PREFIX is a message that should be prepended to its cause. + PREFIX = 0; + // FULL_MESSAGE is a complete error message that can be displayed + // without its cause. + FULL_MESSAGE = 1; +} + // EncodedWrapper is the wire-encodable representation // of an error wrapper. message EncodedWrapper { // The cause error. Mandatory. EncodedError cause = 1 [(gogoproto.nullable) = false]; - // The wrapper message prefix (which may be empty). This - // isbprinted before the cause's own message when - // constructing a full message. This may contain PII. + // The wrapper message. This could either be a full error message + // that can be printed independently, or a (potentially empty) prefix + // which is printed before the cause's own message to construct the + // full message. This may contain PII. // // This is extracted automatically: // // - for wrappers that have a registered encoder, // - otherwise, when the wrapper's Error() has its cause's Error() as suffix. - string message_prefix = 2; + string message = 2; // The error details. EncodedErrorDetails details = 3 [(gogoproto.nullable) = false]; + + // message_type encodes the interpretation of `message`. Prior + // versions will not set this field and it will be left as `PREFIX`. + // This retains backwards compatibility since the new behavior is + // only enabled when this enum is set to `FULL_MESSAGE`. + MessageType message_type = 4; } // ErrorTypeMark identifies an error type for the purpose of determining diff --git a/vendor/github.com/cockroachdb/errors/errorspb/hintdetail.pb.go b/vendor/github.com/cockroachdb/errors/errorspb/hintdetail.pb.go index ade233466..7bb1ac68b 100644 --- a/vendor/github.com/cockroachdb/errors/errorspb/hintdetail.pb.go +++ b/vendor/github.com/cockroachdb/errors/errorspb/hintdetail.pb.go @@ -1,13 +1,15 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: github.com/cockroachdb/errors/errorspb/hintdetail.proto +// source: errorspb/hintdetail.proto package errorspb -import proto "github.com/gogo/protobuf/proto" -import fmt "fmt" -import math "math" - -import io "io" +import ( + fmt "fmt" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal @@ -18,7 +20,7 @@ var _ = math.Inf // is compatible with the proto package it is being compiled against. // A compilation error at this line likely means your copy of the // proto package needs to be updated. -const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type StringPayload struct { Msg string `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg,omitempty"` @@ -28,21 +30,21 @@ func (m *StringPayload) Reset() { *m = StringPayload{} } func (m *StringPayload) String() string { return proto.CompactTextString(m) } func (*StringPayload) ProtoMessage() {} func (*StringPayload) Descriptor() ([]byte, []int) { - return fileDescriptor_hintdetail_429641491537a364, []int{0} + return fileDescriptor_d99b88ec9cc4bc22, []int{0} } func (m *StringPayload) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } func (m *StringPayload) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { b = b[:cap(b)] - n, err := m.MarshalTo(b) + n, err := m.MarshalToSizedBuffer(b) if err != nil { return nil, err } return b[:n], nil } -func (dst *StringPayload) XXX_Merge(src proto.Message) { - xxx_messageInfo_StringPayload.Merge(dst, src) +func (m *StringPayload) XXX_Merge(src proto.Message) { + xxx_messageInfo_StringPayload.Merge(m, src) } func (m *StringPayload) XXX_Size() int { return m.Size() @@ -56,10 +58,26 @@ var xxx_messageInfo_StringPayload proto.InternalMessageInfo func init() { proto.RegisterType((*StringPayload)(nil), "cockroach.errorspb.StringPayload") } + +func init() { proto.RegisterFile("errorspb/hintdetail.proto", fileDescriptor_d99b88ec9cc4bc22) } + +var fileDescriptor_d99b88ec9cc4bc22 = []byte{ + // 143 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0x2d, 0x2a, 0xca, + 0x2f, 0x2a, 0x2e, 0x48, 0xd2, 0xcf, 0xc8, 0xcc, 0x2b, 0x49, 0x49, 0x2d, 0x49, 0xcc, 0xcc, 0xd1, + 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x4a, 0xce, 0x4f, 0xce, 0x2e, 0xca, 0x4f, 0x4c, 0xce, + 0xd0, 0x83, 0x29, 0x52, 0x52, 0xe4, 0xe2, 0x0d, 0x2e, 0x29, 0xca, 0xcc, 0x4b, 0x0f, 0x48, 0xac, + 0xcc, 0xc9, 0x4f, 0x4c, 0x11, 0x12, 0xe0, 0x62, 0xce, 0x2d, 0x4e, 0x97, 0x60, 0x54, 0x60, 0xd4, + 0xe0, 0x0c, 0x02, 0x31, 0x9d, 0xb4, 0x4e, 0x3c, 0x94, 0x63, 0x38, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, + 0x23, 0x39, 0xc6, 0x1b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, + 0xc2, 0x63, 0x39, 0x86, 0x1b, 0x8f, 0xe5, 0x18, 0xa2, 0x38, 0x60, 0xc6, 0x25, 0xb1, 0x81, 0x6d, + 0x32, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xe2, 0xbd, 0x3a, 0x3e, 0x86, 0x00, 0x00, 0x00, +} + func (m *StringPayload) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -67,27 +85,35 @@ func (m *StringPayload) Marshal() (dAtA []byte, err error) { } func (m *StringPayload) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *StringPayload) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l if len(m.Msg) > 0 { - dAtA[i] = 0xa - i++ + i -= len(m.Msg) + copy(dAtA[i:], m.Msg) i = encodeVarintHintdetail(dAtA, i, uint64(len(m.Msg))) - i += copy(dAtA[i:], m.Msg) + i-- + dAtA[i] = 0xa } - return i, nil + return len(dAtA) - i, nil } func encodeVarintHintdetail(dAtA []byte, offset int, v uint64) int { + offset -= sovHintdetail(v) + base := offset for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) v >>= 7 offset++ } dAtA[offset] = uint8(v) - return offset + 1 + return base } func (m *StringPayload) Size() (n int) { if m == nil { @@ -103,14 +129,7 @@ func (m *StringPayload) Size() (n int) { } func sovHintdetail(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } - } - return n + return (math_bits.Len64(x|1) + 6) / 7 } func sozHintdetail(x uint64) (n int) { return sovHintdetail(uint64((x << 1) ^ uint64((int64(x) >> 63)))) @@ -130,7 +149,7 @@ func (m *StringPayload) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -158,7 +177,7 @@ func (m *StringPayload) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -168,6 +187,9 @@ func (m *StringPayload) Unmarshal(dAtA []byte) error { return ErrInvalidLengthHintdetail } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthHintdetail + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -179,7 +201,7 @@ func (m *StringPayload) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthHintdetail } if (iNdEx + skippy) > l { @@ -197,6 +219,7 @@ func (m *StringPayload) Unmarshal(dAtA []byte) error { func skipHintdetail(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 + depth := 0 for iNdEx < l { var wire uint64 for shift := uint(0); ; shift += 7 { @@ -228,10 +251,8 @@ func skipHintdetail(dAtA []byte) (n int, err error) { break } } - return iNdEx, nil case 1: iNdEx += 8 - return iNdEx, nil case 2: var length int for shift := uint(0); ; shift += 7 { @@ -248,72 +269,34 @@ func skipHintdetail(dAtA []byte) (n int, err error) { break } } - iNdEx += length if length < 0 { return 0, ErrInvalidLengthHintdetail } - return iNdEx, nil + iNdEx += length case 3: - for { - var innerWire uint64 - var start int = iNdEx - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowHintdetail - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - innerWire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - innerWireType := int(innerWire & 0x7) - if innerWireType == 4 { - break - } - next, err := skipHintdetail(dAtA[start:]) - if err != nil { - return 0, err - } - iNdEx = start + next - } - return iNdEx, nil + depth++ case 4: - return iNdEx, nil + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupHintdetail + } + depth-- case 5: iNdEx += 4 - return iNdEx, nil default: return 0, fmt.Errorf("proto: illegal wireType %d", wireType) } + if iNdEx < 0 { + return 0, ErrInvalidLengthHintdetail + } + if depth == 0 { + return iNdEx, nil + } } - panic("unreachable") + return 0, io.ErrUnexpectedEOF } var ( - ErrInvalidLengthHintdetail = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowHintdetail = fmt.Errorf("proto: integer overflow") + ErrInvalidLengthHintdetail = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowHintdetail = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupHintdetail = fmt.Errorf("proto: unexpected end of group") ) - -func init() { - proto.RegisterFile("github.com/cockroachdb/errors/errorspb/hintdetail.proto", fileDescriptor_hintdetail_429641491537a364) -} - -var fileDescriptor_hintdetail_429641491537a364 = []byte{ - // 161 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x32, 0x4f, 0xcf, 0x2c, 0xc9, - 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x4f, 0xce, 0x2e, 0xca, 0x4f, 0x4c, 0xce, - 0x48, 0x49, 0xd2, 0x4f, 0x2d, 0x2a, 0xca, 0x2f, 0x2a, 0x86, 0x52, 0x05, 0x49, 0xfa, 0x19, 0x99, - 0x79, 0x25, 0x29, 0xa9, 0x25, 0x89, 0x99, 0x39, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0x42, - 0x70, 0xd5, 0x7a, 0x30, 0x45, 0x4a, 0x8a, 0x5c, 0xbc, 0xc1, 0x25, 0x45, 0x99, 0x79, 0xe9, 0x01, - 0x89, 0x95, 0x39, 0xf9, 0x89, 0x29, 0x42, 0x02, 0x5c, 0xcc, 0xb9, 0xc5, 0xe9, 0x12, 0x8c, 0x0a, - 0x8c, 0x1a, 0x9c, 0x41, 0x20, 0xa6, 0x93, 0xd6, 0x89, 0x87, 0x72, 0x0c, 0x27, 0x1e, 0xc9, 0x31, - 0x5e, 0x78, 0x24, 0xc7, 0x78, 0xe3, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, - 0x31, 0x5c, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x14, 0x07, 0xcc, 0xb8, 0x24, 0x36, - 0xb0, 0x4d, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe0, 0x71, 0x36, 0x88, 0xa4, 0x00, 0x00, - 0x00, -} diff --git a/vendor/github.com/cockroachdb/errors/errorspb/markers.pb.go b/vendor/github.com/cockroachdb/errors/errorspb/markers.pb.go index 8058a225e..c19a3fb81 100644 --- a/vendor/github.com/cockroachdb/errors/errorspb/markers.pb.go +++ b/vendor/github.com/cockroachdb/errors/errorspb/markers.pb.go @@ -1,13 +1,16 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: github.com/cockroachdb/errors/errorspb/markers.proto +// source: errorspb/markers.proto package errorspb -import proto "github.com/gogo/protobuf/proto" -import fmt "fmt" -import math "math" - -import io "io" +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal @@ -18,7 +21,7 @@ var _ = math.Inf // is compatible with the proto package it is being compiled against. // A compilation error at this line likely means your copy of the // proto package needs to be updated. -const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // MarkPayload is the error payload for a forced marker. // See errors/markers/markers.go and the RFC on @@ -32,21 +35,21 @@ func (m *MarkPayload) Reset() { *m = MarkPayload{} } func (m *MarkPayload) String() string { return proto.CompactTextString(m) } func (*MarkPayload) ProtoMessage() {} func (*MarkPayload) Descriptor() ([]byte, []int) { - return fileDescriptor_markers_2a35e57f2b6b5666, []int{0} + return fileDescriptor_84c3fd24ba37816d, []int{0} } func (m *MarkPayload) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } func (m *MarkPayload) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { b = b[:cap(b)] - n, err := m.MarshalTo(b) + n, err := m.MarshalToSizedBuffer(b) if err != nil { return nil, err } return b[:n], nil } -func (dst *MarkPayload) XXX_Merge(src proto.Message) { - xxx_messageInfo_MarkPayload.Merge(dst, src) +func (m *MarkPayload) XXX_Merge(src proto.Message) { + xxx_messageInfo_MarkPayload.Merge(m, src) } func (m *MarkPayload) XXX_Size() int { return m.Size() @@ -60,10 +63,30 @@ var xxx_messageInfo_MarkPayload proto.InternalMessageInfo func init() { proto.RegisterType((*MarkPayload)(nil), "cockroach.errorspb.MarkPayload") } + +func init() { proto.RegisterFile("errorspb/markers.proto", fileDescriptor_84c3fd24ba37816d) } + +var fileDescriptor_84c3fd24ba37816d = []byte{ + // 198 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4b, 0x2d, 0x2a, 0xca, + 0x2f, 0x2a, 0x2e, 0x48, 0xd2, 0xcf, 0x4d, 0x2c, 0xca, 0x4e, 0x2d, 0x2a, 0xd6, 0x2b, 0x28, 0xca, + 0x2f, 0xc9, 0x17, 0x12, 0x4a, 0xce, 0x4f, 0xce, 0x2e, 0xca, 0x4f, 0x4c, 0xce, 0xd0, 0x83, 0xa9, + 0x90, 0x12, 0x85, 0xab, 0x85, 0x30, 0x20, 0x4a, 0xa5, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0x4c, + 0x7d, 0x10, 0x0b, 0x22, 0xaa, 0x14, 0xc7, 0xc5, 0xed, 0x9b, 0x58, 0x94, 0x1d, 0x90, 0x58, 0x99, + 0x93, 0x9f, 0x98, 0x22, 0x24, 0xc0, 0xc5, 0x9c, 0x5b, 0x9c, 0x2e, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, + 0x19, 0x04, 0x62, 0x0a, 0xd9, 0x72, 0xb1, 0x96, 0x54, 0x16, 0xa4, 0x16, 0x4b, 0x30, 0x29, 0x30, + 0x6b, 0x70, 0x1b, 0x29, 0xea, 0x61, 0xda, 0xa8, 0xe7, 0x0a, 0x62, 0x84, 0x54, 0x16, 0xa4, 0x82, + 0x8c, 0x72, 0x62, 0x39, 0x71, 0x4f, 0x9e, 0x21, 0x08, 0xa2, 0xcb, 0x49, 0xeb, 0xc4, 0x43, 0x39, + 0x86, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0xbc, 0xf1, 0x48, 0x8e, 0xf1, 0xc1, 0x23, + 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0x8a, + 0x03, 0x66, 0x4c, 0x12, 0x1b, 0xd8, 0x49, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0x43, + 0x45, 0xef, 0xed, 0x00, 0x00, 0x00, +} + func (m *MarkPayload) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -71,39 +94,49 @@ func (m *MarkPayload) Marshal() (dAtA []byte, err error) { } func (m *MarkPayload) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MarkPayload) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l - if len(m.Msg) > 0 { - dAtA[i] = 0xa - i++ - i = encodeVarintMarkers(dAtA, i, uint64(len(m.Msg))) - i += copy(dAtA[i:], m.Msg) - } if len(m.Types) > 0 { - for _, msg := range m.Types { - dAtA[i] = 0x12 - i++ - i = encodeVarintMarkers(dAtA, i, uint64(msg.Size())) - n, err := msg.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err + for iNdEx := len(m.Types) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Types[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintMarkers(dAtA, i, uint64(size)) } - i += n + i-- + dAtA[i] = 0x12 } } - return i, nil + if len(m.Msg) > 0 { + i -= len(m.Msg) + copy(dAtA[i:], m.Msg) + i = encodeVarintMarkers(dAtA, i, uint64(len(m.Msg))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil } func encodeVarintMarkers(dAtA []byte, offset int, v uint64) int { + offset -= sovMarkers(v) + base := offset for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) v >>= 7 offset++ } dAtA[offset] = uint8(v) - return offset + 1 + return base } func (m *MarkPayload) Size() (n int) { if m == nil { @@ -125,14 +158,7 @@ func (m *MarkPayload) Size() (n int) { } func sovMarkers(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } - } - return n + return (math_bits.Len64(x|1) + 6) / 7 } func sozMarkers(x uint64) (n int) { return sovMarkers(uint64((x << 1) ^ uint64((int64(x) >> 63)))) @@ -152,7 +178,7 @@ func (m *MarkPayload) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -180,7 +206,7 @@ func (m *MarkPayload) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -190,6 +216,9 @@ func (m *MarkPayload) Unmarshal(dAtA []byte) error { return ErrInvalidLengthMarkers } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMarkers + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -209,7 +238,7 @@ func (m *MarkPayload) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } @@ -218,6 +247,9 @@ func (m *MarkPayload) Unmarshal(dAtA []byte) error { return ErrInvalidLengthMarkers } postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthMarkers + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -232,7 +264,7 @@ func (m *MarkPayload) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthMarkers } if (iNdEx + skippy) > l { @@ -250,6 +282,7 @@ func (m *MarkPayload) Unmarshal(dAtA []byte) error { func skipMarkers(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 + depth := 0 for iNdEx < l { var wire uint64 for shift := uint(0); ; shift += 7 { @@ -281,10 +314,8 @@ func skipMarkers(dAtA []byte) (n int, err error) { break } } - return iNdEx, nil case 1: iNdEx += 8 - return iNdEx, nil case 2: var length int for shift := uint(0); ; shift += 7 { @@ -301,75 +332,34 @@ func skipMarkers(dAtA []byte) (n int, err error) { break } } - iNdEx += length if length < 0 { return 0, ErrInvalidLengthMarkers } - return iNdEx, nil + iNdEx += length case 3: - for { - var innerWire uint64 - var start int = iNdEx - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowMarkers - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - innerWire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - innerWireType := int(innerWire & 0x7) - if innerWireType == 4 { - break - } - next, err := skipMarkers(dAtA[start:]) - if err != nil { - return 0, err - } - iNdEx = start + next - } - return iNdEx, nil + depth++ case 4: - return iNdEx, nil + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupMarkers + } + depth-- case 5: iNdEx += 4 - return iNdEx, nil default: return 0, fmt.Errorf("proto: illegal wireType %d", wireType) } + if iNdEx < 0 { + return 0, ErrInvalidLengthMarkers + } + if depth == 0 { + return iNdEx, nil + } } - panic("unreachable") + return 0, io.ErrUnexpectedEOF } var ( - ErrInvalidLengthMarkers = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowMarkers = fmt.Errorf("proto: integer overflow") + ErrInvalidLengthMarkers = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowMarkers = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupMarkers = fmt.Errorf("proto: unexpected end of group") ) - -func init() { - proto.RegisterFile("github.com/cockroachdb/errors/errorspb/markers.proto", fileDescriptor_markers_2a35e57f2b6b5666) -} - -var fileDescriptor_markers_2a35e57f2b6b5666 = []byte{ - // 216 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x32, 0x49, 0xcf, 0x2c, 0xc9, - 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x4f, 0xce, 0x2e, 0xca, 0x4f, 0x4c, 0xce, - 0x48, 0x49, 0xd2, 0x4f, 0x2d, 0x2a, 0xca, 0x2f, 0x2a, 0x86, 0x52, 0x05, 0x49, 0xfa, 0xb9, 0x89, - 0x45, 0xd9, 0xa9, 0x45, 0xc5, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0x42, 0x70, 0xa5, 0x7a, - 0x30, 0x15, 0x52, 0xc6, 0x44, 0x9a, 0x04, 0x61, 0x40, 0x0c, 0x92, 0x12, 0x49, 0xcf, 0x4f, 0xcf, - 0x07, 0x33, 0xf5, 0x41, 0x2c, 0x88, 0xa8, 0x52, 0x1c, 0x17, 0xb7, 0x6f, 0x62, 0x51, 0x76, 0x40, - 0x62, 0x65, 0x4e, 0x7e, 0x62, 0x8a, 0x90, 0x00, 0x17, 0x73, 0x6e, 0x71, 0xba, 0x04, 0xa3, 0x02, - 0xa3, 0x06, 0x67, 0x10, 0x88, 0x29, 0x64, 0xcb, 0xc5, 0x5a, 0x52, 0x59, 0x90, 0x5a, 0x2c, 0xc1, - 0xa4, 0xc0, 0xac, 0xc1, 0x6d, 0xa4, 0xa8, 0x87, 0xe9, 0x1e, 0x3d, 0x57, 0x10, 0x23, 0xa4, 0xb2, - 0x20, 0x15, 0x64, 0x94, 0x13, 0xcb, 0x89, 0x7b, 0xf2, 0x0c, 0x41, 0x10, 0x5d, 0x4e, 0x5a, 0x27, - 0x1e, 0xca, 0x31, 0x9c, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x8d, 0x47, 0x72, 0x8c, - 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d, 0xc7, 0x72, - 0x0c, 0x51, 0x1c, 0x30, 0x63, 0x92, 0xd8, 0xc0, 0x4e, 0x32, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, - 0xdc, 0x2d, 0x59, 0x6b, 0x29, 0x01, 0x00, 0x00, -} diff --git a/vendor/github.com/cockroachdb/errors/errorspb/markers.proto b/vendor/github.com/cockroachdb/errors/errorspb/markers.proto index 02ef1c82b..3ea30ee80 100644 --- a/vendor/github.com/cockroachdb/errors/errorspb/markers.proto +++ b/vendor/github.com/cockroachdb/errors/errorspb/markers.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package cockroach.errorspb; option go_package = "errorspb"; -import "github.com/cockroachdb/errors/errorspb/errors.proto"; +import "errorspb/errors.proto"; import "gogoproto/gogo.proto"; // MarkPayload is the error payload for a forced marker. diff --git a/vendor/github.com/cockroachdb/errors/errorspb/tags.pb.go b/vendor/github.com/cockroachdb/errors/errorspb/tags.pb.go index e8e7227a4..9fea3e6f0 100644 --- a/vendor/github.com/cockroachdb/errors/errorspb/tags.pb.go +++ b/vendor/github.com/cockroachdb/errors/errorspb/tags.pb.go @@ -1,13 +1,16 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: github.com/cockroachdb/errors/errorspb/tags.proto +// source: errorspb/tags.proto package errorspb -import proto "github.com/gogo/protobuf/proto" -import fmt "fmt" -import math "math" - -import io "io" +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal @@ -18,7 +21,7 @@ var _ = math.Inf // is compatible with the proto package it is being compiled against. // A compilation error at this line likely means your copy of the // proto package needs to be updated. -const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // TagsPayload is the error payload for a WithContext // marker. @@ -32,21 +35,21 @@ func (m *TagsPayload) Reset() { *m = TagsPayload{} } func (m *TagsPayload) String() string { return proto.CompactTextString(m) } func (*TagsPayload) ProtoMessage() {} func (*TagsPayload) Descriptor() ([]byte, []int) { - return fileDescriptor_tags_c75c5e322ef6b31c, []int{0} + return fileDescriptor_2f0d1dc5c54e9f63, []int{0} } func (m *TagsPayload) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } func (m *TagsPayload) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { b = b[:cap(b)] - n, err := m.MarshalTo(b) + n, err := m.MarshalToSizedBuffer(b) if err != nil { return nil, err } return b[:n], nil } -func (dst *TagsPayload) XXX_Merge(src proto.Message) { - xxx_messageInfo_TagsPayload.Merge(dst, src) +func (m *TagsPayload) XXX_Merge(src proto.Message) { + xxx_messageInfo_TagsPayload.Merge(m, src) } func (m *TagsPayload) XXX_Size() int { return m.Size() @@ -66,21 +69,21 @@ func (m *TagPayload) Reset() { *m = TagPayload{} } func (m *TagPayload) String() string { return proto.CompactTextString(m) } func (*TagPayload) ProtoMessage() {} func (*TagPayload) Descriptor() ([]byte, []int) { - return fileDescriptor_tags_c75c5e322ef6b31c, []int{1} + return fileDescriptor_2f0d1dc5c54e9f63, []int{1} } func (m *TagPayload) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } func (m *TagPayload) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { b = b[:cap(b)] - n, err := m.MarshalTo(b) + n, err := m.MarshalToSizedBuffer(b) if err != nil { return nil, err } return b[:n], nil } -func (dst *TagPayload) XXX_Merge(src proto.Message) { - xxx_messageInfo_TagPayload.Merge(dst, src) +func (m *TagPayload) XXX_Merge(src proto.Message) { + xxx_messageInfo_TagPayload.Merge(m, src) } func (m *TagPayload) XXX_Size() int { return m.Size() @@ -95,10 +98,30 @@ func init() { proto.RegisterType((*TagsPayload)(nil), "cockroach.errorspb.TagsPayload") proto.RegisterType((*TagPayload)(nil), "cockroach.errorspb.TagPayload") } + +func init() { proto.RegisterFile("errorspb/tags.proto", fileDescriptor_2f0d1dc5c54e9f63) } + +var fileDescriptor_2f0d1dc5c54e9f63 = []byte{ + // 201 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4e, 0x2d, 0x2a, 0xca, + 0x2f, 0x2a, 0x2e, 0x48, 0xd2, 0x2f, 0x49, 0x4c, 0x2f, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, + 0x12, 0x4a, 0xce, 0x4f, 0xce, 0x2e, 0xca, 0x4f, 0x4c, 0xce, 0xd0, 0x83, 0x49, 0x4b, 0x89, 0xa4, + 0xe7, 0xa7, 0xe7, 0x83, 0xa5, 0xf5, 0x41, 0x2c, 0x88, 0x4a, 0x25, 0x77, 0x2e, 0xee, 0x90, 0xc4, + 0xf4, 0xe2, 0x80, 0xc4, 0xca, 0x9c, 0xfc, 0xc4, 0x14, 0x21, 0x0b, 0x2e, 0x16, 0x90, 0x31, 0x12, + 0x8c, 0x0a, 0xcc, 0x1a, 0xdc, 0x46, 0x72, 0x7a, 0x98, 0xe6, 0xe8, 0x85, 0x24, 0xa6, 0x43, 0x55, + 0x3b, 0xb1, 0x9c, 0xb8, 0x27, 0xcf, 0x10, 0x04, 0xd6, 0xa1, 0x64, 0xc2, 0xc5, 0x85, 0x90, 0x11, + 0x12, 0xe0, 0x62, 0x2e, 0x49, 0x4c, 0x97, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x02, 0x31, 0x85, + 0x44, 0xb8, 0x58, 0xcb, 0x12, 0x73, 0x4a, 0x53, 0x25, 0x98, 0xc0, 0x62, 0x10, 0x8e, 0x93, 0xd6, + 0x89, 0x87, 0x72, 0x0c, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0x78, 0xe3, 0x91, 0x1c, + 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, 0x5c, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, + 0x1c, 0x43, 0x14, 0x07, 0xcc, 0xe2, 0x24, 0x36, 0xb0, 0x8b, 0x8d, 0x01, 0x01, 0x00, 0x00, 0xff, + 0xff, 0x0a, 0x90, 0xd1, 0xc9, 0xf2, 0x00, 0x00, 0x00, +} + func (m *TagsPayload) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -106,29 +129,36 @@ func (m *TagsPayload) Marshal() (dAtA []byte, err error) { } func (m *TagsPayload) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TagsPayload) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l if len(m.Tags) > 0 { - for _, msg := range m.Tags { - dAtA[i] = 0xa - i++ - i = encodeVarintTags(dAtA, i, uint64(msg.Size())) - n, err := msg.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err + for iNdEx := len(m.Tags) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Tags[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTags(dAtA, i, uint64(size)) } - i += n + i-- + dAtA[i] = 0xa } } - return i, nil + return len(dAtA) - i, nil } func (m *TagPayload) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -136,33 +166,42 @@ func (m *TagPayload) Marshal() (dAtA []byte, err error) { } func (m *TagPayload) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TagPayload) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l - if len(m.Tag) > 0 { - dAtA[i] = 0xa - i++ - i = encodeVarintTags(dAtA, i, uint64(len(m.Tag))) - i += copy(dAtA[i:], m.Tag) - } if len(m.Value) > 0 { - dAtA[i] = 0x12 - i++ + i -= len(m.Value) + copy(dAtA[i:], m.Value) i = encodeVarintTags(dAtA, i, uint64(len(m.Value))) - i += copy(dAtA[i:], m.Value) + i-- + dAtA[i] = 0x12 } - return i, nil + if len(m.Tag) > 0 { + i -= len(m.Tag) + copy(dAtA[i:], m.Tag) + i = encodeVarintTags(dAtA, i, uint64(len(m.Tag))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil } func encodeVarintTags(dAtA []byte, offset int, v uint64) int { + offset -= sovTags(v) + base := offset for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) v >>= 7 offset++ } dAtA[offset] = uint8(v) - return offset + 1 + return base } func (m *TagsPayload) Size() (n int) { if m == nil { @@ -197,14 +236,7 @@ func (m *TagPayload) Size() (n int) { } func sovTags(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } - } - return n + return (math_bits.Len64(x|1) + 6) / 7 } func sozTags(x uint64) (n int) { return sovTags(uint64((x << 1) ^ uint64((int64(x) >> 63)))) @@ -224,7 +256,7 @@ func (m *TagsPayload) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -252,7 +284,7 @@ func (m *TagsPayload) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } @@ -261,6 +293,9 @@ func (m *TagsPayload) Unmarshal(dAtA []byte) error { return ErrInvalidLengthTags } postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTags + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -275,7 +310,7 @@ func (m *TagsPayload) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTags } if (iNdEx + skippy) > l { @@ -305,7 +340,7 @@ func (m *TagPayload) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -333,7 +368,7 @@ func (m *TagPayload) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -343,6 +378,9 @@ func (m *TagPayload) Unmarshal(dAtA []byte) error { return ErrInvalidLengthTags } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTags + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -362,7 +400,7 @@ func (m *TagPayload) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -372,6 +410,9 @@ func (m *TagPayload) Unmarshal(dAtA []byte) error { return ErrInvalidLengthTags } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTags + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -383,7 +424,7 @@ func (m *TagPayload) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTags } if (iNdEx + skippy) > l { @@ -401,6 +442,7 @@ func (m *TagPayload) Unmarshal(dAtA []byte) error { func skipTags(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 + depth := 0 for iNdEx < l { var wire uint64 for shift := uint(0); ; shift += 7 { @@ -432,10 +474,8 @@ func skipTags(dAtA []byte) (n int, err error) { break } } - return iNdEx, nil case 1: iNdEx += 8 - return iNdEx, nil case 2: var length int for shift := uint(0); ; shift += 7 { @@ -452,75 +492,34 @@ func skipTags(dAtA []byte) (n int, err error) { break } } - iNdEx += length if length < 0 { return 0, ErrInvalidLengthTags } - return iNdEx, nil + iNdEx += length case 3: - for { - var innerWire uint64 - var start int = iNdEx - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowTags - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - innerWire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - innerWireType := int(innerWire & 0x7) - if innerWireType == 4 { - break - } - next, err := skipTags(dAtA[start:]) - if err != nil { - return 0, err - } - iNdEx = start + next - } - return iNdEx, nil + depth++ case 4: - return iNdEx, nil + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTags + } + depth-- case 5: iNdEx += 4 - return iNdEx, nil default: return 0, fmt.Errorf("proto: illegal wireType %d", wireType) } + if iNdEx < 0 { + return 0, ErrInvalidLengthTags + } + if depth == 0 { + return iNdEx, nil + } } - panic("unreachable") + return 0, io.ErrUnexpectedEOF } var ( - ErrInvalidLengthTags = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowTags = fmt.Errorf("proto: integer overflow") + ErrInvalidLengthTags = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTags = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTags = fmt.Errorf("proto: unexpected end of group") ) - -func init() { - proto.RegisterFile("github.com/cockroachdb/errors/errorspb/tags.proto", fileDescriptor_tags_c75c5e322ef6b31c) -} - -var fileDescriptor_tags_c75c5e322ef6b31c = []byte{ - // 218 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x32, 0x4c, 0xcf, 0x2c, 0xc9, - 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x4f, 0xce, 0x2e, 0xca, 0x4f, 0x4c, 0xce, - 0x48, 0x49, 0xd2, 0x4f, 0x2d, 0x2a, 0xca, 0x2f, 0x2a, 0x86, 0x52, 0x05, 0x49, 0xfa, 0x25, 0x89, - 0xe9, 0xc5, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0x42, 0x70, 0x75, 0x7a, 0x30, 0x69, 0x29, - 0x91, 0xf4, 0xfc, 0xf4, 0x7c, 0xb0, 0xb4, 0x3e, 0x88, 0x05, 0x51, 0xa9, 0xe4, 0xce, 0xc5, 0x1d, - 0x92, 0x98, 0x5e, 0x1c, 0x90, 0x58, 0x99, 0x93, 0x9f, 0x98, 0x22, 0x64, 0xc1, 0xc5, 0x02, 0x32, - 0x46, 0x82, 0x51, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x4e, 0x0f, 0xd3, 0x1c, 0xbd, 0x90, 0xc4, 0x74, - 0xa8, 0x6a, 0x27, 0x96, 0x13, 0xf7, 0xe4, 0x19, 0x82, 0xc0, 0x3a, 0x94, 0x4c, 0xb8, 0xb8, 0x10, - 0x32, 0x42, 0x02, 0x5c, 0xcc, 0x25, 0x89, 0xe9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x20, - 0xa6, 0x90, 0x08, 0x17, 0x6b, 0x59, 0x62, 0x4e, 0x69, 0xaa, 0x04, 0x13, 0x58, 0x0c, 0xc2, 0x71, - 0xd2, 0x3a, 0xf1, 0x50, 0x8e, 0xe1, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x6f, 0x3c, - 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, - 0x3c, 0x96, 0x63, 0x88, 0xe2, 0x80, 0x59, 0x9c, 0xc4, 0x06, 0x76, 0xb1, 0x31, 0x20, 0x00, 0x00, - 0xff, 0xff, 0xa6, 0x1b, 0x01, 0x30, 0x10, 0x01, 0x00, 0x00, -} diff --git a/vendor/github.com/cockroachdb/errors/errorspb/testing.pb.go b/vendor/github.com/cockroachdb/errors/errorspb/testing.pb.go index 2779e6e20..fb9bd31cd 100644 --- a/vendor/github.com/cockroachdb/errors/errorspb/testing.pb.go +++ b/vendor/github.com/cockroachdb/errors/errorspb/testing.pb.go @@ -1,13 +1,15 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: github.com/cockroachdb/errors/errorspb/testing.proto +// source: errorspb/testing.proto package errorspb -import proto "github.com/gogo/protobuf/proto" -import fmt "fmt" -import math "math" - -import io "io" +import ( + fmt "fmt" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal @@ -18,7 +20,7 @@ var _ = math.Inf // is compatible with the proto package it is being compiled against. // A compilation error at this line likely means your copy of the // proto package needs to be updated. -const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // TestError is meant for use in testing only. type TestError struct { @@ -28,21 +30,21 @@ func (m *TestError) Reset() { *m = TestError{} } func (m *TestError) String() string { return proto.CompactTextString(m) } func (*TestError) ProtoMessage() {} func (*TestError) Descriptor() ([]byte, []int) { - return fileDescriptor_testing_d9751a0a5e86c096, []int{0} + return fileDescriptor_0551f0d913d6118f, []int{0} } func (m *TestError) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } func (m *TestError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { b = b[:cap(b)] - n, err := m.MarshalTo(b) + n, err := m.MarshalToSizedBuffer(b) if err != nil { return nil, err } return b[:n], nil } -func (dst *TestError) XXX_Merge(src proto.Message) { - xxx_messageInfo_TestError.Merge(dst, src) +func (m *TestError) XXX_Merge(src proto.Message) { + xxx_messageInfo_TestError.Merge(m, src) } func (m *TestError) XXX_Size() int { return m.Size() @@ -56,10 +58,25 @@ var xxx_messageInfo_TestError proto.InternalMessageInfo func init() { proto.RegisterType((*TestError)(nil), "cockroach.errorspb.TestError") } + +func init() { proto.RegisterFile("errorspb/testing.proto", fileDescriptor_0551f0d913d6118f) } + +var fileDescriptor_0551f0d913d6118f = []byte{ + // 118 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4b, 0x2d, 0x2a, 0xca, + 0x2f, 0x2a, 0x2e, 0x48, 0xd2, 0x2f, 0x49, 0x2d, 0x2e, 0xc9, 0xcc, 0x4b, 0xd7, 0x2b, 0x28, 0xca, + 0x2f, 0xc9, 0x17, 0x12, 0x4a, 0xce, 0x4f, 0xce, 0x2e, 0xca, 0x4f, 0x4c, 0xce, 0xd0, 0x83, 0xa9, + 0x50, 0xe2, 0xe6, 0xe2, 0x0c, 0x49, 0x2d, 0x2e, 0x71, 0x05, 0xf1, 0x9d, 0xb4, 0x4e, 0x3c, 0x94, + 0x63, 0x38, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x1b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, + 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, 0x86, 0x1b, 0x8f, 0xe5, 0x18, 0xa2, + 0x38, 0x60, 0x1a, 0x93, 0xd8, 0xc0, 0x66, 0x1a, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x4b, 0xf3, + 0x3e, 0x92, 0x6d, 0x00, 0x00, 0x00, +} + func (m *TestError) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -67,21 +84,28 @@ func (m *TestError) Marshal() (dAtA []byte, err error) { } func (m *TestError) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TestError) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l - return i, nil + return len(dAtA) - i, nil } func encodeVarintTesting(dAtA []byte, offset int, v uint64) int { + offset -= sovTesting(v) + base := offset for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) v >>= 7 offset++ } dAtA[offset] = uint8(v) - return offset + 1 + return base } func (m *TestError) Size() (n int) { if m == nil { @@ -93,14 +117,7 @@ func (m *TestError) Size() (n int) { } func sovTesting(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } - } - return n + return (math_bits.Len64(x|1) + 6) / 7 } func sozTesting(x uint64) (n int) { return sovTesting(uint64((x << 1) ^ uint64((int64(x) >> 63)))) @@ -120,7 +137,7 @@ func (m *TestError) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -140,7 +157,7 @@ func (m *TestError) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTesting } if (iNdEx + skippy) > l { @@ -158,6 +175,7 @@ func (m *TestError) Unmarshal(dAtA []byte) error { func skipTesting(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 + depth := 0 for iNdEx < l { var wire uint64 for shift := uint(0); ; shift += 7 { @@ -189,10 +207,8 @@ func skipTesting(dAtA []byte) (n int, err error) { break } } - return iNdEx, nil case 1: iNdEx += 8 - return iNdEx, nil case 2: var length int for shift := uint(0); ; shift += 7 { @@ -209,70 +225,34 @@ func skipTesting(dAtA []byte) (n int, err error) { break } } - iNdEx += length if length < 0 { return 0, ErrInvalidLengthTesting } - return iNdEx, nil + iNdEx += length case 3: - for { - var innerWire uint64 - var start int = iNdEx - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowTesting - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - innerWire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - innerWireType := int(innerWire & 0x7) - if innerWireType == 4 { - break - } - next, err := skipTesting(dAtA[start:]) - if err != nil { - return 0, err - } - iNdEx = start + next - } - return iNdEx, nil + depth++ case 4: - return iNdEx, nil + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTesting + } + depth-- case 5: iNdEx += 4 - return iNdEx, nil default: return 0, fmt.Errorf("proto: illegal wireType %d", wireType) } + if iNdEx < 0 { + return 0, ErrInvalidLengthTesting + } + if depth == 0 { + return iNdEx, nil + } } - panic("unreachable") + return 0, io.ErrUnexpectedEOF } var ( - ErrInvalidLengthTesting = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowTesting = fmt.Errorf("proto: integer overflow") + ErrInvalidLengthTesting = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTesting = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTesting = fmt.Errorf("proto: unexpected end of group") ) - -func init() { - proto.RegisterFile("github.com/cockroachdb/errors/errorspb/testing.proto", fileDescriptor_testing_d9751a0a5e86c096) -} - -var fileDescriptor_testing_d9751a0a5e86c096 = []byte{ - // 136 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x32, 0x49, 0xcf, 0x2c, 0xc9, - 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x4f, 0xce, 0x2e, 0xca, 0x4f, 0x4c, 0xce, - 0x48, 0x49, 0xd2, 0x4f, 0x2d, 0x2a, 0xca, 0x2f, 0x2a, 0x86, 0x52, 0x05, 0x49, 0xfa, 0x25, 0xa9, - 0xc5, 0x25, 0x99, 0x79, 0xe9, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0x42, 0x70, 0xa5, 0x7a, - 0x30, 0x15, 0x4a, 0xdc, 0x5c, 0x9c, 0x21, 0xa9, 0xc5, 0x25, 0xae, 0x20, 0xbe, 0x93, 0xd6, 0x89, - 0x87, 0x72, 0x0c, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0x78, 0xe3, 0x91, 0x1c, 0xe3, - 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, 0x5c, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, - 0x43, 0x14, 0x07, 0x4c, 0x63, 0x12, 0x1b, 0xd8, 0x4c, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x8a, 0x2c, 0x50, 0x5f, 0x8b, 0x00, 0x00, 0x00, -} diff --git a/vendor/github.com/cockroachdb/errors/errutil/as.go b/vendor/github.com/cockroachdb/errors/errutil/as.go index bf45e4577..ad2a8fc77 100644 --- a/vendor/github.com/cockroachdb/errors/errutil/as.go +++ b/vendor/github.com/cockroachdb/errors/errutil/as.go @@ -58,7 +58,16 @@ func As(err error, target interface{}) bool { if x, ok := c.(interface{ As(interface{}) bool }); ok && x.As(target) { return true } + + // If at any point in the single cause chain including the top, + // we encounter a multi-cause chain, recursively explore it. + for _, cause := range errbase.UnwrapMulti(c) { + if As(cause, target) { + return true + } + } } + return false } diff --git a/vendor/github.com/cockroachdb/errors/errutil/utilities.go b/vendor/github.com/cockroachdb/errors/errutil/utilities.go index 2fd126d74..78e4d20c8 100644 --- a/vendor/github.com/cockroachdb/errors/errutil/utilities.go +++ b/vendor/github.com/cockroachdb/errors/errutil/utilities.go @@ -15,6 +15,7 @@ package errutil import ( + "github.com/cockroachdb/errors/join" "github.com/cockroachdb/errors/secondary" "github.com/cockroachdb/errors/withstack" "github.com/cockroachdb/redact" @@ -158,3 +159,10 @@ func WrapWithDepthf(depth int, err error, format string, args ...interface{}) er err = withstack.WithStackDepth(err, depth+1) return err } + +// JoinWithDepth constructs a Join error with the provided list of +// errors as arguments, and wraps it in a `WithStackDepth` to capture a +// stacktrace alongside. +func JoinWithDepth(depth int, errs ...error) error { + return withstack.WithStackDepth(join.Join(errs...), depth+1) +} diff --git a/vendor/github.com/cockroachdb/errors/errutil_api.go b/vendor/github.com/cockroachdb/errors/errutil_api.go index 512bdedb9..166eee111 100644 --- a/vendor/github.com/cockroachdb/errors/errutil_api.go +++ b/vendor/github.com/cockroachdb/errors/errutil_api.go @@ -192,3 +192,19 @@ func HandleAsAssertionFailureDepth(depth int, origErr error) error { // - it also supports recursing through causes with Cause(). // - if it detects an API use error, its panic object is a valid error. func As(err error, target interface{}) bool { return errutil.As(err, target) } + +// Join returns an error that wraps the given errors. +// Any nil error values are discarded. +// Join returns nil if errs contains no non-nil values. +// The error formats as the concatenation of the strings obtained +// by calling the Error method of each element of errs, with a newline +// between each string. A stack trace is also retained. +func Join(errs ...error) error { + return errutil.JoinWithDepth(1, errs...) +} + +// JoinWithDepth is like Join but the depth at which the call stack is +// captured can be specified. +func JoinWithDepth(depth int, errs ...error) error { + return errutil.JoinWithDepth(depth+1, errs...) +} diff --git a/vendor/github.com/cockroachdb/errors/hintdetail/hintdetail.go b/vendor/github.com/cockroachdb/errors/hintdetail/hintdetail.go index ac12333d1..81c315695 100644 --- a/vendor/github.com/cockroachdb/errors/hintdetail/hintdetail.go +++ b/vendor/github.com/cockroachdb/errors/hintdetail/hintdetail.go @@ -23,6 +23,7 @@ import ( // WithHint decorates an error with a textual hint. // The hint may contain PII and thus will not reportable. +// The suggested use case for hint is to relay information to end users. // // Hint is shown: // - when formatting with `%+v`. @@ -97,10 +98,12 @@ type ErrorHinter interface { // WithDetail decorates an error with a textual detail. // The detail may contain PII and thus will not reportable. +// The suggested use case for detail is to augment errors with information +// useful for debugging. // // Detail is shown: // - when formatting with `%+v`. -// - with `GetAllHints()` / `FlattenHints()` below. +// - with `GetAllDetails()` / `FlattenDetails()` below. // // Note: the detail does not appear in the main error message returned // with Error(). Use GetAllDetails() or FlattenDetails() to retrieve diff --git a/vendor/github.com/cockroachdb/errors/hintdetail_api.go b/vendor/github.com/cockroachdb/errors/hintdetail_api.go index 623bf64af..01a95011f 100644 --- a/vendor/github.com/cockroachdb/errors/hintdetail_api.go +++ b/vendor/github.com/cockroachdb/errors/hintdetail_api.go @@ -27,6 +27,7 @@ type ErrorDetailer = hintdetail.ErrorDetailer // WithHint decorates an error with a textual hint. // The hint may contain PII and thus will not reportable. +// The suggested use case for hint is to relay information to end users. // // Hint is shown: // - when formatting with `%+v`. @@ -44,10 +45,12 @@ func WithHintf(err error, format string, args ...interface{}) error { // WithDetail decorates an error with a textual detail. // The detail may contain PII and thus will not reportable. +// The suggested use case for detail is to augment errors with information +// useful for debugging. // // Detail is shown: // - when formatting with `%+v`. -// - with `GetAllHints()` / `FlattenHints()` below. +// - with `GetAllDetails()` / `FlattenDetails()` below. // // Note: the detail does not appear in the main error message returned // with Error(). Use GetAllDetails() or FlattenDetails() to retrieve diff --git a/vendor/github.com/cockroachdb/errors/join/join.go b/vendor/github.com/cockroachdb/errors/join/join.go new file mode 100644 index 000000000..7ca5fcd44 --- /dev/null +++ b/vendor/github.com/cockroachdb/errors/join/join.go @@ -0,0 +1,105 @@ +// Copyright 2019 The Cockroach 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 join + +import ( + "context" + "fmt" + + "github.com/cockroachdb/errors/errbase" + "github.com/cockroachdb/redact" + "github.com/gogo/protobuf/proto" +) + +// Join returns an error that wraps the given errors. +// Any nil error values are discarded. +// Join returns nil if errs contains no non-nil values. +// The error formats as the concatenation of the strings obtained +// by calling the Error method of each element of errs, with a newline +// between each string. +func Join(errs ...error) error { + n := 0 + for _, err := range errs { + if err != nil { + n++ + } + } + if n == 0 { + return nil + } + e := &joinError{ + errs: make([]error, 0, n), + } + for _, err := range errs { + if err != nil { + e.errs = append(e.errs, err) + } + } + return e +} + +type joinError struct { + errs []error +} + +var _ error = (*joinError)(nil) +var _ fmt.Formatter = (*joinError)(nil) +var _ errbase.SafeFormatter = (*joinError)(nil) + +func (e *joinError) Error() string { + return redact.Sprint(e).StripMarkers() +} + +func (e *joinError) Unwrap() []error { + return e.errs +} + +func (e *joinError) SafeFormatError(p errbase.Printer) error { + for i, err := range e.errs { + if i > 0 { + p.Print("\n") + } + p.Print(err) + } + return nil +} + +func (e *joinError) Format(s fmt.State, verb rune) { + errbase.FormatError(e, s, verb) +} + +func init() { + errbase.RegisterMultiCauseEncoder( + errbase.GetTypeKey(&joinError{}), + func( + ctx context.Context, + err error, + ) (msg string, safeDetails []string, payload proto.Message) { + return "", nil, nil + }, + ) + errbase.RegisterMultiCauseDecoder( + errbase.GetTypeKey(&joinError{}), + func( + ctx context.Context, + causes []error, + msgPrefix string, + safeDetails []string, + payload proto.Message, + ) error { + return Join(causes...) + }, + ) +} diff --git a/vendor/github.com/cockroachdb/errors/markers/markers.go b/vendor/github.com/cockroachdb/errors/markers/markers.go index 8a2c2e62e..fa69b0ca6 100644 --- a/vendor/github.com/cockroachdb/errors/markers/markers.go +++ b/vendor/github.com/cockroachdb/errors/markers/markers.go @@ -28,20 +28,44 @@ import ( // Is determines whether one of the causes of the given error or any // of its causes is equivalent to some reference error. // +// As in the Go standard library, an error is considered to match a +// reference error if it is equal to that target or if it implements a +// method Is(error) bool such that Is(reference) returns true. +// +// Note: the inverse is not true - making an Is(reference) method +// return false does not imply that errors.Is() also returns +// false. Errors can be equal because their network equality marker is +// the same. To force errors to appear different to Is(), use +// errors.Mark(). +// // Note: if any of the error types has been migrated from a previous // package location or a different type, ensure that // RegisterTypeMigration() was called prior to Is(). func Is(err, reference error) bool { if reference == nil { - return err == reference + return err == nil } + isComparable := reflect.TypeOf(reference).Comparable() + // Direct reference comparison is the fastest, and most // likely to be true, so do this first. for c := err; c != nil; c = errbase.UnwrapOnce(c) { - if c == reference { + if isComparable && c == reference { + return true + } + // Compatibility with std go errors: if the error object itself + // implements Is(), try to use that. + if tryDelegateToIsMethod(c, reference) { return true } + + // Recursively try multi-error causes, if applicable. + for _, me := range errbase.UnwrapMulti(c) { + if Is(me, reference) { + return true + } + } } if err == nil { @@ -51,8 +75,8 @@ func Is(err, reference error) bool { return false } - // Not directly equal. Try harder, using error marks. We don't this - // during the loop above as it may be more expensive. + // Not directly equal. Try harder, using error marks. We don't do + // this during the loop above as it may be more expensive. // // Note: there is a more effective recursive algorithm that ensures // that any pair of string only gets compared once. Should the @@ -67,6 +91,13 @@ func Is(err, reference error) bool { return false } +func tryDelegateToIsMethod(err, reference error) bool { + if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(reference) { + return true + } + return false +} + // HasType returns true iff err contains an error whose concrete type // matches that of referenceType. func HasType(err error, referenceType error) bool { @@ -119,21 +150,12 @@ func If(err error, pred func(err error) (interface{}, bool)) (interface{}, bool) // package location or a different type, ensure that // RegisterTypeMigration() was called prior to IsAny(). func IsAny(err error, references ...error) bool { - // First try using direct reference comparison. - for c := err; ; c = errbase.UnwrapOnce(c) { + if err == nil { for _, refErr := range references { - if c == refErr { + if refErr == nil { return true } } - if c == nil { - // This special case is to support a comparison to a nil - // reference. - break - } - } - - if err == nil { // The mark-based comparison below will never match anything if // the error is nil, so don't bother with computing the marks in // that case. This avoids the computational expense of computing @@ -141,6 +163,24 @@ func IsAny(err error, references ...error) bool { return false } + // First try using direct reference comparison. + for c := err; c != nil; c = errbase.UnwrapOnce(c) { + for _, refErr := range references { + if refErr == nil { + continue + } + isComparable := reflect.TypeOf(refErr).Comparable() + if isComparable && c == refErr { + return true + } + // Compatibility with std go errors: if the error object itself + // implements Is(), try to use that. + if tryDelegateToIsMethod(c, refErr) { + return true + } + } + } + // Try harder with marks. // Note: there is a more effective recursive algorithm that ensures // that any pair of string only gets compared once. Should this diff --git a/vendor/github.com/cockroachdb/errors/markers_api.go b/vendor/github.com/cockroachdb/errors/markers_api.go index 64c8f2941..dffc1f60c 100644 --- a/vendor/github.com/cockroachdb/errors/markers_api.go +++ b/vendor/github.com/cockroachdb/errors/markers_api.go @@ -19,6 +19,16 @@ import "github.com/cockroachdb/errors/markers" // Is determines whether one of the causes of the given error or any // of its causes is equivalent to some reference error. // +// As in the Go standard library, an error is considered to match a +// reference error if it is equal to that target or if it implements a +// method Is(error) bool such that Is(reference) returns true. +// +// Note: the inverse is not true - making an Is(reference) method +// return false does not imply that errors.Is() also returns +// false. Errors can be equal because their network equality marker is +// the same. To force errors to appear different to Is(), use +// errors.Mark(). +// // Note: if any of the error types has been migrated from a previous // package location or a different type, ensure that // RegisterTypeMigration() was called prior to Is(). diff --git a/vendor/github.com/cockroachdb/errors/report/report.go b/vendor/github.com/cockroachdb/errors/report/report.go index b999a7f4f..817583d12 100644 --- a/vendor/github.com/cockroachdb/errors/report/report.go +++ b/vendor/github.com/cockroachdb/errors/report/report.go @@ -15,7 +15,6 @@ package report import ( - "bytes" "fmt" "strings" @@ -23,7 +22,7 @@ import ( "github.com/cockroachdb/errors/errbase" "github.com/cockroachdb/errors/withstack" "github.com/cockroachdb/redact" - "github.com/cockroachdb/sentry-go" + sentry "github.com/getsentry/sentry-go" ) // BuildSentryReport builds the components of a sentry report. This @@ -35,36 +34,39 @@ import ( // // A Sentry report is displayed visually in the Sentry UI as follows: // -//////////////// +// ////////////// // Title: (1) some prefix in bold (2) one line for a stack trace // (3) a single-line subtitle // -// (4) the tags, as a tag soup (concatenated in a single paragrah, +// (4) the tags, as a tag soup (concatenated in a single paragraph, // unsorted) // // (5) a "message" // // (6) zero or more "exceptions", each composed of: -// (7) a bold title -// (8) some freeform text -// (9) a stack trace +// +// (7) a bold title +// (8) some freeform text +// (9) a stack trace // // (10) metadata fields: environment, arch, etc // // (11) "Additional data" fields // // (12) SDK version -///////////////// +// /////////////// // // These visual items map to the Sentry Event object as follows: // // (1) the Type field of the 1st Exception object, if any -// otherwise the Message field +// +// otherwise the Message field +// // (2) the topmost entry from the Stacktrace field of the 1st Exception object, if any // (3) the Value field of the 1st Exception object, if any, unwrapped as a single line // (4) the Tags field // (5) the Message field -// (7) the Type field (same as (1) for 1st execption) +// (7) the Type field (same as (1) for 1st exception) // (8) the Value field (same as (3) for 1st exception) // (9) the Stacktrace field (input to (2) on 1st exception) // (10) the other fields on the Event object @@ -76,13 +78,15 @@ import ( // Given this mapping, an error object is decomposed as follows: // // (1)/(7): : () -// (3)/(8): : +// (3)/(8): first line of verbose error printout // (4): not populated in this function, caller is to manage this -// (5): detailed structure of the entire error object, with references to "additional data" -// and additional "exception" objects +// (5): detailed structure of the entire error object, with references to +// +// additional "exception" objects +// // (9): generated from innermost stack trace // (6): every exception object after the 1st reports additional stack trace contexts -// (11): "additional data" populated from safe detail payloads +// (11): the detailed error types and their error mark. // // If there is no stack trace in the error, a synthetic Exception // object is still produced to provide visual detail in the Sentry UI. @@ -93,7 +97,6 @@ import ( // is included in the Sentry report. This does not affect error types // provided by the library, but could impact error types defined by // 3rd parties. This limitation may be lifted in a later version. -// func BuildSentryReport(err error) (event *sentry.Event, extraDetails map[string]interface{}) { if err == nil { // No error: do nothing. @@ -103,13 +106,13 @@ func BuildSentryReport(err error) (event *sentry.Event, extraDetails map[string] // First step is to collect the details. var stacks []*withstack.ReportableStackTrace var details []errbase.SafeDetailPayload - for c := err; c != nil; c = errbase.UnwrapOnce(c) { + visitAllMulti(err, func(c error) { st := withstack.GetReportableStackTrace(c) stacks = append(stacks, st) sd := errbase.GetSafeDetails(c) details = append(details, sd) - } + }) module := string(domains.GetDomain(err)) // firstDetailLine is the first detail string encountered. @@ -119,17 +122,22 @@ func BuildSentryReport(err error) (event *sentry.Event, extraDetails map[string] var firstDetailLine string // longMsgBuf will become the Message field, which contains the full - // structure of the error with cross-references to "Exception" and - // "Additional data" fields. + // structure of the error. var longMsgBuf strings.Builder - redactedErrStr := redact.Sprint(err).Redact() - if redactedErrStr != redactedMarker { - if f, l, _, ok := withstack.GetOneLineSource(err); ok { - fmt.Fprintf(&longMsgBuf, "%s:%d: ", f, l) + if f, l, _, ok := withstack.GetOneLineSource(err); ok { + fmt.Fprintf(&longMsgBuf, "%s:%d: ", f, l) + } + // Include the verbose error printout, with sensitive bits redacted out. + verboseErr := redact.Sprintf("%+v", err).Redact().StripMarkers() + if verboseErr != redactedMarker { + idx := strings.IndexByte(verboseErr, '\n') + if idx == -1 { + firstDetailLine = verboseErr + } else { + firstDetailLine = verboseErr[:idx] } - firstDetailLine = redactedErrStr.StripMarkers() - fmt.Fprintf(&longMsgBuf, "%v\n--\n", firstDetailLine) } + fmt.Fprint(&longMsgBuf, verboseErr) // sep is used to separate the entries in the longMsgBuf / Message // payload. @@ -159,6 +167,7 @@ func BuildSentryReport(err error) (event *sentry.Event, extraDetails map[string] // layer. We iterate in this order because we want to describe the // error from innermost to outermost layer in longMsgBuf and // typesBuf. + longMsgBuf.WriteString("\n-- report composition:\n") for i := len(details) - 1; i >= 0; i-- { // Collect the type name for this layer of error wrapping, towards // the "error types" additional data field. @@ -204,10 +213,6 @@ func BuildSentryReport(err error) (event *sentry.Event, extraDetails map[string] // Now decide what kind of payload we want to add to the Event // object. - // genExtra will remember whether we are adding an - // additional payload or not. - var genExtra bool - // Is there a stack trace? if st := stacks[i]; st != nil { var excType strings.Builder @@ -245,17 +250,21 @@ func BuildSentryReport(err error) (event *sentry.Event, extraDetails map[string] exceptions = append(exceptions, exc) } else { // No stack trace. - // Are there safe details? If so, print them. + // Are there safe details? If so, print the first safe detail + // string (we're assuming that all the important bits will + // also be included in the verbose printout, so there's no + // need to dig out more safe strings here.) + // + // TODO(knz): the SafeDetails API is not really meant for Sentry + // reporting. Once we have more experience to prove that the + // verbose printout is sufficient, we can remove the SafeDetails + // from sentry reports. // // Note: we only print the details if no stack trace was found // at that level. This is because stack trace annotations also // produce the stack trace as safe detail string. - genExtra = len(details[i].SafeDetails) > 1 if len(details[i].SafeDetails) > 0 { d := details[i].SafeDetails[0] - if d != "" { - genExtra = true - } if j := strings.IndexByte(d, '\n'); j >= 0 { d = d[:j] } @@ -269,18 +278,6 @@ func BuildSentryReport(err error) (event *sentry.Event, extraDetails map[string] } } } - - // Are we generating another extra for the safe detail strings? - if genExtra { - stKey := fmt.Sprintf("%d: details", extraNum) - var extraStr bytes.Buffer - for _, d := range details[i].SafeDetails { - fmt.Fprintln(&extraStr, strings.ReplaceAll(d, "\n", "\n ")) - } - extras[stKey] = extraStr.String() - fmt.Fprintf(&longMsgBuf, " (%d)", extraNum) - extraNum++ - } } if extraNum > 1 { @@ -299,7 +296,7 @@ func BuildSentryReport(err error) (event *sentry.Event, extraDetails map[string] event.Message = longMsgBuf.String() event.Exception = exceptions - // If there is no exception payload, synthetize one. + // If there is no exception payload, synthesize one. if len(event.Exception) == 0 { // We know we don't have a stack trace to extract line/function // info from (if we had, we'd have an Exception payload at that @@ -354,7 +351,7 @@ func BuildSentryReport(err error) (event *sentry.Event, extraDetails map[string] return event, extras } -var redactedMarker = redact.RedactableString(redact.RedactedMarker()) +var redactedMarker = redact.RedactableString(redact.RedactedMarker()).StripMarkers() // ReportError reports the given error to Sentry. The caller is responsible for // checking whether telemetry is enabled, and calling the sentry.Flush() @@ -404,3 +401,13 @@ func reverseExceptionOrder(ex []sentry.Exception) { ex[i], ex[len(ex)-i-1] = ex[len(ex)-i-1], ex[i] } } + +func visitAllMulti(err error, f func(error)) { + f(err) + if e := errbase.UnwrapOnce(err); e != nil { + visitAllMulti(e, f) + } + for _, e := range errbase.UnwrapMulti(err) { + visitAllMulti(e, f) + } +} diff --git a/vendor/github.com/cockroachdb/errors/report/reportables.go b/vendor/github.com/cockroachdb/errors/report/reportables.go index 43060f03c..1795c05ac 100644 --- a/vendor/github.com/cockroachdb/errors/report/reportables.go +++ b/vendor/github.com/cockroachdb/errors/report/reportables.go @@ -18,7 +18,7 @@ import ( "bytes" "fmt" - "github.com/cockroachdb/sentry-go" + "github.com/getsentry/sentry-go" ) // StackTrace is an object suitable for inclusion in errors that can diff --git a/vendor/github.com/cockroachdb/errors/report_api.go b/vendor/github.com/cockroachdb/errors/report_api.go index c346990ff..1ac7e6763 100644 --- a/vendor/github.com/cockroachdb/errors/report_api.go +++ b/vendor/github.com/cockroachdb/errors/report_api.go @@ -16,7 +16,7 @@ package errors import ( "github.com/cockroachdb/errors/report" - "github.com/cockroachdb/sentry-go" + "github.com/getsentry/sentry-go" ) // BuildSentryReport builds the components of a sentry report. This @@ -32,7 +32,7 @@ import ( // Title: (1) some prefix in bold (2) one line for a stack trace // (3) a single-line subtitle // -// (4) the tags, as a tag soup (concatenated in a single paragrah, +// (4) the tags, as a tag soup (concatenated in a single paragraph, // unsorted) // // (5) a "message" @@ -57,7 +57,7 @@ import ( // (3) the Value field of the 1st Exception object, if any, unwrapped as a single line // (4) the Tags field // (5) the Message field -// (7) the Type field (same as (1) for 1st execption) +// (7) the Type field (same as (1) for 1st exception) // (8) the Value field (same as (3) for 1st exception) // (9) the Stacktrace field (input to (2) on 1st exception) // (10) the other fields on the Event object diff --git a/vendor/github.com/cockroachdb/errors/withstack/reportable.go b/vendor/github.com/cockroachdb/errors/withstack/reportable.go index 19577ae66..f3ff87e3d 100644 --- a/vendor/github.com/cockroachdb/errors/withstack/reportable.go +++ b/vendor/github.com/cockroachdb/errors/withstack/reportable.go @@ -23,7 +23,7 @@ import ( "strings" "github.com/cockroachdb/errors/errbase" - "github.com/cockroachdb/sentry-go" + "github.com/getsentry/sentry-go" pkgErr "github.com/pkg/errors" ) diff --git a/vendor/github.com/cockroachdb/logtags/buffer.go b/vendor/github.com/cockroachdb/logtags/buffer.go index 736a38d9c..1365a485c 100644 --- a/vendor/github.com/cockroachdb/logtags/buffer.go +++ b/vendor/github.com/cockroachdb/logtags/buffer.go @@ -38,6 +38,20 @@ func (b *Buffer) Get() []Tag { return b.tags } +// GetTag returns the tag corresponding to the given key. If the tag doesn't +// exist, the bool return value will be false. +func (b *Buffer) GetTag(key string) (Tag, bool) { + if b == nil { + return Tag{}, false + } + for _, t := range b.tags { + if t.Key() == key { + return t, true + } + } + return Tag{}, false +} + // Add returns a new buffer with one more tag. If the tag has the same key as an // earlier tag, that tag is overwritten. // The receiver can be nil. @@ -52,6 +66,25 @@ func (b *Buffer) Add(key string, value interface{}) *Buffer { return res } +// Remove returns a new Buffer with the tag with key `key` removed. If the tag +// does not exist, the receiver is returned (unchanged). The bool return value +// is true if the tag existed. +func (b *Buffer) Remove(key string) (*Buffer, bool) { + if b == nil { + return nil, false + } + for i, t := range b.tags { + if t.Key() == key { + res := &Buffer{} + res.init(len(b.tags)-1, 0 /* capacityHint */) + copy(res.tags, b.tags[:i]) + copy(res.tags[i:], b.tags[i+1:]) + return res, true + } + } + return b, false +} + // Merge returns a new buffer which contains tags from the receiver, followed by // the tags from . // @@ -67,7 +100,7 @@ func (b *Buffer) Merge(other *Buffer) *Buffer { if b == nil || len(b.tags) == 0 { return other } - if len(other.tags) == 0 { + if other == nil || len(other.tags) == 0 { return b } @@ -121,12 +154,12 @@ func (b *Buffer) String() string { } // FormatToString emits the k/v pairs to a strings.Builder. -// - the k/v pairs are separated by commas (& no spaces). -// - if there is no value, only the key is printed. -// - if there is a value, and the key is just 1 character long, -// the key and the value are concatenated. -// This supports e.g. printing k="n", v=123 as "n123". -// - otherwise, it prints "k=v". +// - the k/v pairs are separated by commas (& no spaces). +// - if there is no value, only the key is printed. +// - if there is a value, and the key is just 1 character long, +// the key and the value are concatenated. +// This supports e.g. printing k="n", v=123 as "n123". +// - otherwise, it prints "k=v". func (b *Buffer) FormatToString(buf *strings.Builder) { comma := "" for _, t := range b.Get() { @@ -142,13 +175,19 @@ func (b *Buffer) FormatToString(buf *strings.Builder) { } } -func (b *Buffer) init(length, maxLenHint int) { +// init initializes b.tags to a slice of len `length` (filled with zero values). +// The slice may have capacity capacityHint. If capacityHint is less than +// length, it is ignored. +func (b *Buffer) init(length, capacityHint int) { if length <= staticSlots { - // Even if maxLenHint is larger that staticSlots, we still want to try to + // Even if capacityHint is larger that staticSlots, we still want to try to // avoid the allocation (especially since tags frequently get deduplicated). b.tags = b.prealloc[:length] } else { - b.tags = make([]Tag, length, maxLenHint) + if capacityHint < length { + capacityHint = length + } + b.tags = make([]Tag, length, capacityHint) } } diff --git a/vendor/github.com/cockroachdb/logtags/context.go b/vendor/github.com/cockroachdb/logtags/context.go index 240be912f..61e20274c 100644 --- a/vendor/github.com/cockroachdb/logtags/context.go +++ b/vendor/github.com/cockroachdb/logtags/context.go @@ -41,6 +41,18 @@ func AddTag(ctx context.Context, key string, value interface{}) context.Context return WithTags(ctx, b.Add(key, value)) } +// RemoveTag returns a context that has the tags in the given context except the +// tag with key `key`. If such a tag does not exist, the given context is +// returned. +func RemoveTag(ctx context.Context, key string) context.Context { + b := FromContext(ctx) + newB, ok := b.Remove(key) + if !ok { + return ctx + } + return WithTags(ctx, newB) +} + // AddTags returns a context that has the tags in the given context plus another // set of tags. Tags are deduplicated (see Buffer.AddTags). func AddTags(ctx context.Context, tags *Buffer) context.Context { diff --git a/vendor/github.com/cockroachdb/pebble/.gitignore b/vendor/github.com/cockroachdb/pebble/.gitignore index 73c80d764..87ef192f3 100644 --- a/vendor/github.com/cockroachdb/pebble/.gitignore +++ b/vendor/github.com/cockroachdb/pebble/.gitignore @@ -1,6 +1,9 @@ +# Github action artifacts. +artifacts # Profiling artifacts. cpu.*.prof heap.prof mutex.prof +coverprofile.out # Testing artifacts meta.*.test diff --git a/vendor/github.com/cockroachdb/pebble/Makefile b/vendor/github.com/cockroachdb/pebble/Makefile index 5601e2799..e430ff269 100644 --- a/vendor/github.com/cockroachdb/pebble/Makefile +++ b/vendor/github.com/cockroachdb/pebble/Makefile @@ -4,7 +4,7 @@ GOFLAGS := STRESSFLAGS := TAGS := invariants TESTS := . -LATEST_RELEASE := $(shell git fetch origin && git branch -r --list '*/crl-release-*' | grep -o 'crl-release-.*$$' | sort | tail -1) +COVER_PROFILE := coverprofile.out .PHONY: all all: @@ -15,6 +15,7 @@ all: @echo " make stressrace" @echo " make stressmeta" @echo " make crossversion-meta" + @echo " make testcoverage" @echo " make mod-update" @echo " make generate" @echo " make generate-test-data" @@ -25,6 +26,10 @@ override testflags := test: ${GO} test -tags '$(TAGS)' ${testflags} -run ${TESTS} ${PKG} +.PHONY: testcoverage +testcoverage: + ${GO} test -tags '$(TAGS)' ${testflags} -run ${TESTS} ${PKG} -coverprofile ${COVER_PROFILE} + .PHONY: testrace testrace: testflags += -race -timeout 20m testrace: test @@ -57,6 +62,7 @@ stressmeta: stress .PHONY: crossversion-meta crossversion-meta: + $(eval LATEST_RELEASE := $(shell git fetch origin && git branch -r --list '*/crl-release-*' | grep -o 'crl-release-.*$$' | sort | tail -1)) git checkout ${LATEST_RELEASE}; \ ${GO} test -c ./internal/metamorphic -o './internal/metamorphic/crossversion/${LATEST_RELEASE}.test'; \ git checkout -; \ @@ -80,6 +86,7 @@ generate-test-data: ${GO} run -tags make_incorrect_manifests ./tool/make_incorrect_manifests.go ${GO} run -tags make_test_find_db ./tool/make_test_find_db.go ${GO} run -tags make_test_sstables ./tool/make_test_sstables.go + ${GO} run -tags make_test_remotecat ./tool/make_test_remotecat.go mod-update: ${GO} get -u diff --git a/vendor/github.com/cockroachdb/pebble/README.md b/vendor/github.com/cockroachdb/pebble/README.md index 12ccdb2ea..6b216379f 100644 --- a/vendor/github.com/cockroachdb/pebble/README.md +++ b/vendor/github.com/cockroachdb/pebble/README.md @@ -1,4 +1,4 @@ -# Pebble [![Build Status](https://github.com/cockroachdb/pebble/actions/workflows/ci.yaml/badge.svg?branch=master)](https://github.com/cockroachdb/pebble/actions/workflows/ci.yaml) [![GoDoc](https://godoc.org/github.com/cockroachdb/pebble?status.svg)](https://godoc.org/github.com/cockroachdb/pebble) +# Pebble [![Build Status](https://github.com/cockroachdb/pebble/actions/workflows/ci.yaml/badge.svg?branch=master)](https://github.com/cockroachdb/pebble/actions/workflows/ci.yaml) [![GoDoc](https://godoc.org/github.com/cockroachdb/pebble?status.svg)](https://godoc.org/github.com/cockroachdb/pebble) [Coverage](https://storage.googleapis.com/crl-codecover-public/pebble/index.html) #### [Nightly benchmarks](https://cockroachdb.github.io/pebble/) diff --git a/vendor/github.com/cockroachdb/pebble/batch.go b/vendor/github.com/cockroachdb/pebble/batch.go index ac991b811..9779309e8 100644 --- a/vendor/github.com/cockroachdb/pebble/batch.go +++ b/vendor/github.com/cockroachdb/pebble/batch.go @@ -183,6 +183,13 @@ func (d DeferredBatchOp) Finish() error { // WAL, and thus stable. New record kinds may be added, but the existing ones // will not be modified. type Batch struct { + batchInternal + applied atomic.Bool +} + +// batchInternal contains the set of fields within Batch that are non-atomic and +// capable of being reset using a *b = batchInternal{} struct copy. +type batchInternal struct { // Data is the wire format of a batch's log entry: // - 8 bytes for a sequence number of the first batch element, // or zeroes if the batch has not yet been applied, @@ -260,11 +267,6 @@ type Batch struct { // memtable. flushable *flushableBatch - // ingestedSSTBatch indicates that the batch contains one or more key kinds - // of InternalKeyKindIngestSST. If the batch contains key kinds of IngestSST - // then it will only contain key kinds of IngestSST. - ingestedSSTBatch bool - // minimumFormatMajorVersion indicates the format major version required in // order to commit this batch. If an operation requires a particular format // major version, it ratchets the batch's minimumFormatMajorVersion. When @@ -292,7 +294,22 @@ type Batch struct { commitStats BatchCommitStats commitErr error - applied atomic.Bool + + // Position bools together to reduce the sizeof the struct. + + // ingestedSSTBatch indicates that the batch contains one or more key kinds + // of InternalKeyKindIngestSST. If the batch contains key kinds of IngestSST + // then it will only contain key kinds of IngestSST. + ingestedSSTBatch bool + + // committing is set to true when a batch begins to commit. It's used to + // ensure the batch is not mutated concurrently. It is not an atomic + // deliberately, so as to avoid the overhead on batch mutations. This is + // okay, because under correct usage this field will never be accessed + // concurrently. It's only under incorrect usage the memory accesses of this + // variable may violate memory safety. Since we don't use atomics here, + // false negatives are possible. + committing bool } // BatchCommitStats exposes stats related to committing a batch. @@ -367,6 +384,14 @@ func newBatch(db *DB) *Batch { return b } +func newBatchWithSize(db *DB, size int) *Batch { + b := newBatch(db) + if cap(b.data) < size { + b.data = rawalloc.New(0, size) + } + return b +} + func newIndexedBatch(db *DB, comparer *Comparer) *Batch { i := indexedBatchPool.Get().(*indexedBatch) i.batch.cmp = comparer.Compare @@ -378,6 +403,14 @@ func newIndexedBatch(db *DB, comparer *Comparer) *Batch { return &i.batch } +func newIndexedBatchWithSize(db *DB, comparer *Comparer, size int) *Batch { + b := newIndexedBatch(db, comparer) + if cap(b.data) < size { + b.data = rawalloc.New(0, size) + } + return b +} + // nextSeqNum returns the batch "sequence number" that will be given to the next // key written to the batch. During iteration keys within an indexed batch are // given a sequence number consisting of their offset within the batch combined @@ -436,8 +469,8 @@ func (b *Batch) refreshMemTableSize() { case InternalKeyKindRangeKeySet, InternalKeyKindRangeKeyUnset, InternalKeyKindRangeKeyDelete: b.countRangeKeys++ case InternalKeyKindDeleteSized: - if b.minimumFormatMajorVersion < ExperimentalFormatDeleteSizedAndObsolete { - b.minimumFormatMajorVersion = ExperimentalFormatDeleteSizedAndObsolete + if b.minimumFormatMajorVersion < FormatDeleteSizedAndObsolete { + b.minimumFormatMajorVersion = FormatDeleteSizedAndObsolete } case InternalKeyKindIngestSST: if b.minimumFormatMajorVersion < FormatFlushableIngest { @@ -538,6 +571,9 @@ func (b *Batch) Get(key []byte) ([]byte, io.Closer, error) { } func (b *Batch) prepareDeferredKeyValueRecord(keyLen, valueLen int, kind InternalKeyKind) { + if b.committing { + panic("pebble: batch already committing") + } if len(b.data) == 0 { b.init(keyLen + valueLen + 2*binary.MaxVarintLen64 + batchHeaderLen) } @@ -587,6 +623,9 @@ func (b *Batch) prepareDeferredKeyValueRecord(keyLen, valueLen int, kind Interna } func (b *Batch) prepareDeferredKeyRecord(keyLen int, kind InternalKeyKind) { + if b.committing { + panic("pebble: batch already committing") + } if len(b.data) == 0 { b.init(keyLen + binary.MaxVarintLen64 + batchHeaderLen) } @@ -620,31 +659,38 @@ func (b *Batch) prepareDeferredKeyRecord(keyLen int, kind InternalKeyKind) { b.data = b.data[:pos+keyLen] } -// AddInternalKey allows the caller to add an internal key of point key kinds to -// a batch. Passing in an internal key of kind RangeKey* or RangeDelete will -// result in a panic. Note that the seqnum in the internal key is effectively -// ignored, even though the Kind is preserved. This is because the batch format -// does not allow for a per-key seqnum to be specified, only a batch-wide one. +// AddInternalKey allows the caller to add an internal key of point key or range +// key kinds (but not RangeDelete) to a batch. Passing in an internal key of +// kind RangeDelete will result in a panic. Note that the seqnum in the internal +// key is effectively ignored, even though the Kind is preserved. This is +// because the batch format does not allow for a per-key seqnum to be specified, +// only a batch-wide one. // // Note that non-indexed keys (IngestKeyKind{LogData,IngestSST}) are not // supported with this method as they require specialized logic. func (b *Batch) AddInternalKey(key *base.InternalKey, value []byte, _ *WriteOptions) error { keyLen := len(key.UserKey) hasValue := false - switch key.Kind() { - case InternalKeyKindRangeDelete, InternalKeyKindRangeKeySet, InternalKeyKindRangeKeyUnset, InternalKeyKindRangeKeyDelete: - panic("unexpected range delete or range key kind in AddInternalKey") + switch kind := key.Kind(); kind { + case InternalKeyKindRangeDelete: + panic("unexpected range delete in AddInternalKey") case InternalKeyKindSingleDelete, InternalKeyKindDelete: - b.prepareDeferredKeyRecord(len(key.UserKey), key.Kind()) + b.prepareDeferredKeyRecord(keyLen, kind) + b.deferredOp.index = b.index + case InternalKeyKindRangeKeySet, InternalKeyKindRangeKeyUnset, InternalKeyKindRangeKeyDelete: + b.prepareDeferredKeyValueRecord(keyLen, len(value), kind) + hasValue = true + b.incrementRangeKeysCount() default: - b.prepareDeferredKeyValueRecord(keyLen, len(value), key.Kind()) + b.prepareDeferredKeyValueRecord(keyLen, len(value), kind) hasValue = true + b.deferredOp.index = b.index } - b.deferredOp.index = b.index copy(b.deferredOp.Key, key.UserKey) if hasValue { copy(b.deferredOp.Value, value) } + // TODO(peter): Manually inline DeferredBatchOp.Finish(). Mid-stack inlining // in go1.13 will remove the need for this. if b.index != nil { @@ -768,8 +814,8 @@ func (b *Batch) DeleteSized(key []byte, deletedValueSize uint32, _ *WriteOptions // complete key slice, letting the caller encode into the DeferredBatchOp.Key // slice and then call Finish() on the returned object. func (b *Batch) DeleteSizedDeferred(keyLen int, deletedValueSize uint32) *DeferredBatchOp { - if b.minimumFormatMajorVersion < ExperimentalFormatDeleteSizedAndObsolete { - b.minimumFormatMajorVersion = ExperimentalFormatDeleteSizedAndObsolete + if b.minimumFormatMajorVersion < FormatDeleteSizedAndObsolete { + b.minimumFormatMajorVersion = FormatDeleteSizedAndObsolete } // Encode the sum of the key length and the value in the value. @@ -1071,17 +1117,30 @@ func (b *Batch) SetRepr(data []byte) error { // The returned Iterator observes all of the Batch's existing mutations, but no // later mutations. Its view can be refreshed via RefreshBatchSnapshot or // SetOptions(). -func (b *Batch) NewIter(o *IterOptions) *Iterator { +func (b *Batch) NewIter(o *IterOptions) (*Iterator, error) { return b.NewIterWithContext(context.Background(), o) } // NewIterWithContext is like NewIter, and additionally accepts a context for // tracing. -func (b *Batch) NewIterWithContext(ctx context.Context, o *IterOptions) *Iterator { +func (b *Batch) NewIterWithContext(ctx context.Context, o *IterOptions) (*Iterator, error) { + if b.index == nil { + return &Iterator{err: ErrNotIndexed}, nil + } + return b.db.newIter(ctx, b, newIterOpts{}, o), nil +} + +// NewBatchOnlyIter constructs an iterator that only reads the contents of the +// batch, and does not overlay the batch mutations on top of the DB state. +// +// The returned Iterator observes all of the Batch's existing mutations, but +// no later mutations. Its view can be refreshed via RefreshBatchSnapshot or +// SetOptions(). +func (b *Batch) NewBatchOnlyIter(ctx context.Context, o *IterOptions) (*Iterator, error) { if b.index == nil { - return &Iterator{err: ErrNotIndexed} + return &Iterator{err: ErrNotIndexed}, nil } - return b.db.newIter(ctx, b, nil /* snapshot */, o) + return b.db.newIter(ctx, b, newIterOpts{batch: batchIterOpts{batchOnly: true}}, o), nil } // newInternalIter creates a new internalIterator that iterates over the @@ -1294,39 +1353,37 @@ func (b *Batch) Indexed() bool { return b.index != nil } -func (b *Batch) init(cap int) { +// init ensures that the batch data slice is initialized to meet the +// minimum required size and allocates space for the batch header. +func (b *Batch) init(size int) { n := batchInitialSize - for n < cap { + for n < size { n *= 2 } - b.data = rawalloc.New(batchHeaderLen, n) - b.setCount(0) - b.setSeqNum(0) + if cap(b.data) < n { + b.data = rawalloc.New(batchHeaderLen, n) + } b.data = b.data[:batchHeaderLen] + clear(b.data) // Zero the sequence number in the header } // Reset resets the batch for reuse. The underlying byte slice (that is -// returned by Repr()) is not modified. It is only necessary to call this +// returned by Repr()) may not be modified. It is only necessary to call this // method if a batch is explicitly being reused. Close automatically takes are // of releasing resources when appropriate for batches that are internally // being reused. func (b *Batch) Reset() { - b.count = 0 - b.countRangeDels = 0 - b.countRangeKeys = 0 - b.memTableSize = 0 - b.deferredOp = DeferredBatchOp{} - b.tombstones = nil - b.tombstonesSeqNum = 0 - b.rangeKeys = nil - b.rangeKeysSeqNum = 0 - b.flushable = nil - b.commit = sync.WaitGroup{} - b.fsyncWait = sync.WaitGroup{} - b.commitStats = BatchCommitStats{} - b.commitErr = nil + // Zero out the struct, retaining only the fields necessary for manual + // reuse. + b.batchInternal = batchInternal{ + data: b.data, + cmp: b.cmp, + formatKey: b.formatKey, + abbreviatedKey: b.abbreviatedKey, + index: b.index, + db: b.db, + } b.applied.Store(false) - b.minimumFormatMajorVersion = 0 if b.data != nil { if cap(b.data) > batchMaxRetainedSize { // If the capacity of the buffer is larger than our maximum @@ -1337,13 +1394,11 @@ func (b *Batch) Reset() { } else { // Otherwise, reset the buffer for re-use. b.data = b.data[:batchHeaderLen] - b.setSeqNum(0) + clear(b.data) } } if b.index != nil { b.index.Init(&b.data, b.cmp, b.abbreviatedKey) - b.rangeDelIndex = nil - b.rangeKeyIndex = nil } } @@ -1654,6 +1709,8 @@ func (i *batchIter) SetBounds(lower, upper []byte) { i.iter.SetBounds(lower, upper) } +func (i *batchIter) SetContext(_ context.Context) {} + type flushableBatchEntry struct { // offset is the byte offset of the record within the batch repr. offset uint32 @@ -1845,6 +1902,7 @@ func (b *flushableBatch) Swap(i, j int) { b.offsets[i], b.offsets[j] = b.offsets[j], b.offsets[i] } +// newIter is part of the flushable interface. func (b *flushableBatch) newIter(o *IterOptions) internalIterator { return &flushableBatchIter{ batch: b, @@ -1857,6 +1915,7 @@ func (b *flushableBatch) newIter(o *IterOptions) internalIterator { } } +// newFlushIter is part of the flushable interface. func (b *flushableBatch) newFlushIter(o *IterOptions, bytesFlushed *uint64) internalIterator { return &flushFlushableBatchIter{ flushableBatchIter: flushableBatchIter{ @@ -1870,6 +1929,7 @@ func (b *flushableBatch) newFlushIter(o *IterOptions, bytesFlushed *uint64) inte } } +// newRangeDelIter is part of the flushable interface. func (b *flushableBatch) newRangeDelIter(o *IterOptions) keyspan.FragmentIterator { if len(b.tombstones) == 0 { return nil @@ -1877,6 +1937,7 @@ func (b *flushableBatch) newRangeDelIter(o *IterOptions) keyspan.FragmentIterato return keyspan.NewIter(b.cmp, b.tombstones) } +// newRangeKeyIter is part of the flushable interface. func (b *flushableBatch) newRangeKeyIter(o *IterOptions) keyspan.FragmentIterator { if len(b.rangeKeys) == 0 { return nil @@ -1884,17 +1945,23 @@ func (b *flushableBatch) newRangeKeyIter(o *IterOptions) keyspan.FragmentIterato return keyspan.NewIter(b.cmp, b.rangeKeys) } +// containsRangeKeys is part of the flushable interface. func (b *flushableBatch) containsRangeKeys() bool { return len(b.rangeKeys) > 0 } +// inuseBytes is part of the flushable interface. func (b *flushableBatch) inuseBytes() uint64 { return uint64(len(b.data) - batchHeaderLen) } +// totalBytes is part of the flushable interface. func (b *flushableBatch) totalBytes() uint64 { return uint64(cap(b.data)) } +// readyForFlush is part of the flushable interface. func (b *flushableBatch) readyForFlush() bool { + // A flushable batch is always ready for flush; it must be flushed together + // with the previous memtable. return true } @@ -2103,6 +2170,8 @@ func (i *flushableBatchIter) SetBounds(lower, upper []byte) { i.upper = upper } +func (i *flushableBatchIter) SetContext(_ context.Context) {} + // flushFlushableBatchIter is similar to flushableBatchIter but it keeps track // of number of bytes iterated. type flushFlushableBatchIter struct { diff --git a/vendor/github.com/cockroachdb/pebble/bloom/bloom.go b/vendor/github.com/cockroachdb/pebble/bloom/bloom.go index bf72e1de0..2aa51d7b3 100644 --- a/vendor/github.com/cockroachdb/pebble/bloom/bloom.go +++ b/vendor/github.com/cockroachdb/pebble/bloom/bloom.go @@ -62,9 +62,7 @@ func extend(b []byte, n int) (overall, trailer []byte) { if want <= cap(b) { overall = b[:want] trailer = overall[len(b):] - for i := range trailer { - trailer[i] = 0 - } + clear(trailer) } else { // Grow the capacity exponentially, with a 1KiB minimum. c := 1024 diff --git a/vendor/github.com/cockroachdb/pebble/checkpoint.go b/vendor/github.com/cockroachdb/pebble/checkpoint.go index 94c9e6f3f..f321c01ec 100644 --- a/vendor/github.com/cockroachdb/pebble/checkpoint.go +++ b/vendor/github.com/cockroachdb/pebble/checkpoint.go @@ -135,9 +135,6 @@ func mkdirAllAndSyncParents(fs vfs.FS, destDir string) (vfs.File, error) { // space overhead for a checkpoint if hard links are disabled. Also beware that // even if hard links are used, the space overhead for the checkpoint will // increase over time as the DB performs compactions. -// -// TODO(bananabrick): Test checkpointing of virtual sstables once virtual -// sstables is running e2e. func (d *DB) Checkpoint( destDir string, opts ...CheckpointOption, ) ( @@ -192,7 +189,7 @@ func (d *DB) Checkpoint( manifestSize := d.mu.versions.manifest.Size() optionsFileNum := d.optionsFileNum virtualBackingFiles := make(map[base.DiskFileNum]struct{}) - for diskFileNum := range d.mu.versions.fileBackingMap { + for diskFileNum := range d.mu.versions.backingState.fileBackingMap { virtualBackingFiles[diskFileNum] = struct{}{} } // Release the manifest and DB.mu so we don't block other operations on @@ -301,7 +298,7 @@ func (d *DB) Checkpoint( } ckErr = d.writeCheckpointManifest( - fs, formatVers, destDir, dir, manifestFileNum.DiskFileNum(), manifestSize, + fs, formatVers, destDir, dir, manifestFileNum, manifestSize, excludedFiles, removeBackingTables, ) if ckErr != nil { @@ -316,7 +313,7 @@ func (d *DB) Checkpoint( if logNum == 0 { continue } - srcPath := base.MakeFilepath(fs, d.walDirname, fileTypeLog, logNum.DiskFileNum()) + srcPath := base.MakeFilepath(fs, d.walDirname, fileTypeLog, logNum) destPath := fs.PathJoin(destDir, fs.PathBase(srcPath)) ckErr = vfs.Copy(fs, srcPath, destPath) if ckErr != nil { @@ -371,7 +368,7 @@ func (d *DB) writeCheckpointManifest( // need to append another record with the excluded files (we cannot simply // append a record after a raw data copy; see // https://github.com/cockroachdb/cockroach/issues/100935). - r := record.NewReader(&io.LimitedReader{R: src, N: manifestSize}, manifestFileNum.FileNum()) + r := record.NewReader(&io.LimitedReader{R: src, N: manifestSize}, manifestFileNum) w := record.NewWriter(dst) for { rr, err := r.Next() @@ -424,7 +421,7 @@ func (d *DB) writeCheckpointManifest( if err != nil { return err } - if err := setCurrentFunc(formatVers, manifestMarker, fs, destDirPath, destDir)(manifestFileNum.FileNum()); err != nil { + if err := setCurrentFunc(formatVers, manifestMarker, fs, destDirPath, destDir)(manifestFileNum); err != nil { return err } return manifestMarker.Close() diff --git a/vendor/github.com/cockroachdb/pebble/commit.go b/vendor/github.com/cockroachdb/pebble/commit.go index 8ba17a70f..38cdbb8f1 100644 --- a/vendor/github.com/cockroachdb/pebble/commit.go +++ b/vendor/github.com/cockroachdb/pebble/commit.go @@ -66,7 +66,7 @@ func (q *commitQueue) enqueue(b *Batch) { } slot := &q.slots[head&uint32(len(q.slots)-1)] - // Check if the head slot has been released by dequeue. + // Check if the head slot has been released by dequeueApplied. for slot.Load() != nil { // Another goroutine is still cleaning up the tail, so the queue is // actually still full. We spin because this should resolve itself @@ -77,12 +77,16 @@ func (q *commitQueue) enqueue(b *Batch) { // The head slot is free, so we own it. slot.Store(b) - // Increment head. This passes ownership of slot to dequeue and acts as a + // Increment head. This passes ownership of slot to dequeueApplied and acts as a // store barrier for writing the slot. q.headTail.Add(1 << dequeueBits) } -func (q *commitQueue) dequeue() *Batch { +// dequeueApplied removes the earliest enqueued Batch, if it is applied. +// +// Returns nil if the commit queue is empty or the earliest Batch is not yet +// applied. +func (q *commitQueue) dequeueApplied() *Batch { for { ptrs := q.headTail.Load() head, tail := q.unpack(ptrs) @@ -472,13 +476,13 @@ func (p *commitPipeline) publish(b *Batch) { // Loop dequeuing applied batches from the pending queue. If our batch was // the head of the pending queue we are guaranteed that either we'll publish - // it or someone else will dequeue and publish it. If our batch is not the - // head of the queue then either we'll dequeue applied batches and reach our + // it or someone else will dequeueApplied and publish it. If our batch is not the + // head of the queue then either we'll dequeueApplied applied batches and reach our // batch or there is an unapplied batch blocking us. When that unapplied // batch applies it will go through the same process and publish our batch // for us. for { - t := p.pending.dequeue() + t := p.pending.dequeueApplied() if t == nil { // Wait for another goroutine to publish us. We might also be waiting for // the WAL sync to finish. diff --git a/vendor/github.com/cockroachdb/pebble/compaction.go b/vendor/github.com/cockroachdb/pebble/compaction.go index 54b1ce4d4..574bb34ca 100644 --- a/vendor/github.com/cockroachdb/pebble/compaction.go +++ b/vendor/github.com/cockroachdb/pebble/compaction.go @@ -6,18 +6,21 @@ package pebble import ( "bytes" + "cmp" "context" "fmt" "io" "math" "runtime/pprof" + "slices" "sort" - "strings" "sync/atomic" "time" "github.com/cockroachdb/errors" "github.com/cockroachdb/pebble/internal/base" + "github.com/cockroachdb/pebble/internal/invalidating" + "github.com/cockroachdb/pebble/internal/invariants" "github.com/cockroachdb/pebble/internal/keyspan" "github.com/cockroachdb/pebble/internal/manifest" "github.com/cockroachdb/pebble/internal/private" @@ -25,13 +28,16 @@ import ( "github.com/cockroachdb/pebble/internal/rangekey" "github.com/cockroachdb/pebble/objstorage" "github.com/cockroachdb/pebble/objstorage/objstorageprovider/objiotracing" + "github.com/cockroachdb/pebble/objstorage/remote" "github.com/cockroachdb/pebble/sstable" "github.com/cockroachdb/pebble/vfs" ) var errEmptyTable = errors.New("pebble: empty table") -var errFlushInvariant = errors.New("pebble: flush next log number is unset") -var errCancelledCompaction = errors.New("pebble: compaction cancelled by a concurrent operation, will retry compaction") + +// ErrCancelledCompaction is returned if a compaction is cancelled by a +// concurrent excise or ingest-split operation. +var ErrCancelledCompaction = errors.New("pebble: compaction cancelled by a concurrent operation, will retry compaction") var compactLabels = pprof.Labels("pebble", "compact") var flushLabels = pprof.Labels("pebble", "flush") @@ -88,6 +94,10 @@ func (i noCloseIter) Close() error { type compactionLevel struct { level int files manifest.LevelSlice + // l0SublevelInfo contains information about L0 sublevels being compacted. + // It's only set for the start level of a compaction starting out of L0 and + // is nil for all other compactions. + l0SublevelInfo []sublevelInfo } func (cl compactionLevel) Clone() compactionLevel { @@ -297,7 +307,7 @@ func (f *fileSizeSplitter) shouldSplitBefore(key *InternalKey, tw *sstable.Write // NB: Subtract 1 from `boundariesObserved` to account for the current // boundary we're considering splitting at. `reached` will have // incremented it at the same time it set `atGrandparentBoundary`. - minimumPctOfTargetSize := 50 + 5*minUint64(f.boundariesObserved-1, 8) + minimumPctOfTargetSize := 50 + 5*min(f.boundariesObserved-1, 8) if estSize < (minimumPctOfTargetSize*f.targetFileSize)/100 { return noSplit } @@ -305,13 +315,6 @@ func (f *fileSizeSplitter) shouldSplitBefore(key *InternalKey, tw *sstable.Write } } -func minUint64(a, b uint64) uint64 { - if b < a { - a = b - } - return a -} - func (f *fileSizeSplitter) onNewOutput(key []byte) []byte { f.boundariesObserved = 0 return nil @@ -452,7 +455,12 @@ type compactionKind int const ( compactionKindDefault compactionKind = iota compactionKindFlush + // compactionKindMove denotes a move compaction where the input file is + // retained and linked in a new level without being obsoleted. compactionKindMove + // compactionKindCopy denotes a copy compaction where the input file is + // copied byte-by-byte into a new file with a new FileNum in the output level. + compactionKindCopy compactionKindDeleteOnly compactionKindElisionOnly compactionKindRead @@ -478,6 +486,8 @@ func (k compactionKind) String() string { return "rewrite" case compactionKindIngestedFlushable: return "ingested-flushable" + case compactionKindCopy: + return "copy" } return "?" } @@ -568,8 +578,6 @@ type compaction struct { versionEditApplied bool bufferPool sstable.BufferPool - score float64 - // startLevel is the level that is being compacted. Inputs from startLevel // and outputLevel will be merged to produce a set of outputLevel files. startLevel *compactionLevel @@ -640,10 +648,6 @@ type compaction struct { // L0Sublevels. If nil, flushes aren't split. l0Limits [][]byte - // L0 sublevel info is used for compactions out of L0. It is nil for all - // other compactions. - l0SublevelInfo []sublevelInfo - // List of disjoint inuse key ranges the compaction overlaps with in // grandparent and lower levels. See setupInuseKeyRanges() for the // construction. Used by elideTombstone() and elideRangeTombstone() to @@ -662,13 +666,16 @@ type compaction struct { allowedZeroSeqNum bool metrics map[int]*LevelMetrics + + pickerMetrics compactionPickerMetrics } func (c *compaction) makeInfo(jobID int) CompactionInfo { info := CompactionInfo{ - JobID: jobID, - Reason: c.kind.String(), - Input: make([]LevelInfo, 0, len(c.inputs)), + JobID: jobID, + Reason: c.kind.String(), + Input: make([]LevelInfo, 0, len(c.inputs)), + Annotations: []string{}, } for _, cl := range c.inputs { inputInfo := LevelInfo{Level: cl.level, Tables: nil} @@ -693,17 +700,27 @@ func (c *compaction) makeInfo(jobID int) CompactionInfo { // semantic distinction. info.Output.Level = numLevels - 1 } + + for i, score := range c.pickerMetrics.scores { + info.Input[i].Score = score + } + info.SingleLevelOverlappingRatio = c.pickerMetrics.singleLevelOverlappingRatio + info.MultiLevelOverlappingRatio = c.pickerMetrics.multiLevelOverlappingRatio + if len(info.Input) > 2 { + info.Annotations = append(info.Annotations, "multilevel") + } return info } -func newCompaction(pc *pickedCompaction, opts *Options, beganAt time.Time) *compaction { +func newCompaction( + pc *pickedCompaction, opts *Options, beganAt time.Time, provider objstorage.Provider, +) *compaction { c := &compaction{ kind: compactionKindDefault, cmp: pc.cmp, equal: opts.equal(), comparer: opts.Comparer, formatKey: opts.Comparer.FormatKey, - score: pc.score, inputs: pc.inputs, smallest: pc.smallest, largest: pc.largest, @@ -712,9 +729,12 @@ func newCompaction(pc *pickedCompaction, opts *Options, beganAt time.Time) *comp beganAt: beganAt, maxOutputFileSize: pc.maxOutputFileSize, maxOverlapBytes: pc.maxOverlapBytes, - l0SublevelInfo: pc.l0SublevelInfo, + pickerMetrics: pc.pickerMetrics, } c.startLevel = &c.inputs[0] + if pc.startLevel.l0SublevelInfo != nil { + c.startLevel.l0SublevelInfo = pc.startLevel.l0SublevelInfo + } c.outputLevel = &c.inputs[1] if len(pc.extraLevels) > 0 { @@ -728,15 +748,41 @@ func newCompaction(pc *pickedCompaction, opts *Options, beganAt time.Time) *comp c.smallest.UserKey, c.largest.UserKey, c.largest.IsExclusiveSentinel()) } c.setupInuseKeyRanges() - c.kind = pc.kind + if c.kind == compactionKindDefault && c.outputLevel.files.Empty() && !c.hasExtraLevelData() && c.startLevel.files.Len() == 1 && c.grandparents.SizeSum() <= c.maxOverlapBytes { - // This compaction can be converted into a trivial move from one level + // This compaction can be converted into a move or copy from one level // to the next. We avoid such a move if there is lots of overlapping // grandparent data. Otherwise, the move could create a parent file // that will require a very expensive merge later on. - c.kind = compactionKindMove + iter := c.startLevel.files.Iter() + meta := iter.First() + isRemote := false + // We should always be passed a provider, except in some unit tests. + if provider != nil { + objMeta, err := provider.Lookup(fileTypeTable, meta.FileBacking.DiskFileNum) + if err != nil { + panic(errors.Wrapf(err, "cannot lookup table %s in provider", meta.FileBacking.DiskFileNum)) + } + isRemote = objMeta.IsRemote() + } + // Avoid a trivial move or copy if all of these are true, as rewriting a + // new file is better: + // + // 1) The source file is a virtual sstable + // 2) The existing file `meta` is on non-remote storage + // 3) The output level prefers shared storage + mustCopy := !isRemote && remote.ShouldCreateShared(opts.Experimental.CreateOnShared, c.outputLevel.level) + if mustCopy { + // If the source is virtual, it's best to just rewrite the file as all + // conditions in the above comment are met. + if !meta.Virtual { + c.kind = compactionKindCopy + } + } else { + c.kind = compactionKindMove + } } return c } @@ -1230,92 +1276,60 @@ func (c *compaction) elideRangeKey(start, end []byte) bool { func (c *compaction) newInputIter( newIters tableNewIters, newRangeKeyIter keyspan.TableNewSpanIter, snapshots []uint64, ) (_ internalIterator, retErr error) { - var rangeDelIters []keyspan.FragmentIterator - var rangeKeyIters []keyspan.FragmentIterator - - if len(c.flushing) != 0 { - if len(c.flushing) == 1 { - f := c.flushing[0] - iter := f.newFlushIter(nil, &c.bytesIterated) - if rangeDelIter := f.newRangeDelIter(nil); rangeDelIter != nil { - c.rangeDelIter.Init(c.cmp, rangeDelIter) - iter = newMergingIter(c.logger, &c.stats, c.cmp, nil, iter, &c.rangeDelIter) - } - if rangeKeyIter := f.newRangeKeyIter(nil); rangeKeyIter != nil { - mi := &keyspan.MergingIter{} - mi.Init(c.cmp, rangeKeyCompactionTransform(c.equal, snapshots, c.elideRangeKey), new(keyspan.MergingBuffers), rangeKeyIter) - c.rangeKeyInterleaving.Init(c.comparer, iter, mi, nil /* hooks */, nil /* lowerBound */, nil /* upperBound */) - iter = &c.rangeKeyInterleaving - } - return iter, nil - } - iters := make([]internalIterator, 0, len(c.flushing)+1) - rangeDelIters = make([]keyspan.FragmentIterator, 0, len(c.flushing)) - rangeKeyIters = make([]keyspan.FragmentIterator, 0, len(c.flushing)) - for i := range c.flushing { - f := c.flushing[i] - iters = append(iters, f.newFlushIter(nil, &c.bytesIterated)) - rangeDelIter := f.newRangeDelIter(nil) - if rangeDelIter != nil { - rangeDelIters = append(rangeDelIters, rangeDelIter) - } - if rangeKeyIter := f.newRangeKeyIter(nil); rangeKeyIter != nil { - rangeKeyIters = append(rangeKeyIters, rangeKeyIter) + // Validate the ordering of compaction input files for defense in depth. + if len(c.flushing) == 0 { + if c.startLevel.level >= 0 { + err := manifest.CheckOrdering(c.cmp, c.formatKey, + manifest.Level(c.startLevel.level), c.startLevel.files.Iter()) + if err != nil { + return nil, err } } - if len(rangeDelIters) > 0 { - c.rangeDelIter.Init(c.cmp, rangeDelIters...) - iters = append(iters, &c.rangeDelIter) - } - var iter internalIterator = newMergingIter(c.logger, &c.stats, c.cmp, nil, iters...) - if len(rangeKeyIters) > 0 { - mi := &keyspan.MergingIter{} - mi.Init(c.cmp, rangeKeyCompactionTransform(c.equal, snapshots, c.elideRangeKey), new(keyspan.MergingBuffers), rangeKeyIters...) - c.rangeKeyInterleaving.Init(c.comparer, iter, mi, nil /* hooks */, nil /* lowerBound */, nil /* upperBound */) - iter = &c.rangeKeyInterleaving - } - return iter, nil - } - - if c.startLevel.level >= 0 { err := manifest.CheckOrdering(c.cmp, c.formatKey, - manifest.Level(c.startLevel.level), c.startLevel.files.Iter()) + manifest.Level(c.outputLevel.level), c.outputLevel.files.Iter()) if err != nil { return nil, err } - } - err := manifest.CheckOrdering(c.cmp, c.formatKey, - manifest.Level(c.outputLevel.level), c.outputLevel.files.Iter()) - if err != nil { - return nil, err - } - - if c.startLevel.level == 0 { - if c.l0SublevelInfo == nil { - panic("l0SublevelInfo not created for compaction out of L0") + if c.startLevel.level == 0 { + if c.startLevel.l0SublevelInfo == nil { + panic("l0SublevelInfo not created for compaction out of L0") + } + for _, info := range c.startLevel.l0SublevelInfo { + err := manifest.CheckOrdering(c.cmp, c.formatKey, + info.sublevel, info.Iter()) + if err != nil { + return nil, err + } + } } - - for _, info := range c.l0SublevelInfo { + if len(c.extraLevels) > 0 { + if len(c.extraLevels) > 1 { + panic("n>2 multi level compaction not implemented yet") + } + interLevel := c.extraLevels[0] err := manifest.CheckOrdering(c.cmp, c.formatKey, - info.sublevel, info.Iter()) + manifest.Level(interLevel.level), interLevel.files.Iter()) if err != nil { return nil, err } } } - if len(c.extraLevels) > 0 { - if len(c.extraLevels) > 1 { - panic("n>2 multi level compaction not implemented yet") - } - interLevel := c.extraLevels[0] - err := manifest.CheckOrdering(c.cmp, c.formatKey, - manifest.Level(interLevel.level), interLevel.files.Iter()) - if err != nil { - return nil, err - } - } - iters := make([]internalIterator, 0, len(c.inputs)*c.startLevel.files.Len()+1) + // There are three classes of keys that a compaction needs to process: point + // keys, range deletion tombstones and range keys. Collect all iterators for + // all these classes of keys from all the levels. We'll aggregate them + // together farther below. + // + // numInputLevels is an approximation of the number of iterator levels. Due + // to idiosyncrasies in iterator construction, we may (rarely) exceed this + // initial capacity. + numInputLevels := max(len(c.flushing), len(c.inputs)) + iters := make([]internalIterator, 0, numInputLevels) + rangeDelIters := make([]keyspan.FragmentIterator, 0, numInputLevels) + rangeKeyIters := make([]keyspan.FragmentIterator, 0, numInputLevels) + + // If construction of the iterator inputs fails, ensure that we close all + // the consitutent iterators. defer func() { if retErr != nil { for _, iter := range iters { @@ -1328,175 +1342,110 @@ func (c *compaction) newInputIter( } } }() + iterOpts := IterOptions{ + CategoryAndQoS: sstable.CategoryAndQoS{ + Category: "pebble-compaction", + QoSLevel: sstable.NonLatencySensitiveQoSLevel, + }, + logger: c.logger, + } - // In normal operation, levelIter iterates over the point operations in a - // level, and initializes a rangeDelIter pointer for the range deletions in - // each table. During compaction, we want to iterate over the merged view of - // point operations and range deletions. In order to do this we create one - // levelIter per level to iterate over the point operations, and collect up - // all the range deletion files. - // - // The range deletion levels are first combined with a keyspan.MergingIter - // (currently wrapped by a keyspan.InternalIteratorShim to satisfy the - // internal iterator interface). The resulting merged rangedel iterator is - // then included with the point levels in a single mergingIter. - newRangeDelIter := func( - f manifest.LevelFile, _ *IterOptions, l manifest.Level, bytesIterated *uint64, - ) (keyspan.FragmentIterator, error) { - iter, rangeDelIter, err := newIters(context.Background(), f.FileMetadata, - &IterOptions{level: l}, internalIterOpts{ - bytesIterated: &c.bytesIterated, - bufferPool: &c.bufferPool, - }) - if err == nil { - // TODO(peter): It is mildly wasteful to open the point iterator only to - // immediately close it. One way to solve this would be to add new - // methods to tableCache for creating point and range-deletion iterators - // independently. We'd only want to use those methods here, - // though. Doesn't seem worth the hassle in the near term. - if err = iter.Close(); err != nil { - rangeDelIter.Close() - rangeDelIter = nil + // Populate iters, rangeDelIters and rangeKeyIters with the appropriate + // constituent iterators. This depends on whether this is a flush or a + // compaction. + if len(c.flushing) != 0 { + // If flushing, we need to build the input iterators over the memtables + // stored in c.flushing. + for i := range c.flushing { + f := c.flushing[i] + iters = append(iters, f.newFlushIter(nil, &c.bytesIterated)) + rangeDelIter := f.newRangeDelIter(nil) + if rangeDelIter != nil { + rangeDelIters = append(rangeDelIters, rangeDelIter) + } + if rangeKeyIter := f.newRangeKeyIter(nil); rangeKeyIter != nil { + rangeKeyIters = append(rangeKeyIters, rangeKeyIter) } } - if rangeDelIter != nil { - // Ensure that rangeDelIter is not closed until the compaction is - // finished. This is necessary because range tombstone processing - // requires the range tombstones to be held in memory for up to the - // lifetime of the compaction. - c.closers = append(c.closers, rangeDelIter) - rangeDelIter = noCloseIter{rangeDelIter} - - // Truncate the range tombstones returned by the iterator to the - // upper bound of the atomic compaction unit of the file. We want to - // truncate the range tombstone to the bounds of the file, but files - // with split user keys pose an obstacle: The file's largest bound - // is inclusive whereas the range tombstone's end is exclusive. - // - // Consider the example: + } else { + addItersForLevel := func(level *compactionLevel, l manifest.Level) error { + // Add a *levelIter for point iterators. Because we don't call + // initRangeDel, the levelIter will close and forget the range + // deletion iterator when it steps on to a new file. Surfacing range + // deletions to compactions are handled below. + iters = append(iters, newLevelIter(context.Background(), + iterOpts, c.comparer, newIters, level.files.Iter(), l, internalIterOpts{ + bytesIterated: &c.bytesIterated, + bufferPool: &c.bufferPool, + })) + // TODO(jackson): Use keyspan.LevelIter to avoid loading all the range + // deletions into memory upfront. (See #2015, which reverted this.) + // There will be no user keys that are split between sstables + // within a level in Cockroach 23.1, which unblocks this optimization. + + // Add the range deletion iterator for each file as an independent level + // in mergingIter, as opposed to making a levelIter out of those. This + // is safer as levelIter expects all keys coming from underlying + // iterators to be in order. Due to compaction / tombstone writing + // logic in finishOutput(), it is possible for range tombstones to not + // be strictly ordered across all files in one level. // - // 000001:[b-f#200] range del [c,k) - // 000002:[f#190-g#inf] range del [c,k) - // 000003:[g#500-i#3] + // Consider this example from the metamorphic tests (also repeated in + // finishOutput()), consisting of three L3 files with their bounds + // specified in square brackets next to the file name: // - // Files 000001 and 000002 contain the untruncated range tombstones - // [c,k). While the keyspace covered by 000003 was at one point - // deleted by the tombstone [c,k), the tombstone may have already - // been compacted away and the file does not contain an untruncated - // range tombstone. We want to bound 000001's tombstone to the file - // bounds, but it's not possible to encode a range tombstone with an - // end boundary within a user key (eg, between sequence numbers - // f#200 and f#190). Instead, we expand 000001 to its atomic - // compaction unit (000001 and 000002) and truncate the tombstone to - // g#inf. + // ./000240.sst [tmgc#391,MERGE-tmgc#391,MERGE] + // tmgc#391,MERGE [786e627a] + // tmgc-udkatvs#331,RANGEDEL // - // NB: We must not use the atomic compaction unit of the entire - // compaction, because the [c,k) tombstone contained in the file - // 000001 ≥ g. If 000001, 000002 and 000003 are all included in the - // same compaction, the compaction's atomic compaction unit includes - // 000003. However 000003's keys must not be covered by 000001's - // untruncated range tombstone. + // ./000241.sst [tmgc#384,MERGE-tmgc#384,MERGE] + // tmgc#384,MERGE [666c7070] + // tmgc-tvsalezade#383,RANGEDEL + // tmgc-tvsalezade#331,RANGEDEL // - // Note that we need do this truncation at read time in order to - // handle sstables generated by RocksDB and earlier versions of - // Pebble which do not truncate range tombstones to atomic - // compaction unit boundaries at write time. + // ./000242.sst [tmgc#383,RANGEDEL-tvsalezade#72057594037927935,RANGEDEL] + // tmgc-tvsalezade#383,RANGEDEL + // tmgc#375,SET [72646c78766965616c72776865676e79] + // tmgc-tvsalezade#356,RANGEDEL // - // The current Pebble compaction logic DOES truncate tombstones to - // atomic unit boundaries at compaction time too. - atomicUnit, _ := expandToAtomicUnit(c.cmp, f.Slice(), true /* disableIsCompacting */) - lowerBound, upperBound := manifest.KeyRange(c.cmp, atomicUnit.Iter()) - // Range deletion tombstones are often written to sstables - // untruncated on the end key side. However, they are still only - // valid within a given file's bounds. The logic for writing range - // tombstones to an output file sometimes has an incomplete view - // of range tombstones outside the file's internal key bounds. Skip - // any range tombstones completely outside file bounds. - rangeDelIter = keyspan.Truncate( - c.cmp, rangeDelIter, lowerBound.UserKey, upperBound.UserKey, - &f.Smallest, &f.Largest, false, /* panicOnUpperTruncate */ - ) - } - if rangeDelIter == nil { - rangeDelIter = emptyKeyspanIter - } - return rangeDelIter, err - } - - iterOpts := IterOptions{logger: c.logger} - // TODO(bananabrick): Get rid of the extra manifest.Level parameter and fold it into - // compactionLevel. - // - // TODO(bilal): when we start using strict obsolete sstables for L5 and L6 - // in disaggregated storage, and rely on the obsolete bit, we will also need - // to configure the levelIter at these levels to hide the obsolete points. - addItersForLevel := func(level *compactionLevel, l manifest.Level) error { - iters = append(iters, newLevelIter(iterOpts, c.cmp, nil /* split */, newIters, - level.files.Iter(), l, internalIterOpts{ - bytesIterated: &c.bytesIterated, - bufferPool: &c.bufferPool, - })) - // TODO(jackson): Use keyspan.LevelIter to avoid loading all the range - // deletions into memory upfront. (See #2015, which reverted this.) - // There will be no user keys that are split between sstables - // within a level in Cockroach 23.1, which unblocks this optimization. - - // Add the range deletion iterator for each file as an independent level - // in mergingIter, as opposed to making a levelIter out of those. This - // is safer as levelIter expects all keys coming from underlying - // iterators to be in order. Due to compaction / tombstone writing - // logic in finishOutput(), it is possible for range tombstones to not - // be strictly ordered across all files in one level. - // - // Consider this example from the metamorphic tests (also repeated in - // finishOutput()), consisting of three L3 files with their bounds - // specified in square brackets next to the file name: - // - // ./000240.sst [tmgc#391,MERGE-tmgc#391,MERGE] - // tmgc#391,MERGE [786e627a] - // tmgc-udkatvs#331,RANGEDEL - // - // ./000241.sst [tmgc#384,MERGE-tmgc#384,MERGE] - // tmgc#384,MERGE [666c7070] - // tmgc-tvsalezade#383,RANGEDEL - // tmgc-tvsalezade#331,RANGEDEL - // - // ./000242.sst [tmgc#383,RANGEDEL-tvsalezade#72057594037927935,RANGEDEL] - // tmgc-tvsalezade#383,RANGEDEL - // tmgc#375,SET [72646c78766965616c72776865676e79] - // tmgc-tvsalezade#356,RANGEDEL - // - // Here, the range tombstone in 000240.sst falls "after" one in - // 000241.sst, despite 000240.sst being ordered "before" 000241.sst for - // levelIter's purposes. While each file is still consistent before its - // bounds, it's safer to have all rangedel iterators be visible to - // mergingIter. - iter := level.files.Iter() - for f := iter.First(); f != nil; f = iter.Next() { - rangeDelIter, err := newRangeDelIter(iter.Take(), nil, l, &c.bytesIterated) - if err != nil { - // The error will already be annotated with the BackingFileNum, so - // we annotate it with the FileNum. - return errors.Wrapf(err, "pebble: could not open table %s", errors.Safe(f.FileNum)) - } - if rangeDelIter != emptyKeyspanIter { + // Here, the range tombstone in 000240.sst falls "after" one in + // 000241.sst, despite 000240.sst being ordered "before" 000241.sst for + // levelIter's purposes. While each file is still consistent before its + // bounds, it's safer to have all rangedel iterators be visible to + // mergingIter. + iter := level.files.Iter() + for f := iter.First(); f != nil; f = iter.Next() { + rangeDelIter, closer, err := c.newRangeDelIter( + newIters, iter.Take(), iterOpts, l, &c.bytesIterated) + if err != nil { + // The error will already be annotated with the BackingFileNum, so + // we annotate it with the FileNum. + return errors.Wrapf(err, "pebble: could not open table %s", errors.Safe(f.FileNum)) + } + if rangeDelIter == nil { + continue + } rangeDelIters = append(rangeDelIters, rangeDelIter) + c.closers = append(c.closers, closer) } - } - // Check if this level has any range keys. - hasRangeKeys := false - for f := iter.First(); f != nil; f = iter.Next() { - if f.HasRangeKeys { - hasRangeKeys = true - break + // Check if this level has any range keys. + hasRangeKeys := false + for f := iter.First(); f != nil; f = iter.Next() { + if f.HasRangeKeys { + hasRangeKeys = true + break + } } - } - if hasRangeKeys { - li := &keyspan.LevelIter{} - newRangeKeyIterWrapper := func(file *manifest.FileMetadata, iterOptions keyspan.SpanIterOptions) (keyspan.FragmentIterator, error) { - iter, err := newRangeKeyIter(file, iterOptions) - if iter != nil { + if hasRangeKeys { + li := &keyspan.LevelIter{} + newRangeKeyIterWrapper := func(file *manifest.FileMetadata, iterOptions keyspan.SpanIterOptions) (keyspan.FragmentIterator, error) { + iter, err := newRangeKeyIter(file, iterOptions) + if err != nil { + return nil, err + } else if iter == nil { + return emptyKeyspanIter, nil + } // Ensure that the range key iter is not closed until the compaction is // finished. This is necessary because range key processing // requires the range keys to be held in memory for up to the @@ -1509,39 +1458,46 @@ func (c *compaction) newInputIter( // range tombstones. This is because range keys were added after we // stopped splitting user keys across sstables, so all the range keys // in this sstable must wholly lie within the file's bounds. + return iter, err } - if iter == nil { - iter = emptyKeyspanIter - } - return iter, err + li.Init(keyspan.SpanIterOptions{}, c.cmp, newRangeKeyIterWrapper, level.files.Iter(), l, manifest.KeyTypeRange) + rangeKeyIters = append(rangeKeyIters, li) } - li.Init(keyspan.SpanIterOptions{Level: l}, c.cmp, newRangeKeyIterWrapper, level.files.Iter(), l, manifest.KeyTypeRange) - rangeKeyIters = append(rangeKeyIters, li) + return nil } - return nil - } - if c.startLevel.level != 0 { - if err = addItersForLevel(c.startLevel, manifest.Level(c.startLevel.level)); err != nil { - return nil, err - } - } else { - for _, info := range c.l0SublevelInfo { - if err = addItersForLevel( - &compactionLevel{0, info.LevelSlice}, info.sublevel); err != nil { + for i := range c.inputs { + // If the level is annotated with l0SublevelInfo, expand it into one + // level per sublevel. + // TODO(jackson): Perform this expansion even earlier when we pick the + // compaction? + if len(c.inputs[i].l0SublevelInfo) > 0 { + for _, info := range c.startLevel.l0SublevelInfo { + sublevelCompactionLevel := &compactionLevel{0, info.LevelSlice, nil} + if err := addItersForLevel(sublevelCompactionLevel, info.sublevel); err != nil { + return nil, err + } + } + continue + } + if err := addItersForLevel(&c.inputs[i], manifest.Level(c.inputs[i].level)); err != nil { return nil, err } } } - if len(c.extraLevels) > 0 { - if err = addItersForLevel(c.extraLevels[0], manifest.Level(c.extraLevels[0].level)); err != nil { - return nil, err - } - } - if err = addItersForLevel(c.outputLevel, manifest.Level(c.outputLevel.level)); err != nil { - return nil, err - } + // In normal operation, levelIter iterates over the point operations in a + // level, and initializes a rangeDelIter pointer for the range deletions in + // each table. During compaction, we want to iterate over the merged view of + // point operations and range deletions. In order to do this we create one + // levelIter per level to iterate over the point operations, and collect up + // all the range deletion files. + // + // The range deletion levels are first combined with a keyspan.MergingIter + // (currently wrapped by a keyspan.InternalIteratorShim to satisfy the + // internal iterator interface). The resulting merged rangedel iterator is + // then included with the point levels in a single mergingIter. + // // Combine all the rangedel iterators using a keyspan.MergingIterator and a // InternalIteratorShim so that the range deletions may be interleaved in // the compaction input. @@ -1551,17 +1507,117 @@ func (c *compaction) newInputIter( c.rangeDelIter.Init(c.cmp, rangeDelIters...) iters = append(iters, &c.rangeDelIter) } - pointKeyIter := newMergingIter(c.logger, &c.stats, c.cmp, nil, iters...) + + // If there's only one constituent point iterator, we can avoid the overhead + // of a *mergingIter. This is possible, for example, when performing a flush + // of a single memtable. Otherwise, combine all the iterators into a merging + // iter. + iter := iters[0] + if len(iters) > 0 { + iter = newMergingIter(c.logger, &c.stats, c.cmp, nil, iters...) + } + // If there are range key iterators, we need to combine them using + // keyspan.MergingIter, and then interleave them among the points. if len(rangeKeyIters) > 0 { mi := &keyspan.MergingIter{} mi.Init(c.cmp, rangeKeyCompactionTransform(c.equal, snapshots, c.elideRangeKey), new(keyspan.MergingBuffers), rangeKeyIters...) di := &keyspan.DefragmentingIter{} di.Init(c.comparer, mi, keyspan.DefragmentInternal, keyspan.StaticDefragmentReducer, new(keyspan.DefragmentingBuffers)) - c.rangeKeyInterleaving.Init(c.comparer, pointKeyIter, di, nil /* hooks */, nil /* lowerBound */, nil /* upperBound */) - return &c.rangeKeyInterleaving, nil + c.rangeKeyInterleaving.Init(c.comparer, iter, di, keyspan.InterleavingIterOpts{}) + iter = &c.rangeKeyInterleaving + } + return iter, nil +} + +func (c *compaction) newRangeDelIter( + newIters tableNewIters, + f manifest.LevelFile, + opts IterOptions, + l manifest.Level, + bytesIterated *uint64, +) (keyspan.FragmentIterator, io.Closer, error) { + opts.level = l + iter, rangeDelIter, err := newIters(context.Background(), f.FileMetadata, + &opts, internalIterOpts{ + bytesIterated: &c.bytesIterated, + bufferPool: &c.bufferPool, + }) + if err != nil { + return nil, nil, err + } + // TODO(peter): It is mildly wasteful to open the point iterator only to + // immediately close it. One way to solve this would be to add new + // methods to tableCache for creating point and range-deletion iterators + // independently. We'd only want to use those methods here, + // though. Doesn't seem worth the hassle in the near term. + if err = iter.Close(); err != nil { + if rangeDelIter != nil { + err = errors.CombineErrors(err, rangeDelIter.Close()) + } + return nil, nil, err + } + if rangeDelIter == nil { + // The file doesn't contain any range deletions. + return nil, nil, nil } - return pointKeyIter, nil + // Ensure that rangeDelIter is not closed until the compaction is + // finished. This is necessary because range tombstone processing + // requires the range tombstones to be held in memory for up to the + // lifetime of the compaction. + closer := rangeDelIter + rangeDelIter = noCloseIter{rangeDelIter} + + // Truncate the range tombstones returned by the iterator to the + // upper bound of the atomic compaction unit of the file. We want to + // truncate the range tombstone to the bounds of the file, but files + // with split user keys pose an obstacle: The file's largest bound + // is inclusive whereas the range tombstone's end is exclusive. + // + // Consider the example: + // + // 000001:[b-f#200] range del [c,k) + // 000002:[f#190-g#inf] range del [c,k) + // 000003:[g#500-i#3] + // + // Files 000001 and 000002 contain the untruncated range tombstones + // [c,k). While the keyspace covered by 000003 was at one point + // deleted by the tombstone [c,k), the tombstone may have already + // been compacted away and the file does not contain an untruncated + // range tombstone. We want to bound 000001's tombstone to the file + // bounds, but it's not possible to encode a range tombstone with an + // end boundary within a user key (eg, between sequence numbers + // f#200 and f#190). Instead, we expand 000001 to its atomic + // compaction unit (000001 and 000002) and truncate the tombstone to + // g#inf. + // + // NB: We must not use the atomic compaction unit of the entire + // compaction, because the [c,k) tombstone contained in the file + // 000001 ≥ g. If 000001, 000002 and 000003 are all included in the + // same compaction, the compaction's atomic compaction unit includes + // 000003. However 000003's keys must not be covered by 000001's + // untruncated range tombstone. + // + // Note that we need do this truncation at read time in order to + // handle sstables generated by RocksDB and earlier versions of + // Pebble which do not truncate range tombstones to atomic + // compaction unit boundaries at write time. + // + // The current Pebble compaction logic DOES truncate tombstones to + // atomic unit boundaries at compaction time too. + atomicUnit, _ := expandToAtomicUnit(c.cmp, f.Slice(), true /* disableIsCompacting */) + lowerBound, upperBound := manifest.KeyRange(c.cmp, atomicUnit.Iter()) + // Range deletion tombstones are often written to sstables + // untruncated on the end key side. However, they are still only + // valid within a given file's bounds. The logic for writing range + // tombstones to an output file sometimes has an incomplete view + // of range tombstones outside the file's internal key bounds. Skip + // any range tombstones completely outside file bounds. + rangeDelIter = keyspan.Truncate( + c.cmp, rangeDelIter, lowerBound.UserKey, upperBound.UserKey, + &f.Smallest, &f.Largest, false, /* panicOnUpperTruncate */ + ) + return rangeDelIter, closer, nil } func (c *compaction) String() string { @@ -1636,39 +1692,15 @@ func (d *DB) addInProgressCompaction(c *compaction) { d.opts.Logger.Fatalf("could not update state for compaction: %s", err) } } - - if false { - // TODO(peter): Do we want to keep this? It is useful for seeing the - // concurrent compactions/flushes that are taking place. Right now, this - // spams the logs and output to tests. Figure out a way to useful expose - // it. - strs := make([]string, 0, len(d.mu.compact.inProgress)) - for c := range d.mu.compact.inProgress { - var s string - if c.startLevel.level == -1 { - s = fmt.Sprintf("mem->L%d", c.outputLevel.level) - } else { - s = fmt.Sprintf("L%d->L%d:%.1f", c.startLevel.level, c.outputLevel.level, c.score) - } - strs = append(strs, s) - } - // This odd sorting function is intended to sort "mem" before "L*". - sort.Slice(strs, func(i, j int) bool { - if strs[i][0] == strs[j][0] { - return strs[i] < strs[j] - } - return strs[i] > strs[j] - }) - d.opts.Logger.Infof("compactions: %s", strings.Join(strs, " ")) - } } // Removes compaction markers from files in a compaction. The rollback parameter // indicates whether the compaction state should be rolled back to its original // state in the case of an unsuccessful compaction. // -// DB.mu must be held when calling this method. All writes to the manifest for -// this compaction should have completed by this point. +// DB.mu must be held when calling this method, however this method can drop and +// re-acquire that mutex. All writes to the manifest for this compaction should +// have completed by this point. func (d *DB) clearCompactingState(c *compaction, rollback bool) { c.versionEditApplied = true for _, cl := range c.inputs { @@ -1695,7 +1727,17 @@ func (d *DB) clearCompactingState(c *compaction, rollback bool) { } } l0InProgress := inProgressL0Compactions(d.getInProgressCompactionInfoLocked(c)) - d.mu.versions.currentVersion().L0Sublevels.InitCompactingFileInfo(l0InProgress) + func() { + // InitCompactingFileInfo requires that no other manifest writes be + // happening in parallel with it, i.e. we're not in the midst of installing + // another version. Otherwise, it's possible that we've created another + // L0Sublevels instance, but not added it to the versions list, causing + // all the indices in FileMetadata to be inaccurate. To ensure this, + // grab the manifest lock. + d.mu.versions.logLock() + defer d.mu.versions.logUnlock() + d.mu.versions.currentVersion().L0Sublevels.InitCompactingFileInfo(l0InProgress) + }() } func (d *DB) calculateDiskAvailableBytes() uint64 { @@ -1708,10 +1750,6 @@ func (d *DB) calculateDiskAvailableBytes() uint64 { return d.diskAvailBytes.Load() } -func (d *DB) getDiskAvailableBytesCached() uint64 { - return d.diskAvailBytes.Load() -} - func (d *DB) getDeletionPacerInfo() deletionPacerInfo { var pacerInfo deletionPacerInfo // Call GetDiskUsage after every file deletion. This may seem inefficient, @@ -1763,7 +1801,7 @@ func (d *DB) passedFlushThreshold() bool { if d.mu.mem.queue[n].flushForced { // A flush was forced. Pretend the memtable size is the configured // size. See minFlushSize below. - size += uint64(d.opts.MemTableSize) + size += d.opts.MemTableSize } else { size += d.mu.mem.queue[n].totalBytes() } @@ -1777,7 +1815,7 @@ func (d *DB) passedFlushThreshold() bool { // configured memtable size. This prevents flushing of memtables at startup // while we're undergoing the ramp period on the memtable size. See // DB.newMemTable(). - minFlushSize := uint64(d.opts.MemTableSize) / 2 + minFlushSize := d.opts.MemTableSize / 2 return size >= minFlushSize } @@ -1827,8 +1865,8 @@ func (d *DB) maybeScheduleDelayedFlush(tbl *memTable, dur time.Duration) { d.makeRoomForWrite(nil) } else { mem.flushForced = true - d.maybeScheduleFlush() } + d.maybeScheduleFlush() } }() } @@ -1880,26 +1918,58 @@ func (d *DB) runIngestFlush(c *compaction) (*manifest.VersionEdit, error) { ve := &versionEdit{} var level int var err error + var fileToSplit *fileMetadata + var ingestSplitFiles []ingestSplitFile for _, file := range c.flushing[0].flushable.(*ingestedFlushable).files { - level, err = ingestTargetLevel( - d.newIters, d.tableNewRangeKeyIter, iterOpts, d.cmp, + suggestSplit := d.opts.Experimental.IngestSplit != nil && d.opts.Experimental.IngestSplit() && + d.FormatMajorVersion() >= FormatVirtualSSTables + level, fileToSplit, err = ingestTargetLevel( + d.newIters, d.tableNewRangeKeyIter, iterOpts, d.opts.Comparer, c.version, baseLevel, d.mu.compact.inProgress, file.FileMetadata, + suggestSplit, ) if err != nil { return nil, err } ve.NewFiles = append(ve.NewFiles, newFileEntry{Level: level, Meta: file.FileMetadata}) + if fileToSplit != nil { + ingestSplitFiles = append(ingestSplitFiles, ingestSplitFile{ + ingestFile: file.FileMetadata, + splitFile: fileToSplit, + level: level, + }) + } levelMetrics := c.metrics[level] if levelMetrics == nil { levelMetrics = &LevelMetrics{} c.metrics[level] = levelMetrics } - levelMetrics.NumFiles++ - levelMetrics.Size += int64(file.Size) levelMetrics.BytesIngested += file.Size levelMetrics.TablesIngested++ } + updateLevelMetricsOnExcise := func(m *fileMetadata, level int, added []newFileEntry) { + levelMetrics := c.metrics[level] + if levelMetrics == nil { + levelMetrics = &LevelMetrics{} + c.metrics[level] = levelMetrics + } + levelMetrics.NumFiles-- + levelMetrics.Size -= int64(m.Size) + for i := range added { + levelMetrics.NumFiles++ + levelMetrics.Size += int64(added[i].Meta.Size) + } + } + + if len(ingestSplitFiles) > 0 { + ve.DeletedFiles = make(map[manifest.DeletedFileEntry]*manifest.FileMetadata) + replacedFiles := make(map[base.FileNum][]newFileEntry) + if err := d.ingestSplit(ve, updateLevelMetricsOnExcise, ingestSplitFiles, replacedFiles); err != nil { + return nil, err + } + } + return ve, nil } @@ -1937,9 +2007,9 @@ func (d *DB) flush1() (bytesFlushed uint64, err error) { // the commitPipeline.mu and then holding DB.mu. As an extra defensive // measure, if we try to flush the memtable without also flushing the // flushable batch in the same flush, since the memtable and flushableBatch - // have the same logNum, the errFlushInvariant check below will trigger and - // prevent the flush from continuing. + // have the same logNum, the logNum invariant check below will trigger. var n, inputs int + var inputBytes uint64 var ingest bool for ; n < len(d.mu.mem.queue)-1; n++ { if f, ok := d.mu.mem.queue[n].flushable.(*ingestedFlushable); ok { @@ -1968,6 +2038,7 @@ func (d *DB) flush1() (bytesFlushed uint64, err error) { if !d.mu.mem.queue[n].readyForFlush() { break } + inputBytes += d.mu.mem.queue[n].inuseBytes() } if n == 0 { // None of the immutable memtables are ready for flushing. @@ -1984,9 +2055,11 @@ func (d *DB) flush1() (bytesFlushed uint64, err error) { minUnflushedLogNum := d.mu.mem.queue[n].logNum if !d.opts.DisableWAL { for i := 0; i < n; i++ { - logNum := d.mu.mem.queue[i].logNum - if logNum >= minUnflushedLogNum { - return 0, errFlushInvariant + if logNum := d.mu.mem.queue[i].logNum; logNum >= minUnflushedLogNum { + panic(errors.AssertionFailedf("logNum invariant violated: flushing %d items; %d:type=%T,logNum=%d; %d:type=%T,logNum=%d", + n, + i, d.mu.mem.queue[i].flushable, logNum, + n, d.mu.mem.queue[n].flushable, minUnflushedLogNum)) } } } @@ -1998,9 +2071,10 @@ func (d *DB) flush1() (bytesFlushed uint64, err error) { jobID := d.mu.nextJobID d.mu.nextJobID++ d.opts.EventListener.FlushBegin(FlushInfo{ - JobID: jobID, - Input: inputs, - Ingest: ingest, + JobID: jobID, + Input: inputs, + InputBytes: inputBytes, + Ingest: ingest, }) startTime := d.timeNow() @@ -2026,12 +2100,13 @@ func (d *DB) flush1() (bytesFlushed uint64, err error) { } info := FlushInfo{ - JobID: jobID, - Input: inputs, - Duration: d.timeNow().Sub(startTime), - Done: true, - Ingest: ingest, - Err: err, + JobID: jobID, + Input: inputs, + InputBytes: inputBytes, + Duration: d.timeNow().Sub(startTime), + Done: true, + Ingest: ingest, + Err: err, } if err == nil { for i := range ve.NewFiles { @@ -2065,6 +2140,24 @@ func (d *DB) flush1() (bytesFlushed uint64, err error) { metrics.BytesIn += d.mu.mem.queue[i].logSize } } + } else if len(ve.DeletedFiles) > 0 { + // c.kind == compactionKindIngestedFlushable && we have deleted files due + // to ingest-time splits. + // + // Iterate through all other compactions, and check if their inputs have + // been replaced due to an ingest-time split. In that case, cancel the + // compaction. + for c2 := range d.mu.compact.inProgress { + for i := range c2.inputs { + iter := c2.inputs[i].files.Iter() + for f := iter.First(); f != nil; f = iter.Next() { + if _, ok := ve.DeletedFiles[deletedFileEntry{FileNum: f.FileNum, Level: c2.inputs[i].level}]; ok { + c2.cancel.Store(true) + break + } + } + } + } } err = d.mu.versions.logAndApply(jobID, ve, c.metrics, false, /* forceRotation */ func() []compactionInfo { return d.getInProgressCompactionInfoLocked(c) }) @@ -2092,14 +2185,19 @@ func (d *DB) flush1() (bytesFlushed uint64, err error) { } bytesFlushed = c.bytesIterated - d.mu.snapshots.cumulativePinnedCount += stats.cumulativePinnedKeys - d.mu.snapshots.cumulativePinnedSize += stats.cumulativePinnedSize - d.mu.versions.metrics.Keys.MissizedTombstonesCount += stats.countMissizedDels - d.maybeUpdateDeleteCompactionHints(c) + // If err != nil, then the flush will be retried, and we will recalculate + // these metrics. + if err == nil { + d.mu.snapshots.cumulativePinnedCount += stats.cumulativePinnedKeys + d.mu.snapshots.cumulativePinnedSize += stats.cumulativePinnedSize + d.mu.versions.metrics.Keys.MissizedTombstonesCount += stats.countMissizedDels + d.maybeUpdateDeleteCompactionHints(c) + } + d.clearCompactingState(c, err != nil) delete(d.mu.compact.inProgress, c) - d.mu.versions.incrementCompactions(c.kind, c.extraLevels) + d.mu.versions.incrementCompactions(c.kind, c.extraLevels, c.pickerMetrics) var flushed flushableList if err == nil { @@ -2114,6 +2212,36 @@ func (d *DB) flush1() (bytesFlushed uint64, err error) { d.mu.versions.metrics.Flush.AsIngestTableCount += l.TablesIngested } } + + // Update if any eventually file-only snapshots have now transitioned to + // being file-only. + earliestUnflushedSeqNum := d.getEarliestUnflushedSeqNumLocked() + currentVersion := d.mu.versions.currentVersion() + for s := d.mu.snapshots.root.next; s != &d.mu.snapshots.root; { + if s.efos == nil { + s = s.next + continue + } + if base.Visible(earliestUnflushedSeqNum, s.efos.seqNum, InternalKeySeqNumMax) { + s = s.next + continue + } + if s.efos.excised.Load() { + // If a concurrent excise has happened that overlaps with one of the key + // ranges this snapshot is interested in, this EFOS cannot transition to + // a file-only snapshot as keys in that range could now be deleted. Move + // onto the next snapshot. + s = s.next + continue + } + currentVersion.Ref() + + // NB: s.efos.transitionToFileOnlySnapshot could close s, in which + // case s.next would be nil. Save it before calling it. + next := s.next + _ = s.efos.transitionToFileOnlySnapshot(currentVersion) + s = next + } } // Signal FlushEnd after installing the new readState. This helps for unit // tests that use the callback to trigger a read using an iterator with @@ -2201,6 +2329,7 @@ func (d *DB) maybeScheduleCompactionPicker( } env := compactionEnv{ + diskAvailBytes: d.diskAvailBytes.Load(), earliestSnapshotSeqNum: d.mu.snapshots.earliest(), earliestUnflushedSeqNum: d.getEarliestUnflushedSeqNumLocked(), } @@ -2209,7 +2338,6 @@ func (d *DB) maybeScheduleCompactionPicker( // cheap and reduce future compaction work. if !d.opts.private.disableDeleteOnlyCompactions && len(d.mu.compact.deletionHints) > 0 && - d.mu.compact.compactingCount < maxConcurrentCompactions && !d.opts.DisableAutomaticCompactions { v := d.mu.versions.currentVersion() snapshots := d.mu.snapshots.toSlice() @@ -2225,11 +2353,12 @@ func (d *DB) maybeScheduleCompactionPicker( } for len(d.mu.compact.manual) > 0 && d.mu.compact.compactingCount < maxConcurrentCompactions { + v := d.mu.versions.currentVersion() manual := d.mu.compact.manual[0] env.inProgressCompactions = d.getInProgressCompactionInfoLocked(nil) - pc, retryLater := d.mu.versions.picker.pickManual(env, manual) + pc, retryLater := pickManualCompaction(v, d.opts, env, d.mu.versions.picker.getBaseLevel(), manual) if pc != nil { - c := newCompaction(pc, d.opts, d.timeNow()) + c := newCompaction(pc, d.opts, d.timeNow(), d.ObjProvider()) d.mu.compact.manual = d.mu.compact.manual[1:] d.mu.compact.compactingCount++ d.addInProgressCompaction(c) @@ -2256,7 +2385,7 @@ func (d *DB) maybeScheduleCompactionPicker( if pc == nil { break } - c := newCompaction(pc, d.opts, d.timeNow()) + c := newCompaction(pc, d.opts, d.timeNow(), d.ObjProvider()) d.mu.compact.compactingCount++ d.addInProgressCompaction(c) go d.compact(c, nil) @@ -2589,7 +2718,7 @@ func (d *DB) compact1(c *compaction, errChannel chan error) (err error) { // the manifest lock, we don't expect this bool to change its value // as only the holder of the manifest lock will ever write to it. if c.cancel.Load() { - err = firstError(err, errCancelledCompaction) + err = firstError(err, ErrCancelledCompaction) } if err != nil { // logAndApply calls logUnlock. If we didn't call it, we need to call @@ -2626,15 +2755,16 @@ func (d *DB) compact1(c *compaction, errChannel chan error) (err error) { e := &ve.NewFiles[i] info.Output.Tables = append(info.Output.Tables, e.Meta.TableInfo()) } + d.mu.snapshots.cumulativePinnedCount += stats.cumulativePinnedKeys + d.mu.snapshots.cumulativePinnedSize += stats.cumulativePinnedSize + d.mu.versions.metrics.Keys.MissizedTombstonesCount += stats.countMissizedDels + d.maybeUpdateDeleteCompactionHints(c) } - d.mu.snapshots.cumulativePinnedCount += stats.cumulativePinnedKeys - d.mu.snapshots.cumulativePinnedSize += stats.cumulativePinnedSize - d.maybeUpdateDeleteCompactionHints(c) // NB: clearing compacting state must occur before updating the read state; // L0Sublevels initialization depends on it. d.clearCompactingState(c, err != nil) - d.mu.versions.incrementCompactions(c.kind, c.extraLevels) + d.mu.versions.incrementCompactions(c.kind, c.extraLevels, c.pickerMetrics) d.mu.versions.incrementCompactionBytes(-c.bytesWritten) info.TotalDuration = d.timeNow().Sub(c.beganAt) @@ -2659,6 +2789,77 @@ type compactStats struct { countMissizedDels uint64 } +// runCopyCompaction runs a copy compaction where a new FileNum is created that +// is a byte-for-byte copy of the input file. This is used in lieu of a move +// compaction when a file is being moved across the local/remote storage +// boundary. +// +// d.mu must be held when calling this method. +func (d *DB) runCopyCompaction( + jobID int, + c *compaction, + meta *fileMetadata, + objMeta objstorage.ObjectMetadata, + versionEdit *versionEdit, +) (ve *versionEdit, pendingOutputs []physicalMeta, retErr error) { + ve = versionEdit + if objMeta.IsRemote() || !remote.ShouldCreateShared(d.opts.Experimental.CreateOnShared, c.outputLevel.level) { + panic("pebble: scheduled a copy compaction that is not actually moving files to shared storage") + } + // Note that based on logic in the compaction picker, we're guaranteed + // meta.Virtual is false. + if meta.Virtual { + panic(errors.AssertionFailedf("cannot do a copy compaction of a virtual sstable across local/remote storage")) + } + // We are in the relatively more complex case where we need to copy this + // file to remote/shared storage. Drop the db mutex while we do the + // copy. + // + // To ease up cleanup of the local file and tracking of refs, we create + // a new FileNum. This has the potential of making the block cache less + // effective, however. + metaCopy := new(fileMetadata) + *metaCopy = fileMetadata{ + Size: meta.Size, + CreationTime: meta.CreationTime, + SmallestSeqNum: meta.SmallestSeqNum, + LargestSeqNum: meta.LargestSeqNum, + Stats: meta.Stats, + Virtual: meta.Virtual, + } + if meta.HasPointKeys { + metaCopy.ExtendPointKeyBounds(c.cmp, meta.SmallestPointKey, meta.LargestPointKey) + } + if meta.HasRangeKeys { + metaCopy.ExtendRangeKeyBounds(c.cmp, meta.SmallestRangeKey, meta.LargestRangeKey) + } + metaCopy.FileNum = d.mu.versions.getNextFileNum() + metaCopy.InitPhysicalBacking() + c.metrics = map[int]*LevelMetrics{ + c.outputLevel.level: { + BytesIn: meta.Size, + BytesCompacted: meta.Size, + TablesCompacted: 1, + }, + } + pendingOutputs = append(pendingOutputs, metaCopy.PhysicalMeta()) + + d.mu.Unlock() + defer d.mu.Lock() + _, err := d.objProvider.LinkOrCopyFromLocal(context.TODO(), d.opts.FS, + d.objProvider.Path(objMeta), fileTypeTable, metaCopy.FileBacking.DiskFileNum, + objstorage.CreateOptions{PreferSharedStorage: true}) + if err != nil { + return ve, pendingOutputs, err + } + ve.NewFiles[0].Meta = metaCopy + + if err := d.objProvider.Sync(); err != nil { + return nil, pendingOutputs, err + } + return ve, pendingOutputs, nil +} + // runCompactions runs a compaction that produces new on-disk tables from // memtables or old on-disk tables. // @@ -2693,8 +2894,6 @@ func (d *DB) runCompaction( levelMetrics := &LevelMetrics{} iter := cl.files.Iter() for f := iter.First(); f != nil; f = iter.Next() { - levelMetrics.NumFiles-- - levelMetrics.Size -= int64(f.Size) ve.DeletedFiles[deletedFileEntry{ Level: cl.level, FileNum: f.FileNum, @@ -2709,21 +2908,24 @@ func (d *DB) runCompaction( panic("pebble: runCompaction cannot handle compactionKindIngestedFlushable.") } - // Check for a trivial move of one table from one level to the next. We avoid + // Check for a move or copy of one table from one level to the next. We avoid // such a move if there is lots of overlapping grandparent data. Otherwise, // the move could create a parent file that will require a very expensive // merge later on. - if c.kind == compactionKindMove { + if c.kind == compactionKindMove || c.kind == compactionKindCopy { iter := c.startLevel.files.Iter() meta := iter.First() + if invariants.Enabled { + if iter.Next() != nil { + panic("got more than one file for a move or copy compaction") + } + } + objMeta, err := d.objProvider.Lookup(fileTypeTable, meta.FileBacking.DiskFileNum) + if err != nil { + return ve, pendingOutputs, stats, err + } c.metrics = map[int]*LevelMetrics{ - c.startLevel.level: { - NumFiles: -1, - Size: -int64(meta.Size), - }, c.outputLevel.level: { - NumFiles: 1, - Size: int64(meta.Size), BytesMoved: meta.Size, TablesMoved: 1, }, @@ -2736,6 +2938,12 @@ func (d *DB) runCompaction( {Level: c.outputLevel.level, Meta: meta}, }, } + if c.kind == compactionKindCopy { + ve, pendingOutputs, retErr = d.runCopyCompaction(jobID, c, meta, objMeta, ve) + if retErr != nil { + return ve, pendingOutputs, stats, retErr + } + } return ve, nil, stats, nil } @@ -2748,6 +2956,22 @@ func (d *DB) runCompaction( snapshots := d.mu.snapshots.toSlice() formatVers := d.FormatMajorVersion() + if c.flushing == nil { + // Before dropping the db mutex, grab a ref to the current version. This + // prevents any concurrent excises from deleting files that this compaction + // needs to read/maintain a reference to. + // + // Note that unlike user iterators, compactionIter does not maintain a ref + // of the version or read state. + vers := d.mu.versions.currentVersion() + vers.Ref() + defer vers.UnrefLocked() + } + + if c.cancel.Load() { + return ve, nil, stats, ErrCancelledCompaction + } + // Release the d.mu lock while doing I/O. // Note the unusual order: Unlock and then Lock. d.mu.Unlock() @@ -2784,6 +3008,7 @@ func (d *DB) runCompaction( return nil, pendingOutputs, stats, err } c.allowedZeroSeqNum = c.allowZeroSeqNum() + iiter = invalidating.MaybeWrapIfInvariants(iiter) iter := newCompactionIter(c.cmp, c.equal, c.formatKey, d.merge, iiter, snapshots, &c.rangeDelFrag, &c.rangeKeyFrag, c.allowedZeroSeqNum, c.elideTombstone, c.elideRangeTombstone, d.FormatMajorVersion()) @@ -2816,8 +3041,9 @@ func (d *DB) runCompaction( DeletedFiles: map[deletedFileEntry]*fileMetadata{}, } + startLevelBytes := c.startLevel.files.SizeSum() outputMetrics := &LevelMetrics{ - BytesIn: c.startLevel.files.SizeSum(), + BytesIn: startLevelBytes, BytesRead: c.outputLevel.files.SizeSum(), } if len(c.extraLevels) > 0 { @@ -2833,6 +3059,9 @@ func (d *DB) runCompaction( } if len(c.extraLevels) > 0 { c.metrics[c.extraLevels[0].level] = &LevelMetrics{} + outputMetrics.MultiLevel.BytesInTop = startLevelBytes + outputMetrics.MultiLevel.BytesIn = outputMetrics.BytesIn + outputMetrics.MultiLevel.BytesRead = outputMetrics.BytesRead } // The table is typically written at the maximum allowable format implied by @@ -2873,7 +3102,7 @@ func (d *DB) runCompaction( newOutput := func() error { // Check if we've been cancelled by a concurrent operation. if c.cancel.Load() { - return errCancelledCompaction + return ErrCancelledCompaction } fileMeta := &fileMetadata{} d.mu.Lock() @@ -2895,15 +3124,8 @@ func (d *DB) runCompaction( } } // Prefer shared storage if present. - // - // TODO(bilal): This might be inefficient for short-lived files in higher - // levels if we're only writing to shared storage and not double-writing - // to local storage. Either implement double-writing functionality, or - // set PreferSharedStorage to c.outputLevel.level >= 5. The latter needs - // some careful handling around move compactions to ensure all files in - // lower levels are in shared storage. createOpts := objstorage.CreateOptions{ - PreferSharedStorage: true, + PreferSharedStorage: remote.ShouldCreateShared(d.opts.Experimental.CreateOnShared, c.outputLevel.level), } writable, objMeta, err := d.objProvider.Create(ctx, fileTypeTable, fileNum.DiskFileNum(), createOpts) if err != nil { @@ -3348,8 +3570,6 @@ func (d *DB) runCompaction( for _, cl := range c.inputs { iter := cl.files.Iter() for f := iter.First(); f != nil; f = iter.Next() { - c.metrics[cl.level].NumFiles-- - c.metrics[cl.level].Size -= int64(f.Size) ve.DeletedFiles[deletedFileEntry{ Level: cl.level, FileNum: f.FileNum, @@ -3451,7 +3671,7 @@ func (d *DB) scanObsoleteFiles(list []string) { } switch fileType { case fileTypeLog: - if diskFileNum.FileNum() >= minUnflushedLogNum { + if diskFileNum >= minUnflushedLogNum { continue } fi := fileInfo{fileNum: diskFileNum} @@ -3460,7 +3680,7 @@ func (d *DB) scanObsoleteFiles(list []string) { } obsoleteLogs = append(obsoleteLogs, fi) case fileTypeManifest: - if diskFileNum.FileNum() >= manifestFileNum { + if diskFileNum >= manifestFileNum { continue } fi := fileInfo{fileNum: diskFileNum} @@ -3506,7 +3726,7 @@ func (d *DB) scanObsoleteFiles(list []string) { d.mu.log.queue = merge(d.mu.log.queue, obsoleteLogs) d.mu.versions.metrics.WAL.Files = int64(len(d.mu.log.queue)) - d.mu.versions.obsoleteTables = mergeFileInfo(d.mu.versions.obsoleteTables, obsoleteTables) + d.mu.versions.obsoleteTables = merge(d.mu.versions.obsoleteTables, obsoleteTables) d.mu.versions.updateObsoleteTableMetricsLocked() d.mu.versions.obsoleteManifests = merge(d.mu.versions.obsoleteManifests, obsoleteManifests) d.mu.versions.obsoleteOptions = merge(d.mu.versions.obsoleteOptions, obsoleteOptions) @@ -3566,7 +3786,7 @@ func (d *DB) deleteObsoleteFiles(jobID int) { // log that has not had its contents flushed to an sstable. We can recycle // the prefix of d.mu.log.queue with log numbers less than // minUnflushedLogNum. - if d.mu.log.queue[i].fileNum.FileNum() >= d.mu.versions.minUnflushedLogNum { + if d.mu.log.queue[i].fileNum >= d.mu.versions.minUnflushedLogNum { obsoleteLogs = d.mu.log.queue[:i] d.mu.log.queue = d.mu.log.queue[i:] d.mu.versions.metrics.WAL.Files -= int64(len(obsoleteLogs)) @@ -3583,9 +3803,8 @@ func (d *DB) deleteObsoleteFiles(jobID int) { // Sort the manifests cause we want to delete some contiguous prefix // of the older manifests. - sort.Slice(d.mu.versions.obsoleteManifests, func(i, j int) bool { - return d.mu.versions.obsoleteManifests[i].fileNum.FileNum() < - d.mu.versions.obsoleteManifests[j].fileNum.FileNum() + slices.SortFunc(d.mu.versions.obsoleteManifests, func(a, b fileInfo) int { + return cmp.Compare(a.fileNum, b.fileNum) }) var obsoleteManifests []fileInfo @@ -3620,8 +3839,8 @@ func (d *DB) deleteObsoleteFiles(jobID int) { for _, f := range files { // We sort to make the order of deletions deterministic, which is nice for // tests. - sort.Slice(f.obsolete, func(i, j int) bool { - return f.obsolete[i].fileNum.FileNum() < f.obsolete[j].fileNum.FileNum() + slices.SortFunc(f.obsolete, func(a, b fileInfo) int { + return cmp.Compare(a.fileNum, b.fileNum) }) for _, fi := range f.obsolete { dir := d.dirname @@ -3646,7 +3865,7 @@ func (d *DB) deleteObsoleteFiles(jobID int) { if len(filesToDelete) > 0 { d.cleanupManager.EnqueueJob(jobID, filesToDelete) } - if d.testingAlwaysWaitForCleanup { + if d.opts.private.testingAlwaysWaitForCleanup { d.cleanupManager.Wait() } } @@ -3671,36 +3890,10 @@ func merge(a, b []fileInfo) []fileInfo { } a = append(a, b...) - sort.Slice(a, func(i, j int) bool { - return a[i].fileNum.FileNum() < a[j].fileNum.FileNum() + slices.SortFunc(a, func(a, b fileInfo) int { + return cmp.Compare(a.fileNum, b.fileNum) }) - - n := 0 - for i := 0; i < len(a); i++ { - if n == 0 || a[i].fileNum != a[n-1].fileNum { - a[n] = a[i] - n++ - } - } - return a[:n] -} - -func mergeFileInfo(a, b []fileInfo) []fileInfo { - if len(b) == 0 { - return a - } - - a = append(a, b...) - sort.Slice(a, func(i, j int) bool { - return a[i].fileNum.FileNum() < a[j].fileNum.FileNum() + return slices.CompactFunc(a, func(a, b fileInfo) bool { + return a.fileNum == b.fileNum }) - - n := 0 - for i := 0; i < len(a); i++ { - if n == 0 || a[i].fileNum != a[n-1].fileNum { - a[n] = a[i] - n++ - } - } - return a[:n] } diff --git a/vendor/github.com/cockroachdb/pebble/compaction_picker.go b/vendor/github.com/cockroachdb/pebble/compaction_picker.go index 69158d65a..6567391f3 100644 --- a/vendor/github.com/cockroachdb/pebble/compaction_picker.go +++ b/vendor/github.com/cockroachdb/pebble/compaction_picker.go @@ -21,6 +21,17 @@ import ( const minIntraL0Count = 4 type compactionEnv struct { + // diskAvailBytes holds a statistic on the number of bytes available on + // disk, as reported by the filesystem. It's used to be more restrictive in + // expanding compactions if available disk space is limited. + // + // The cached value (d.diskAvailBytes) is updated whenever a file is deleted + // and whenever a compaction or flush completes. Since file removal is the + // primary means of reclaiming space, there is a rough bound on the + // statistic's staleness when available bytes is growing. Compactions and + // flushes are longer, slower operations and provide a much looser bound + // when available bytes is decreasing. + diskAvailBytes uint64 earliestUnflushedSeqNum uint64 earliestSnapshotSeqNum uint64 inProgressCompactions []compactionInfo @@ -30,10 +41,8 @@ type compactionEnv struct { type compactionPicker interface { getScores([]compactionInfo) [numLevels]float64 getBaseLevel() int - getEstimatedMaxWAmp() float64 estimatedCompactionDebt(l0ExtraSize uint64) uint64 pickAuto(env compactionEnv) (pc *pickedCompaction) - pickManual(env compactionEnv, manual *manualCompaction) (c *pickedCompaction, retryLater bool) pickElisionOnlyCompaction(env compactionEnv) (pc *pickedCompaction) pickRewriteCompaction(env compactionEnv) (pc *pickedCompaction) pickReadTriggeredCompaction(env compactionEnv) (pc *pickedCompaction) @@ -81,18 +90,38 @@ func (info compactionInfo) String() string { return buf.String() } -type sortCompactionLevelsDecreasingScore []candidateLevelInfo +type sortCompactionLevelsByPriority []candidateLevelInfo -func (s sortCompactionLevelsDecreasingScore) Len() int { +func (s sortCompactionLevelsByPriority) Len() int { return len(s) } -func (s sortCompactionLevelsDecreasingScore) Less(i, j int) bool { - if s[i].score != s[j].score { - return s[i].score > s[j].score + +// A level should be picked for compaction if the compensatedScoreRatio is >= the +// compactionScoreThreshold. +const compactionScoreThreshold = 1 + +// Less should return true if s[i] must be placed earlier than s[j] in the final +// sorted list. The candidateLevelInfo for the level placed earlier is more likely +// to be picked for a compaction. +func (s sortCompactionLevelsByPriority) Less(i, j int) bool { + iShouldCompact := s[i].compensatedScoreRatio >= compactionScoreThreshold + jShouldCompact := s[j].compensatedScoreRatio >= compactionScoreThreshold + // Ordering is defined as decreasing on (shouldCompact, uncompensatedScoreRatio) + // where shouldCompact is 1 for true and 0 for false. + if iShouldCompact && !jShouldCompact { + return true + } + if !iShouldCompact && jShouldCompact { + return false + } + + if s[i].uncompensatedScoreRatio != s[j].uncompensatedScoreRatio { + return s[i].uncompensatedScoreRatio > s[j].uncompensatedScoreRatio } return s[i].level < s[j].level } -func (s sortCompactionLevelsDecreasingScore) Swap(i, j int) { + +func (s sortCompactionLevelsByPriority) Swap(i, j int) { s[i], s[j] = s[j], s[i] } @@ -142,49 +171,43 @@ func generateSublevelInfo(cmp base.Compare, levelFiles manifest.LevelSlice) []su return levelSlices } +// compactionPickerMetrics holds metrics related to the compaction picking process +type compactionPickerMetrics struct { + // scores contains the compensatedScoreRatio from the candidateLevelInfo. + scores []float64 + singleLevelOverlappingRatio float64 + multiLevelOverlappingRatio float64 +} + // pickedCompaction contains information about a compaction that has already // been chosen, and is being constructed. Compaction construction info lives in // this struct, and is copied over into the compaction struct when that's // created. type pickedCompaction struct { cmp Compare - - // score of the chosen compaction. Taken from candidateLevelInfo. + // score of the chosen compaction. This is the same as the + // compensatedScoreRatio in the candidateLevelInfo. score float64 - // kind indicates the kind of compaction. kind compactionKind - // startLevel is the level that is being compacted. Inputs from startLevel // and outputLevel will be merged to produce a set of outputLevel files. startLevel *compactionLevel - // outputLevel is the level that files are being produced in. outputLevel is // equal to startLevel+1 except when: // - if startLevel is 0, the output level equals compactionPicker.baseLevel(). // - in multilevel compaction, the output level is the lowest level involved in // the compaction outputLevel *compactionLevel - // extraLevels contain additional levels in between the input and output // levels that get compacted in multi level compactions extraLevels []*compactionLevel - - // adjustedOutputLevel is the output level used for the purpose of - // determining the target output file size, overlap bytes, and expanded - // bytes, taking into account the base level. - adjustedOutputLevel int - - inputs []compactionLevel - + inputs []compactionLevel + // LBase at the time of compaction picking. + baseLevel int // L0-specific compaction info. Set to a non-nil value for all compactions // where startLevel == 0 that were generated by L0Sublevels. lcf *manifest.L0CompactionFiles - - // L0SublevelInfo is used for compactions out of L0. It is nil for all - // other compactions. - l0SublevelInfo []sublevelInfo - // maxOutputFileSize is the maximum size of an individual table created // during compaction. maxOutputFileSize uint64 @@ -195,12 +218,11 @@ type pickedCompaction struct { // overlap in its output level with. If the overlap is greater than // maxReadCompaction bytes, then we don't proceed with the compaction. maxReadCompactionBytes uint64 - // The boundaries of the input data. - smallest InternalKey - largest InternalKey - - version *version + smallest InternalKey + largest InternalKey + version *version + pickerMetrics compactionPickerMetrics } func defaultOutputLevel(startLevel, baseLevel int) int { @@ -222,28 +244,35 @@ func newPickedCompaction( startLevel, baseLevel)) } - adjustedOutputLevel := outputLevel - if adjustedOutputLevel > 0 { - // Output level is in the range [baseLevel,numLevels]. For the purpose of - // determining the target output file size, overlap bytes, and expanded - // bytes, we want to adjust the range to [1,numLevels]. - adjustedOutputLevel = 1 + outputLevel - baseLevel - } - + adjustedLevel := adjustedOutputLevel(outputLevel, baseLevel) pc := &pickedCompaction{ cmp: opts.Comparer.Compare, version: cur, + baseLevel: baseLevel, inputs: []compactionLevel{{level: startLevel}, {level: outputLevel}}, - adjustedOutputLevel: adjustedOutputLevel, - maxOutputFileSize: uint64(opts.Level(adjustedOutputLevel).TargetFileSize), - maxOverlapBytes: maxGrandparentOverlapBytes(opts, adjustedOutputLevel), - maxReadCompactionBytes: maxReadCompactionBytes(opts, adjustedOutputLevel), + maxOutputFileSize: uint64(opts.Level(adjustedLevel).TargetFileSize), + maxOverlapBytes: maxGrandparentOverlapBytes(opts, adjustedLevel), + maxReadCompactionBytes: maxReadCompactionBytes(opts, adjustedLevel), } pc.startLevel = &pc.inputs[0] pc.outputLevel = &pc.inputs[1] return pc } +// adjustedOutputLevel is the output level used for the purpose of +// determining the target output file size, overlap bytes, and expanded +// bytes, taking into account the base level. +func adjustedOutputLevel(outputLevel int, baseLevel int) int { + adjustedOutputLevel := outputLevel + if adjustedOutputLevel > 0 { + // Output level is in the range [baseLevel, numLevels]. For the purpose of + // determining the target output file size, overlap bytes, and expanded + // bytes, we want to adjust the range to [1,numLevels]. + adjustedOutputLevel = 1 + outputLevel - baseLevel + } + return adjustedOutputLevel +} + func newPickedCompactionFromL0( lcf *manifest.L0CompactionFiles, opts *Options, vers *version, baseLevel int, isBase bool, ) *pickedCompaction { @@ -276,7 +305,7 @@ func (pc *pickedCompaction) String() string { var builder strings.Builder builder.WriteString(fmt.Sprintf(`Score=%f, `, pc.score)) builder.WriteString(fmt.Sprintf(`Kind=%s, `, pc.kind)) - builder.WriteString(fmt.Sprintf(`AdjustedOutputLevel=%d, `, pc.adjustedOutputLevel)) + builder.WriteString(fmt.Sprintf(`AdjustedOutputLevel=%d, `, adjustedOutputLevel(pc.outputLevel.level, pc.baseLevel))) builder.WriteString(fmt.Sprintf(`maxOutputFileSize=%d, `, pc.maxOutputFileSize)) builder.WriteString(fmt.Sprintf(`maxReadCompactionBytes=%d, `, pc.maxReadCompactionBytes)) builder.WriteString(fmt.Sprintf(`smallest=%s, `, pc.smallest)) @@ -286,7 +315,7 @@ func (pc *pickedCompaction) String() string { builder.WriteString(fmt.Sprintf(`startlevel=%s, `, pc.startLevel)) builder.WriteString(fmt.Sprintf(`outputLevel=%s, `, pc.outputLevel)) builder.WriteString(fmt.Sprintf(`extraLevels=%s, `, pc.extraLevels)) - builder.WriteString(fmt.Sprintf(`l0SublevelInfo=%s, `, pc.l0SublevelInfo)) + builder.WriteString(fmt.Sprintf(`l0SublevelInfo=%s, `, pc.startLevel.l0SublevelInfo)) builder.WriteString(fmt.Sprintf(`lcf=%s`, pc.lcf)) return builder.String() } @@ -300,13 +329,16 @@ func (pc *pickedCompaction) clone() *pickedCompaction { cmp: pc.cmp, score: pc.score, kind: pc.kind, - adjustedOutputLevel: pc.adjustedOutputLevel, + baseLevel: pc.baseLevel, maxOutputFileSize: pc.maxOutputFileSize, maxOverlapBytes: pc.maxOverlapBytes, maxReadCompactionBytes: pc.maxReadCompactionBytes, smallest: pc.smallest.Clone(), largest: pc.largest.Clone(), + // TODO(msbutler): properly clone picker metrics + pickerMetrics: pc.pickerMetrics, + // Both copies see the same manifest, therefore, it's ok for them to se // share the same pc. version. version: pc.version, @@ -325,9 +357,11 @@ func (pc *pickedCompaction) clone() *pickedCompaction { } } - newPC.l0SublevelInfo = make([]sublevelInfo, len(pc.l0SublevelInfo)) - for i := range pc.l0SublevelInfo { - newPC.l0SublevelInfo[i] = pc.l0SublevelInfo[i].Clone() + if len(pc.startLevel.l0SublevelInfo) > 0 { + newPC.startLevel.l0SublevelInfo = make([]sublevelInfo, len(pc.startLevel.l0SublevelInfo)) + for i := range pc.startLevel.l0SublevelInfo { + newPC.startLevel.l0SublevelInfo[i] = pc.startLevel.l0SublevelInfo[i].Clone() + } } if pc.lcf != nil { newPC.lcf = pc.lcf.Clone() @@ -373,7 +407,7 @@ func (pc *pickedCompaction) setupInputs( // growing a compaction results in a larger size, the original compaction // is used instead. maxExpandedBytes := expandedCompactionByteSizeLimit( - opts, pc.adjustedOutputLevel, diskAvailBytes, + opts, adjustedOutputLevel(pc.outputLevel.level, pc.baseLevel), diskAvailBytes, ) // Expand the initial inputs to a clean cut. @@ -468,7 +502,7 @@ func (pc *pickedCompaction) setupInputs( if pc.startLevel.level == 0 { // We don't change the input files for the compaction beyond this point. - pc.l0SublevelInfo = generateSublevelInfo(pc.cmp, pc.startLevel.files) + pc.startLevel.l0SublevelInfo = generateSublevelInfo(pc.cmp, pc.startLevel.files) } return true @@ -531,8 +565,6 @@ func (pc *pickedCompaction) setupMultiLevelCandidate(opts *Options, diskAvailByt pc.startLevel = &pc.inputs[0] pc.extraLevels = []*compactionLevel{&pc.inputs[1]} pc.outputLevel = &pc.inputs[2] - - pc.adjustedOutputLevel++ return pc.setupInputs(opts, diskAvailBytes, pc.extraLevels[len(pc.extraLevels)-1]) } @@ -643,17 +675,11 @@ func expandToAtomicUnit( } func newCompactionPicker( - v *version, - opts *Options, - inProgressCompactions []compactionInfo, - levelSizes [numLevels]int64, - diskAvailBytes func() uint64, + v *version, opts *Options, inProgressCompactions []compactionInfo, ) compactionPicker { p := &compactionPickerByScore{ - opts: opts, - vers: v, - levelSizes: levelSizes, - diskAvailBytes: diskAvailBytes, + opts: opts, + vers: v, } p.initLevelMaxBytes(inProgressCompactions) return p @@ -662,16 +688,23 @@ func newCompactionPicker( // Information about a candidate compaction level that has been identified by // the compaction picker. type candidateLevelInfo struct { - // The score of the level to be compacted, with compensated file sizes and - // adjustments. - score float64 - // The original score of the level to be compacted, before adjusting - // according to other levels' sizes. - origScore float64 - // The raw score of the level to be compacted, calculated using - // uncompensated file sizes and without any adjustments. - rawScore float64 - level int + // The compensatedScore of the level after adjusting according to the other + // levels' sizes. For L0, the compensatedScoreRatio is equivalent to the + // uncompensatedScoreRatio as we don't account for level size compensation in + // L0. + compensatedScoreRatio float64 + // The score of the level after accounting for level size compensation before + // adjusting according to other levels' sizes. For L0, the compensatedScore + // is equivalent to the uncompensatedScore as we don't account for level + // size compensation in L0. + compensatedScore float64 + // The score of the level to be compacted, calculated using uncompensated file + // sizes and without any adjustments. + uncompensatedScore float64 + // uncompensatedScoreRatio is the uncompensatedScore adjusted according to + // the other levels' sizes. + uncompensatedScoreRatio float64 + level int // The level to compact to. outputLevel int // The file in level that will be compacted. Additional files may be @@ -680,6 +713,10 @@ type candidateLevelInfo struct { file manifest.LevelFile } +func (c *candidateLevelInfo) shouldCompact() bool { + return c.compensatedScoreRatio >= compactionScoreThreshold +} + func fileCompensation(f *fileMetadata) uint64 { return uint64(f.Stats.PointDeletionsBytesEstimate) + f.Stats.RangeDeletionsBytesEstimate } @@ -744,42 +781,20 @@ func totalCompensatedSize(iter manifest.LevelIterator) uint64 { type compactionPickerByScore struct { opts *Options vers *version - // The level to target for L0 compactions. Levels L1 to baseLevel must be // empty. baseLevel int - - // estimatedMaxWAmp is the estimated maximum write amp per byte that is - // added to L0. - estimatedMaxWAmp float64 - // levelMaxBytes holds the dynamically adjusted max bytes setting for each // level. levelMaxBytes [numLevels]int64 - - // levelSizes holds the current size of each level. - levelSizes [numLevels]int64 - - // diskAvailBytes returns a cached statistic on the number of bytes - // available on disk, as reported by the filesystem. It's used to be more - // restrictive in expanding compactions if available disk space is - // limited. - // - // The cached value is updated whenever a file is deleted and - // whenever a compaction or flush completes. Since file removal is - // the primary means of reclaiming space, there is a rough bound on - // the statistic's staleness when available bytes is growing. - // Compactions and flushes are longer, slower operations and provide - // a much looser bound when available bytes is decreasing. - diskAvailBytes func() uint64 } var _ compactionPicker = &compactionPickerByScore{} func (p *compactionPickerByScore) getScores(inProgress []compactionInfo) [numLevels]float64 { var scores [numLevels]float64 - for _, info := range p.calculateScores(inProgress) { - scores[info.level] = info.score + for _, info := range p.calculateLevelScores(inProgress) { + scores[info.level] = info.compensatedScoreRatio } return scores } @@ -791,10 +806,6 @@ func (p *compactionPickerByScore) getBaseLevel() int { return p.baseLevel } -func (p *compactionPickerByScore) getEstimatedMaxWAmp() float64 { - return p.estimatedMaxWAmp -} - // estimatedCompactionDebt estimates the number of bytes which need to be // compacted before the LSM tree becomes stable. func (p *compactionPickerByScore) estimatedCompactionDebt(l0ExtraSize uint64) uint64 { @@ -804,8 +815,8 @@ func (p *compactionPickerByScore) estimatedCompactionDebt(l0ExtraSize uint64) ui // We assume that all the bytes in L0 need to be compacted to Lbase. This is // unlike the RocksDB logic that figures out whether L0 needs compaction. - bytesAddedToNextLevel := l0ExtraSize + uint64(p.levelSizes[0]) - lbaseSize := uint64(p.levelSizes[p.baseLevel]) + bytesAddedToNextLevel := l0ExtraSize + p.vers.Levels[0].Size() + lbaseSize := p.vers.Levels[p.baseLevel].Size() var compactionDebt uint64 if bytesAddedToNextLevel > 0 && lbaseSize > 0 { @@ -818,8 +829,8 @@ func (p *compactionPickerByScore) estimatedCompactionDebt(l0ExtraSize uint64) ui // loop invariant: At the beginning of the loop, bytesAddedToNextLevel is the // bytes added to `level` in the loop. for level := p.baseLevel; level < numLevels-1; level++ { - levelSize := uint64(p.levelSizes[level]) + bytesAddedToNextLevel - nextLevelSize := uint64(p.levelSizes[level+1]) + levelSize := p.vers.Levels[level].Size() + bytesAddedToNextLevel + nextLevelSize := p.vers.Levels[level+1].Size() if levelSize > uint64(p.levelMaxBytes[level]) { bytesAddedToNextLevel = levelSize - uint64(p.levelMaxBytes[level]) if nextLevelSize > 0 { @@ -859,13 +870,13 @@ func (p *compactionPickerByScore) initLevelMaxBytes(inProgressCompactions []comp // Determine the first non-empty level and the total DB size. firstNonEmptyLevel := -1 - var dbSize int64 + var dbSize uint64 for level := 1; level < numLevels; level++ { - if p.levelSizes[level] > 0 { + if p.vers.Levels[level].Size() > 0 { if firstNonEmptyLevel == -1 { firstNonEmptyLevel = level } - dbSize += p.levelSizes[level] + dbSize += p.vers.Levels[level].Size() } } for _, c := range inProgressCompactions { @@ -894,20 +905,20 @@ func (p *compactionPickerByScore) initLevelMaxBytes(inProgressCompactions []comp return } - dbSize += p.levelSizes[0] - bottomLevelSize := dbSize - dbSize/int64(p.opts.Experimental.LevelMultiplier) + dbSize += p.vers.Levels[0].Size() + bottomLevelSize := dbSize - dbSize/uint64(p.opts.Experimental.LevelMultiplier) curLevelSize := bottomLevelSize for level := numLevels - 2; level >= firstNonEmptyLevel; level-- { - curLevelSize = int64(float64(curLevelSize) / float64(p.opts.Experimental.LevelMultiplier)) + curLevelSize = uint64(float64(curLevelSize) / float64(p.opts.Experimental.LevelMultiplier)) } // Compute base level (where L0 data is compacted to). - baseBytesMax := p.opts.LBaseMaxBytes + baseBytesMax := uint64(p.opts.LBaseMaxBytes) p.baseLevel = firstNonEmptyLevel for p.baseLevel > 1 && curLevelSize > baseBytesMax { p.baseLevel-- - curLevelSize = int64(float64(curLevelSize) / float64(p.opts.Experimental.LevelMultiplier)) + curLevelSize = uint64(float64(curLevelSize) / float64(p.opts.Experimental.LevelMultiplier)) } smoothedLevelMultiplier := 1.0 @@ -917,8 +928,6 @@ func (p *compactionPickerByScore) initLevelMaxBytes(inProgressCompactions []comp 1.0/float64(numLevels-p.baseLevel-1)) } - p.estimatedMaxWAmp = float64(numLevels-p.baseLevel) * (smoothedLevelMultiplier + 1) - levelSize := float64(baseBytesMax) for level := p.baseLevel; level < numLevels; level++ { if level > p.baseLevel && levelSize > 0 { @@ -936,16 +945,16 @@ func (p *compactionPickerByScore) initLevelMaxBytes(inProgressCompactions []comp } type levelSizeAdjust struct { - incomingActualBytes int64 - outgoingActualBytes int64 - outgoingCompensatedBytes int64 + incomingActualBytes uint64 + outgoingActualBytes uint64 + outgoingCompensatedBytes uint64 } -func (a levelSizeAdjust) compensated() int64 { +func (a levelSizeAdjust) compensated() uint64 { return a.incomingActualBytes - a.outgoingCompensatedBytes } -func (a levelSizeAdjust) actual() int64 { +func (a levelSizeAdjust) actual() uint64 { return a.incomingActualBytes - a.outgoingActualBytes } @@ -977,8 +986,8 @@ func calculateSizeAdjust(inProgressCompactions []compactionInfo) [numLevels]leve } for _, input := range c.inputs { - actualSize := int64(input.files.SizeSum()) - compensatedSize := int64(totalCompensatedSize(input.files.Iter())) + actualSize := input.files.SizeSum() + compensatedSize := totalCompensatedSize(input.files.Iter()) if input.level != c.outputLevel { sizeAdjust[input.level].outgoingCompensatedBytes += compensatedSize @@ -996,7 +1005,7 @@ func levelCompensatedSize(lm manifest.LevelMetadata) uint64 { return *lm.Annotation(compensatedSizeAnnotator{}).(*uint64) } -func (p *compactionPickerByScore) calculateScores( +func (p *compactionPickerByScore) calculateLevelScores( inProgressCompactions []compactionInfo, ) [numLevels]candidateLevelInfo { var scores [numLevels]candidateLevelInfo @@ -1004,72 +1013,89 @@ func (p *compactionPickerByScore) calculateScores( scores[i].level = i scores[i].outputLevel = i + 1 } - scores[0] = p.calculateL0Score(inProgressCompactions) - + l0UncompensatedScore := calculateL0UncompensatedScore(p.vers, p.opts, inProgressCompactions) + scores[0] = candidateLevelInfo{ + outputLevel: p.baseLevel, + uncompensatedScore: l0UncompensatedScore, + compensatedScore: l0UncompensatedScore, /* No level size compensation for L0 */ + } sizeAdjust := calculateSizeAdjust(inProgressCompactions) for level := 1; level < numLevels; level++ { - compensatedLevelSize := int64(levelCompensatedSize(p.vers.Levels[level])) + sizeAdjust[level].compensated() - scores[level].score = float64(compensatedLevelSize) / float64(p.levelMaxBytes[level]) - scores[level].origScore = scores[level].score - - // In addition to the compensated score, we calculate a separate score - // that uses actual file sizes, not compensated sizes. This is used - // during score smoothing down below to prevent excessive - // prioritization of reclaiming disk space. - scores[level].rawScore = float64(p.levelSizes[level]+sizeAdjust[level].actual()) / float64(p.levelMaxBytes[level]) - } - - // Adjust each level's score by the score of the next level. If the next - // level has a high score, and is thus a priority for compaction, this - // reduces the priority for compacting the current level. If the next level - // has a low score (i.e. it is below its target size), this increases the - // priority for compacting the current level. + compensatedLevelSize := levelCompensatedSize(p.vers.Levels[level]) + sizeAdjust[level].compensated() + scores[level].compensatedScore = float64(compensatedLevelSize) / float64(p.levelMaxBytes[level]) + scores[level].uncompensatedScore = float64(p.vers.Levels[level].Size()+sizeAdjust[level].actual()) / float64(p.levelMaxBytes[level]) + } + + // Adjust each level's {compensated, uncompensated}Score by the uncompensatedScore + // of the next level to get a {compensated, uncompensated}ScoreRatio. If the + // next level has a high uncompensatedScore, and is thus a priority for compaction, + // this reduces the priority for compacting the current level. If the next level + // has a low uncompensatedScore (i.e. it is below its target size), this increases + // the priority for compacting the current level. // // The effect of this adjustment is to help prioritize compactions in lower - // levels. The following shows the new score and original score. In this - // scenario, L0 has 68 sublevels. L3 (a.k.a. Lbase) is significantly above - // its target size. The original score prioritizes compactions from those two - // levels, but doing so ends up causing a future problem: data piles up in - // the higher levels, starving L5->L6 compactions, and to a lesser degree - // starving L4->L5 compactions. + // levels. The following example shows the compensatedScoreRatio and the + // compensatedScore. In this scenario, L0 has 68 sublevels. L3 (a.k.a. Lbase) + // is significantly above its target size. The original score prioritizes + // compactions from those two levels, but doing so ends up causing a future + // problem: data piles up in the higher levels, starving L5->L6 compactions, + // and to a lesser degree starving L4->L5 compactions. + // + // Note that in the example shown there is no level size compensation so the + // compensatedScore and the uncompensatedScore is the same for each level. // - // adjusted original - // score score size max-size - // L0 3.2 68.0 2.2 G - - // L3 3.2 21.1 1.3 G 64 M - // L4 3.4 6.7 3.1 G 467 M - // L5 3.4 2.0 6.6 G 3.3 G - // L6 0.6 0.6 14 G 24 G + // compensatedScoreRatio compensatedScore uncompensatedScore size max-size + // L0 3.2 68.0 68.0 2.2 G - + // L3 3.2 21.1 21.1 1.3 G 64 M + // L4 3.4 6.7 6.7 3.1 G 467 M + // L5 3.4 2.0 2.0 6.6 G 3.3 G + // L6 0.6 0.6 0.6 14 G 24 G var prevLevel int for level := p.baseLevel; level < numLevels; level++ { - if scores[prevLevel].score >= 1 { - // Avoid absurdly large scores by placing a floor on the score that we'll - // adjust a level by. The value of 0.01 was chosen somewhat arbitrarily - const minScore = 0.01 - if scores[level].rawScore >= minScore { - scores[prevLevel].score /= scores[level].rawScore + // The compensated scores, and uncompensated scores will be turned into + // ratios as they're adjusted according to other levels' sizes. + scores[prevLevel].compensatedScoreRatio = scores[prevLevel].compensatedScore + scores[prevLevel].uncompensatedScoreRatio = scores[prevLevel].uncompensatedScore + + // Avoid absurdly large scores by placing a floor on the score that we'll + // adjust a level by. The value of 0.01 was chosen somewhat arbitrarily. + const minScore = 0.01 + if scores[prevLevel].compensatedScoreRatio >= compactionScoreThreshold { + if scores[level].uncompensatedScore >= minScore { + scores[prevLevel].compensatedScoreRatio /= scores[level].uncompensatedScore } else { - scores[prevLevel].score /= minScore + scores[prevLevel].compensatedScoreRatio /= minScore + } + } + if scores[prevLevel].uncompensatedScoreRatio >= compactionScoreThreshold { + if scores[level].uncompensatedScore >= minScore { + scores[prevLevel].uncompensatedScoreRatio /= scores[level].uncompensatedScore + } else { + scores[prevLevel].uncompensatedScoreRatio /= minScore } } prevLevel = level } + // Set the score ratios for the lowest level. + // INVARIANT: prevLevel == numLevels-1 + scores[prevLevel].compensatedScoreRatio = scores[prevLevel].compensatedScore + scores[prevLevel].uncompensatedScoreRatio = scores[prevLevel].uncompensatedScore - sort.Sort(sortCompactionLevelsDecreasingScore(scores[:])) + sort.Sort(sortCompactionLevelsByPriority(scores[:])) return scores } -func (p *compactionPickerByScore) calculateL0Score( - inProgressCompactions []compactionInfo, -) candidateLevelInfo { - var info candidateLevelInfo - info.outputLevel = p.baseLevel - - // If L0Sublevels are present, use the sublevel count to calculate the - // score. The base vs intra-L0 compaction determination happens in pickAuto, - // not here. - info.score = float64(2*p.vers.L0Sublevels.MaxDepthAfterOngoingCompactions()) / - float64(p.opts.L0CompactionThreshold) +// calculateL0UncompensatedScore calculates a float score representing the +// relative priority of compacting L0. Level L0 is special in that files within +// L0 may overlap one another, so a different set of heuristics that take into +// account read amplification apply. +func calculateL0UncompensatedScore( + vers *version, opts *Options, inProgressCompactions []compactionInfo, +) float64 { + // Use the sublevel count to calculate the score. The base vs intra-L0 + // compaction determination happens in pickAuto, not here. + score := float64(2*vers.L0Sublevels.MaxDepthAfterOngoingCompactions()) / + float64(opts.L0CompactionThreshold) // Also calculate a score based on the file count but use it only if it // produces a higher score than the sublevel-based one. This heuristic is @@ -1079,7 +1105,7 @@ func (p *compactionPickerByScore) calculateL0Score( // 1) we can produce a massive backlog to compact once files do overlap. // 2) constructing L0 sublevels has a runtime that grows superlinearly with // the number of files in L0 and must be done while holding D.mu. - noncompactingFiles := p.vers.Levels[0].Len() + noncompactingFiles := vers.Levels[0].Len() for _, c := range inProgressCompactions { for _, cl := range c.inputs { if cl.level == 0 { @@ -1087,15 +1113,20 @@ func (p *compactionPickerByScore) calculateL0Score( } } } - fileScore := float64(noncompactingFiles) / float64(p.opts.L0CompactionFileThreshold) - if info.score < fileScore { - info.score = fileScore + fileScore := float64(noncompactingFiles) / float64(opts.L0CompactionFileThreshold) + if score < fileScore { + score = fileScore } - return info + return score } -func (p *compactionPickerByScore) pickFile( - level, outputLevel int, earliestSnapshotSeqNum uint64, +// pickCompactionSeedFile picks a file from `level` in the `vers` to build a +// compaction around. Currently, this function implements a heuristic similar to +// RocksDB's kMinOverlappingRatio, seeking to minimize write amplification. This +// function is linear with respect to the number of files in `level` and +// `outputLevel`. +func pickCompactionSeedFile( + vers *version, opts *Options, level, outputLevel int, earliestSnapshotSeqNum uint64, ) (manifest.LevelFile, bool) { // Select the file within the level to compact. We want to minimize write // amplification, but also ensure that deletes are propagated to the @@ -1119,9 +1150,9 @@ func (p *compactionPickerByScore) pickFile( // pick a seed file whose resulting compaction bounds do not overlap with // an in-progress compaction. - cmp := p.opts.Comparer.Compare - startIter := p.vers.Levels[level].Iter() - outputIter := p.vers.Levels[outputLevel].Iter() + cmp := opts.Comparer.Compare + startIter := vers.Levels[level].Iter() + outputIter := vers.Levels[outputLevel].Iter() var file manifest.LevelFile smallestRatio := uint64(math.MaxUint64) @@ -1230,15 +1261,15 @@ func (p *compactionPickerByScore) pickAuto(env compactionEnv) (pc *pickedCompact // bytes have been compacted further down the LSM. if n := len(env.inProgressCompactions); n > 0 { l0ReadAmp := p.vers.L0Sublevels.MaxDepthAfterOngoingCompactions() - compactionDebt := int(p.estimatedCompactionDebt(0)) + compactionDebt := p.estimatedCompactionDebt(0) ccSignal1 := n * p.opts.Experimental.L0CompactionConcurrency - ccSignal2 := n * p.opts.Experimental.CompactionDebtConcurrency + ccSignal2 := uint64(n) * p.opts.Experimental.CompactionDebtConcurrency if l0ReadAmp < ccSignal1 && compactionDebt < ccSignal2 { return nil } } - scores := p.calculateScores(env.inProgressCompactions) + scores := p.calculateLevelScores(env.inProgressCompactions) // TODO(bananabrick): Either remove, or change this into an event sent to the // EventListener. @@ -1261,8 +1292,9 @@ func (p *compactionPickerByScore) pickAuto(env compactionEnv) (pc *pickedCompact if pc.startLevel.level == info.level { marker = "*" } - fmt.Fprintf(&buf, " %sL%d: %5.1f %5.1f %5.1f %8s %8s", - marker, info.level, info.score, info.origScore, info.rawScore, + fmt.Fprintf(&buf, " %sL%d: %5.1f %5.1f %5.1f %5.1f %8s %8s", + marker, info.level, info.compensatedScoreRatio, info.compensatedScore, + info.uncompensatedScoreRatio, info.uncompensatedScore, humanize.Bytes.Int64(int64(totalCompensatedSize( p.vers.Levels[info.level].Iter(), ))), @@ -1292,12 +1324,12 @@ func (p *compactionPickerByScore) pickAuto(env compactionEnv) (pc *pickedCompact pc.startLevel.level, pc.outputLevel.level, buf.String()) } - // Check for a score-based compaction. "scores" has been sorted in order of - // decreasing score. For each level with a score >= 1, we attempt to find a - // compaction anchored at at that level. + // Check for a score-based compaction. candidateLevelInfos are first sorted + // by whether they should be compacted, so if we find a level which shouldn't + // be compacted, we can break early. for i := range scores { info := &scores[i] - if info.score < 1 { + if !info.shouldCompact() { break } if info.level == numLevels-1 { @@ -1305,11 +1337,12 @@ func (p *compactionPickerByScore) pickAuto(env compactionEnv) (pc *pickedCompact } if info.level == 0 { - pc = pickL0(env, p.opts, p.vers, p.baseLevel, p.diskAvailBytes) + pc = pickL0(env, p.opts, p.vers, p.baseLevel) // Fail-safe to protect against compacting the same sstable // concurrently. if pc != nil && !inputRangeAlreadyCompacting(env, pc) { - pc.score = info.score + p.addScoresToPickedCompactionMetrics(pc, scores) + pc.score = info.compensatedScoreRatio // TODO(bananabrick): Create an EventListener for logCompaction. if false { logCompaction(pc) @@ -1321,15 +1354,16 @@ func (p *compactionPickerByScore) pickAuto(env compactionEnv) (pc *pickedCompact // info.level > 0 var ok bool - info.file, ok = p.pickFile(info.level, info.outputLevel, env.earliestSnapshotSeqNum) + info.file, ok = pickCompactionSeedFile(p.vers, p.opts, info.level, info.outputLevel, env.earliestSnapshotSeqNum) if !ok { continue } - pc := pickAutoLPositive(env, p.opts, p.vers, *info, p.baseLevel, p.diskAvailBytes, p.levelMaxBytes) + pc := pickAutoLPositive(env, p.opts, p.vers, *info, p.baseLevel, p.levelMaxBytes) // Fail-safe to protect against compacting the same sstable concurrently. if pc != nil && !inputRangeAlreadyCompacting(env, pc) { - pc.score = info.score + p.addScoresToPickedCompactionMetrics(pc, scores) + pc.score = info.compensatedScoreRatio // TODO(bananabrick): Create an EventListener for logCompaction. if false { logCompaction(pc) @@ -1390,6 +1424,30 @@ func (p *compactionPickerByScore) pickAuto(env compactionEnv) (pc *pickedCompact return nil } +func (p *compactionPickerByScore) addScoresToPickedCompactionMetrics( + pc *pickedCompaction, candInfo [numLevels]candidateLevelInfo, +) { + + // candInfo is sorted by score, not by compaction level. + infoByLevel := [numLevels]candidateLevelInfo{} + for i := range candInfo { + level := candInfo[i].level + infoByLevel[level] = candInfo[i] + } + // Gather the compaction scores for the levels participating in the compaction. + pc.pickerMetrics.scores = make([]float64, len(pc.inputs)) + inputIdx := 0 + for i := range infoByLevel { + if pc.inputs[inputIdx].level == infoByLevel[i].level { + pc.pickerMetrics.scores[inputIdx] = infoByLevel[i].compensatedScoreRatio + inputIdx++ + } + if inputIdx == len(pc.inputs) { + break + } + } +} + // elisionOnlyAnnotator implements the manifest.Annotator interface, // annotating B-Tree nodes with the *fileMetadata of a file meeting the // obsolete keys criteria for an elision-only compaction within the subtree. @@ -1588,7 +1646,7 @@ func (p *compactionPickerByScore) pickRewriteCompaction(env compactionEnv) (pc * // Fail-safe to protect against compacting the same sstable concurrently. if !inputRangeAlreadyCompacting(env, pc) { if pc.startLevel.level == 0 { - pc.l0SublevelInfo = generateSublevelInfo(pc.cmp, pc.startLevel.files) + pc.startLevel.l0SublevelInfo = generateSublevelInfo(pc.cmp, pc.startLevel.files) } return pc } @@ -1605,8 +1663,7 @@ func pickAutoLPositive( vers *version, cInfo candidateLevelInfo, baseLevel int, - diskAvailBytes func() uint64, - levelMaxBytes [7]int64, + levelMaxBytes [numLevels]int64, ) (pc *pickedCompaction) { if cInfo.level == 0 { panic("pebble: pickAutoLPositive called for L0") @@ -1628,46 +1685,124 @@ func pickAutoLPositive( } } - if !pc.setupInputs(opts, diskAvailBytes(), pc.startLevel) { + if !pc.setupInputs(opts, env.diskAvailBytes, pc.startLevel) { return nil } - return pc.maybeAddLevel(opts, diskAvailBytes()) + return pc.maybeAddLevel(opts, env.diskAvailBytes) } // maybeAddLevel maybe adds a level to the picked compaction. func (pc *pickedCompaction) maybeAddLevel(opts *Options, diskAvailBytes uint64) *pickedCompaction { + pc.pickerMetrics.singleLevelOverlappingRatio = pc.overlappingRatio() if pc.outputLevel.level == numLevels-1 { // Don't add a level if the current output level is in L6 return pc } + if !opts.Experimental.MultiLevelCompactionHeuristic.allowL0() && pc.startLevel.level == 0 { + return pc + } if pc.compactionSize() > expandedCompactionByteSizeLimit( - opts, pc.adjustedOutputLevel, diskAvailBytes) { + opts, adjustedOutputLevel(pc.outputLevel.level, pc.baseLevel), diskAvailBytes) { // Don't add a level if the current compaction exceeds the compaction size limit return pc } - return opts.Experimental.MultiLevelCompactionHueristic.pick(pc, opts, diskAvailBytes) + return opts.Experimental.MultiLevelCompactionHeuristic.pick(pc, opts, diskAvailBytes) } // MultiLevelHeuristic evaluates whether to add files from the next level into the compaction. type MultiLevelHeuristic interface { - // evaluate returns the preferred compaction. + // Evaluate returns the preferred compaction. pick(pc *pickedCompaction, opts *Options, diskAvailBytes uint64) *pickedCompaction + + // Returns if the heuristic allows L0 to be involved in ML compaction + allowL0() bool } // NoMultiLevel will never add an additional level to the compaction. type NoMultiLevel struct{} +var _ MultiLevelHeuristic = (*NoMultiLevel)(nil) + func (nml NoMultiLevel) pick( pc *pickedCompaction, opts *Options, diskAvailBytes uint64, ) *pickedCompaction { return pc } +func (nml NoMultiLevel) allowL0() bool { + return false +} + +func (pc *pickedCompaction) predictedWriteAmp() float64 { + var bytesToCompact uint64 + var higherLevelBytes uint64 + for i := range pc.inputs { + levelSize := pc.inputs[i].files.SizeSum() + bytesToCompact += levelSize + if i != len(pc.inputs)-1 { + higherLevelBytes += levelSize + } + } + return float64(bytesToCompact) / float64(higherLevelBytes) +} + +func (pc *pickedCompaction) overlappingRatio() float64 { + var higherLevelBytes uint64 + var lowestLevelBytes uint64 + for i := range pc.inputs { + levelSize := pc.inputs[i].files.SizeSum() + if i == len(pc.inputs)-1 { + lowestLevelBytes += levelSize + continue + } + higherLevelBytes += levelSize + } + return float64(lowestLevelBytes) / float64(higherLevelBytes) +} + +// WriteAmpHeuristic defines a multi level compaction heuristic which will add +// an additional level to the picked compaction if it reduces predicted write +// amp of the compaction + the addPropensity constant. +type WriteAmpHeuristic struct { + // addPropensity is a constant that affects the propensity to conduct multilevel + // compactions. If positive, a multilevel compaction may get picked even if + // the single level compaction has lower write amp, and vice versa. + AddPropensity float64 + + // AllowL0 if true, allow l0 to be involved in a ML compaction. + AllowL0 bool +} + +var _ MultiLevelHeuristic = (*WriteAmpHeuristic)(nil) + +// TODO(msbutler): microbenchmark the extent to which multilevel compaction +// picking slows down the compaction picking process. This should be as fast as +// possible since Compaction-picking holds d.mu, which prevents WAL rotations, +// in-progress flushes and compactions from completing, etc. Consider ways to +// deduplicate work, given that setupInputs has already been called. +func (wa WriteAmpHeuristic) pick( + pcOrig *pickedCompaction, opts *Options, diskAvailBytes uint64, +) *pickedCompaction { + pcMulti := pcOrig.clone() + if !pcMulti.setupMultiLevelCandidate(opts, diskAvailBytes) { + return pcOrig + } + picked := pcOrig + if pcMulti.predictedWriteAmp() <= pcOrig.predictedWriteAmp()+wa.AddPropensity { + picked = pcMulti + } + // Regardless of what compaction was picked, log the multilevelOverlapping ratio. + picked.pickerMetrics.multiLevelOverlappingRatio = pcMulti.overlappingRatio() + return picked +} + +func (wa WriteAmpHeuristic) allowL0() bool { + return wa.AllowL0 +} + // Helper method to pick compactions originating from L0. Uses information about // sublevels to generate a compaction. -func pickL0( - env compactionEnv, opts *Options, vers *version, baseLevel int, diskAvailBytes func() uint64, -) (pc *pickedCompaction) { +func pickL0(env compactionEnv, opts *Options, vers *version, baseLevel int) (pc *pickedCompaction) { // It is important to pass information about Lbase files to L0Sublevels // so it can pick a compaction that does not conflict with an Lbase => Lbase+1 // compaction. Without this, we observed reduced concurrency of L0=>Lbase @@ -1677,16 +1812,16 @@ func pickL0( // has been shown to not cause a performance regression. lcf, err := vers.L0Sublevels.PickBaseCompaction(1, vers.Levels[baseLevel].Slice()) if err != nil { - opts.Logger.Infof("error when picking base compaction: %s", err) + opts.Logger.Errorf("error when picking base compaction: %s", err) return } if lcf != nil { pc = newPickedCompactionFromL0(lcf, opts, vers, baseLevel, true) - pc.setupInputs(opts, diskAvailBytes(), pc.startLevel) + pc.setupInputs(opts, env.diskAvailBytes, pc.startLevel) if pc.startLevel.files.Empty() { opts.Logger.Fatalf("empty compaction chosen") } - return pc + return pc.maybeAddLevel(opts, env.diskAvailBytes) } // Couldn't choose a base compaction. Try choosing an intra-L0 @@ -1695,12 +1830,12 @@ func pickL0( // counterproductive. lcf, err = vers.L0Sublevels.PickIntraL0Compaction(env.earliestUnflushedSeqNum, minIntraL0Count) if err != nil { - opts.Logger.Infof("error when picking intra-L0 compaction: %s", err) + opts.Logger.Errorf("error when picking intra-L0 compaction: %s", err) return } if lcf != nil { pc = newPickedCompactionFromL0(lcf, opts, vers, 0, false) - if !pc.setupInputs(opts, diskAvailBytes(), pc.startLevel) { + if !pc.setupInputs(opts, env.diskAvailBytes, pc.startLevel) { return nil } if pc.startLevel.files.Empty() { @@ -1719,17 +1854,13 @@ func pickL0( return pc } -func (p *compactionPickerByScore) pickManual( - env compactionEnv, manual *manualCompaction, +func pickManualCompaction( + vers *version, opts *Options, env compactionEnv, baseLevel int, manual *manualCompaction, ) (pc *pickedCompaction, retryLater bool) { - if p == nil { - return nil, false - } - outputLevel := manual.level + 1 if manual.level == 0 { - outputLevel = p.baseLevel - } else if manual.level < p.baseLevel { + outputLevel = baseLevel + } else if manual.level < baseLevel { // The start level for a compaction must be >= Lbase. A manual // compaction could have been created adhering to that condition, and // then an automatic compaction came in and compacted all of the @@ -1743,11 +1874,22 @@ func (p *compactionPickerByScore) pickManual( // it, the compaction is dropped due to pc.setupInputs returning false since // the input/output range is already being compacted, and the manual // compaction ends with a non-compacted LSM. - if conflictsWithInProgress(manual, outputLevel, env.inProgressCompactions, p.opts.Comparer.Compare) { + if conflictsWithInProgress(manual, outputLevel, env.inProgressCompactions, opts.Comparer.Compare) { return nil, true } - pc = pickManualHelper(p.opts, manual, p.vers, p.baseLevel, p.diskAvailBytes, p.levelMaxBytes) - if pc == nil { + pc = newPickedCompaction(opts, vers, manual.level, defaultOutputLevel(manual.level, baseLevel), baseLevel) + manual.outputLevel = pc.outputLevel.level + pc.startLevel.files = vers.Overlaps(manual.level, opts.Comparer.Compare, manual.start, manual.end, false) + if pc.startLevel.files.Empty() { + // Nothing to do + return nil, false + } + if !pc.setupInputs(opts, env.diskAvailBytes, pc.startLevel) { + // setupInputs returned false indicating there's a conflicting + // concurrent compaction. + return nil, true + } + if pc = pc.maybeAddLevel(opts, env.diskAvailBytes); pc == nil { return nil, false } if pc.outputLevel.level != outputLevel { @@ -1764,28 +1906,6 @@ func (p *compactionPickerByScore) pickManual( return pc, false } -func pickManualHelper( - opts *Options, - manual *manualCompaction, - vers *version, - baseLevel int, - diskAvailBytes func() uint64, - levelMaxBytes [7]int64, -) (pc *pickedCompaction) { - pc = newPickedCompaction(opts, vers, manual.level, defaultOutputLevel(manual.level, baseLevel), baseLevel) - manual.outputLevel = pc.outputLevel.level - cmp := opts.Comparer.Compare - pc.startLevel.files = vers.Overlaps(manual.level, cmp, manual.start, manual.end, false) - if pc.startLevel.files.Empty() { - // Nothing to do - return nil - } - if !pc.setupInputs(opts, diskAvailBytes(), pc.startLevel) { - return nil - } - return pc.maybeAddLevel(opts, diskAvailBytes()) -} - func (p *compactionPickerByScore) pickReadTriggeredCompaction( env compactionEnv, ) (pc *pickedCompaction) { @@ -1831,7 +1951,7 @@ func pickReadTriggeredCompactionHelper( pc = newPickedCompaction(p.opts, p.vers, rc.level, defaultOutputLevel(rc.level, p.baseLevel), p.baseLevel) pc.startLevel.files = overlapSlice - if !pc.setupInputs(p.opts, p.diskAvailBytes(), pc.startLevel) { + if !pc.setupInputs(p.opts, env.diskAvailBytes, pc.startLevel) { return nil } if inputRangeAlreadyCompacting(env, pc) { diff --git a/vendor/github.com/cockroachdb/pebble/db.go b/vendor/github.com/cockroachdb/pebble/db.go index d95f4e68f..d9f27bc4b 100644 --- a/vendor/github.com/cockroachdb/pebble/db.go +++ b/vendor/github.com/cockroachdb/pebble/db.go @@ -18,6 +18,7 @@ import ( "github.com/cockroachdb/errors" "github.com/cockroachdb/pebble/internal/arenaskl" "github.com/cockroachdb/pebble/internal/base" + "github.com/cockroachdb/pebble/internal/invalidating" "github.com/cockroachdb/pebble/internal/invariants" "github.com/cockroachdb/pebble/internal/keyspan" "github.com/cockroachdb/pebble/internal/manifest" @@ -29,6 +30,7 @@ import ( "github.com/cockroachdb/pebble/sstable" "github.com/cockroachdb/pebble/vfs" "github.com/cockroachdb/pebble/vfs/atomicfs" + "github.com/cockroachdb/tokenbucket" "github.com/prometheus/client_golang/prometheus" ) @@ -73,7 +75,11 @@ type Reader interface { // NewIter returns an iterator that is unpositioned (Iterator.Valid() will // return false). The iterator can be positioned via a call to SeekGE, // SeekLT, First or Last. - NewIter(o *IterOptions) *Iterator + NewIter(o *IterOptions) (*Iterator, error) + + // NewIterWithContext is like NewIter, and additionally accepts a context + // for tracing. + NewIterWithContext(ctx context.Context, o *IterOptions) (*Iterator, error) // Close closes the Reader. It may or may not close any underlying io.Reader // or io.Writer, depending on how the DB was created. @@ -253,9 +259,14 @@ func (d defaultCPUWorkGranter) CPUWorkDone(_ CPUWorkHandle) {} type DB struct { // The count and size of referenced memtables. This includes memtables // present in DB.mu.mem.queue, as well as memtables that have been flushed - // but are still referenced by an inuse readState. + // but are still referenced by an inuse readState, as well as up to one + // memTable waiting to be reused and stored in d.memTableRecycle. memTableCount atomic.Int64 memTableReserved atomic.Int64 // number of bytes reserved in the cache for memtables + // memTableRecycle holds a pointer to an obsolete memtable. The next + // memtable allocation will reuse this memtable if it has not already been + // recycled. + memTableRecycle atomic.Pointer[memTable] // The size of the current log file (i.e. db.mu.log.queue[len(queue)-1]. logSize atomic.Uint64 @@ -274,7 +285,7 @@ type DB struct { abbreviatedKey AbbreviatedKey // The threshold for determining when a batch is "large" and will skip being // inserted into a memtable. - largeBatchThreshold int + largeBatchThreshold uint64 // The current OPTIONS file number. optionsFileNum base.DiskFileNum // The on-disk size of the current OPTIONS file. @@ -309,9 +320,6 @@ type DB struct { closedCh chan struct{} cleanupManager *cleanupManager - // testingAlwaysWaitForCleanup is set by some tests to force waiting for - // obsolete file deletion (to make events deterministic). - testingAlwaysWaitForCleanup bool // During an iterator close, we may asynchronously schedule read compactions. // We want to wait for those goroutines to finish, before closing the DB. @@ -401,7 +409,7 @@ type DB struct { // is allocated up to Options.MemTableSize. This reduces the memory // footprint of memtables when lots of DB instances are used concurrently // in test environments. - nextSize int + nextSize uint64 } compact struct { @@ -552,8 +560,7 @@ func (d *DB) getInternal(key []byte, b *Batch, s *Snapshot) ([]byte, io.Closer, get := &buf.get *get = getIter{ logger: d.opts.Logger, - cmp: d.cmp, - equal: d.equal, + comparer: d.opts.Comparer, newIters: d.newIters, snapshot: seqNum, key: key, @@ -801,6 +808,9 @@ func (d *DB) applyInternal(batch *Batch, opts *WriteOptions, noSyncWait bool) er if err := d.closed.Load(); err != nil { panic(err) } + if batch.committing { + panic("pebble: batch already committing") + } if batch.applied.Load() { panic("pebble: batch already applied") } @@ -831,11 +841,12 @@ func (d *DB) applyInternal(batch *Batch, opts *WriteOptions, noSyncWait bool) er } // TODO(jackson): Assert that all range key operands are suffixless. } + batch.committing = true if batch.db == nil { batch.refreshMemTableSize() } - if int(batch.memTableSize) >= d.largeBatchThreshold { + if batch.memTableSize >= d.largeBatchThreshold { batch.flushable = newFlushableBatch(batch, d.opts.Comparer) } if err := d.commit.Commit(batch, sync, noSyncWait); err != nil { @@ -974,12 +985,46 @@ var iterAllocPool = sync.Pool{ }, } +// snapshotIterOpts denotes snapshot-related iterator options when calling +// newIter. These are the possible cases for a snapshotIterOpts: +// - No snapshot: All fields are zero values. +// - Classic snapshot: Only `seqNum` is set. The latest readState will be used +// and the specified seqNum will be used as the snapshot seqNum. +// - EventuallyFileOnlySnapshot (EFOS) behaving as a classic snapshot. Only +// the `seqNum` is set. The latest readState will be used +// and the specified seqNum will be used as the snapshot seqNum. +// - EFOS in file-only state: Only `seqNum` and `vers` are set. All the +// relevant SSTs are referenced by the *version. +type snapshotIterOpts struct { + seqNum uint64 + vers *version +} + +type batchIterOpts struct { + batchOnly bool +} +type newIterOpts struct { + snapshot snapshotIterOpts + batch batchIterOpts +} + // newIter constructs a new iterator, merging in batch iterators as an extra // level. -func (d *DB) newIter(ctx context.Context, batch *Batch, s *Snapshot, o *IterOptions) *Iterator { +func (d *DB) newIter( + ctx context.Context, batch *Batch, internalOpts newIterOpts, o *IterOptions, +) *Iterator { + if internalOpts.batch.batchOnly { + if batch == nil { + panic("batchOnly is true, but batch is nil") + } + if internalOpts.snapshot.vers != nil { + panic("batchOnly is true, but snapshotIterOpts is initialized") + } + } if err := d.closed.Load(); err != nil { panic(err) } + seqNum := internalOpts.snapshot.seqNum if o.rangeKeys() { if d.FormatMajorVersion() < FormatRangeKeys { panic(fmt.Sprintf( @@ -991,25 +1036,35 @@ func (d *DB) newIter(ctx context.Context, batch *Batch, s *Snapshot, o *IterOpti if o != nil && o.RangeKeyMasking.Suffix != nil && o.KeyTypes != IterKeyTypePointsAndRanges { panic("pebble: range key masking requires IterKeyTypePointsAndRanges") } - if (batch != nil || s != nil) && (o != nil && o.OnlyReadGuaranteedDurable) { + if (batch != nil || seqNum != 0) && (o != nil && o.OnlyReadGuaranteedDurable) { // We could add support for OnlyReadGuaranteedDurable on snapshots if // there was a need: this would require checking that the sequence number // of the snapshot has been flushed, by comparing with // DB.mem.queue[0].logSeqNum. panic("OnlyReadGuaranteedDurable is not supported for batches or snapshots") } - // Grab and reference the current readState. This prevents the underlying - // files in the associated version from being deleted if there is a current - // compaction. The readState is unref'd by Iterator.Close(). - readState := d.loadReadState() + var readState *readState + var newIters tableNewIters + var newIterRangeKey keyspan.TableNewSpanIter + if !internalOpts.batch.batchOnly { + // Grab and reference the current readState. This prevents the underlying + // files in the associated version from being deleted if there is a current + // compaction. The readState is unref'd by Iterator.Close(). + if internalOpts.snapshot.vers == nil { + // NB: loadReadState() calls readState.ref(). + readState = d.loadReadState() + } else { + // vers != nil + internalOpts.snapshot.vers.Ref() + } - // Determine the seqnum to read at after grabbing the read state (current and - // memtables) above. - var seqNum uint64 - if s != nil { - seqNum = s.seqNum - } else { - seqNum = d.mu.versions.visibleSeqNum.Load() + // Determine the seqnum to read at after grabbing the read state (current and + // memtables) above. + if seqNum == 0 { + seqNum = d.mu.versions.visibleSeqNum.Load() + } + newIters = d.newIters + newIterRangeKey = d.tableNewRangeKeyIter } // Bundle various structures under a single umbrella in order to allocate @@ -1022,13 +1077,15 @@ func (d *DB) newIter(ctx context.Context, batch *Batch, s *Snapshot, o *IterOpti merge: d.merge, comparer: *d.opts.Comparer, readState: readState, + version: internalOpts.snapshot.vers, keyBuf: buf.keyBuf, prefixOrFullSeekKey: buf.prefixOrFullSeekKey, boundsBuf: buf.boundsBuf, batch: batch, - newIters: d.newIters, - newIterRangeKey: d.tableNewRangeKeyIter, + newIters: newIters, + newIterRangeKey: newIterRangeKey, seqNum: seqNum, + batchOnlyIter: internalOpts.batch.batchOnly, } if o != nil { dbi.opts = *o @@ -1051,7 +1108,10 @@ func (d *DB) newIter(ctx context.Context, batch *Batch, s *Snapshot, o *IterOpti func finishInitializingIter(ctx context.Context, buf *iterAlloc) *Iterator { // Short-hand. dbi := &buf.dbi - memtables := dbi.readState.memtables + var memtables flushableList + if dbi.readState != nil { + memtables = dbi.readState.memtables + } if dbi.opts.OnlyReadGuaranteedDurable { memtables = nil } else { @@ -1113,6 +1173,7 @@ func finishInitializingIter(ctx context.Context, buf *iterAlloc) *Iterator { }, } dbi.iter = &dbi.lazyCombinedIter + dbi.iter = invalidating.MaybeWrapIfInvariants(dbi.iter) } else { dbi.lazyCombinedIter.combinedIterState = combinedIterState{ initialized: true, @@ -1133,7 +1194,11 @@ func finishInitializingIter(ctx context.Context, buf *iterAlloc) *Iterator { // dbi already had an initialized range key iterator, in case the point // iterator changed or the range key masking suffix changed. dbi.rangeKey.iiter.Init(&dbi.comparer, dbi.iter, dbi.rangeKey.rangeKeyIter, - &dbi.rangeKeyMasking, dbi.opts.LowerBound, dbi.opts.UpperBound) + keyspan.InterleavingIterOpts{ + Mask: &dbi.rangeKeyMasking, + LowerBound: dbi.opts.LowerBound, + UpperBound: dbi.opts.UpperBound, + }) dbi.iter = &dbi.rangeKey.iiter } } else { @@ -1172,22 +1237,29 @@ func finishInitializingIter(ctx context.Context, buf *iterAlloc) *Iterator { // iteration is invalid in those cases. func (d *DB) ScanInternal( ctx context.Context, + categoryAndQoS sstable.CategoryAndQoS, lower, upper []byte, - visitPointKey func(key *InternalKey, value LazyValue) error, + visitPointKey func(key *InternalKey, value LazyValue, iterInfo IteratorLevel) error, visitRangeDel func(start, end []byte, seqNum uint64) error, visitRangeKey func(start, end []byte, keys []rangekey.Key) error, visitSharedFile func(sst *SharedSSTMeta) error, ) error { - iter := d.newInternalIter(nil /* snapshot */, &scanInternalOptions{ + scanInternalOpts := &scanInternalOptions{ + CategoryAndQoS: categoryAndQoS, + visitPointKey: visitPointKey, + visitRangeDel: visitRangeDel, + visitRangeKey: visitRangeKey, + visitSharedFile: visitSharedFile, + skipSharedLevels: visitSharedFile != nil, IterOptions: IterOptions{ KeyTypes: IterKeyTypePointsAndRanges, LowerBound: lower, UpperBound: upper, }, - skipSharedLevels: visitSharedFile != nil, - }) + } + iter := d.newInternalIter(ctx, snapshotIterOpts{} /* snapshot */, scanInternalOpts) defer iter.close() - return scanInternalImpl(ctx, lower, upper, iter, visitPointKey, visitRangeDel, visitRangeKey, visitSharedFile) + return scanInternalImpl(ctx, lower, upper, iter, scanInternalOpts) } // newInternalIter constructs and returns a new scanInternalIterator on this db. @@ -1197,39 +1269,47 @@ func (d *DB) ScanInternal( // TODO(bilal): This method has a lot of similarities with db.newIter as well as // finishInitializingIter. Both pairs of methods should be refactored to reduce // this duplication. -func (d *DB) newInternalIter(s *Snapshot, o *scanInternalOptions) *scanInternalIterator { +func (d *DB) newInternalIter( + ctx context.Context, sOpts snapshotIterOpts, o *scanInternalOptions, +) *scanInternalIterator { if err := d.closed.Load(); err != nil { panic(err) } // Grab and reference the current readState. This prevents the underlying // files in the associated version from being deleted if there is a current // compaction. The readState is unref'd by Iterator.Close(). - readState := d.loadReadState() + var readState *readState + if sOpts.vers == nil { + readState = d.loadReadState() + } + if sOpts.vers != nil { + sOpts.vers.Ref() + } // Determine the seqnum to read at after grabbing the read state (current and // memtables) above. - var seqNum uint64 - if s == nil { + seqNum := sOpts.seqNum + if seqNum == 0 { seqNum = d.mu.versions.visibleSeqNum.Load() - } else { - seqNum = s.seqNum } // Bundle various structures under a single umbrella in order to allocate // them together. buf := iterAllocPool.Get().(*iterAlloc) dbi := &scanInternalIterator{ + ctx: ctx, + db: d, comparer: d.opts.Comparer, merge: d.opts.Merger.Merge, readState: readState, + version: sOpts.vers, alloc: buf, newIters: d.newIters, newIterRangeKey: d.tableNewRangeKeyIter, seqNum: seqNum, + mergingIter: &buf.merging, } - if o != nil { - dbi.opts = *o - } + dbi.opts = *o dbi.opts.logger = d.opts.Logger if d.opts.private.disableLazyCombinedIteration { dbi.opts.disableLazyCombinedIteration = true @@ -1239,7 +1319,10 @@ func (d *DB) newInternalIter(s *Snapshot, o *scanInternalOptions) *scanInternalI func finishInitializingInternalIter(buf *iterAlloc, i *scanInternalIterator) *scanInternalIterator { // Short-hand. - memtables := i.readState.memtables + var memtables flushableList + if i.readState != nil { + memtables = i.readState.memtables + } // We only need to read from memtables which contain sequence numbers older // than seqNum. Trim off newer memtables. for j := len(memtables) - 1; j >= 0; j-- { @@ -1250,7 +1333,7 @@ func finishInitializingInternalIter(buf *iterAlloc, i *scanInternalIterator) *sc } i.initializeBoundBufs(i.opts.LowerBound, i.opts.UpperBound) - i.constructPointIter(memtables, buf) + i.constructPointIter(i.opts.CategoryAndQoS, memtables, buf) // For internal iterators, we skip the lazy combined iteration optimization // entirely, and create the range key iterator stack directly. @@ -1262,7 +1345,10 @@ func finishInitializingInternalIter(buf *iterAlloc, i *scanInternalIterator) *sc // iterator that interleaves range keys pulled from // i.rangeKey.rangeKeyIter. i.rangeKey.iiter.Init(i.comparer, i.iter, i.rangeKey.rangeKeyIter, - nil /* mask */, i.opts.LowerBound, i.opts.UpperBound) + keyspan.InterleavingIterOpts{ + LowerBound: i.opts.LowerBound, + UpperBound: i.opts.UpperBound, + }) i.iter = &i.rangeKey.iiter return i @@ -1292,17 +1378,24 @@ func (i *Iterator) constructPointIter( if i.batch != nil { numMergingLevels++ } - numMergingLevels += len(memtables) - current := i.readState.current - numMergingLevels += len(current.L0SublevelFiles) - numLevelIters += len(current.L0SublevelFiles) - for level := 1; level < len(current.Levels); level++ { - if current.Levels[level].Empty() { - continue + var current *version + if !i.batchOnlyIter { + numMergingLevels += len(memtables) + + current = i.version + if current == nil { + current = i.readState.current + } + numMergingLevels += len(current.L0SublevelFiles) + numLevelIters += len(current.L0SublevelFiles) + for level := 1; level < len(current.Levels); level++ { + if current.Levels[level].Empty() { + continue + } + numMergingLevels++ + numLevelIters++ } - numMergingLevels++ - numLevelIters++ } if numMergingLevels > cap(mlevels) { @@ -1340,47 +1433,49 @@ func (i *Iterator) constructPointIter( } } - // Next are the memtables. - for j := len(memtables) - 1; j >= 0; j-- { - mem := memtables[j] - mlevels = append(mlevels, mergingIterLevel{ - iter: mem.newIter(&i.opts), - rangeDelIter: mem.newRangeDelIter(&i.opts), - }) - } - - // Next are the file levels: L0 sub-levels followed by lower levels. - mlevelsIndex := len(mlevels) - levelsIndex := len(levels) - mlevels = mlevels[:numMergingLevels] - levels = levels[:numLevelIters] - i.opts.snapshotForHideObsoletePoints = buf.dbi.seqNum - addLevelIterForFiles := func(files manifest.LevelIterator, level manifest.Level) { - li := &levels[levelsIndex] - - li.init( - ctx, i.opts, i.comparer.Compare, i.comparer.Split, i.newIters, files, level, internalOpts) - li.initRangeDel(&mlevels[mlevelsIndex].rangeDelIter) - li.initBoundaryContext(&mlevels[mlevelsIndex].levelIterBoundaryContext) - li.initCombinedIterState(&i.lazyCombinedIter.combinedIterState) - mlevels[mlevelsIndex].iter = li + if !i.batchOnlyIter { + // Next are the memtables. + for j := len(memtables) - 1; j >= 0; j-- { + mem := memtables[j] + mlevels = append(mlevels, mergingIterLevel{ + iter: mem.newIter(&i.opts), + rangeDelIter: mem.newRangeDelIter(&i.opts), + }) + } - levelsIndex++ - mlevelsIndex++ - } + // Next are the file levels: L0 sub-levels followed by lower levels. + mlevelsIndex := len(mlevels) + levelsIndex := len(levels) + mlevels = mlevels[:numMergingLevels] + levels = levels[:numLevelIters] + i.opts.snapshotForHideObsoletePoints = buf.dbi.seqNum + addLevelIterForFiles := func(files manifest.LevelIterator, level manifest.Level) { + li := &levels[levelsIndex] + + li.init(ctx, i.opts, &i.comparer, i.newIters, files, level, internalOpts) + li.initRangeDel(&mlevels[mlevelsIndex].rangeDelIter) + li.initBoundaryContext(&mlevels[mlevelsIndex].levelIterBoundaryContext) + li.initCombinedIterState(&i.lazyCombinedIter.combinedIterState) + mlevels[mlevelsIndex].levelIter = li + mlevels[mlevelsIndex].iter = invalidating.MaybeWrapIfInvariants(li) + + levelsIndex++ + mlevelsIndex++ + } - // Add level iterators for the L0 sublevels, iterating from newest to - // oldest. - for i := len(current.L0SublevelFiles) - 1; i >= 0; i-- { - addLevelIterForFiles(current.L0SublevelFiles[i].Iter(), manifest.L0Sublevel(i)) - } + // Add level iterators for the L0 sublevels, iterating from newest to + // oldest. + for i := len(current.L0SublevelFiles) - 1; i >= 0; i-- { + addLevelIterForFiles(current.L0SublevelFiles[i].Iter(), manifest.L0Sublevel(i)) + } - // Add level iterators for the non-empty non-L0 levels. - for level := 1; level < len(current.Levels); level++ { - if current.Levels[level].Empty() { - continue + // Add level iterators for the non-empty non-L0 levels. + for level := 1; level < len(current.Levels); level++ { + if current.Levels[level].Empty() { + continue + } + addLevelIterForFiles(current.Levels[level].Iter(), manifest.Level(level)) } - addLevelIterForFiles(current.Levels[level].Iter(), manifest.Level(level)) } buf.merging.init(&i.opts, &i.stats.InternalStats, i.comparer.Compare, i.comparer.Split, mlevels...) if len(mlevels) <= cap(buf.levelsPositioned) { @@ -1389,7 +1484,7 @@ func (i *Iterator) constructPointIter( buf.merging.snapshot = i.seqNum buf.merging.batchSnapshot = i.batchSeqNum buf.merging.combinedIterState = &i.lazyCombinedIter.combinedIterState - i.pointIter = &buf.merging + i.pointIter = invalidating.MaybeWrapIfInvariants(&buf.merging) i.merging = &buf.merging } @@ -1399,6 +1494,12 @@ func (d *DB) NewBatch() *Batch { return newBatch(d) } +// NewBatchWithSize is mostly identical to NewBatch, but it will allocate the +// the specified memory space for the internal slice in advance. +func (d *DB) NewBatchWithSize(size int) *Batch { + return newBatchWithSize(d, size) +} + // NewIndexedBatch returns a new empty read-write batch. Any reads on the batch // will read from both the batch and the DB. If the batch is committed it will // be applied to the DB. An indexed batch is slower that a non-indexed batch @@ -1408,6 +1509,12 @@ func (d *DB) NewIndexedBatch() *Batch { return newIndexedBatch(d, d.opts.Comparer) } +// NewIndexedBatchWithSize is mostly identical to NewIndexedBatch, but it will +// allocate the the specified memory space for the internal slice in advance. +func (d *DB) NewIndexedBatchWithSize(size int) *Batch { + return newIndexedBatchWithSize(d, d.opts.Comparer, size) +} + // NewIter returns an iterator that is unpositioned (Iterator.Valid() will // return false). The iterator can be positioned via a call to SeekGE, SeekLT, // First or Last. The iterator provides a point-in-time view of the current DB @@ -1416,14 +1523,14 @@ func (d *DB) NewIndexedBatch() *Batch { // to maintain a long-lived point-in-time view of the DB state can lead to an // apparent memory and disk usage leak. Use snapshots (see NewSnapshot) for // point-in-time snapshots which avoids these problems. -func (d *DB) NewIter(o *IterOptions) *Iterator { +func (d *DB) NewIter(o *IterOptions) (*Iterator, error) { return d.NewIterWithContext(context.Background(), o) } // NewIterWithContext is like NewIter, and additionally accepts a context for // tracing. -func (d *DB) NewIterWithContext(ctx context.Context, o *IterOptions) *Iterator { - return d.newIter(ctx, nil /* batch */, nil /* snapshot */, o) +func (d *DB) NewIterWithContext(ctx context.Context, o *IterOptions) (*Iterator, error) { + return d.newIter(ctx, nil /* batch */, newIterOpts{}, o), nil } // NewSnapshot returns a point-in-time view of the current DB state. Iterators @@ -1449,6 +1556,29 @@ func (d *DB) NewSnapshot() *Snapshot { return s } +// NewEventuallyFileOnlySnapshot returns a point-in-time view of the current DB +// state, similar to NewSnapshot, but with consistency constrained to the +// provided set of key ranges. See the comment at EventuallyFileOnlySnapshot for +// its semantics. +func (d *DB) NewEventuallyFileOnlySnapshot(keyRanges []KeyRange) *EventuallyFileOnlySnapshot { + if err := d.closed.Load(); err != nil { + panic(err) + } + + internalKeyRanges := make([]internalKeyRange, len(keyRanges)) + for i := range keyRanges { + if i > 0 && d.cmp(keyRanges[i-1].End, keyRanges[i].Start) > 0 { + panic("pebble: key ranges for eventually-file-only-snapshot not in order") + } + internalKeyRanges[i] = internalKeyRange{ + smallest: base.MakeInternalKey(keyRanges[i].Start, InternalKeySeqNumMax, InternalKeyKindMax), + largest: base.MakeExclusiveSentinelKey(InternalKeyKindRangeDelete, keyRanges[i].End), + } + } + + return d.makeEventuallyFileOnlySnapshot(keyRanges, internalKeyRanges) +} + // Close closes the DB. // // It is not safe to close a DB until all outstanding iterators are closed @@ -1540,6 +1670,10 @@ func (d *DB) Close() error { // replay. mem.readerUnrefLocked(false) } + // If there's an unused, recycled memtable, we need to release its memory. + if obsoleteMemTable := d.memTableRecycle.Swap(nil); obsoleteMemTable != nil { + d.freeMemTable(obsoleteMemTable) + } if reserved := d.memTableReserved.Load(); reserved != 0 { err = firstError(err, errors.Errorf("leaked memtable reservation: %d", errors.Safe(reserved))) } @@ -1615,6 +1749,10 @@ func (d *DB) Compact(start, end []byte, parallelize bool) error { } } + keyRanges := make([]internalKeyRange, len(meta)) + for i := range meta { + keyRanges[i] = internalKeyRange{smallest: m.Smallest, largest: m.Largest} + } // Determine if any memtable overlaps with the compaction range. We wait for // any such overlap to flush (initiating a flush if necessary). mem, err := func() (*flushableEntry, error) { @@ -1624,7 +1762,7 @@ func (d *DB) Compact(start, end []byte, parallelize bool) error { // overlaps. for i := len(d.mu.mem.queue) - 1; i >= 0; i-- { mem := d.mu.mem.queue[i] - if ingestMemtableOverlaps(d.cmp, mem, meta) { + if ingestMemtableOverlaps(d.cmp, mem, keyRanges) { var err error if mem.flushable == d.mu.mem.mutable { // We have to hold both commitPipeline.mu and DB.mu when calling @@ -1657,9 +1795,15 @@ func (d *DB) Compact(start, end []byte, parallelize bool) error { } for level := 0; level < maxLevelWithFiles; { - if err := d.manualCompact( - iStart.UserKey, iEnd.UserKey, level, parallelize); err != nil { - return err + for { + if err := d.manualCompact( + iStart.UserKey, iEnd.UserKey, level, parallelize); err != nil { + if errors.Is(err, ErrCancelledCompaction) { + continue + } + return err + } + break } level++ if level == numLevels-1 { @@ -1734,6 +1878,30 @@ func (d *DB) splitManualCompaction( return splitCompactions } +// DownloadSpan is a key range passed to the Download method. +type DownloadSpan struct { + StartKey []byte + // EndKey is exclusive. + EndKey []byte +} + +// Download ensures that the LSM does not use any external sstables for the +// given key ranges. It does so by performing appropriate compactions so that +// all external data becomes available locally. +// +// Note that calling this method does not imply that all other compactions stop; +// it simply informs Pebble of a list of spans for which external data should be +// downloaded with high priority. +// +// The method returns once no external sstasbles overlap the given spans, the +// context is canceled, or an error is hit. +// +// TODO(radu): consider passing a priority/impact knob to express how important +// the download is (versus live traffic performance, LSM health). +func (d *DB) Download(ctx context.Context, spans []DownloadSpan) error { + return errors.Errorf("not implemented") +} + // Flush the memtable to stable storage. func (d *DB) Flush() error { flushDone, err := d.AsyncFlush() @@ -1838,11 +2006,22 @@ func (d *DB) Metrics() *Metrics { d.mu.versions.logLock() metrics.private.manifestFileSize = uint64(d.mu.versions.manifest.Size()) + metrics.Table.BackingTableCount = uint64(len(d.mu.versions.backingState.fileBackingMap)) + metrics.Table.BackingTableSize = d.mu.versions.backingState.fileBackingSize + if invariants.Enabled { + var totalSize uint64 + for _, backing := range d.mu.versions.backingState.fileBackingMap { + totalSize += backing.Size + } + if totalSize != metrics.Table.BackingTableSize { + panic("pebble: invalid backing table size accounting") + } + } d.mu.versions.logUnlock() metrics.LogWriter.FsyncLatency = d.mu.log.metrics.fsyncLatency if err := metrics.LogWriter.Merge(&d.mu.log.metrics.LogWriterMetrics); err != nil { - d.opts.Logger.Infof("metrics error: %s", err) + d.opts.Logger.Errorf("metrics error: %s", err) } metrics.Flush.WriteThroughput = d.mu.compact.flushWriteThroughput if d.mu.compact.flushing { @@ -1857,7 +2036,12 @@ func (d *DB) Metrics() *Metrics { metrics.BlockCache = d.opts.Cache.Metrics() metrics.TableCache, metrics.Filter = d.tableCache.metrics() metrics.TableIters = int64(d.tableCache.iterCount()) + metrics.CategoryStats = d.tableCache.dbOpts.sstStatsCollector.GetStats() + + metrics.SecondaryCacheMetrics = d.objProvider.Metrics() + metrics.Uptime = d.timeNow().Sub(d.openedAt) + return metrics } @@ -1988,7 +2172,6 @@ func (d *DB) SSTables(opts ...SSTablesOption) ([][]SSTableInfo, error) { if opt.start != nil && opt.end != nil && !m.Overlaps(d.opts.Comparer.Compare, opt.start, opt.end, true /* exclusive end */) { continue } - destTables[j] = SSTableInfo{TableInfo: m.TableInfo()} if opt.withProperties { p, err := d.tableCache.getTableProperties( @@ -2007,7 +2190,7 @@ func (d *DB) SSTables(opts ...SSTablesOption) ([][]SSTableInfo, error) { } if objMeta.IsRemote() { if objMeta.IsShared() { - if d.objProvider.IsForeign(objMeta) { + if d.objProvider.IsSharedForeign(objMeta) { destTables[j].BackingType = BackingTypeSharedForeign } else { destTables[j].BackingType = BackingTypeShared @@ -2163,10 +2346,10 @@ func (d *DB) walPreallocateSize() int { // RocksDB. Could a smaller preallocation block size be used? size := d.opts.MemTableSize size = (size / 10) + size - return size + return int(size) } -func (d *DB) newMemTable(logNum FileNum, logSeqNum uint64) (*memTable, *flushableEntry) { +func (d *DB) newMemTable(logNum base.DiskFileNum, logSeqNum uint64) (*memTable, *flushableEntry) { size := d.mu.mem.nextSize if d.mu.mem.nextSize < d.opts.MemTableSize { d.mu.mem.nextSize *= 2 @@ -2175,31 +2358,71 @@ func (d *DB) newMemTable(logNum FileNum, logSeqNum uint64) (*memTable, *flushabl } } - d.memTableCount.Add(1) - d.memTableReserved.Add(int64(size)) - releaseAccountingReservation := d.opts.Cache.Reserve(size) - - mem := newMemTable(memTableOptions{ + memtblOpts := memTableOptions{ Options: d.opts, - arenaBuf: manual.New(int(size)), logSeqNum: logSeqNum, - }) + } - // Note: this is a no-op if invariants are disabled or race is enabled. - invariants.SetFinalizer(mem, checkMemTable) + // Before attempting to allocate a new memtable, check if there's one + // available for recycling in memTableRecycle. Large contiguous allocations + // can be costly as fragmentation makes it more difficult to find a large + // contiguous free space. We've observed 64MB allocations taking 10ms+. + // + // To reduce these costly allocations, up to 1 obsolete memtable is stashed + // in `d.memTableRecycle` to allow a future memtable rotation to reuse + // existing memory. + var mem *memTable + mem = d.memTableRecycle.Swap(nil) + if mem != nil && uint64(len(mem.arenaBuf)) != size { + d.freeMemTable(mem) + mem = nil + } + if mem != nil { + // Carry through the existing buffer and memory reservation. + memtblOpts.arenaBuf = mem.arenaBuf + memtblOpts.releaseAccountingReservation = mem.releaseAccountingReservation + } else { + mem = new(memTable) + memtblOpts.arenaBuf = manual.New(int(size)) + memtblOpts.releaseAccountingReservation = d.opts.Cache.Reserve(int(size)) + d.memTableCount.Add(1) + d.memTableReserved.Add(int64(size)) + + // Note: this is a no-op if invariants are disabled or race is enabled. + invariants.SetFinalizer(mem, checkMemTable) + } + mem.init(memtblOpts) entry := d.newFlushableEntry(mem, logNum, logSeqNum) entry.releaseMemAccounting = func() { - manual.Free(mem.arenaBuf) - mem.arenaBuf = nil - d.memTableCount.Add(-1) - d.memTableReserved.Add(-int64(size)) - releaseAccountingReservation() + // If the user leaks iterators, we may be releasing the memtable after + // the DB is already closed. In this case, we want to just release the + // memory because DB.Close won't come along to free it for us. + if err := d.closed.Load(); err != nil { + d.freeMemTable(mem) + return + } + + // The next memtable allocation might be able to reuse this memtable. + // Stash it on d.memTableRecycle. + if unusedMem := d.memTableRecycle.Swap(mem); unusedMem != nil { + // There was already a memtable waiting to be recycled. We're now + // responsible for freeing it. + d.freeMemTable(unusedMem) + } } return mem, entry } -func (d *DB) newFlushableEntry(f flushable, logNum FileNum, logSeqNum uint64) *flushableEntry { +func (d *DB) freeMemTable(m *memTable) { + d.memTableCount.Add(-1) + d.memTableReserved.Add(-int64(len(m.arenaBuf))) + m.free() +} + +func (d *DB) newFlushableEntry( + f flushable, logNum base.DiskFileNum, logSeqNum uint64, +) *flushableEntry { fe := &flushableEntry{ flushable: f, flushed: make(chan struct{}), @@ -2249,7 +2472,7 @@ func (d *DB) makeRoomForWrite(b *Batch) error { for i := range d.mu.mem.queue { size += d.mu.mem.queue[i].totalBytes() } - if size >= uint64(d.opts.MemTableStopWritesThreshold)*uint64(d.opts.MemTableSize) { + if size >= uint64(d.opts.MemTableStopWritesThreshold)*d.opts.MemTableSize { // We have filled up the current memtable, but already queued memtables // are still flushing, so we wait. if !stalled { @@ -2283,7 +2506,7 @@ func (d *DB) makeRoomForWrite(b *Batch) error { continue } - var newLogNum base.FileNum + var newLogNum base.DiskFileNum var prevLogSize uint64 if !d.opts.DisableWAL { now := time.Now() @@ -2303,7 +2526,7 @@ func (d *DB) makeRoomForWrite(b *Batch) error { // reduces memtable memory pressure when an application is frequently // manually flushing. if (b == nil) && uint64(immMem.availBytes()) > immMem.totalBytes()/2 { - d.mu.mem.nextSize = int(immMem.totalBytes()) + d.mu.mem.nextSize = immMem.totalBytes() } if b != nil && b.flushable != nil { @@ -2340,7 +2563,7 @@ func (d *DB) makeRoomForWrite(b *Batch) error { } // Both DB.mu and commitPipeline.mu must be held by the caller. -func (d *DB) rotateMemtable(newLogNum FileNum, logSeqNum uint64, prev *memTable) { +func (d *DB) rotateMemtable(newLogNum base.DiskFileNum, logSeqNum uint64, prev *memTable) { // Create a new memtable, scheduling the previous one for flushing. We do // this even if the previous memtable was empty because the DB.Flush // mechanism is dependent on being able to wait for the empty memtable to @@ -2367,14 +2590,14 @@ func (d *DB) rotateMemtable(newLogNum FileNum, logSeqNum uint64, prev *memTable) // Both DB.mu and commitPipeline.mu must be held by the caller. Note that DB.mu // may be released and reacquired. -func (d *DB) recycleWAL() (newLogNum FileNum, prevLogSize uint64) { +func (d *DB) recycleWAL() (newLogNum base.DiskFileNum, prevLogSize uint64) { if d.opts.DisableWAL { panic("pebble: invalid function call") } jobID := d.mu.nextJobID d.mu.nextJobID++ - newLogNum = d.mu.versions.getNextFileNum() + newLogNum = d.mu.versions.getNextDiskFileNum() prevLogSize = uint64(d.mu.log.Size()) @@ -2396,11 +2619,11 @@ func (d *DB) recycleWAL() (newLogNum FileNum, prevLogSize uint64) { metrics := d.mu.log.LogWriter.Metrics() d.mu.Lock() if err := d.mu.log.metrics.Merge(metrics); err != nil { - d.opts.Logger.Infof("metrics error: %s", err) + d.opts.Logger.Errorf("metrics error: %s", err) } d.mu.Unlock() - newLogName := base.MakeFilepath(d.opts.FS, d.walDirname, fileTypeLog, newLogNum.DiskFileNum()) + newLogName := base.MakeFilepath(d.opts.FS, d.walDirname, fileTypeLog, newLogNum) // Try to use a recycled log file. Recycling log files is an important // performance optimization as it is faster to sync a file that has @@ -2481,7 +2704,7 @@ func (d *DB) recycleWAL() (newLogNum FileNum, prevLogSize uint64) { panic(err) } - d.mu.log.queue = append(d.mu.log.queue, fileInfo{fileNum: newLogNum.DiskFileNum(), fileSize: newLogSize}) + d.mu.log.queue = append(d.mu.log.queue, fileInfo{fileNum: newLogNum, fileSize: newLogSize}) d.mu.log.LogWriter = record.NewLogWriter(newLogFile, newLogNum, record.LogWriterConfig{ WALFsyncLatency: d.mu.log.metrics.fsyncLatency, WALMinSyncInterval: d.opts.WALMinSyncInterval, @@ -2573,8 +2796,234 @@ func (d *DB) SetCreatorID(creatorID uint64) error { return d.objProvider.SetCreatorID(objstorage.CreatorID(creatorID)) } +// KeyStatistics keeps track of the number of keys that have been pinned by a +// snapshot as well as counts of the different key kinds in the lsm. +// +// One way of using the accumulated stats, when we only have sets and dels, +// and say the counts are represented as del_count, set_count, +// del_latest_count, set_latest_count, snapshot_pinned_count. +// +// - del_latest_count + set_latest_count is the set of unique user keys +// (unique). +// +// - set_latest_count is the set of live unique user keys (live_unique). +// +// - Garbage is del_count + set_count - live_unique. +// +// - If everything were in the LSM, del_count+set_count-snapshot_pinned_count +// would also be the set of unique user keys (note that +// snapshot_pinned_count is counting something different -- see comment below). +// But snapshot_pinned_count only counts keys in the LSM so the excess here +// must be keys in memtables. +type KeyStatistics struct { + // TODO(sumeer): the SnapshotPinned* are incorrect in that these older + // versions can be in a different level. Either fix the accounting or + // rename these fields. + + // SnapshotPinnedKeys represents obsolete keys that cannot be elided during + // a compaction, because they are required by an open snapshot. + SnapshotPinnedKeys int + // SnapshotPinnedKeysBytes is the total number of bytes of all snapshot + // pinned keys. + SnapshotPinnedKeysBytes uint64 + // KindsCount is the count for each kind of key. It includes point keys, + // range deletes and range keys. + KindsCount [InternalKeyKindMax + 1]int + // LatestKindsCount is the count for each kind of key when it is the latest + // kind for a user key. It is only populated for point keys. + LatestKindsCount [InternalKeyKindMax + 1]int +} + +// LSMKeyStatistics is used by DB.ScanStatistics. +type LSMKeyStatistics struct { + Accumulated KeyStatistics + // Levels contains statistics only for point keys. Range deletions and range keys will + // appear in Accumulated but not Levels. + Levels [numLevels]KeyStatistics + // BytesRead represents the logical, pre-compression size of keys and values read + BytesRead uint64 +} + +// ScanStatisticsOptions is used by DB.ScanStatistics. +type ScanStatisticsOptions struct { + // LimitBytesPerSecond indicates the number of bytes that are able to be read + // per second using ScanInternal. + // A value of 0 indicates that there is no limit set. + LimitBytesPerSecond int64 +} + +// ScanStatistics returns the count of different key kinds within the lsm for a +// key span [lower, upper) as well as the number of snapshot keys. +func (d *DB) ScanStatistics( + ctx context.Context, lower, upper []byte, opts ScanStatisticsOptions, +) (LSMKeyStatistics, error) { + stats := LSMKeyStatistics{} + var prevKey InternalKey + var rateLimitFunc func(key *InternalKey, val LazyValue) error + tb := tokenbucket.TokenBucket{} + + if opts.LimitBytesPerSecond != 0 { + // Each "token" roughly corresponds to a byte that was read. + tb.Init(tokenbucket.TokensPerSecond(opts.LimitBytesPerSecond), tokenbucket.Tokens(1024)) + rateLimitFunc = func(key *InternalKey, val LazyValue) error { + return tb.WaitCtx(ctx, tokenbucket.Tokens(key.Size()+val.Len())) + } + } + + scanInternalOpts := &scanInternalOptions{ + visitPointKey: func(key *InternalKey, value LazyValue, iterInfo IteratorLevel) error { + // If the previous key is equal to the current point key, the current key was + // pinned by a snapshot. + size := uint64(key.Size()) + kind := key.Kind() + sameKey := d.equal(prevKey.UserKey, key.UserKey) + if iterInfo.Kind == IteratorLevelLSM && sameKey { + stats.Levels[iterInfo.Level].SnapshotPinnedKeys++ + stats.Levels[iterInfo.Level].SnapshotPinnedKeysBytes += size + stats.Accumulated.SnapshotPinnedKeys++ + stats.Accumulated.SnapshotPinnedKeysBytes += size + } + if iterInfo.Kind == IteratorLevelLSM { + stats.Levels[iterInfo.Level].KindsCount[kind]++ + } + if !sameKey { + if iterInfo.Kind == IteratorLevelLSM { + stats.Levels[iterInfo.Level].LatestKindsCount[kind]++ + } + stats.Accumulated.LatestKindsCount[kind]++ + } + + stats.Accumulated.KindsCount[kind]++ + prevKey.CopyFrom(*key) + stats.BytesRead += uint64(key.Size() + value.Len()) + return nil + }, + visitRangeDel: func(start, end []byte, seqNum uint64) error { + stats.Accumulated.KindsCount[InternalKeyKindRangeDelete]++ + stats.BytesRead += uint64(len(start) + len(end)) + return nil + }, + visitRangeKey: func(start, end []byte, keys []rangekey.Key) error { + stats.BytesRead += uint64(len(start) + len(end)) + for _, key := range keys { + stats.Accumulated.KindsCount[key.Kind()]++ + stats.BytesRead += uint64(len(key.Value) + len(key.Suffix)) + } + return nil + }, + includeObsoleteKeys: true, + IterOptions: IterOptions{ + KeyTypes: IterKeyTypePointsAndRanges, + LowerBound: lower, + UpperBound: upper, + }, + rateLimitFunc: rateLimitFunc, + } + iter := d.newInternalIter(ctx, snapshotIterOpts{}, scanInternalOpts) + defer iter.close() + + err := scanInternalImpl(ctx, lower, upper, iter, scanInternalOpts) + + if err != nil { + return LSMKeyStatistics{}, err + } + + return stats, nil +} + // ObjProvider returns the objstorage.Provider for this database. Meant to be // used for internal purposes only. func (d *DB) ObjProvider() objstorage.Provider { return d.objProvider } + +func (d *DB) checkVirtualBounds(m *fileMetadata) { + if !invariants.Enabled { + return + } + + if m.HasPointKeys { + pointIter, rangeDelIter, err := d.newIters(context.TODO(), m, nil, internalIterOpts{}) + if err != nil { + panic(errors.Wrap(err, "pebble: error creating point iterator")) + } + + defer pointIter.Close() + if rangeDelIter != nil { + defer rangeDelIter.Close() + } + + pointKey, _ := pointIter.First() + var rangeDel *keyspan.Span + if rangeDelIter != nil { + rangeDel = rangeDelIter.First() + } + + // Check that the lower bound is tight. + if (rangeDel == nil || d.cmp(rangeDel.SmallestKey().UserKey, m.SmallestPointKey.UserKey) != 0) && + (pointKey == nil || d.cmp(pointKey.UserKey, m.SmallestPointKey.UserKey) != 0) { + panic(errors.Newf("pebble: virtual sstable %s lower point key bound is not tight", m.FileNum)) + } + + pointKey, _ = pointIter.Last() + rangeDel = nil + if rangeDelIter != nil { + rangeDel = rangeDelIter.Last() + } + + // Check that the upper bound is tight. + if (rangeDel == nil || d.cmp(rangeDel.LargestKey().UserKey, m.LargestPointKey.UserKey) != 0) && + (pointKey == nil || d.cmp(pointKey.UserKey, m.LargestPointKey.UserKey) != 0) { + panic(errors.Newf("pebble: virtual sstable %s upper point key bound is not tight", m.FileNum)) + } + + // Check that iterator keys are within bounds. + for key, _ := pointIter.First(); key != nil; key, _ = pointIter.Next() { + if d.cmp(key.UserKey, m.SmallestPointKey.UserKey) < 0 || d.cmp(key.UserKey, m.LargestPointKey.UserKey) > 0 { + panic(errors.Newf("pebble: virtual sstable %s point key %s is not within bounds", m.FileNum, key.UserKey)) + } + } + + if rangeDelIter != nil { + for key := rangeDelIter.First(); key != nil; key = rangeDelIter.Next() { + if d.cmp(key.SmallestKey().UserKey, m.SmallestPointKey.UserKey) < 0 { + panic(errors.Newf("pebble: virtual sstable %s point key %s is not within bounds", m.FileNum, key.SmallestKey().UserKey)) + } + + if d.cmp(key.LargestKey().UserKey, m.LargestPointKey.UserKey) > 0 { + panic(errors.Newf("pebble: virtual sstable %s point key %s is not within bounds", m.FileNum, key.LargestKey().UserKey)) + } + } + } + } + + if !m.HasRangeKeys { + return + } + + rangeKeyIter, err := d.tableNewRangeKeyIter(m, keyspan.SpanIterOptions{}) + defer rangeKeyIter.Close() + + if err != nil { + panic(errors.Wrap(err, "pebble: error creating range key iterator")) + } + + // Check that the lower bound is tight. + if d.cmp(rangeKeyIter.First().SmallestKey().UserKey, m.SmallestRangeKey.UserKey) != 0 { + panic(errors.Newf("pebble: virtual sstable %s lower range key bound is not tight", m.FileNum)) + } + + // Check that upper bound is tight. + if d.cmp(rangeKeyIter.Last().LargestKey().UserKey, m.LargestRangeKey.UserKey) != 0 { + panic(errors.Newf("pebble: virtual sstable %s upper range key bound is not tight", m.FileNum)) + } + + for key := rangeKeyIter.First(); key != nil; key = rangeKeyIter.Next() { + if d.cmp(key.SmallestKey().UserKey, m.SmallestRangeKey.UserKey) < 0 { + panic(errors.Newf("pebble: virtual sstable %s point key %s is not within bounds", m.FileNum, key.SmallestKey().UserKey)) + } + if d.cmp(key.LargestKey().UserKey, m.LargestRangeKey.UserKey) > 0 { + panic(errors.Newf("pebble: virtual sstable %s point key %s is not within bounds", m.FileNum, key.LargestKey().UserKey)) + } + } +} diff --git a/vendor/github.com/cockroachdb/pebble/error_iter.go b/vendor/github.com/cockroachdb/pebble/error_iter.go index de0ed3511..9b23904c9 100644 --- a/vendor/github.com/cockroachdb/pebble/error_iter.go +++ b/vendor/github.com/cockroachdb/pebble/error_iter.go @@ -5,6 +5,8 @@ package pebble import ( + "context" + "github.com/cockroachdb/pebble/internal/base" "github.com/cockroachdb/pebble/internal/keyspan" ) @@ -68,6 +70,8 @@ func (c *errorIter) String() string { func (c *errorIter) SetBounds(lower, upper []byte) {} +func (c *errorIter) SetContext(_ context.Context) {} + type errorKeyspanIter struct { err error } diff --git a/vendor/github.com/cockroachdb/pebble/event.go b/vendor/github.com/cockroachdb/pebble/event.go index 5caccab33..ea527efdf 100644 --- a/vendor/github.com/cockroachdb/pebble/event.go +++ b/vendor/github.com/cockroachdb/pebble/event.go @@ -10,6 +10,7 @@ import ( "time" "github.com/cockroachdb/errors" + "github.com/cockroachdb/pebble/internal/base" "github.com/cockroachdb/pebble/internal/humanize" "github.com/cockroachdb/pebble/internal/invariants" "github.com/cockroachdb/pebble/internal/manifest" @@ -39,10 +40,11 @@ func formatFileNums(tables []TableInfo) string { return buf.String() } -// LevelInfo contains info pertaining to a partificular level. +// LevelInfo contains info pertaining to a particular level. type LevelInfo struct { Level int Tables []TableInfo + Score float64 } func (i LevelInfo) String() string { @@ -51,8 +53,11 @@ func (i LevelInfo) String() string { // SafeFormat implements redact.SafeFormatter. func (i LevelInfo) SafeFormat(w redact.SafePrinter, _ rune) { - w.Printf("L%d [%s] (%s)", redact.Safe(i.Level), redact.Safe(formatFileNums(i.Tables)), - redact.Safe(humanize.Bytes.Uint64(tablesTotalSize(i.Tables)))) + w.Printf("L%d [%s] (%s) Score=%.2f", + redact.Safe(i.Level), + redact.Safe(formatFileNums(i.Tables)), + redact.Safe(humanize.Bytes.Uint64(tablesTotalSize(i.Tables))), + redact.Safe(i.Score)) } // CompactionInfo contains the info for a compaction event. @@ -75,6 +80,27 @@ type CompactionInfo struct { TotalDuration time.Duration Done bool Err error + + SingleLevelOverlappingRatio float64 + MultiLevelOverlappingRatio float64 + + // Annotations specifies additional info to appear in a compaction's event log line + Annotations compactionAnnotations +} + +type compactionAnnotations []string + +// SafeFormat implements redact.SafeFormatter. +func (ca compactionAnnotations) SafeFormat(w redact.SafePrinter, _ rune) { + if len(ca) == 0 { + return + } + for i := range ca { + if i != 0 { + w.Print(" ") + } + w.Printf("%s", redact.SafeString(ca[i])) + } } func (i CompactionInfo) String() string { @@ -90,12 +116,17 @@ func (i CompactionInfo) SafeFormat(w redact.SafePrinter, _ rune) { } if !i.Done { - w.Printf("[JOB %d] compacting(%s) ", redact.Safe(i.JobID), redact.SafeString(i.Reason)) - w.Print(levelInfos(i.Input)) + w.Printf("[JOB %d] compacting(%s) ", + redact.Safe(i.JobID), + redact.SafeString(i.Reason)) + w.Printf("%s", i.Annotations) + w.Printf("%s; ", levelInfos(i.Input)) + w.Printf("OverlappingRatio: Single %.2f, Multi %.2f", i.SingleLevelOverlappingRatio, i.MultiLevelOverlappingRatio) return } outputSize := tablesTotalSize(i.Output.Tables) w.Printf("[JOB %d] compacted(%s) ", redact.Safe(i.JobID), redact.SafeString(i.Reason)) + w.Printf("%s", i.Annotations) w.Print(levelInfos(i.Input)) w.Printf(" -> L%d [%s] (%s), in %.1fs (%.1fs total), output rate %s/s", redact.Safe(i.Output.Level), @@ -129,6 +160,9 @@ type FlushInfo struct { Reason string // Input contains the count of input memtables that were flushed. Input int + // InputBytes contains the total in-memory size of the memtable(s) that were + // flushed. This size includes skiplist indexing data structures. + InputBytes uint64 // Output contains the ouptut table generated by the flush. The output info // is empty for the flush begin event. Output []TableInfo @@ -168,7 +202,7 @@ func (i FlushInfo) SafeFormat(w redact.SafePrinter, _ rune) { if !i.Ingest { w.Printf("flushing %d memtable", redact.Safe(i.Input)) w.SafeString(plural) - w.Printf(" to L0") + w.Printf(" (%s) to L0", redact.Safe(humanize.Bytes.Uint64(i.InputBytes))) } else { w.Printf("flushing %d ingested table%s", redact.Safe(i.Input), plural) } @@ -180,8 +214,9 @@ func (i FlushInfo) SafeFormat(w redact.SafePrinter, _ rune) { if invariants.Enabled && len(i.IngestLevels) > 0 { panic(errors.AssertionFailedf("pebble: expected len(IngestedLevels) == 0")) } - w.Printf("[JOB %d] flushed %d memtable%s to L0 [%s] (%s), in %.1fs (%.1fs total), output rate %s/s", + w.Printf("[JOB %d] flushed %d memtable%s (%s) to L0 [%s] (%s), in %.1fs (%.1fs total), output rate %s/s", redact.Safe(i.JobID), redact.Safe(i.Input), plural, + redact.Safe(humanize.Bytes.Uint64(i.InputBytes)), redact.Safe(formatFileNums(i.Output)), redact.Safe(humanize.Bytes.Uint64(outputSize)), redact.Safe(i.Duration.Seconds()), @@ -198,7 +233,7 @@ func (i FlushInfo) SafeFormat(w redact.SafePrinter, _ rune) { if j > 0 { w.Printf(" +") } - w.Printf(" L%d:%s (%s)", level, redact.Safe(file.FileNum), humanize.Bytes.Uint64(file.Size)) + w.Printf(" L%d:%s (%s)", level, file.FileNum, humanize.Bytes.Uint64(file.Size)) } w.Printf(" in %.1fs (%.1fs total), output rate %s/s", redact.Safe(i.Duration.Seconds()), @@ -213,7 +248,7 @@ type ManifestCreateInfo struct { JobID int Path string // The file number of the new Manifest. - FileNum FileNum + FileNum base.DiskFileNum Err error } @@ -227,7 +262,7 @@ func (i ManifestCreateInfo) SafeFormat(w redact.SafePrinter, _ rune) { w.Printf("[JOB %d] MANIFEST create error: %s", redact.Safe(i.JobID), i.Err) return } - w.Printf("[JOB %d] MANIFEST created %s", redact.Safe(i.JobID), redact.Safe(i.FileNum)) + w.Printf("[JOB %d] MANIFEST created %s", redact.Safe(i.JobID), i.FileNum) } // ManifestDeleteInfo contains the info for a Manifest deletion event. @@ -249,7 +284,7 @@ func (i ManifestDeleteInfo) SafeFormat(w redact.SafePrinter, _ rune) { w.Printf("[JOB %d] MANIFEST delete error: %s", redact.Safe(i.JobID), i.Err) return } - w.Printf("[JOB %d] MANIFEST deleted %s", redact.Safe(i.JobID), redact.Safe(i.FileNum)) + w.Printf("[JOB %d] MANIFEST deleted %s", redact.Safe(i.JobID), i.FileNum) } // TableCreateInfo contains the info for a table creation event. @@ -269,7 +304,7 @@ func (i TableCreateInfo) String() string { // SafeFormat implements redact.SafeFormatter. func (i TableCreateInfo) SafeFormat(w redact.SafePrinter, _ rune) { w.Printf("[JOB %d] %s: sstable created %s", - redact.Safe(i.JobID), redact.Safe(i.Reason), redact.Safe(i.FileNum)) + redact.Safe(i.JobID), redact.Safe(i.Reason), i.FileNum) } // TableDeleteInfo contains the info for a table deletion event. @@ -288,10 +323,10 @@ func (i TableDeleteInfo) String() string { func (i TableDeleteInfo) SafeFormat(w redact.SafePrinter, _ rune) { if i.Err != nil { w.Printf("[JOB %d] sstable delete error %s: %s", - redact.Safe(i.JobID), redact.Safe(i.FileNum), i.Err) + redact.Safe(i.JobID), i.FileNum, i.Err) return } - w.Printf("[JOB %d] sstable deleted %s", redact.Safe(i.JobID), redact.Safe(i.FileNum)) + w.Printf("[JOB %d] sstable deleted %s", redact.Safe(i.JobID), i.FileNum) } // TableIngestInfo contains the info for a table ingestion event. @@ -337,7 +372,7 @@ func (i TableIngestInfo) SafeFormat(w redact.SafePrinter, _ rune) { if !i.flushable { levelStr = fmt.Sprintf("L%d:", t.Level) } - w.Printf(" %s%s (%s)", redact.Safe(levelStr), redact.Safe(t.FileNum), + w.Printf(" %s%s (%s)", redact.Safe(levelStr), t.FileNum, redact.Safe(humanize.Bytes.Uint64(t.Size))) } } @@ -380,7 +415,7 @@ type WALCreateInfo struct { JobID int Path string // The file number of the new WAL. - FileNum FileNum + FileNum base.DiskFileNum // The file number of a previous WAL which was recycled to create this // one. Zero if recycling did not take place. RecycledFileNum FileNum @@ -399,12 +434,12 @@ func (i WALCreateInfo) SafeFormat(w redact.SafePrinter, _ rune) { } if i.RecycledFileNum == 0 { - w.Printf("[JOB %d] WAL created %s", redact.Safe(i.JobID), redact.Safe(i.FileNum)) + w.Printf("[JOB %d] WAL created %s", redact.Safe(i.JobID), i.FileNum) return } w.Printf("[JOB %d] WAL created %s (recycled %s)", - redact.Safe(i.JobID), redact.Safe(i.FileNum), redact.Safe(i.RecycledFileNum)) + redact.Safe(i.JobID), i.FileNum, i.RecycledFileNum) } // WALDeleteInfo contains the info for a WAL deletion event. @@ -426,7 +461,7 @@ func (i WALDeleteInfo) SafeFormat(w redact.SafePrinter, _ rune) { w.Printf("[JOB %d] WAL delete error: %s", redact.Safe(i.JobID), i.Err) return } - w.Printf("[JOB %d] WAL deleted %s", redact.Safe(i.JobID), redact.Safe(i.FileNum)) + w.Printf("[JOB %d] WAL deleted %s", redact.Safe(i.JobID), i.FileNum) } // WriteStallBeginInfo contains the info for a write stall begin event. @@ -527,7 +562,7 @@ func (l *EventListener) EnsureDefaults(logger Logger) { if l.BackgroundError == nil { if logger != nil { l.BackgroundError = func(err error) { - logger.Infof("background error: %s", err) + logger.Errorf("background error: %s", err) } } else { l.BackgroundError = func(error) {} @@ -595,7 +630,7 @@ func MakeLoggingEventListener(logger Logger) EventListener { return EventListener{ BackgroundError: func(err error) { - logger.Infof("background error: %s", err) + logger.Errorf("background error: %s", err) }, CompactionBegin: func(info CompactionInfo) { logger.Infof("%s", info) diff --git a/vendor/github.com/cockroachdb/pebble/external_iterator.go b/vendor/github.com/cockroachdb/pebble/external_iterator.go index 8fbef76e7..2c156fd38 100644 --- a/vendor/github.com/cockroachdb/pebble/external_iterator.go +++ b/vendor/github.com/cockroachdb/pebble/external_iterator.go @@ -217,7 +217,8 @@ func createExternalPointIter(ctx context.Context, it *Iterator) (internalIterato pointIter, err = r.NewIterWithBlockPropertyFiltersAndContextEtc( ctx, it.opts.LowerBound, it.opts.UpperBound, nil, /* BlockPropertiesFilterer */ false /* hideObsoletePoints */, false, /* useFilterBlock */ - &it.stats.InternalStats, sstable.TrivialReaderProvider{Reader: r}) + &it.stats.InternalStats, it.opts.CategoryAndQoS, nil, + sstable.TrivialReaderProvider{Reader: r}) if err != nil { return nil, err } @@ -319,8 +320,12 @@ func finishInitializingExternal(ctx context.Context, it *Iterator) { } } if it.rangeKey != nil { - it.rangeKey.iiter.Init(&it.comparer, it.iter, it.rangeKey.rangeKeyIter, &it.rangeKeyMasking, - it.opts.LowerBound, it.opts.UpperBound) + it.rangeKey.iiter.Init(&it.comparer, it.iter, it.rangeKey.rangeKeyIter, + keyspan.InterleavingIterOpts{ + Mask: &it.rangeKeyMasking, + LowerBound: it.opts.LowerBound, + UpperBound: it.opts.UpperBound, + }) it.iter = &it.rangeKey.iiter } } @@ -541,6 +546,8 @@ func (s *simpleLevelIter) SetBounds(lower, upper []byte) { s.resetFilteredIters() } +func (s *simpleLevelIter) SetContext(_ context.Context) {} + func (s *simpleLevelIter) String() string { if s.currentIdx < 0 || s.currentIdx >= len(s.filtered) { return "simpleLevelIter: current=" diff --git a/vendor/github.com/cockroachdb/pebble/flushable.go b/vendor/github.com/cockroachdb/pebble/flushable.go index 474d410c5..473dc6adf 100644 --- a/vendor/github.com/cockroachdb/pebble/flushable.go +++ b/vendor/github.com/cockroachdb/pebble/flushable.go @@ -10,6 +10,7 @@ import ( "sync/atomic" "time" + "github.com/cockroachdb/pebble/internal/base" "github.com/cockroachdb/pebble/internal/keyspan" "github.com/cockroachdb/pebble/internal/manifest" ) @@ -46,7 +47,7 @@ type flushableEntry struct { delayedFlushForcedAt time.Time // logNum corresponds to the WAL that contains the records present in the // receiver. - logNum FileNum + logNum base.DiskFileNum // logSize is the size in bytes of the associated WAL. Protected by DB.mu. logSize uint64 // The current logSeqNum at the time the memtable was created. This is @@ -117,8 +118,7 @@ type flushableList []*flushableEntry // ingesting sstables which are added to the flushable list. type ingestedFlushable struct { files []physicalMeta - cmp Compare - split Split + comparer *Comparer newIters tableNewIters newRangeKeyIters keyspan.TableNewSpanIter @@ -131,8 +131,7 @@ type ingestedFlushable struct { func newIngestedFlushable( files []*fileMetadata, - cmp Compare, - split Split, + comparer *Comparer, newIters tableNewIters, newRangeKeyIters keyspan.TableNewSpanIter, ) *ingestedFlushable { @@ -147,12 +146,11 @@ func newIngestedFlushable( ret := &ingestedFlushable{ files: physicalFiles, - cmp: cmp, - split: split, + comparer: comparer, newIters: newIters, newRangeKeyIters: newRangeKeyIters, // slice is immutable and can be set once and used many times. - slice: manifest.NewLevelSliceKeySorted(cmp, files), + slice: manifest.NewLevelSliceKeySorted(comparer.Compare, files), hasRangeKeys: hasRangeKeys, } @@ -162,6 +160,7 @@ func newIngestedFlushable( // TODO(sumeer): ingestedFlushable iters also need to plumb context for // tracing. +// newIter is part of the flushable interface. func (s *ingestedFlushable) newIter(o *IterOptions) internalIterator { var opts IterOptions if o != nil { @@ -172,10 +171,12 @@ func (s *ingestedFlushable) newIter(o *IterOptions) internalIterator { // aren't truly levels in the lsm. Right now, the encoding only supports // L0 sublevels, and the rest of the levels in the lsm. return newLevelIter( - opts, s.cmp, s.split, s.newIters, s.slice.Iter(), manifest.Level(0), internalIterOpts{}, + context.Background(), opts, s.comparer, s.newIters, s.slice.Iter(), manifest.Level(0), + internalIterOpts{}, ) } +// newFlushIter is part of the flushable interface. func (s *ingestedFlushable) newFlushIter(o *IterOptions, bytesFlushed *uint64) internalIterator { // newFlushIter is only used for writing memtables to disk as sstables. // Since ingested sstables are already present on disk, they don't need to @@ -199,41 +200,50 @@ func (s *ingestedFlushable) constructRangeDelIter( return rangeDelIter, nil } +// newRangeDelIter is part of the flushable interface. // TODO(bananabrick): Using a level iter instead of a keyspan level iter to // surface range deletes is more efficient. +// +// TODO(sumeer): *IterOptions are being ignored, so the index block load for +// the point iterator in constructRangeDeIter is not tracked. func (s *ingestedFlushable) newRangeDelIter(_ *IterOptions) keyspan.FragmentIterator { return keyspan.NewLevelIter( - keyspan.SpanIterOptions{}, s.cmp, + keyspan.SpanIterOptions{}, s.comparer.Compare, s.constructRangeDelIter, s.slice.Iter(), manifest.Level(0), manifest.KeyTypePoint, ) } +// newRangeKeyIter is part of the flushable interface. func (s *ingestedFlushable) newRangeKeyIter(o *IterOptions) keyspan.FragmentIterator { if !s.containsRangeKeys() { return nil } return keyspan.NewLevelIter( - keyspan.SpanIterOptions{}, s.cmp, s.newRangeKeyIters, + keyspan.SpanIterOptions{}, s.comparer.Compare, s.newRangeKeyIters, s.slice.Iter(), manifest.Level(0), manifest.KeyTypeRange, ) } +// containsRangeKeys is part of the flushable interface. func (s *ingestedFlushable) containsRangeKeys() bool { return s.hasRangeKeys } +// inuseBytes is part of the flushable interface. func (s *ingestedFlushable) inuseBytes() uint64 { // inuseBytes is only used when memtables are flushed to disk as sstables. panic("pebble: not implemented") } +// totalBytes is part of the flushable interface. func (s *ingestedFlushable) totalBytes() uint64 { // We don't allocate additional bytes for the ingestedFlushable. return 0 } +// readyForFlush is part of the flushable interface. func (s *ingestedFlushable) readyForFlush() bool { // ingestedFlushable should always be ready to flush. However, note that // memtables before the ingested sstables in the memtable queue must be diff --git a/vendor/github.com/cockroachdb/pebble/format_major_version.go b/vendor/github.com/cockroachdb/pebble/format_major_version.go index 92dd34574..baa67cf2b 100644 --- a/vendor/github.com/cockroachdb/pebble/format_major_version.go +++ b/vendor/github.com/cockroachdb/pebble/format_major_version.go @@ -28,10 +28,13 @@ import ( // FormatVersion that the default corresponds to may change with time. type FormatMajorVersion uint64 +// SafeValue implements redact.SafeValue. +func (v FormatMajorVersion) SafeValue() {} + // String implements fmt.Stringer. func (v FormatMajorVersion) String() string { - // NB: This must not change. It's used as the value for the the - // on-disk version marker file. + // NB: This must not change. It's used as the value for the on-disk + // version marker file. // // Specifically, this value must always parse as a base 10 integer // that fits in a uint64. We format it as zero-padded, 3-digit @@ -151,20 +154,20 @@ const ( // compactions for files marked for compaction are complete. FormatPrePebblev1MarkedCompacted - // ExperimentalFormatDeleteSizedAndObsolete is a format major version that adds support + // FormatDeleteSizedAndObsolete is a format major version that adds support // for deletion tombstones that encode the size of the value they're // expected to delete. This format major version is required before the // associated key kind may be committed through batch applications or // ingests. It also adds support for keys that are marked obsolete (see // sstable/format.go for details). - ExperimentalFormatDeleteSizedAndObsolete + FormatDeleteSizedAndObsolete - // ExperimentalFormatVirtualSSTables is a format major version that adds support for + // FormatVirtualSSTables is a format major version that adds support for // virtual sstables that can reference a sub-range of keys in an underlying // physical sstable. This information is persisted through new, // backward-incompatible fields in the Manifest, and therefore requires // a format major version. - ExperimentalFormatVirtualSSTables + FormatVirtualSSTables // internalFormatNewest holds the newest format major version, including // experimental ones excluded from the exported FormatNewest constant until @@ -172,8 +175,7 @@ const ( internalFormatNewest FormatMajorVersion = iota - 1 // FormatNewest always contains the most recent format major version. - // TODO(jackson): restore FormatNewest to internalFormatNewest. - FormatNewest FormatMajorVersion = FormatPrePebblev1MarkedCompacted + FormatNewest FormatMajorVersion = internalFormatNewest ) // MaxTableFormat returns the maximum sstable.TableFormat that can be used at @@ -191,7 +193,7 @@ func (v FormatMajorVersion) MaxTableFormat() sstable.TableFormat { return sstable.TableFormatPebblev2 case FormatSSTableValueBlocks, FormatFlushableIngest, FormatPrePebblev1MarkedCompacted: return sstable.TableFormatPebblev3 - case ExperimentalFormatDeleteSizedAndObsolete, ExperimentalFormatVirtualSSTables: + case FormatDeleteSizedAndObsolete, FormatVirtualSSTables: return sstable.TableFormatPebblev4 default: panic(fmt.Sprintf("pebble: unsupported format major version: %s", v)) @@ -210,7 +212,7 @@ func (v FormatMajorVersion) MinTableFormat() sstable.TableFormat { case FormatMinTableFormatPebblev1, FormatPrePebblev1Marked, FormatUnusedPrePebblev1MarkedCompacted, FormatSSTableValueBlocks, FormatFlushableIngest, FormatPrePebblev1MarkedCompacted, - ExperimentalFormatDeleteSizedAndObsolete, ExperimentalFormatVirtualSSTables: + FormatDeleteSizedAndObsolete, FormatVirtualSSTables: return sstable.TableFormatPebblev1 default: panic(fmt.Sprintf("pebble: unsupported format major version: %s", v)) @@ -242,7 +244,7 @@ var formatMajorVersionMigrations = map[FormatMajorVersion]func(*DB) error{ // guaranteed to exist, because we unconditionally locate it // during Open. manifestFileNum := d.mu.versions.manifestFileNum - filename := base.MakeFilename(fileTypeManifest, manifestFileNum.DiskFileNum()) + filename := base.MakeFilename(fileTypeManifest, manifestFileNum) if err := d.mu.versions.manifestMarker.Move(filename); err != nil { return errors.Wrap(err, "moving manifest marker") } @@ -343,11 +345,11 @@ var formatMajorVersionMigrations = map[FormatMajorVersion]func(*DB) error{ } return d.finalizeFormatVersUpgrade(FormatPrePebblev1MarkedCompacted) }, - ExperimentalFormatDeleteSizedAndObsolete: func(d *DB) error { - return d.finalizeFormatVersUpgrade(ExperimentalFormatDeleteSizedAndObsolete) + FormatDeleteSizedAndObsolete: func(d *DB) error { + return d.finalizeFormatVersUpgrade(FormatDeleteSizedAndObsolete) }, - ExperimentalFormatVirtualSSTables: func(d *DB) error { - return d.finalizeFormatVersUpgrade(ExperimentalFormatVirtualSSTables) + FormatVirtualSSTables: func(d *DB) error { + return d.finalizeFormatVersUpgrade(FormatVirtualSSTables) }, } diff --git a/vendor/github.com/cockroachdb/pebble/get_iter.go b/vendor/github.com/cockroachdb/pebble/get_iter.go index 17d7de313..6ebdd5939 100644 --- a/vendor/github.com/cockroachdb/pebble/get_iter.go +++ b/vendor/github.com/cockroachdb/pebble/get_iter.go @@ -11,6 +11,7 @@ import ( "github.com/cockroachdb/pebble/internal/base" "github.com/cockroachdb/pebble/internal/keyspan" "github.com/cockroachdb/pebble/internal/manifest" + "github.com/cockroachdb/pebble/sstable" ) // getIter is an internal iterator used to perform gets. It iterates through @@ -19,8 +20,7 @@ import ( // lazily. type getIter struct { logger Logger - cmp Compare - equal Equal + comparer *Comparer newIters tableNewIters snapshot uint64 key []byte @@ -83,7 +83,7 @@ func (g *getIter) Next() (*InternalKey, base.LazyValue) { // key. Every call to levelIter.Next() potentially switches to a new // table and thus reinitializes rangeDelIter. if g.rangeDelIter != nil { - g.tombstone = keyspan.Get(g.cmp, g.rangeDelIter, g.key) + g.tombstone = keyspan.Get(g.comparer.Compare, g.rangeDelIter, g.key) if g.err = g.rangeDelIter.Close(); g.err != nil { return nil, base.LazyValue{} } @@ -101,7 +101,7 @@ func (g *getIter) Next() (*InternalKey, base.LazyValue) { g.iter = nil return nil, base.LazyValue{} } - if g.equal(g.key, key.UserKey) { + if g.comparer.Equal(g.key, key.UserKey) { if !key.Visible(g.snapshot, base.InternalKeySeqNumMax) { g.iterKey, g.iterValue = g.iter.Next() continue @@ -158,14 +158,28 @@ func (g *getIter) Next() (*InternalKey, base.LazyValue) { if n := len(g.l0); n > 0 { files := g.l0[n-1].Iter() g.l0 = g.l0[:n-1] - iterOpts := IterOptions{logger: g.logger, snapshotForHideObsoletePoints: g.snapshot} - g.levelIter.init(context.Background(), iterOpts, g.cmp, nil /* split */, g.newIters, + iterOpts := IterOptions{ + // TODO(sumeer): replace with a parameter provided by the caller. + CategoryAndQoS: sstable.CategoryAndQoS{ + Category: "pebble-get", + QoSLevel: sstable.LatencySensitiveQoSLevel, + }, + logger: g.logger, + snapshotForHideObsoletePoints: g.snapshot} + g.levelIter.init(context.Background(), iterOpts, g.comparer, g.newIters, files, manifest.L0Sublevel(n), internalIterOpts{}) g.levelIter.initRangeDel(&g.rangeDelIter) bc := levelIterBoundaryContext{} g.levelIter.initBoundaryContext(&bc) g.iter = &g.levelIter - g.iterKey, g.iterValue = g.iter.SeekGE(g.key, base.SeekGEFlagsNone) + + // Compute the key prefix for bloom filtering if split function is + // specified, or use the user key as default. + prefix := g.key + if g.comparer.Split != nil { + prefix = g.key[:g.comparer.Split(g.key)] + } + g.iterKey, g.iterValue = g.iter.SeekPrefixGE(prefix, g.key, base.SeekGEFlagsNone) if bc.isSyntheticIterBoundsKey || bc.isIgnorableBoundaryKey { g.iterKey = nil g.iterValue = base.LazyValue{} @@ -183,15 +197,27 @@ func (g *getIter) Next() (*InternalKey, base.LazyValue) { continue } - iterOpts := IterOptions{logger: g.logger, snapshotForHideObsoletePoints: g.snapshot} - g.levelIter.init(context.Background(), iterOpts, g.cmp, nil /* split */, g.newIters, + iterOpts := IterOptions{ + // TODO(sumeer): replace with a parameter provided by the caller. + CategoryAndQoS: sstable.CategoryAndQoS{ + Category: "pebble-get", + QoSLevel: sstable.LatencySensitiveQoSLevel, + }, logger: g.logger, snapshotForHideObsoletePoints: g.snapshot} + g.levelIter.init(context.Background(), iterOpts, g.comparer, g.newIters, g.version.Levels[g.level].Iter(), manifest.Level(g.level), internalIterOpts{}) g.levelIter.initRangeDel(&g.rangeDelIter) bc := levelIterBoundaryContext{} g.levelIter.initBoundaryContext(&bc) g.level++ g.iter = &g.levelIter - g.iterKey, g.iterValue = g.iter.SeekGE(g.key, base.SeekGEFlagsNone) + + // Compute the key prefix for bloom filtering if split function is + // specified, or use the user key as default. + prefix := g.key + if g.comparer.Split != nil { + prefix = g.key[:g.comparer.Split(g.key)] + } + g.iterKey, g.iterValue = g.iter.SeekPrefixGE(prefix, g.key, base.SeekGEFlagsNone) if bc.isSyntheticIterBoundsKey || bc.isIgnorableBoundaryKey { g.iterKey = nil g.iterValue = base.LazyValue{} @@ -228,3 +254,5 @@ func (g *getIter) Close() error { func (g *getIter) SetBounds(lower, upper []byte) { panic("pebble: SetBounds unimplemented") } + +func (g *getIter) SetContext(_ context.Context) {} diff --git a/vendor/github.com/cockroachdb/pebble/ingest.go b/vendor/github.com/cockroachdb/pebble/ingest.go index 41ee4875f..c9596e47e 100644 --- a/vendor/github.com/cockroachdb/pebble/ingest.go +++ b/vendor/github.com/cockroachdb/pebble/ingest.go @@ -6,15 +6,18 @@ package pebble import ( "context" + "slices" "sort" "time" "github.com/cockroachdb/errors" "github.com/cockroachdb/pebble/internal/base" + "github.com/cockroachdb/pebble/internal/invariants" "github.com/cockroachdb/pebble/internal/keyspan" "github.com/cockroachdb/pebble/internal/manifest" "github.com/cockroachdb/pebble/internal/private" "github.com/cockroachdb/pebble/objstorage" + "github.com/cockroachdb/pebble/objstorage/remote" "github.com/cockroachdb/pebble/sstable" ) @@ -67,6 +70,13 @@ func (k *KeyRange) Overlaps(cmp base.Compare, m *fileMetadata) bool { return k.OverlapsInternalKeyRange(cmp, m.Smallest, m.Largest) } +// OverlapsKeyRange checks if this span overlaps with the provided KeyRange. +// Note that we aren't checking for full containment of either span in the other, +// just that there's a key x that is in both key ranges. +func (k *KeyRange) OverlapsKeyRange(cmp Compare, span KeyRange) bool { + return cmp(k.Start, span.End) < 0 && cmp(k.End, span.Start) > 0 +} + func ingestValidateKey(opts *Options, key *InternalKey) error { if key.Kind() == InternalKeyKindInvalid { return base.CorruptionErrorf("pebble: external sstable has corrupted key: %s", @@ -79,9 +89,9 @@ func ingestValidateKey(opts *Options, key *InternalKey) error { return nil } -// ingestLoad1Shared loads the fileMetadata for one shared sstable owned or -// shared by another node. It also sets the sequence numbers for a shared sstable. -func ingestLoad1Shared( +// ingestSynthesizeShared constructs a fileMetadata for one shared sstable owned +// or shared by another node. +func ingestSynthesizeShared( opts *Options, sm SharedSSTMeta, fileNum base.DiskFileNum, ) (*fileMetadata, error) { if sm.Size == 0 { @@ -90,44 +100,116 @@ func ingestLoad1Shared( } // Don't load table stats. Doing a round trip to shared storage, one SST // at a time is not worth it as it slows down ingestion. - meta := &fileMetadata{} - meta.FileNum = fileNum.FileNum() - meta.CreationTime = time.Now().Unix() - meta.Virtual = true - meta.Size = sm.Size + meta := &fileMetadata{ + FileNum: fileNum.FileNum(), + CreationTime: time.Now().Unix(), + Virtual: true, + Size: sm.Size, + } meta.InitProviderBacking(fileNum) // Set the underlying FileBacking's size to the same size as the virtualized // view of the sstable. This ensures that we don't over-prioritize this - // sstable for compaction just yet, as we do not have a clear sense of - // what parts of this sstable are referenced by other nodes. + // sstable for compaction just yet, as we do not have a clear sense of what + // parts of this sstable are referenced by other nodes. meta.FileBacking.Size = sm.Size - seqNum := base.SeqNumForLevel(int(sm.Level)) if sm.LargestRangeKey.Valid() && sm.LargestRangeKey.UserKey != nil { - meta.HasRangeKeys = true - meta.SmallestRangeKey = sm.SmallestRangeKey - meta.LargestRangeKey = sm.LargestRangeKey - meta.SmallestRangeKey.SetSeqNum(seqNum) - if !meta.LargestRangeKey.IsExclusiveSentinel() { - meta.LargestRangeKey.SetSeqNum(seqNum) - } - meta.SmallestSeqNum = seqNum - meta.LargestSeqNum = seqNum - // Initialize meta.{Smallest,Largest} and others by calling this. - meta.ExtendRangeKeyBounds(opts.Comparer.Compare, meta.SmallestRangeKey, meta.LargestRangeKey) + // Initialize meta.{HasRangeKeys,Smallest,Largest}, etc. + // + // NB: We create new internal keys and pass them into ExternalRangeKeyBounds + // so that we can sub a zero sequence number into the bounds. We can set + // the sequence number to anything here; it'll be reset in ingestUpdateSeqNum + // anyway. However we do need to use the same sequence number across all + // bound keys at this step so that we end up with bounds that are consistent + // across point/range keys. + smallestRangeKey := base.MakeInternalKey(sm.SmallestRangeKey.UserKey, 0, sm.SmallestRangeKey.Kind()) + largestRangeKey := base.MakeExclusiveSentinelKey(sm.LargestRangeKey.Kind(), sm.LargestRangeKey.UserKey) + meta.ExtendRangeKeyBounds(opts.Comparer.Compare, smallestRangeKey, largestRangeKey) } if sm.LargestPointKey.Valid() && sm.LargestPointKey.UserKey != nil { - meta.HasPointKeys = true - meta.SmallestPointKey = sm.SmallestPointKey - meta.LargestPointKey = sm.LargestPointKey - meta.SmallestPointKey.SetSeqNum(seqNum) - if !meta.LargestPointKey.IsExclusiveSentinel() { - meta.LargestPointKey.SetSeqNum(seqNum) + // Initialize meta.{HasPointKeys,Smallest,Largest}, etc. + // + // See point above in the ExtendRangeKeyBounds call on why we use a zero + // sequence number here. + smallestPointKey := base.MakeInternalKey(sm.SmallestPointKey.UserKey, 0, sm.SmallestPointKey.Kind()) + largestPointKey := base.MakeInternalKey(sm.LargestPointKey.UserKey, 0, sm.LargestPointKey.Kind()) + if sm.LargestPointKey.IsExclusiveSentinel() { + largestPointKey = base.MakeRangeDeleteSentinelKey(sm.LargestPointKey.UserKey) } - meta.SmallestSeqNum = seqNum - meta.LargestSeqNum = seqNum - // Initialize meta.{Smallest,Largest} and others by calling this. - meta.ExtendPointKeyBounds(opts.Comparer.Compare, meta.SmallestPointKey, meta.LargestPointKey) + meta.ExtendPointKeyBounds(opts.Comparer.Compare, smallestPointKey, largestPointKey) } + if err := meta.Validate(opts.Comparer.Compare, opts.Comparer.FormatKey); err != nil { + return nil, err + } + return meta, nil +} + +// ingestLoad1External loads the fileMetadata for one external sstable. +// Sequence number and target level calculation happens during prepare/apply. +func ingestLoad1External( + opts *Options, + e ExternalFile, + fileNum base.DiskFileNum, + objprovider objstorage.Provider, + jobID int, +) (*fileMetadata, error) { + if e.Size == 0 { + // Disallow 0 file sizes + return nil, errors.New("pebble: cannot ingest external file with size 0") + } + if !e.HasRangeKey && !e.HasPointKey { + return nil, errors.New("pebble: cannot ingest external file with no point or range keys") + } + // Don't load table stats. Doing a round trip to shared storage, one SST + // at a time is not worth it as it slows down ingestion. + meta := &fileMetadata{} + meta.FileNum = fileNum.FileNum() + meta.CreationTime = time.Now().Unix() + meta.Virtual = true + meta.Size = e.Size + meta.InitProviderBacking(fileNum) + + // Try to resolve a reference to the external file. + backing, err := objprovider.CreateExternalObjectBacking(e.Locator, e.ObjName) + if err != nil { + return nil, err + } + metas, err := objprovider.AttachRemoteObjects([]objstorage.RemoteObjectToAttach{{ + FileNum: fileNum, + FileType: fileTypeTable, + Backing: backing, + }}) + if err != nil { + return nil, err + } + if opts.EventListener.TableCreated != nil { + opts.EventListener.TableCreated(TableCreateInfo{ + JobID: jobID, + Reason: "ingesting", + Path: objprovider.Path(metas[0]), + FileNum: fileNum.FileNum(), + }) + } + // In the name of keeping this ingestion as fast as possible, we avoid + // *all* existence checks and synthesize a file metadata with smallest/largest + // keys that overlap whatever the passed-in span was. + smallestCopy := make([]byte, len(e.SmallestUserKey)) + copy(smallestCopy, e.SmallestUserKey) + largestCopy := make([]byte, len(e.LargestUserKey)) + copy(largestCopy, e.LargestUserKey) + if e.HasPointKey { + meta.ExtendPointKeyBounds(opts.Comparer.Compare, base.MakeInternalKey(smallestCopy, 0, InternalKeyKindMax), + base.MakeRangeDeleteSentinelKey(largestCopy)) + } + if e.HasRangeKey { + meta.ExtendRangeKeyBounds(opts.Comparer.Compare, base.MakeInternalKey(smallestCopy, 0, InternalKeyKindRangeKeySet), + base.MakeExclusiveSentinelKey(InternalKeyKindRangeKeyDelete, largestCopy)) + } + + // Set the underlying FileBacking's size to the same size as the virtualized + // view of the sstable. This ensures that we don't over-prioritize this + // sstable for compaction just yet, as we do not have a clear sense of + // what parts of this sstable are referenced by other nodes. + meta.FileBacking.Size = e.Size if err := meta.Validate(opts.Comparer.Compare, opts.Comparer.FormatKey); err != nil { return nil, err @@ -283,8 +365,10 @@ func ingestLoad1( type ingestLoadResult struct { localMeta, sharedMeta []*fileMetadata + externalMeta []*fileMetadata localPaths []string sharedLevels []uint8 + fileCount int } func ingestLoad( @@ -292,8 +376,11 @@ func ingestLoad( fmv FormatMajorVersion, paths []string, shared []SharedSSTMeta, + external []ExternalFile, cacheID uint64, pending []base.DiskFileNum, + objProvider objstorage.Provider, + jobID int, ) (ingestLoadResult, error) { meta := make([]*fileMetadata, 0, len(paths)) newPaths := make([]string, 0, len(paths)) @@ -316,13 +403,17 @@ func ingestLoad( newPaths = append(newPaths, paths[i]) } } - if len(shared) == 0 { - return ingestLoadResult{localMeta: meta, localPaths: newPaths}, nil + if len(shared) == 0 && len(external) == 0 { + return ingestLoadResult{localMeta: meta, localPaths: newPaths, fileCount: len(meta)}, nil } + + // Sort the shared files according to level. + sort.Sort(sharedByLevel(shared)) + sharedMeta := make([]*fileMetadata, 0, len(shared)) levels := make([]uint8, 0, len(shared)) for i := range shared { - m, err := ingestLoad1Shared(opts, shared[i], pending[len(paths)+i]) + m, err := ingestSynthesizeShared(opts, shared[i], pending[len(paths)+i]) if err != nil { return ingestLoadResult{}, err } @@ -332,11 +423,21 @@ func ingestLoad( sharedMeta = append(sharedMeta, m) levels = append(levels, shared[i].Level) } + externalMeta := make([]*fileMetadata, 0, len(external)) + for i := range external { + m, err := ingestLoad1External(opts, external[i], pending[len(paths)+len(shared)+i], objProvider, jobID) + if err != nil { + return ingestLoadResult{}, err + } + externalMeta = append(externalMeta, m) + } result := ingestLoadResult{ localMeta: meta, sharedMeta: sharedMeta, + externalMeta: externalMeta, localPaths: newPaths, sharedLevels: levels, + fileCount: len(meta) + len(sharedMeta) + len(externalMeta), } return result, nil } @@ -360,7 +461,9 @@ func (m metaAndPaths) Less(i, j int) bool { func (m metaAndPaths) Swap(i, j int) { m.meta[i], m.meta[j] = m.meta[j], m.meta[i] - m.paths[i], m.paths[j] = m.paths[j], m.paths[i] + if m.paths != nil { + m.paths[i], m.paths[j] = m.paths[j], m.paths[i] + } } func ingestSortAndVerify(cmp Compare, lr ingestLoadResult, exciseSpan KeyRange) error { @@ -372,6 +475,23 @@ func ingestSortAndVerify(cmp Compare, lr ingestLoadResult, exciseSpan KeyRange) return errors.AssertionFailedf("pebble: shared file outside of excise span, span [%s-%s), file = %s", exciseSpan.Start, exciseSpan.End, f.String()) } } + if len(lr.externalMeta) > 0 { + if len(lr.localMeta) > 0 || len(lr.sharedMeta) > 0 { + // Currently we only support external ingests on their own. If external + // files are present alongside local/shared files, return an error. + return errors.AssertionFailedf("pebble: external files cannot be ingested atomically alongside other types of files") + } + sort.Sort(&metaAndPaths{ + meta: lr.externalMeta, + cmp: cmp, + }) + for i := 1; i < len(lr.externalMeta); i++ { + if sstableKeyCompare(cmp, lr.externalMeta[i-1].Largest, lr.externalMeta[i].Smallest) >= 0 { + return errors.AssertionFailedf("pebble: external sstables have overlapping ranges") + } + } + return nil + } if len(lr.localMeta) <= 1 || len(lr.localPaths) <= 1 { return nil } @@ -384,7 +504,7 @@ func ingestSortAndVerify(cmp Compare, lr ingestLoadResult, exciseSpan KeyRange) for i := 1; i < len(lr.localPaths); i++ { if sstableKeyCompare(cmp, lr.localMeta[i-1].Largest, lr.localMeta[i].Smallest) >= 0 { - return errors.AssertionFailedf("pebble: external sstables have overlapping ranges") + return errors.AssertionFailedf("pebble: local ingestion sstables have overlapping ranges") } } if len(lr.sharedMeta) == 0 { @@ -398,8 +518,8 @@ func ingestSortAndVerify(cmp Compare, lr ingestLoadResult, exciseSpan KeyRange) filesInLevel = append(filesInLevel, lr.sharedMeta[i]) } } - sort.Slice(filesInLevel, func(i, j int) bool { - return cmp(filesInLevel[i].Smallest.UserKey, filesInLevel[j].Smallest.UserKey) < 0 + slices.SortFunc(filesInLevel, func(a, b *fileMetadata) int { + return cmp(a.Smallest.UserKey, b.Smallest.UserKey) }) for i := 1; i < len(filesInLevel); i++ { if sstableKeyCompare(cmp, filesInLevel[i-1].Largest, filesInLevel[i].Smallest) >= 0 { @@ -436,7 +556,7 @@ func ingestLink( ) if err != nil { if err2 := ingestCleanup(objProvider, lr.localMeta[:i]); err2 != nil { - opts.Logger.Infof("ingest cleanup failed: %v", err2) + opts.Logger.Errorf("ingest cleanup failed: %v", err2) } return err } @@ -473,7 +593,7 @@ func ingestLink( // open the db again after a crash/restart (see checkConsistency in open.go), // plus it more accurately allows us to prioritize compactions of files // that were originally created by us. - if sharedObjMetas[i].IsShared() && !objProvider.IsForeign(sharedObjMetas[i]) { + if sharedObjMetas[i].IsShared() && !objProvider.IsSharedForeign(sharedObjMetas[i]) { size, err := objProvider.Size(sharedObjMetas[i]) if err != nil { return err @@ -489,11 +609,13 @@ func ingestLink( }) } } + // We do not need to do anything about lr.externalMetas. Those were already + // linked in ingestLoad. return nil } -func ingestMemtableOverlaps(cmp Compare, mem flushable, meta []*fileMetadata) bool { +func ingestMemtableOverlaps(cmp Compare, mem flushable, keyRanges []internalKeyRange) bool { iter := mem.newIter(nil) rangeDelIter := mem.newRangeDelIter(nil) rkeyIter := mem.newRangeKeyIter(nil) @@ -509,8 +631,7 @@ func ingestMemtableOverlaps(cmp Compare, mem flushable, meta []*fileMetadata) bo return err } - for _, m := range meta { - kr := internalKeyRange{smallest: m.Smallest, largest: m.Largest} + for _, kr := range keyRanges { if overlapWithIterator(iter, &rangeDelIter, rkeyIter, kr, cmp) { closeIters() return true @@ -522,12 +643,12 @@ func ingestMemtableOverlaps(cmp Compare, mem flushable, meta []*fileMetadata) bo } func ingestUpdateSeqNum( - cmp Compare, format base.FormatKey, seqNum uint64, meta []*fileMetadata, + cmp Compare, format base.FormatKey, seqNum uint64, loadResult ingestLoadResult, ) error { setSeqFn := func(k base.InternalKey) base.InternalKey { return base.MakeInternalKey(k.UserKey, seqNum, k.Kind()) } - for _, m := range meta { + updateMetadata := func(m *fileMetadata) error { // NB: we set the fields directly here, rather than via their Extend* // methods, as we are updating sequence numbers. if m.HasPointKeys { @@ -559,10 +680,36 @@ func ingestUpdateSeqNum( return err } seqNum++ + return nil + } + + // Shared sstables are required to be sorted by level ascending. We then + // iterate the shared sstables in reverse, assigning the lower sequence + // numbers to the shared sstables that will be ingested into the lower + // (larger numbered) levels first. This ensures sequence number shadowing is + // correct. + for i := len(loadResult.sharedMeta) - 1; i >= 0; i-- { + if i-1 >= 0 && loadResult.sharedLevels[i-1] > loadResult.sharedLevels[i] { + panic(errors.AssertionFailedf("shared files %s, %s out of order", loadResult.sharedMeta[i-1], loadResult.sharedMeta[i])) + } + if err := updateMetadata(loadResult.sharedMeta[i]); err != nil { + return err + } + } + for i := range loadResult.localMeta { + if err := updateMetadata(loadResult.localMeta[i]); err != nil { + return err + } + } + for i := range loadResult.externalMeta { + if err := updateMetadata(loadResult.externalMeta[i]); err != nil { + return err + } } return nil } +// Denotes an internal key range. Smallest and largest are both inclusive. type internalKeyRange struct { smallest, largest InternalKey } @@ -651,16 +798,21 @@ func overlapWithIterator( return computeOverlapWithSpans(*rangeDelIter) } +// ingestTargetLevel returns the target level for a file being ingested. +// If suggestSplit is true, it accounts for ingest-time splitting as part of +// its target level calculation, and if a split candidate is found, that file +// is returned as the splitFile. func ingestTargetLevel( newIters tableNewIters, newRangeKeyIter keyspan.TableNewSpanIter, iterOps IterOptions, - cmp Compare, + comparer *Comparer, v *version, baseLevel int, compactions map[*compaction]struct{}, meta *fileMetadata, -) (int, error) { + suggestSplit bool, +) (targetLevel int, splitFile *fileMetadata, err error) { // Find the lowest level which does not have any files which overlap meta. We // search from L0 to L6 looking for whether there are any files in the level // which overlap meta. We want the "lowest" level (where lower means @@ -675,6 +827,14 @@ func ingestTargetLevel( // violate the sequence number invariant. // - no file boundary overlap with level i, since that will violate the // invariant that files do not overlap in levels i > 0. + // - if there is only a file overlap at a given level, and no data overlap, + // we can still slot a file at that level. We return the fileMetadata with + // which we have file boundary overlap (must be only one file, as sstable + // bounds are usually tight on user keys) and the caller is expected to split + // that sstable into two virtual sstables, allowing this file to go into that + // level. Note that if we have file boundary overlap with two files, which + // should only happen on rare occasions, we treat it as data overlap and + // don't use this optimization. // // The file boundary overlap check is simpler to conceptualize. Consider the // following example, in which the ingested file lies completely before or @@ -719,17 +879,19 @@ func ingestTargetLevel( // existing point that falls within the ingested table bounds as being "data // overlap". - targetLevel := 0 - // This assertion implicitly checks that we have the current version of // the metadata. if v.L0Sublevels == nil { - return 0, errors.AssertionFailedf("could not read L0 sublevels") + return 0, nil, errors.AssertionFailedf("could not read L0 sublevels") + } + iterOps.CategoryAndQoS = sstable.CategoryAndQoS{ + Category: "pebble-ingest", + QoSLevel: sstable.LatencySensitiveQoSLevel, } // Check for overlap over the keys of L0 by iterating over the sublevels. for subLevel := 0; subLevel < len(v.L0SublevelFiles); subLevel++ { - iter := newLevelIter(iterOps, cmp, nil /* split */, newIters, - v.L0Sublevels.Levels[subLevel].Iter(), manifest.Level(0), internalIterOpts{}) + iter := newLevelIter(context.Background(), + iterOps, comparer, newIters, v.L0Sublevels.Levels[subLevel].Iter(), manifest.Level(0), internalIterOpts{}) var rangeDelIter keyspan.FragmentIterator // Pass in a non-nil pointer to rangeDelIter so that levelIter.findFileGE @@ -738,7 +900,7 @@ func ingestTargetLevel( levelIter := keyspan.LevelIter{} levelIter.Init( - keyspan.SpanIterOptions{}, cmp, newRangeKeyIter, + keyspan.SpanIterOptions{}, comparer.Compare, newRangeKeyIter, v.L0Sublevels.Levels[subLevel].Iter(), manifest.Level(0), manifest.KeyTypeRange, ) @@ -746,21 +908,21 @@ func ingestTargetLevel( smallest: meta.Smallest, largest: meta.Largest, } - overlap := overlapWithIterator(iter, &rangeDelIter, &levelIter, kr, cmp) + overlap := overlapWithIterator(iter, &rangeDelIter, &levelIter, kr, comparer.Compare) err := iter.Close() // Closes range del iter as well. err = firstError(err, levelIter.Close()) if err != nil { - return 0, err + return 0, nil, err } if overlap { - return targetLevel, nil + return targetLevel, nil, nil } } level := baseLevel for ; level < numLevels; level++ { - levelIter := newLevelIter(iterOps, cmp, nil /* split */, newIters, - v.Levels[level].Iter(), manifest.Level(level), internalIterOpts{}) + levelIter := newLevelIter(context.Background(), + iterOps, comparer, newIters, v.Levels[level].Iter(), manifest.Level(level), internalIterOpts{}) var rangeDelIter keyspan.FragmentIterator // Pass in a non-nil pointer to rangeDelIter so that levelIter.findFileGE // sets it up for the target file. @@ -768,7 +930,7 @@ func ingestTargetLevel( rkeyLevelIter := &keyspan.LevelIter{} rkeyLevelIter.Init( - keyspan.SpanIterOptions{}, cmp, newRangeKeyIter, + keyspan.SpanIterOptions{}, comparer.Compare, newRangeKeyIter, v.Levels[level].Iter(), manifest.Level(level), manifest.KeyTypeRange, ) @@ -776,46 +938,68 @@ func ingestTargetLevel( smallest: meta.Smallest, largest: meta.Largest, } - overlap := overlapWithIterator(levelIter, &rangeDelIter, rkeyLevelIter, kr, cmp) + overlap := overlapWithIterator(levelIter, &rangeDelIter, rkeyLevelIter, kr, comparer.Compare) err := levelIter.Close() // Closes range del iter as well. err = firstError(err, rkeyLevelIter.Close()) if err != nil { - return 0, err + return 0, nil, err } if overlap { - return targetLevel, nil + return targetLevel, splitFile, nil } // Check boundary overlap. - boundaryOverlaps := v.Overlaps(level, cmp, meta.Smallest.UserKey, + var candidateSplitFile *fileMetadata + boundaryOverlaps := v.Overlaps(level, comparer.Compare, meta.Smallest.UserKey, meta.Largest.UserKey, meta.Largest.IsExclusiveSentinel()) if !boundaryOverlaps.Empty() { - continue + // We are already guaranteed to not have any data overlaps with files + // in boundaryOverlaps, otherwise we'd have returned in the above if + // statements. Use this, plus boundaryOverlaps.Len() == 1 to detect for + // the case where we can slot this file into the current level despite + // a boundary overlap, by splitting one existing file into two virtual + // sstables. + if suggestSplit && boundaryOverlaps.Len() == 1 { + iter := boundaryOverlaps.Iter() + candidateSplitFile = iter.First() + } else { + // We either don't want to suggest ingest-time splits (i.e. + // !suggestSplit), or we boundary-overlapped with more than one file. + continue + } } - // Check boundary overlap with any ongoing compactions. + // Check boundary overlap with any ongoing compactions. We consider an + // overlapping compaction that's writing files to an output level as + // equivalent to boundary overlap with files in that output level. + // + // We cannot check for data overlap with the new SSTs compaction will produce + // since compaction hasn't been done yet. However, there's no need to check + // since all keys in them will be from levels in [c.startLevel, + // c.outputLevel], and all those levels have already had their data overlap + // tested negative (else we'd have returned earlier). // - // We cannot check for data overlap with the new SSTs compaction will - // produce since compaction hasn't been done yet. However, there's no need - // to check since all keys in them will either be from c.startLevel or - // c.outputLevel, both levels having their data overlap already tested - // negative (else we'd have returned earlier). + // An alternative approach would be to cancel these compactions and proceed + // with an ingest-time split on this level if necessary. However, compaction + // cancellation can result in significant wasted effort and is best avoided + // unless necessary. overlaps := false for c := range compactions { if c.outputLevel == nil || level != c.outputLevel.level { continue } - if cmp(meta.Smallest.UserKey, c.largest.UserKey) <= 0 && - cmp(meta.Largest.UserKey, c.smallest.UserKey) >= 0 { + if comparer.Compare(meta.Smallest.UserKey, c.largest.UserKey) <= 0 && + comparer.Compare(meta.Largest.UserKey, c.smallest.UserKey) >= 0 { overlaps = true break } } if !overlaps { targetLevel = level + splitFile = candidateSplitFile } } - return targetLevel, nil + return targetLevel, splitFile, nil } // Ingest ingests a set of sstables into the DB. Ingestion of the files is @@ -881,7 +1065,7 @@ func (d *DB) Ingest(paths []string) error { if d.opts.ReadOnly { return ErrReadOnly } - _, err := d.ingest(paths, ingestTargetLevel, nil /* shared */, KeyRange{}) + _, err := d.ingest(paths, ingestTargetLevel, nil /* shared */, KeyRange{}, nil /* external */) return err } @@ -901,6 +1085,32 @@ type IngestOperationStats struct { MemtableOverlappingFiles int } +// ExternalFile are external sstables that can be referenced through +// objprovider and ingested as remote files that will not be refcounted or +// cleaned up. For use with online restore. Note that the underlying sstable +// could contain keys outside the [Smallest,Largest) bounds; however Pebble +// is expected to only read the keys within those bounds. +type ExternalFile struct { + // Locator is the shared.Locator that can be used with objProvider to + // resolve a reference to this external sstable. + Locator remote.Locator + // ObjName is the unique name of this sstable on Locator. + ObjName string + // Size of the referenced proportion of the virtualized sstable. An estimate + // is acceptable in lieu of the backing file size. + Size uint64 + // SmallestUserKey and LargestUserKey are the [smallest,largest) user key + // bounds of the sstable. Both these bounds are loose i.e. it's possible for + // the sstable to not span the entirety of this range. However, multiple + // ExternalFiles in one ingestion must all have non-overlapping + // [smallest, largest) spans. Note that this Largest bound is exclusive. + SmallestUserKey, LargestUserKey []byte + // HasPointKey and HasRangeKey denote whether this file contains point keys + // or range keys. If both structs are false, an error is returned during + // ingestion. + HasPointKey, HasRangeKey bool +} + // IngestWithStats does the same as Ingest, and additionally returns // IngestOperationStats. func (d *DB) IngestWithStats(paths []string) (IngestOperationStats, error) { @@ -910,7 +1120,25 @@ func (d *DB) IngestWithStats(paths []string) (IngestOperationStats, error) { if d.opts.ReadOnly { return IngestOperationStats{}, ErrReadOnly } - return d.ingest(paths, ingestTargetLevel, nil /* shared */, KeyRange{}) + return d.ingest(paths, ingestTargetLevel, nil /* shared */, KeyRange{}, nil /* external */) +} + +// IngestExternalFiles does the same as IngestWithStats, and additionally +// accepts external files (with locator info that can be resolved using +// d.opts.SharedStorage). These files must also be non-overlapping with +// each other, and must be resolvable through d.objProvider. +func (d *DB) IngestExternalFiles(external []ExternalFile) (IngestOperationStats, error) { + if err := d.closed.Load(); err != nil { + panic(err) + } + + if d.opts.ReadOnly { + return IngestOperationStats{}, ErrReadOnly + } + if d.opts.Experimental.RemoteStorage == nil { + return IngestOperationStats{}, errors.New("pebble: cannot ingest external files without shared storage configured") + } + return d.ingest(nil, ingestTargetLevel, nil /* shared */, KeyRange{}, external) } // IngestAndExcise does the same as IngestWithStats, and additionally accepts a @@ -932,12 +1160,12 @@ func (d *DB) IngestAndExcise( if d.opts.ReadOnly { return IngestOperationStats{}, ErrReadOnly } - return d.ingest(paths, ingestTargetLevel, shared, exciseSpan) + return d.ingest(paths, ingestTargetLevel, shared, exciseSpan, nil /* external */) } // Both DB.mu and commitPipeline.mu must be held while this is called. func (d *DB) newIngestedFlushableEntry( - meta []*fileMetadata, seqNum uint64, logNum FileNum, + meta []*fileMetadata, seqNum uint64, logNum base.DiskFileNum, ) (*flushableEntry, error) { // Update the sequence number for all of the sstables in the // metadata. Writing the metadata to the manifest when the @@ -948,12 +1176,12 @@ func (d *DB) newIngestedFlushableEntry( // time, then we'll lose the ingest sequence number information. But this // information will also be reconstructed on node restart. if err := ingestUpdateSeqNum( - d.cmp, d.opts.Comparer.FormatKey, seqNum, meta, + d.cmp, d.opts.Comparer.FormatKey, seqNum, ingestLoadResult{localMeta: meta}, ); err != nil { return nil, err } - f := newIngestedFlushable(meta, d.cmp, d.split, d.newIters, d.tableNewRangeKeyIter) + f := newIngestedFlushable(meta, d.opts.Comparer, d.newIters, d.tableNewRangeKeyIter) // NB: The logNum/seqNum are the WAL number which we're writing this entry // to and the sequence number within the WAL which we'll write this entry @@ -1048,12 +1276,13 @@ func (d *DB) ingest( targetLevelFunc ingestTargetLevelFunc, shared []SharedSSTMeta, exciseSpan KeyRange, + external []ExternalFile, ) (IngestOperationStats, error) { if len(shared) > 0 && d.opts.Experimental.RemoteStorage == nil { panic("cannot ingest shared sstables with nil SharedStorage") } - if (exciseSpan.Valid() || len(shared) > 0) && d.opts.FormatMajorVersion < ExperimentalFormatVirtualSSTables { - return IngestOperationStats{}, errors.New("pebble: format major version too old for excise or shared sstable ingestion") + if (exciseSpan.Valid() || len(shared) > 0 || len(external) > 0) && d.FormatMajorVersion() < FormatVirtualSSTables { + return IngestOperationStats{}, errors.New("pebble: format major version too old for excise, shared or external sstable ingestion") } // Allocate file numbers for all of the files being ingested and mark them as // pending in order to prevent them from being deleted. Note that this causes @@ -1061,25 +1290,23 @@ func (d *DB) ingest( // ordering. The sorting of L0 tables by sequence number avoids relying on // that (busted) invariant. d.mu.Lock() - pendingOutputs := make([]base.DiskFileNum, len(paths)+len(shared)) - for i := range paths { - pendingOutputs[i] = d.mu.versions.getNextFileNum().DiskFileNum() - } - for i := range shared { - pendingOutputs[len(paths)+i] = d.mu.versions.getNextFileNum().DiskFileNum() + pendingOutputs := make([]base.DiskFileNum, len(paths)+len(shared)+len(external)) + for i := 0; i < len(paths)+len(shared)+len(external); i++ { + pendingOutputs[i] = d.mu.versions.getNextDiskFileNum() } + jobID := d.mu.nextJobID d.mu.nextJobID++ d.mu.Unlock() - // Load the metadata for all of the files being ingested. This step detects + // Load the metadata for all the files being ingested. This step detects // and elides empty sstables. - loadResult, err := ingestLoad(d.opts, d.FormatMajorVersion(), paths, shared, d.cacheID, pendingOutputs) + loadResult, err := ingestLoad(d.opts, d.FormatMajorVersion(), paths, shared, external, d.cacheID, pendingOutputs, d.objProvider, jobID) if err != nil { return IngestOperationStats{}, err } - if len(loadResult.localMeta) == 0 && len(loadResult.sharedMeta) == 0 { + if loadResult.fileCount == 0 { // All of the sstables to be ingested were empty. Nothing to do. return IngestOperationStats{}, nil } @@ -1097,6 +1324,7 @@ func (d *DB) ingest( if err := ingestLink(jobID, d.opts, d.objProvider, loadResult, shared); err != nil { return IngestOperationStats{}, err } + // Make the new tables durable. We need to do this at some point before we // update the MANIFEST (via logAndApply), otherwise a crash can have the // tables referenced in the MANIFEST, but not present in the provider. @@ -1107,11 +1335,17 @@ func (d *DB) ingest( // metaFlushableOverlaps is a slice parallel to meta indicating which of the // ingested sstables overlap some table in the flushable queue. It's used to // approximate ingest-into-L0 stats when using flushable ingests. - metaFlushableOverlaps := make([]bool, len(loadResult.localMeta)+len(loadResult.sharedMeta)) + metaFlushableOverlaps := make([]bool, loadResult.fileCount) var mem *flushableEntry var mut *memTable // asFlushable indicates whether the sstable was ingested as a flushable. var asFlushable bool + iterOps := IterOptions{ + CategoryAndQoS: sstable.CategoryAndQoS{ + Category: "pebble-ingest", + QoSLevel: sstable.LatencySensitiveQoSLevel, + }, + } prepare := func(seqNum uint64) { // Note that d.commit.mu is held by commitPipeline when calling prepare. @@ -1125,9 +1359,9 @@ func (d *DB) ingest( for i := len(d.mu.mem.queue) - 1; i >= 0; i-- { m := d.mu.mem.queue[i] - iter := m.newIter(nil) - rangeDelIter := m.newRangeDelIter(nil) - rkeyIter := m.newRangeKeyIter(nil) + iter := m.newIter(&iterOps) + rangeDelIter := m.newRangeDelIter(&iterOps) + rkeyIter := m.newRangeKeyIter(&iterOps) checkForOverlap := func(i int, meta *fileMetadata) { if metaFlushableOverlaps[i] { @@ -1154,6 +1388,9 @@ func (d *DB) ingest( for i := range loadResult.sharedMeta { checkForOverlap(len(loadResult.localMeta)+i, loadResult.sharedMeta[i]) } + for i := range loadResult.externalMeta { + checkForOverlap(len(loadResult.localMeta)+len(loadResult.sharedMeta)+i, loadResult.externalMeta[i]) + } if exciseSpan.Valid() { kr := internalKeyRange{ smallest: base.MakeInternalKey(exciseSpan.Start, InternalKeySeqNumMax, InternalKeyKindMax), @@ -1173,7 +1410,7 @@ func (d *DB) ingest( err = firstError(err, rkeyIter.Close()) } if err != nil { - d.opts.Logger.Infof("ingest error reading flushable for log %s: %s", m.logNum, err) + d.opts.Logger.Errorf("ingest error reading flushable for log %s: %s", m.logNum, err) } } @@ -1195,7 +1432,7 @@ func (d *DB) ingest( // The ingestion overlaps with some entry in the flushable queue. if d.FormatMajorVersion() < FormatFlushableIngest || d.opts.Experimental.DisableIngestAsFlushable() || - len(shared) > 0 || exciseSpan.Valid() || + len(shared) > 0 || exciseSpan.Valid() || len(external) > 0 || (len(d.mu.mem.queue) > d.opts.MemTableStopWritesThreshold-1) { // We're not able to ingest as a flushable, // so we must synchronously flush. @@ -1241,15 +1478,12 @@ func (d *DB) ingest( return } - // Update the sequence number for all local sstables in the - // metadata. Writing the metadata to the manifest when the - // version edit is applied is the mechanism that persists the - // sequence number. The sstables themselves are left unmodified. - // - // For shared sstables, we do not need to update sequence numbers. These - // sequence numbers are already set in ingestLoad. + // Update the sequence numbers for all ingested sstables' + // metadata. When the version edit is applied, the metadata is + // written to the manifest, persisting the sequence number. + // The sstables themselves are left unmodified. if err = ingestUpdateSeqNum( - d.cmp, d.opts.Comparer.FormatKey, seqNum, loadResult.localMeta, + d.cmp, d.opts.Comparer.FormatKey, seqNum, loadResult, ); err != nil { if mut != nil { if mut.writerUnref() { @@ -1278,34 +1512,40 @@ func (d *DB) ingest( // changes to the WAL and memtable. This will cause a bigger commit hiccup // during ingestion. d.commit.ingestSem <- struct{}{} - d.commit.AllocateSeqNum(len(loadResult.localPaths), prepare, apply) + d.commit.AllocateSeqNum(loadResult.fileCount, prepare, apply) <-d.commit.ingestSem if err != nil { if err2 := ingestCleanup(d.objProvider, loadResult.localMeta); err2 != nil { - d.opts.Logger.Infof("ingest cleanup failed: %v", err2) + d.opts.Logger.Errorf("ingest cleanup failed: %v", err2) } } else { // Since we either created a hard link to the ingesting files, or copied // them over, it is safe to remove the originals paths. for _, path := range loadResult.localPaths { if err2 := d.opts.FS.Remove(path); err2 != nil { - d.opts.Logger.Infof("ingest failed to remove original file: %s", err2) + d.opts.Logger.Errorf("ingest failed to remove original file: %s", err2) } } } - // NB: Remote-sstable-only ingestions do not assign a sequence number to - // any sstables. - globalSeqNum := uint64(0) - if len(loadResult.localMeta) > 0 { - globalSeqNum = loadResult.localMeta[0].SmallestSeqNum + if invariants.Enabled { + for _, sharedMeta := range loadResult.sharedMeta { + d.checkVirtualBounds(sharedMeta) + } } + info := TableIngestInfo{ - JobID: jobID, - GlobalSeqNum: globalSeqNum, - Err: err, - flushable: asFlushable, + JobID: jobID, + Err: err, + flushable: asFlushable, + } + if len(loadResult.localMeta) > 0 { + info.GlobalSeqNum = loadResult.localMeta[0].SmallestSeqNum + } else if len(loadResult.sharedMeta) > 0 { + info.GlobalSeqNum = loadResult.sharedMeta[0].SmallestSeqNum + } else { + info.GlobalSeqNum = loadResult.externalMeta[0].SmallestSeqNum } var stats IngestOperationStats if ve != nil { @@ -1379,7 +1619,7 @@ func (d *DB) excise( var iter internalIterator var rangeDelIter keyspan.FragmentIterator var rangeKeyIter keyspan.FragmentIterator - backingTableCreated := false + needsBacking := false // Create a file to the left of the excise span, if necessary. // The bounds of this file will be [m.Smallest, lastKeyBefore(exciseSpan.Start)]. // @@ -1416,7 +1656,13 @@ func (d *DB) excise( // This file will contain point keys smallestPointKey := m.SmallestPointKey var err error - iter, rangeDelIter, err = d.newIters(context.TODO(), m, &IterOptions{level: manifest.Level(level)}, internalIterOpts{}) + iter, rangeDelIter, err = d.newIters(context.TODO(), m, &IterOptions{ + CategoryAndQoS: sstable.CategoryAndQoS{ + Category: "pebble-ingest", + QoSLevel: sstable.LatencySensitiveQoSLevel, + }, + level: manifest.Level(level), + }, internalIterOpts{}) if err != nil { return nil, err } @@ -1490,15 +1736,23 @@ func (d *DB) excise( if err := leftFile.Validate(d.cmp, d.opts.Comparer.FormatKey); err != nil { return nil, err } + leftFile.ValidateVirtual(m) + d.checkVirtualBounds(leftFile) ve.NewFiles = append(ve.NewFiles, newFileEntry{Level: level, Meta: leftFile}) - ve.CreatedBackingTables = append(ve.CreatedBackingTables, leftFile.FileBacking) - backingTableCreated = true + needsBacking = true numCreatedFiles++ } } // Create a file to the right, if necessary. if exciseSpan.Contains(d.cmp, m.Largest) { // No key exists to the right of the excise span in this file. + if needsBacking && !m.Virtual { + // If m is virtual, then its file backing is already known to the manifest. + // We don't need to create another file backing. Note that there must be + // only one CreatedBackingTables entry per backing sstable. This is + // indicated by the VersionEdit.CreatedBackingTables invariant. + ve.CreatedBackingTables = append(ve.CreatedBackingTables, m.FileBacking) + } return ve.NewFiles[len(ve.NewFiles)-numCreatedFiles:], nil } // Create a new file, rightFile, between [firstKeyAfter(exciseSpan.End), m.Largest]. @@ -1519,7 +1773,13 @@ func (d *DB) excise( largestPointKey := m.LargestPointKey var err error if iter == nil && rangeDelIter == nil { - iter, rangeDelIter, err = d.newIters(context.TODO(), m, &IterOptions{level: manifest.Level(level)}, internalIterOpts{}) + iter, rangeDelIter, err = d.newIters(context.TODO(), m, &IterOptions{ + CategoryAndQoS: sstable.CategoryAndQoS{ + Category: "pebble-ingest", + QoSLevel: sstable.LatencySensitiveQoSLevel, + }, + level: manifest.Level(level), + }, internalIterOpts{}) if err != nil { return nil, err } @@ -1553,7 +1813,8 @@ func (d *DB) excise( smallestPointKey.UserKey = firstRangeDel rightFile.ExtendPointKeyBounds(d.cmp, smallestPointKey, largestPointKey) } - } else if m.HasRangeKeys && !exciseSpan.Contains(d.cmp, m.LargestRangeKey) { + } + if m.HasRangeKeys && !exciseSpan.Contains(d.cmp, m.LargestRangeKey) { // This file will contain range keys. largestRangeKey := m.LargestRangeKey if rangeKeyIter == nil { @@ -1597,14 +1858,21 @@ func (d *DB) excise( // for it here. rightFile.Size = 1 } + rightFile.ValidateVirtual(m) + d.checkVirtualBounds(rightFile) ve.NewFiles = append(ve.NewFiles, newFileEntry{Level: level, Meta: rightFile}) - if !backingTableCreated { - ve.CreatedBackingTables = append(ve.CreatedBackingTables, rightFile.FileBacking) - backingTableCreated = true - } + needsBacking = true numCreatedFiles++ } + if needsBacking && !m.Virtual { + // If m is virtual, then its file backing is already known to the manifest. + // We don't need to create another file backing. Note that there must be + // only one CreatedBackingTables entry per backing sstable. This is + // indicated by the VersionEdit.CreatedBackingTables invariant. + ve.CreatedBackingTables = append(ve.CreatedBackingTables, m.FileBacking) + } + if err := rightFile.Validate(d.cmp, d.opts.Comparer.FormatKey); err != nil { return nil, err } @@ -1615,12 +1883,129 @@ type ingestTargetLevelFunc func( newIters tableNewIters, newRangeKeyIter keyspan.TableNewSpanIter, iterOps IterOptions, - cmp Compare, + comparer *Comparer, v *version, baseLevel int, compactions map[*compaction]struct{}, meta *fileMetadata, -) (int, error) + suggestSplit bool, +) (int, *fileMetadata, error) + +type ingestSplitFile struct { + // ingestFile is the file being ingested. + ingestFile *fileMetadata + // splitFile is the file that needs to be split to allow ingestFile to slot + // into `level` level. + splitFile *fileMetadata + // The level where ingestFile will go (and where splitFile already is). + level int +} + +// ingestSplit splits files specified in `files` and updates ve in-place to +// account for existing files getting split into two virtual sstables. The map +// `replacedFiles` contains an in-progress map of all files that have been +// replaced with new virtual sstables in this version edit so far, which is also +// updated in-place. +// +// d.mu as well as the manifest lock must be held when calling this method. +func (d *DB) ingestSplit( + ve *versionEdit, + updateMetrics func(*fileMetadata, int, []newFileEntry), + files []ingestSplitFile, + replacedFiles map[base.FileNum][]newFileEntry, +) error { + for _, s := range files { + // replacedFiles can be thought of as a tree, where we start iterating with + // s.splitFile and run its fileNum through replacedFiles, then find which of + // the replaced files overlaps with s.ingestFile, which becomes the new + // splitFile, then we check splitFile's replacements in replacedFiles again + // for overlap with s.ingestFile, and so on until we either can't find the + // current splitFile in replacedFiles (i.e. that's the file that now needs to + // be split), or we don't find a file that overlaps with s.ingestFile, which + // means a prior ingest split already produced enough room for s.ingestFile + // to go into this level without necessitating another ingest split. + splitFile := s.splitFile + for splitFile != nil { + replaced, ok := replacedFiles[splitFile.FileNum] + if !ok { + break + } + updatedSplitFile := false + for i := range replaced { + if replaced[i].Meta.Overlaps(d.cmp, s.ingestFile.Smallest.UserKey, s.ingestFile.Largest.UserKey, s.ingestFile.Largest.IsExclusiveSentinel()) { + if updatedSplitFile { + // This should never happen because the earlier ingestTargetLevel + // function only finds split file candidates that are guaranteed to + // have no data overlap, only boundary overlap. See the comments + // in that method to see the definitions of data vs boundary + // overlap. That, plus the fact that files in `replaced` are + // guaranteed to have file bounds that are tight on user keys + // (as that's what `d.excise` produces), means that the only case + // where we overlap with two or more files in `replaced` is if we + // actually had data overlap all along, or if the ingestion files + // were overlapping, either of which is an invariant violation. + panic("updated with two files in ingestSplit") + } + splitFile = replaced[i].Meta + updatedSplitFile = true + } + } + if !updatedSplitFile { + // None of the replaced files overlapped with the file being ingested. + // This can happen if we've already excised a span overlapping with + // this file, or if we have consecutive ingested files that can slide + // within the same gap between keys in an existing file. For instance, + // if an existing file has keys a and g and we're ingesting b-c, d-e, + // the first loop iteration will split the existing file into one that + // ends in a and another that starts at g, and the second iteration will + // fall into this case and require no splitting. + // + // No splitting necessary. + splitFile = nil + } + } + if splitFile == nil { + continue + } + // NB: excise operates on [start, end). We're splitting at [start, end] + // (assuming !s.ingestFile.Largest.IsExclusiveSentinel()). The conflation + // of exclusive vs inclusive end bounds should not make a difference here + // as we're guaranteed to not have any data overlap between splitFile and + // s.ingestFile, so panic if we do see a newly added file with an endKey + // equalling s.ingestFile.Largest, and !s.ingestFile.Largest.IsExclusiveSentinel() + added, err := d.excise(KeyRange{Start: s.ingestFile.Smallest.UserKey, End: s.ingestFile.Largest.UserKey}, splitFile, ve, s.level) + if err != nil { + return err + } + if _, ok := ve.DeletedFiles[deletedFileEntry{ + Level: s.level, + FileNum: splitFile.FileNum, + }]; !ok { + panic("did not split file that was expected to be split") + } + replacedFiles[splitFile.FileNum] = added + for i := range added { + if s.ingestFile.Overlaps(d.cmp, added[i].Meta.Smallest.UserKey, added[i].Meta.Largest.UserKey, added[i].Meta.Largest.IsExclusiveSentinel()) { + panic("ingest-time split produced a file that overlaps with ingested file") + } + } + updateMetrics(splitFile, s.level, added) + } + // Flatten the version edit by removing any entries from ve.NewFiles that + // are also in ve.DeletedFiles. + newNewFiles := ve.NewFiles[:0] + for i := range ve.NewFiles { + fn := ve.NewFiles[i].Meta.FileNum + deEntry := deletedFileEntry{Level: ve.NewFiles[i].Level, FileNum: fn} + if _, ok := ve.DeletedFiles[deEntry]; ok { + delete(ve.DeletedFiles, deEntry) + } else { + newNewFiles = append(newNewFiles, ve.NewFiles[i]) + } + } + ve.NewFiles = newNewFiles + return nil +} func (d *DB) ingestApply( jobID int, @@ -1633,9 +2018,9 @@ func (d *DB) ingestApply( defer d.mu.Unlock() ve := &versionEdit{ - NewFiles: make([]newFileEntry, len(lr.localMeta)+len(lr.sharedMeta)), + NewFiles: make([]newFileEntry, lr.fileCount), } - if exciseSpan.Valid() { + if exciseSpan.Valid() || (d.opts.Experimental.IngestSplit != nil && d.opts.Experimental.IngestSplit()) { ve.DeletedFiles = map[manifest.DeletedFileEntry]*manifest.FileMetadata{} } metrics := make(map[int]*LevelMetrics) @@ -1660,21 +2045,36 @@ func (d *DB) ingestApply( } } + shouldIngestSplit := d.opts.Experimental.IngestSplit != nil && + d.opts.Experimental.IngestSplit() && d.FormatMajorVersion() >= FormatVirtualSSTables current := d.mu.versions.currentVersion() baseLevel := d.mu.versions.picker.getBaseLevel() iterOps := IterOptions{logger: d.opts.Logger} - for i := 0; i < len(lr.localMeta)+len(lr.sharedMeta); i++ { + // filesToSplit is a list where each element is a pair consisting of a file + // being ingested and a file being split to make room for an ingestion into + // that level. Each ingested file will appear at most once in this list. It + // is possible for split files to appear twice in this list. + filesToSplit := make([]ingestSplitFile, 0) + checkCompactions := false + for i := 0; i < lr.fileCount; i++ { // Determine the lowest level in the LSM for which the sstable doesn't // overlap any existing files in the level. var m *fileMetadata sharedIdx := -1 sharedLevel := -1 + externalFile := false if i < len(lr.localMeta) { + // local file. m = lr.localMeta[i] - } else { + } else if (i - len(lr.localMeta)) < len(lr.sharedMeta) { + // shared file. sharedIdx = i - len(lr.localMeta) m = lr.sharedMeta[sharedIdx] sharedLevel = int(lr.sharedLevels[sharedIdx]) + } else { + // external file. + externalFile = true + m = lr.externalMeta[i-(len(lr.localMeta)+len(lr.sharedMeta))] } f := &ve.NewFiles[i] var err error @@ -1685,6 +2085,10 @@ func (d *DB) ingestApply( } ve.CreatedBackingTables = append(ve.CreatedBackingTables, m.FileBacking) } else { + if externalFile { + ve.CreatedBackingTables = append(ve.CreatedBackingTables, m.FileBacking) + } + var splitFile *fileMetadata if exciseSpan.Valid() && exciseSpan.Contains(d.cmp, m.Smallest) && exciseSpan.Contains(d.cmp, m.Largest) { // This file fits perfectly within the excise span. We can slot it at // L6, or sharedLevelsStart - 1 if we have shared files. @@ -1697,7 +2101,31 @@ func (d *DB) ingestApply( f.Level = 6 } } else { - f.Level, err = findTargetLevel(d.newIters, d.tableNewRangeKeyIter, iterOps, d.cmp, current, baseLevel, d.mu.compact.inProgress, m) + // TODO(bilal): findTargetLevel does disk IO (reading files for data + // overlap) even though we're holding onto d.mu. Consider unlocking + // d.mu while we do this. We already hold versions.logLock so we should + // not see any version applications while we're at this. The one + // complication here would be pulling out the mu.compact.inProgress + // check from findTargetLevel, as that requires d.mu to be held. + f.Level, splitFile, err = findTargetLevel( + d.newIters, d.tableNewRangeKeyIter, iterOps, d.opts.Comparer, current, baseLevel, d.mu.compact.inProgress, m, shouldIngestSplit) + } + + if splitFile != nil { + if invariants.Enabled { + if lf := current.Levels[f.Level].Find(d.cmp, splitFile); lf == nil { + panic("splitFile returned is not in level it should be") + } + } + // We take advantage of the fact that we won't drop the db mutex + // between now and the call to logAndApply. So, no files should + // get added to a new in-progress compaction at this point. We can + // avoid having to iterate on in-progress compactions to cancel them + // if none of the files being split have a compacting state. + if splitFile.IsCompacting() { + checkCompactions = true + } + filesToSplit = append(filesToSplit, ingestSplitFile{ingestFile: m, splitFile: splitFile, level: f.Level}) } } if err != nil { @@ -1715,6 +2143,26 @@ func (d *DB) ingestApply( levelMetrics.BytesIngested += m.Size levelMetrics.TablesIngested++ } + // replacedFiles maps files excised due to exciseSpan (or splitFiles returned + // by ingestTargetLevel), to files that were created to replace it. This map + // is used to resolve references to split files in filesToSplit, as it is + // possible for a file that we want to split to no longer exist or have a + // newer fileMetadata due to a split induced by another ingestion file, or an + // excise. + replacedFiles := make(map[base.FileNum][]newFileEntry) + updateLevelMetricsOnExcise := func(m *fileMetadata, level int, added []newFileEntry) { + levelMetrics := metrics[level] + if levelMetrics == nil { + levelMetrics = &LevelMetrics{} + metrics[level] = levelMetrics + } + levelMetrics.NumFiles-- + levelMetrics.Size -= int64(m.Size) + for i := range added { + levelMetrics.NumFiles++ + levelMetrics.Size += int64(added[i].Meta.Size) + } + } if exciseSpan.Valid() { // Iterate through all levels and find files that intersect with exciseSpan. // @@ -1736,7 +2184,7 @@ func (d *DB) ingestApply( iter := overlaps.Iter() for m := iter.First(); m != nil; m = iter.Next() { - excised, err := d.excise(exciseSpan, m, ve, level) + newFiles, err := d.excise(exciseSpan, m, ve, level) if err != nil { return nil, err } @@ -1748,33 +2196,70 @@ func (d *DB) ingestApply( // We did not excise this file. continue } - levelMetrics := metrics[level] - if levelMetrics == nil { - levelMetrics = &LevelMetrics{} - metrics[level] = levelMetrics - } - levelMetrics.NumFiles-- - levelMetrics.Size -= int64(m.Size) - for i := range excised { - levelMetrics.NumFiles++ - levelMetrics.Size += int64(excised[i].Meta.Size) - } + replacedFiles[m.FileNum] = newFiles + updateLevelMetricsOnExcise(m, level, newFiles) } } } - for c := range d.mu.compact.inProgress { - if c.versionEditApplied { - continue + if len(filesToSplit) > 0 { + // For the same reasons as the above call to excise, we hold the db mutex + // while calling this method. + if err := d.ingestSplit(ve, updateLevelMetricsOnExcise, filesToSplit, replacedFiles); err != nil { + return nil, err + } + } + if len(filesToSplit) > 0 || exciseSpan.Valid() { + for c := range d.mu.compact.inProgress { + if c.versionEditApplied { + continue + } + // Check if this compaction overlaps with the excise span. Note that just + // checking if the inputs individually overlap with the excise span + // isn't sufficient; for instance, a compaction could have [a,b] and [e,f] + // as inputs and write it all out as [a,b,e,f] in one sstable. If we're + // doing a [c,d) excise at the same time as this compaction, we will have + // to error out the whole compaction as we can't guarantee it hasn't/won't + // write a file overlapping with the excise span. + if exciseSpan.OverlapsInternalKeyRange(d.cmp, c.smallest, c.largest) { + c.cancel.Store(true) + } + // Check if this compaction's inputs have been replaced due to an + // ingest-time split. In that case, cancel the compaction as a newly picked + // compaction would need to include any new files that slid in between + // previously-existing files. Note that we cancel any compaction that has a + // file that was ingest-split as an input, even if it started before this + // ingestion. + if checkCompactions { + for i := range c.inputs { + iter := c.inputs[i].files.Iter() + for f := iter.First(); f != nil; f = iter.Next() { + if _, ok := replacedFiles[f.FileNum]; ok { + c.cancel.Store(true) + break + } + } + } + } } - // Check if this compaction overlaps with the excise span. Note that just - // checking if the inputs individually overlap with the excise span - // isn't sufficient; for instance, a compaction could have [a,b] and [e,f] - // as inputs and write it all out as [a,b,e,f] in one sstable. If we're - // doing a [c,d) excise at the same time as this compaction, we will have - // to error out the whole compaction as we can't guarantee it hasn't/won't - // write a file overlapping with the excise span. - if exciseSpan.OverlapsInternalKeyRange(d.cmp, c.smallest, c.largest) { - c.cancel.Store(true) + // Check for any EventuallyFileOnlySnapshots that could be watching for + // an excise on this span. + if exciseSpan.Valid() { + for s := d.mu.snapshots.root.next; s != &d.mu.snapshots.root; s = s.next { + if s.efos == nil { + continue + } + efos := s.efos + // TODO(bilal): We can make this faster by taking advantage of the sorted + // nature of protectedRanges to do a sort.Search, or even maintaining a + // global list of all protected ranges instead of having to peer into every + // snapshot. + for i := range efos.protectedRanges { + if efos.protectedRanges[i].OverlapsKeyRange(d.cmp, exciseSpan) { + efos.excised.Store(true) + break + } + } + } } } if err := d.mu.versions.logAndApply(jobID, ve, metrics, false /* forceRotation */, func() []compactionInfo { @@ -1793,28 +2278,31 @@ func (d *DB) ingestApply( // The ingestion may have pushed a level over the threshold for compaction, // so check to see if one is necessary and schedule it. d.maybeScheduleCompaction() - d.maybeValidateSSTablesLocked(ve.NewFiles) + var toValidate []manifest.NewFileEntry + dedup := make(map[base.DiskFileNum]struct{}) + for _, entry := range ve.NewFiles { + if _, ok := dedup[entry.Meta.FileBacking.DiskFileNum]; !ok { + toValidate = append(toValidate, entry) + dedup[entry.Meta.FileBacking.DiskFileNum] = struct{}{} + } + } + d.maybeValidateSSTablesLocked(toValidate) return ve, nil } // maybeValidateSSTablesLocked adds the slice of newFileEntrys to the pending // queue of files to be validated, when the feature is enabled. -// DB.mu must be locked when calling. // -// TODO(bananabrick): Make sure that the ingestion step only passes in the -// physical sstables for validation here. +// Note that if two entries with the same backing file are added twice, then the +// block checksums for the backing file will be validated twice. +// +// DB.mu must be locked when calling. func (d *DB) maybeValidateSSTablesLocked(newFiles []newFileEntry) { // Only add to the validation queue when the feature is enabled. if !d.opts.Experimental.ValidateOnIngest { return } - for _, f := range newFiles { - if f.Meta.Virtual { - panic("pebble: invalid call to maybeValidateSSTablesLocked") - } - } - d.mu.tableValidation.pending = append(d.mu.tableValidation.pending, newFiles...) if d.shouldValidateSSTablesLocked() { go d.validateSSTables() @@ -1853,6 +2341,11 @@ func (d *DB) validateSSTables() { // where we are starving IO from other tasks due to having to page through // all the blocks in all the sstables in the queue. // TODO(travers): Add some form of pacing to avoid IO starvation. + + // If we fail to validate any files due to reasons other than uncovered + // corruption, accumulate them and re-queue them for another attempt. + var retry []manifest.NewFileEntry + for _, f := range pending { // The file may have been moved or deleted since it was ingested, in // which case we skip. @@ -1874,14 +2367,38 @@ func (d *DB) validateSSTables() { } } - err := d.tableCache.withReader( - f.Meta.PhysicalMeta(), func(r *sstable.Reader) error { - return r.ValidateBlockChecksums() - }) + var err error + if f.Meta.Virtual { + err = d.tableCache.withVirtualReader( + f.Meta.VirtualMeta(), func(v sstable.VirtualReader) error { + return v.ValidateBlockChecksumsOnBacking() + }) + } else { + err = d.tableCache.withReader( + f.Meta.PhysicalMeta(), func(r *sstable.Reader) error { + return r.ValidateBlockChecksums() + }) + } + if err != nil { - // TODO(travers): Hook into the corruption reporting pipeline, once - // available. See pebble#1192. - d.opts.Logger.Fatalf("pebble: encountered corruption during ingestion: %s", err) + if IsCorruptionError(err) { + // TODO(travers): Hook into the corruption reporting pipeline, once + // available. See pebble#1192. + d.opts.Logger.Fatalf("pebble: encountered corruption during ingestion: %s", err) + } else { + // If there was some other, possibly transient, error that + // caused table validation to fail inform the EventListener and + // move on. We remember the table so that we can retry it in a + // subsequent table validation job. + // + // TODO(jackson): If the error is not transient, this will retry + // validation indefinitely. While not great, it's the same + // behavior as erroring flushes and compactions. We should + // address this as a part of #270. + d.opts.EventListener.BackgroundError(err) + retry = append(retry, f) + continue + } } d.opts.EventListener.TableValidated(TableValidatedInfo{ @@ -1890,9 +2407,9 @@ func (d *DB) validateSSTables() { }) } rs.unref() - d.mu.Lock() defer d.mu.Unlock() + d.mu.tableValidation.pending = append(d.mu.tableValidation.pending, retry...) d.mu.tableValidation.validating = false d.mu.tableValidation.cond.Broadcast() if d.shouldValidateSSTablesLocked() { diff --git a/vendor/github.com/cockroachdb/pebble/internal/arenaskl/arena.go b/vendor/github.com/cockroachdb/pebble/internal/arenaskl/arena.go index 5151fe491..011c3b024 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/arenaskl/arena.go +++ b/vendor/github.com/cockroachdb/pebble/internal/arenaskl/arena.go @@ -18,11 +18,12 @@ package arenaskl import ( - "math" "sync/atomic" "unsafe" "github.com/cockroachdb/errors" + "github.com/cockroachdb/pebble/internal/constants" + "github.com/cockroachdb/pebble/internal/invariants" ) // Arena is lock-free. @@ -31,9 +32,7 @@ type Arena struct { buf []byte } -const ( - align4 = 3 -) +const nodeAlignment = 4 var ( // ErrArenaFull indicates that the arena is full and cannot perform any more @@ -44,11 +43,17 @@ var ( // NewArena allocates a new arena using the specified buffer as the backing // store. func NewArena(buf []byte) *Arena { - // Don't store data at position 0 in order to reserve offset=0 as a kind - // of nil pointer. + if len(buf) > constants.MaxUint32OrInt { + if invariants.Enabled { + panic(errors.AssertionFailedf("attempting to create arena of size %d", len(buf))) + } + buf = buf[:constants.MaxUint32OrInt] + } a := &Arena{ buf: buf, } + // We don't store data at position 0 in order to reserve offset=0 as a kind of + // nil pointer. a.n.Store(1) return a } @@ -56,9 +61,10 @@ func NewArena(buf []byte) *Arena { // Size returns the number of bytes allocated by the arena. func (a *Arena) Size() uint32 { s := a.n.Load() - if s > math.MaxUint32 { - // Saturate at MaxUint32. - return math.MaxUint32 + if s > constants.MaxUint32OrInt { + // The last failed allocation can push the size higher than len(a.buf). + // Saturate at the maximum representable offset. + return constants.MaxUint32OrInt } return uint32(s) } @@ -68,7 +74,16 @@ func (a *Arena) Capacity() uint32 { return uint32(len(a.buf)) } -func (a *Arena) alloc(size, align, overflow uint32) (uint32, uint32, error) { +// alloc allocates a buffer of the given size and with the given alignment +// (which must be a power of 2). +// +// If overflow is not 0, it also ensures that many bytes after the buffer are +// inside the arena (this is used for structures that are larger than the +// requested size but don't use those extra bytes). +func (a *Arena) alloc(size, alignment, overflow uint32) (uint32, uint32, error) { + if invariants.Enabled && (alignment&(alignment-1)) != 0 { + panic(errors.AssertionFailedf("invalid alignment %d", alignment)) + } // Verify that the arena isn't already full. origSize := a.n.Load() if int(origSize) > len(a.buf) { @@ -76,16 +91,16 @@ func (a *Arena) alloc(size, align, overflow uint32) (uint32, uint32, error) { } // Pad the allocation with enough bytes to ensure the requested alignment. - padded := uint32(size) + align + padded := uint64(size) + uint64(alignment) - 1 - newSize := a.n.Add(uint64(padded)) - if int(newSize)+int(overflow) > len(a.buf) { + newSize := a.n.Add(padded) + if newSize+uint64(overflow) > uint64(len(a.buf)) { return 0, 0, ErrArenaFull } // Return the aligned offset. - offset := (uint32(newSize) - padded + align) & ^align - return offset, padded, nil + offset := (uint32(newSize) - size) & ^(alignment - 1) + return offset, uint32(padded), nil } func (a *Arena) getBytes(offset uint32, size uint32) []byte { diff --git a/vendor/github.com/cockroachdb/pebble/internal/arenaskl/iterator.go b/vendor/github.com/cockroachdb/pebble/internal/arenaskl/iterator.go index bad49099f..a41dd7e74 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/arenaskl/iterator.go +++ b/vendor/github.com/cockroachdb/pebble/internal/arenaskl/iterator.go @@ -18,6 +18,7 @@ package arenaskl import ( + "context" "sync" "github.com/cockroachdb/pebble/internal/base" @@ -238,6 +239,9 @@ func (it *Iterator) SetBounds(lower, upper []byte) { it.upper = upper } +// SetContext implements base.InternalIterator. +func (it *Iterator) SetContext(_ context.Context) {} + func (it *Iterator) decodeKey() { it.key.UserKey = it.list.arena.getBytes(it.nd.keyOffset, it.nd.keySize) it.key.Trailer = it.nd.keyTrailer diff --git a/vendor/github.com/cockroachdb/pebble/internal/arenaskl/node.go b/vendor/github.com/cockroachdb/pebble/internal/arenaskl/node.go index fb50421b1..d464bc56b 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/arenaskl/node.go +++ b/vendor/github.com/cockroachdb/pebble/internal/arenaskl/node.go @@ -29,7 +29,8 @@ import ( // is used here. If a key/value overflows a uint32, it should not be added to // the skiplist. func MaxNodeSize(keySize, valueSize uint32) uint64 { - return uint64(maxNodeSize) + uint64(keySize) + uint64(valueSize) + align4 + const maxPadding = nodeAlignment - 1 + return uint64(maxNodeSize) + uint64(keySize) + uint64(valueSize) + maxPadding } type links struct { @@ -94,7 +95,7 @@ func newRawNode(arena *Arena, height uint32, keySize, valueSize uint32) (nd *nod unusedSize := uint32((maxHeight - int(height)) * linksSize) nodeSize := uint32(maxNodeSize) - unusedSize - nodeOffset, allocSize, err := arena.alloc(nodeSize+keySize+valueSize, align4, unusedSize) + nodeOffset, allocSize, err := arena.alloc(nodeSize+keySize+valueSize, nodeAlignment, unusedSize) if err != nil { return } diff --git a/vendor/github.com/cockroachdb/pebble/internal/base/filenames.go b/vendor/github.com/cockroachdb/pebble/internal/base/filenames.go index b08069897..06098ab63 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/base/filenames.go +++ b/vendor/github.com/cockroachdb/pebble/internal/base/filenames.go @@ -20,12 +20,17 @@ type FileNum uint64 // String returns a string representation of the file number. func (fn FileNum) String() string { return fmt.Sprintf("%06d", fn) } +// SafeFormat implements redact.SafeFormatter. +func (fn FileNum) SafeFormat(w redact.SafePrinter, _ rune) { + w.Printf("%06d", redact.SafeUint(fn)) +} + // DiskFileNum converts a FileNum to a DiskFileNum. DiskFileNum should only be // called if the caller can ensure that the FileNum belongs to a physical file // on disk. These could be manifests, log files, physical sstables on disk, the // options file, but not virtual sstables. func (fn FileNum) DiskFileNum() DiskFileNum { - return DiskFileNum{fn} + return DiskFileNum(fn) } // A DiskFileNum is just a FileNum belonging to a file which exists on disk. @@ -34,15 +39,18 @@ func (fn FileNum) DiskFileNum() DiskFileNum { // Converting a DiskFileNum to a FileNum is always valid, whereas converting a // FileNum to DiskFileNum may not be valid and care should be taken to prove // that the FileNum actually exists on disk. -type DiskFileNum struct { - fn FileNum -} +type DiskFileNum uint64 -func (dfn DiskFileNum) String() string { return dfn.fn.String() } +func (dfn DiskFileNum) String() string { return fmt.Sprintf("%06d", dfn) } + +// SafeFormat implements redact.SafeFormatter. +func (dfn DiskFileNum) SafeFormat(w redact.SafePrinter, verb rune) { + w.Printf("%06d", redact.SafeUint(dfn)) +} // FileNum converts a DiskFileNum to a FileNum. This conversion is always valid. func (dfn DiskFileNum) FileNum() FileNum { - return dfn.fn + return FileNum(dfn) } // FileType enumerates the types of files found in a DB. @@ -93,9 +101,9 @@ func ParseFilename(fs vfs.FS, filename string) (fileType FileType, dfn DiskFileN filename = fs.PathBase(filename) switch { case filename == "CURRENT": - return FileTypeCurrent, DiskFileNum{0}, true + return FileTypeCurrent, 0, true case filename == "LOCK": - return FileTypeLock, DiskFileNum{0}, true + return FileTypeLock, 0, true case strings.HasPrefix(filename, "MANIFEST-"): dfn, ok = parseDiskFileNum(filename[len("MANIFEST-"):]) if !ok { @@ -146,7 +154,7 @@ func parseDiskFileNum(s string) (dfn DiskFileNum, ok bool) { if err != nil { return dfn, false } - return DiskFileNum{FileNum(u)}, true + return DiskFileNum(u), true } // A Fataler fatals a process with a message when called. diff --git a/vendor/github.com/cockroachdb/pebble/internal/base/internal.go b/vendor/github.com/cockroachdb/pebble/internal/base/internal.go index 082307a35..19f421a3f 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/base/internal.go +++ b/vendor/github.com/cockroachdb/pebble/internal/base/internal.go @@ -5,12 +5,22 @@ package base // import "github.com/cockroachdb/pebble/internal/base" import ( + "cmp" "encoding/binary" "fmt" "strconv" "strings" ) +const ( + // SeqNumZero is the zero sequence number, set by compactions if they can + // guarantee there are no keys underneath an internal key. + SeqNumZero = uint64(0) + // SeqNumStart is the first sequence number assigned to a key. Sequence + // numbers 1-9 are reserved for potential future use. + SeqNumStart = uint64(10) +) + // InternalKeyKind enumerates the kind of key: a deletion tombstone, a set // value, a merged value, etc. type InternalKeyKind uint8 @@ -290,13 +300,8 @@ func InternalCompare(userCmp Compare, a, b InternalKey) int { if x := userCmp(a.UserKey, b.UserKey); x != 0 { return x } - if a.Trailer > b.Trailer { - return -1 - } - if a.Trailer < b.Trailer { - return 1 - } - return 0 + // Reverse order for trailer comparison. + return cmp.Compare(b.Trailer, a.Trailer) } // Encode encodes the receiver into the buffer. The buffer must be large enough diff --git a/vendor/github.com/cockroachdb/pebble/internal/base/iterator.go b/vendor/github.com/cockroachdb/pebble/internal/base/iterator.go index 8ab10a6cf..1b72432f6 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/base/iterator.go +++ b/vendor/github.com/cockroachdb/pebble/internal/base/iterator.go @@ -5,6 +5,7 @@ package base import ( + "context" "fmt" "time" ) @@ -204,6 +205,10 @@ type InternalIterator interface { // optimizations. SetBounds(lower, upper []byte) + // SetContext replaces the context provided at iterator creation, or the + // last one provided by SetContext. + SetContext(ctx context.Context) + fmt.Stringer } diff --git a/vendor/github.com/cockroachdb/pebble/internal/base/logger.go b/vendor/github.com/cockroachdb/pebble/internal/base/logger.go index e4a2f44fa..5448137df 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/base/logger.go +++ b/vendor/github.com/cockroachdb/pebble/internal/base/logger.go @@ -19,6 +19,7 @@ import ( // Logger defines an interface for writing log messages. type Logger interface { Infof(format string, args ...interface{}) + Errorf(format string, args ...interface{}) Fatalf(format string, args ...interface{}) } type defaultLogger struct{} @@ -33,6 +34,11 @@ func (defaultLogger) Infof(format string, args ...interface{}) { _ = log.Output(2, fmt.Sprintf(format, args...)) } +// Errorf implements the Logger.Errorf interface. +func (defaultLogger) Errorf(format string, args ...interface{}) { + _ = log.Output(2, fmt.Sprintf(format, args...)) +} + // Fatalf implements the Logger.Fatalf interface. func (defaultLogger) Fatalf(format string, args ...interface{}) { _ = log.Output(2, fmt.Sprintf(format, args...)) @@ -75,6 +81,11 @@ func (b *InMemLogger) Infof(format string, args ...interface{}) { } } +// Errorf is part of the Logger interface. +func (b *InMemLogger) Errorf(format string, args ...interface{}) { + b.Infof(format, args...) +} + // Fatalf is part of the Logger interface. func (b *InMemLogger) Fatalf(format string, args ...interface{}) { b.Infof(format, args...) @@ -125,6 +136,9 @@ var _ LoggerAndTracer = NoopLoggerAndTracer{} // Infof implements LoggerAndTracer. func (l NoopLoggerAndTracer) Infof(format string, args ...interface{}) {} +// Errorf implements LoggerAndTracer. +func (l NoopLoggerAndTracer) Errorf(format string, args ...interface{}) {} + // Fatalf implements LoggerAndTracer. func (l NoopLoggerAndTracer) Fatalf(format string, args ...interface{}) {} diff --git a/vendor/github.com/cockroachdb/pebble/internal/base/seqnums.go b/vendor/github.com/cockroachdb/pebble/internal/base/seqnums.go deleted file mode 100644 index cd95724e5..000000000 --- a/vendor/github.com/cockroachdb/pebble/internal/base/seqnums.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2023 The LevelDB-Go and Pebble Authors. All rights reserved. Use -// of this source code is governed by a BSD-style license that can be found in -// the LICENSE file. - -package base - -import "fmt" - -// This file defines sequence numbers that are reserved for foreign keys i.e. -// internal keys coming from other Pebble instances and existing in shared -// storage, as those will "slot below" any internal keys added by our own Pebble -// instance. Any keys created by this Pebble instance need to be greater than -// all reserved sequence numbers (i.e. >= SeqNumStart). -const ( - // SeqNumZero is the zero sequence number, set by compactions if they can - // guarantee there are no keys underneath an internal key. - SeqNumZero = uint64(0) - - // SeqNumL6 is the sequence number reserved for foreign keys in L6. This seqnum - // will be used to expose any range key sets as well as point keys in L6. Range - // deletes do not need to be exposed in L6. - SeqNumL6 = uint64(1) - - // SeqNumL5 is the sequence number reserved for foreign keys in L5. This seqnum - // needs to be greater than SeqNumL6, so that range deletes in L5 can be - // exposed at this level and will correctly delete covering points in L6. Also - // range key unsets/dels will be exposed at this seqnum and will need to shadow - // overlapping range keys in L6. - // - // Note that we can use the same sequence number for all exposed keys in L5 as - // range dels do not delete points at the same seqnum, and range key - // unsets/deletes do not coalesce with range key sets at the same seqnum. Range - // key masking does not care about the sequence number of overlapping points - // (rather, it applies to points based on suffixes), so we can use this seqnum - // for all L5 keys exposed. - SeqNumL5 = uint64(2) - - // Sequence numbers 3-9 are reserved for future use. - - // SeqNumStart is the first sequence number assigned to a key written by - // ourselves. - SeqNumStart = uint64(10) -) - -// SeqNumForLevel returns the appropriate reserved sequence number for keys in -// foreign sstables at the specified level. -func SeqNumForLevel(level int) uint64 { - switch level { - case 5: - return SeqNumL5 - case 6: - return SeqNumL6 - default: - panic(fmt.Sprintf("unexpected foreign sstable at level %d", level)) - } -} diff --git a/vendor/github.com/cockroachdb/pebble/internal/batchskl/skl.go b/vendor/github.com/cockroachdb/pebble/internal/batchskl/skl.go index 73bfa0e10..f56d95c28 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/batchskl/skl.go +++ b/vendor/github.com/cockroachdb/pebble/internal/batchskl/skl.go @@ -63,14 +63,15 @@ import ( "github.com/cockroachdb/errors" "github.com/cockroachdb/pebble/internal/base" + "github.com/cockroachdb/pebble/internal/constants" "golang.org/x/exp/rand" ) const ( maxHeight = 20 - maxNodeSize = int(unsafe.Sizeof(node{})) - linksSize = int(unsafe.Sizeof(links{})) - maxNodesSize = math.MaxUint32 + maxNodeSize = uint64(unsafe.Sizeof(node{})) + linksSize = uint64(unsafe.Sizeof(links{})) + maxNodesSize = constants.MaxUint32OrInt ) var ( @@ -281,7 +282,7 @@ func (s *Skiplist) newNode( panic("height cannot be less than one or greater than the max height") } - unusedSize := (maxHeight - int(height)) * linksSize + unusedSize := uint64(maxHeight-int(height)) * linksSize nodeOffset, err := s.alloc(uint32(maxNodeSize - unusedSize)) if err != nil { return 0, err @@ -296,13 +297,13 @@ func (s *Skiplist) newNode( } func (s *Skiplist) alloc(size uint32) (uint32, error) { - offset := len(s.nodes) + offset := uint64(len(s.nodes)) // We only have a need for memory up to offset + size, but we never want // to allocate a node whose tail points into unallocated memory. minAllocSize := offset + maxNodeSize - if cap(s.nodes) < minAllocSize { - allocSize := cap(s.nodes) * 2 + if uint64(cap(s.nodes)) < minAllocSize { + allocSize := uint64(cap(s.nodes)) * 2 if allocSize < minAllocSize { allocSize = minAllocSize } diff --git a/vendor/github.com/cockroachdb/pebble/internal/cache/clockpro.go b/vendor/github.com/cockroachdb/pebble/internal/cache/clockpro.go index 94102a274..cdae6a9fe 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/cache/clockpro.go +++ b/vendor/github.com/cockroachdb/pebble/internal/cache/clockpro.go @@ -71,9 +71,7 @@ func (h Handle) Get() []byte { // Release releases the reference to the cache entry. func (h Handle) Release() { - if h.value != nil { - h.value.release() - } + h.value.release() } type shard struct { @@ -176,7 +174,7 @@ func (c *shard) Set(id uint64, fileNum base.DiskFileNum, offset uint64, value *V // cache entry was a test page c.sizeTest -= e.size c.countTest-- - c.metaDel(e) + c.metaDel(e).release() c.metaCheck(e) e.size = int64(len(value.buf)) @@ -233,37 +231,75 @@ func (c *shard) Delete(id uint64, fileNum base.DiskFileNum, offset uint64) { return } - c.mu.Lock() - defer c.mu.Unlock() + var deletedValue *Value + func() { + c.mu.Lock() + defer c.mu.Unlock() - e := c.blocks.Get(k) - if e == nil { - return - } - c.metaEvict(e) - - c.checkConsistency() + e := c.blocks.Get(k) + if e == nil { + return + } + deletedValue = c.metaEvict(e) + c.checkConsistency() + }() + // Now that the mutex has been dropped, release the reference which will + // potentially free the memory associated with the previous cached value. + deletedValue.release() } // EvictFile evicts all of the cache values for the specified file. func (c *shard) EvictFile(id uint64, fileNum base.DiskFileNum) { + fkey := key{fileKey{id, fileNum}, 0} + for c.evictFileRun(fkey) { + // Sched switch to give another goroutine an opportunity to acquire the + // shard mutex. + runtime.Gosched() + } +} + +func (c *shard) evictFileRun(fkey key) (moreRemaining bool) { + // If most of the file's blocks are held in the block cache, evicting all + // the blocks may take a while. We don't want to block the entire cache + // shard, forcing concurrent readers to wait until we're finished. We drop + // the mutex every [blocksPerMutexAcquisition] blocks to give other + // goroutines an opportunity to make progress. + const blocksPerMutexAcquisition = 5 c.mu.Lock() - defer c.mu.Unlock() - fkey := key{fileKey{id, fileNum}, 0} + // Releasing a value may result in free-ing it back to the memory allocator. + // This can have a nontrivial cost that we'd prefer to not pay while holding + // the shard mutex, so we collect the evicted values in a local slice and + // only release them in a defer after dropping the cache mutex. + var obsoleteValuesAlloc [blocksPerMutexAcquisition]*Value + obsoleteValues := obsoleteValuesAlloc[:0] + defer func() { + c.mu.Unlock() + for _, v := range obsoleteValues { + v.release() + } + }() + blocks := c.files.Get(fkey) if blocks == nil { - return + // No blocks for this file. + return false } - for b, n := blocks, (*entry)(nil); ; b = n { + + // b is the current head of the doubly linked list, and n is the entry after b. + for b, n := blocks, (*entry)(nil); len(obsoleteValues) < cap(obsoleteValues); b = n { n = b.fileLink.next - c.metaEvict(b) + obsoleteValues = append(obsoleteValues, c.metaEvict(b)) if b == n { - break + // b == n represents the case where b was the last entry remaining + // in the doubly linked list, which is why it pointed at itself. So + // no more entries left. + c.checkConsistency() + return false } } - - c.checkConsistency() + // Exhausted blocksPerMutexAcquisition. + return true } func (c *shard) Free() { @@ -274,7 +310,7 @@ func (c *shard) Free() { // metaCheck call when the "invariants" build tag is specified. for c.handHot != nil { e := c.handHot - c.metaDel(c.handHot) + c.metaDel(c.handHot).release() e.free() } @@ -359,12 +395,14 @@ func (c *shard) metaAdd(key key, e *entry) bool { // Remove the entry from the cache. This removes the entry from the blocks map, // the files map, and ensures that hand{Hot,Cold,Test} are not pointing at the -// entry. -func (c *shard) metaDel(e *entry) { +// entry. Returns the deleted value that must be released, if any. +func (c *shard) metaDel(e *entry) (deletedValue *Value) { if value := e.peekValue(); value != nil { value.ref.trace("metaDel") } - e.setValue(nil) + // Remove the pointer to the value. + deletedValue = e.val + e.val = nil c.blocks.Delete(e.key) if entriesGoAllocated { @@ -396,6 +434,7 @@ func (c *shard) metaDel(e *entry) { } else { c.files.Put(fkey, next) } + return deletedValue } // Check that the specified entry is not referenced by the cache. @@ -455,7 +494,7 @@ func (c *shard) metaCheck(e *entry) { } } -func (c *shard) metaEvict(e *entry) { +func (c *shard) metaEvict(e *entry) (evictedValue *Value) { switch e.ptype { case etHot: c.sizeHot -= e.size @@ -467,9 +506,10 @@ func (c *shard) metaEvict(e *entry) { c.sizeTest -= e.size c.countTest-- } - c.metaDel(e) + evictedValue = c.metaDel(e) c.metaCheck(e) e.free() + return evictedValue } func (c *shard) evict() { @@ -564,7 +604,7 @@ func (c *shard) runHandTest() { if c.coldTarget < 0 { c.coldTarget = 0 } - c.metaDel(e) + c.metaDel(e).release() c.metaCheck(e) e.free() } @@ -587,7 +627,7 @@ type Metrics struct { // Cache implements Pebble's sharded block cache. The Clock-PRO algorithm is // used for page replacement // (http://static.usenix.org/event/usenix05/tech/general/full_papers/jiang/jiang_html/html.html). In -// order to provide better concurrency, 2 x NumCPUs shards are created, with +// order to provide better concurrency, 4 x NumCPUs shards are created, with // each shard being given 1/n of the target cache size. The Clock-PRO algorithm // is run independently on each shard. // @@ -643,7 +683,34 @@ type Cache struct { // defer c.Unref() // d, err := pebble.Open(pebble.Options{Cache: c}) func New(size int64) *Cache { - return newShards(size, 2*runtime.GOMAXPROCS(0)) + // How many cache shards should we create? + // + // Note that the probability two processors will try to access the same + // shard at the same time increases superlinearly with the number of + // processors (Eg, consider the brithday problem where each CPU is a person, + // and each shard is a possible birthday). + // + // We could consider growing the number of shards superlinearly, but + // increasing the shard count may reduce the effectiveness of the caching + // algorithm if frequently-accessed blocks are insufficiently distributed + // across shards. If a shard's size is smaller than a single frequently + // scanned sstable, then the shard will be unable to hold the entire + // frequently-scanned table in memory despite other shards still holding + // infrequently accessed blocks. + // + // Experimentally, we've observed contention contributing to tail latencies + // at 2 shards per processor. For now we use 4 shards per processor, + // recognizing this may not be final word. + m := 4 * runtime.GOMAXPROCS(0) + + // In tests we can use large CPU machines with small cache sizes and have + // many caches in existence at a time. If sharding into m shards would + // produce too small shards, constrain the number of shards to 4. + const minimumShardSize = 4 << 20 // 4 MiB + if m > 4 && int(size)/m < minimumShardSize { + m = 4 + } + return newShards(size, m) } func newShards(size int64, shards int) *Cache { diff --git a/vendor/github.com/cockroachdb/pebble/internal/cache/entry.go b/vendor/github.com/cockroachdb/pebble/internal/cache/entry.go index 28a3a3f29..a49fde6b7 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/cache/entry.go +++ b/vendor/github.com/cockroachdb/pebble/internal/cache/entry.go @@ -139,9 +139,7 @@ func (e *entry) setValue(v *Value) { } old := e.val e.val = v - if old != nil { - old.release() - } + old.release() } func (e *entry) peekValue() *Value { diff --git a/vendor/github.com/cockroachdb/pebble/internal/cache/refcnt_normal.go b/vendor/github.com/cockroachdb/pebble/internal/cache/refcnt_normal.go index 2a947bee9..9ab334861 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/cache/refcnt_normal.go +++ b/vendor/github.com/cockroachdb/pebble/internal/cache/refcnt_normal.go @@ -10,6 +10,8 @@ package cache import ( "fmt" "sync/atomic" + + "github.com/cockroachdb/redact" ) // refcnt provides an atomic reference count. This version is used when the @@ -31,14 +33,14 @@ func (v *refcnt) refs() int32 { func (v *refcnt) acquire() { switch v := v.val.Add(1); { case v <= 1: - panic(fmt.Sprintf("pebble: inconsistent reference count: %d", v)) + panic(redact.Safe(fmt.Sprintf("pebble: inconsistent reference count: %d", v))) } } func (v *refcnt) release() bool { switch v := v.val.Add(-1); { case v < 0: - panic(fmt.Sprintf("pebble: inconsistent reference count: %d", v)) + panic(redact.Safe(fmt.Sprintf("pebble: inconsistent reference count: %d", v))) case v == 0: return true default: diff --git a/vendor/github.com/cockroachdb/pebble/internal/cache/value.go b/vendor/github.com/cockroachdb/pebble/internal/cache/value.go index c5c967aff..6d2cae15e 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/cache/value.go +++ b/vendor/github.com/cockroachdb/pebble/internal/cache/value.go @@ -40,7 +40,7 @@ func (v *Value) acquire() { } func (v *Value) release() { - if v.ref.release() { + if v != nil && v.ref.release() { v.free() } } diff --git a/vendor/github.com/cockroachdb/pebble/internal/constants/constants.go b/vendor/github.com/cockroachdb/pebble/internal/constants/constants.go new file mode 100644 index 000000000..8d9198cee --- /dev/null +++ b/vendor/github.com/cockroachdb/pebble/internal/constants/constants.go @@ -0,0 +1,17 @@ +// Copyright 2023 The LevelDB-Go and Pebble Authors. All rights reserved. Use +// of this source code is governed by a BSD-style license that can be found in +// the LICENSE file. + +package constants + +const ( + // oneIf64Bit is 1 on 64-bit platforms and 0 on 32-bit platforms. + oneIf64Bit = ^uint(0) >> 63 + + // MaxUint32OrInt returns min(MaxUint32, MaxInt), i.e + // - MaxUint32 on 64-bit platforms; + // - MaxInt on 32-bit platforms. + // It is used when slices are limited to Uint32 on 64-bit platforms (the + // length limit for slices is naturally MaxInt on 32-bit platforms). + MaxUint32OrInt = (1<<31)<= key, _if_ the filterFunc (which has + // no knowledge of the seek key) mutated the span to start at a key greater + // than or equal to `key`. Detect this case and prev/invalidate the iter. + if span != nil && i.cmp(span.Start, key) >= 0 { + return i.Prev() + } + return span } // First implements FragmentIterator. diff --git a/vendor/github.com/cockroachdb/pebble/internal/keyspan/interleaving_iter.go b/vendor/github.com/cockroachdb/pebble/internal/keyspan/interleaving_iter.go index a507b758b..e1fd600a2 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/keyspan/interleaving_iter.go +++ b/vendor/github.com/cockroachdb/pebble/internal/keyspan/interleaving_iter.go @@ -5,8 +5,10 @@ package keyspan import ( + "context" "fmt" + "github.com/cockroachdb/errors" "github.com/cockroachdb/pebble/internal/base" "github.com/cockroachdb/pebble/internal/invariants" ) @@ -111,6 +113,28 @@ type InterleavingIter struct { nextPrefixBuf []byte pointKey *base.InternalKey pointVal base.LazyValue + // err holds an iterator error from either pointIter or keyspanIter. It's + // reset to nil on seeks. An overview of error-handling mechanics: + // + // Whenever either pointIter or keyspanIter is respositioned and a nil + // key/span is returned, the code performing the positioning is responsible + // for checking the iterator's Error() value. This happens in savePoint and + // saveSpan[Forward,Backward]. + // + // Once i.err is non-nil, the computation of i.pos must set i.pos = + // posExhausted. This happens in compute[Smallest|Largest]Pos and + // [next|prev]Pos. Setting i.pos to posExhausted ensures we'll yield nil to + // the caller, which they'll interpret as a signal they must check Error(). + // + // INVARIANTS: + // i.err != nil => i.pos = posExhausted + err error + // prefix records the iterator's current prefix if the iterator is in prefix + // mode. During prefix mode, Pebble will truncate spans to the next prefix. + // If the iterator subsequently leaves prefix mode, the existing span cached + // in i.span must be invalidated because its bounds do not reflect the + // original span's true bounds. + prefix []byte // span holds the span at the keyspanIter's current position. If the span is // wholly contained within the iterator bounds, this span is directly // returned to the iterator consumer through Span(). If either bound needed @@ -126,31 +150,16 @@ type InterleavingIter struct { truncatedSpan Span truncated bool - // Keeping all of the bools together reduces the sizeof the struct. - - // spanCoversKey indicates whether the current span covers the last-returned - // key. - spanCoversKey bool - // pointKeyInterleaved indicates whether the current point key has been - // interleaved in the current direction. - pointKeyInterleaved bool - // keyspanInterleaved indicates whether or not the current span has been - // interleaved at its start key in the current direction. A span marker is - // interleaved when first passing over the start key. - // - // When iterating in the forward direction, the span start key is - // interleaved when the span first begins to cover the current iterator - // position. The keyspan iterator isn't advanced until the - // InterleavingIterator moves beyond the current span's end key. This field - // is used to remember that the span has already been interleaved and - // shouldn't be interleaved again. - // - // When iterating in the reverse direction, the span start key is - // interleaved immediately before the iterator will move to a key no longer - // be covered by the span. This field behaves analagously to - // pointKeyInterleaved and if true signals that we must Prev the keyspan - // iterator on the next Prev call. - keyspanInterleaved bool + // Keeping all of the bools/uint8s together reduces the sizeof the struct. + + // pos encodes the current position of the iterator: exhausted, on the point + // key, on a keyspan start, or on a keyspan end. + pos interleavePos + // withinSpan indicates whether the iterator is currently positioned within + // the bounds of the current span (i.span). withinSpan must be updated + // whenever the interleaving iterator's position enters or exits the bounds + // of a span. + withinSpan bool // spanMarkerTruncated is set by SeekGE/SeekPrefixGE calls that truncate a // span's start bound marker to the search key. It's returned to false on // the next repositioning of the keyspan iterator. @@ -158,39 +167,54 @@ type InterleavingIter struct { // maskSpanChangedCalled records whether or not the last call to // SpanMask.SpanChanged provided the current span (i.span) or not. maskSpanChangedCalled bool - // prefix records whether the iteator is in prefix mode. During prefix mode, - // Pebble will truncate spans to the next prefix. If the iterator - // subsequently leaves prefix mode, the existing span cached in i.span must - // be invalidated because its bounds do not reflect the original span's true - // bounds. - prefix bool // dir indicates the direction of iteration: forward (+1) or backward (-1) dir int8 } +// interleavePos indicates the iterator's current position. Note that both +// keyspanStart and keyspanEnd positions correspond to their user key boundaries +// with maximal sequence numbers. This means in the forward direction +// posKeyspanStart and posKeyspanEnd are always interleaved before a posPointKey +// with the same user key. +type interleavePos int8 + +const ( + posUninitialized interleavePos = iota + posExhausted + posPointKey + posKeyspanStart + posKeyspanEnd +) + // Assert that *InterleavingIter implements the InternalIterator interface. var _ base.InternalIterator = &InterleavingIter{} +// InterleavingIterOpts holds options configuring the behavior of a +// InterleavingIter. +type InterleavingIterOpts struct { + Mask SpanMask + LowerBound, UpperBound []byte +} + // Init initializes the InterleavingIter to interleave point keys from pointIter // with key spans from keyspanIter. // -// The point iterator must already have the provided bounds. Init does not -// propagate the bounds down the iterator stack. +// The point iterator must already have the bounds provided on opts. Init does +// not propagate the bounds down the iterator stack. func (i *InterleavingIter) Init( comparer *base.Comparer, pointIter base.InternalIterator, keyspanIter FragmentIterator, - mask SpanMask, - lowerBound, upperBound []byte, + opts InterleavingIterOpts, ) { *i = InterleavingIter{ cmp: comparer.Compare, comparer: comparer, pointIter: pointIter, keyspanIter: keyspanIter, - mask: mask, - lower: lowerBound, - upper: upperBound, + mask: opts.Mask, + lower: opts.LowerBound, + upper: opts.UpperBound, } } @@ -209,14 +233,14 @@ func (i *InterleavingIter) InitSeekGE( ) (*base.InternalKey, base.LazyValue) { i.dir = +1 i.clearMask() - i.prefix = prefix != nil - i.pointKey, i.pointVal = pointKey, pointValue - i.pointKeyInterleaved = false + i.prefix = prefix + i.savePoint(pointKey, pointValue) // NB: This keyspanSeekGE call will truncate the span to the seek key if // necessary. This truncation is important for cases where a switch to // combined iteration is made during a user-initiated SeekGE. i.keyspanSeekGE(key, prefix) - return i.interleaveForward(key, prefix) + i.computeSmallestPos() + return i.yieldPosition(key, i.nextPos) } // InitSeekLT may be called after Init but before any positioning method. @@ -234,10 +258,10 @@ func (i *InterleavingIter) InitSeekLT( ) (*base.InternalKey, base.LazyValue) { i.dir = -1 i.clearMask() - i.pointKey, i.pointVal = pointKey, pointValue - i.pointKeyInterleaved = false + i.savePoint(pointKey, pointValue) i.keyspanSeekLT(key) - return i.interleaveBackward() + i.computeLargestPos() + return i.yieldPosition(i.lower, i.prevPos) } // SeekGE implements (base.InternalIterator).SeekGE. @@ -254,10 +278,10 @@ func (i *InterleavingIter) InitSeekLT( func (i *InterleavingIter) SeekGE( key []byte, flags base.SeekGEFlags, ) (*base.InternalKey, base.LazyValue) { + i.err = nil i.clearMask() i.disablePrefixMode() - i.pointKey, i.pointVal = i.pointIter.SeekGE(key, flags) - i.pointKeyInterleaved = false + i.savePoint(i.pointIter.SeekGE(key, flags)) // We need to seek the keyspan iterator too. If the keyspan iterator was // already positioned at a span, we might be able to avoid the seek if the @@ -265,14 +289,15 @@ func (i *InterleavingIter) SeekGE( if i.span != nil && i.cmp(key, i.span.End) < 0 && i.cmp(key, i.span.Start) >= 0 { // We're seeking within the existing span's bounds. We still might need // truncate the span to the iterator's bounds. - i.checkForwardBound(nil /* prefix */) + i.saveSpanForward(i.span) i.savedKeyspan() } else { i.keyspanSeekGE(key, nil /* prefix */) } i.dir = +1 - return i.interleaveForward(key, nil /* prefix */) + i.computeSmallestPos() + return i.yieldPosition(key, i.nextPos) } // SeekPrefixGE implements (base.InternalIterator).SeekPrefixGE. @@ -289,10 +314,10 @@ func (i *InterleavingIter) SeekGE( func (i *InterleavingIter) SeekPrefixGE( prefix, key []byte, flags base.SeekGEFlags, ) (*base.InternalKey, base.LazyValue) { + i.err = nil i.clearMask() - i.pointKey, i.pointVal = i.pointIter.SeekPrefixGE(prefix, key, flags) - i.pointKeyInterleaved = false - i.prefix = true + i.prefix = prefix + i.savePoint(i.pointIter.SeekPrefixGE(prefix, key, flags)) // We need to seek the keyspan iterator too. If the keyspan iterator was // already positioned at a span, we might be able to avoid the seek if the @@ -321,7 +346,7 @@ func (i *InterleavingIter) SeekPrefixGE( if ei := i.comparer.Split(i.span.End); i.cmp(prefix, i.span.End[:ei]) < 0 { // We're seeking within the existing span's bounds. We still might need // truncate the span to the iterator's bounds. - i.checkForwardBound(prefix) + i.saveSpanForward(i.span) i.savedKeyspan() seekKeyspanIter = false } @@ -331,17 +356,18 @@ func (i *InterleavingIter) SeekPrefixGE( } i.dir = +1 - return i.interleaveForward(key, prefix) + i.computeSmallestPos() + return i.yieldPosition(key, i.nextPos) } // SeekLT implements (base.InternalIterator).SeekLT. func (i *InterleavingIter) SeekLT( key []byte, flags base.SeekLTFlags, ) (*base.InternalKey, base.LazyValue) { + i.err = nil i.clearMask() i.disablePrefixMode() - i.pointKey, i.pointVal = i.pointIter.SeekLT(key, flags) - i.pointKeyInterleaved = false + i.savePoint(i.pointIter.SeekLT(key, flags)) // We need to seek the keyspan iterator too. If the keyspan iterator was // already positioned at a span, we might be able to avoid the seek if the @@ -349,13 +375,13 @@ func (i *InterleavingIter) SeekLT( if i.span != nil && i.cmp(key, i.span.Start) > 0 && i.cmp(key, i.span.End) < 0 { // We're seeking within the existing span's bounds. We still might need // truncate the span to the iterator's bounds. - i.checkBackwardBound() + i.saveSpanBackward(i.span) // The span's start key is still not guaranteed to be less than key, // because of the bounds enforcement. Consider the following example: // // Bounds are set to [d,e). The user performs a SeekLT(d). The // FragmentIterator.SeekLT lands on a span [b,f). This span has a start - // key less than d, as expected. Above, checkBackwardBound truncates the + // key less than d, as expected. Above, saveSpanBackward truncates the // span to match the iterator's current bounds, modifying the span to // [d,e), which does not overlap the search space of [-∞, d). // @@ -371,33 +397,34 @@ func (i *InterleavingIter) SeekLT( } i.dir = -1 - return i.interleaveBackward() + i.computeLargestPos() + return i.yieldPosition(i.lower, i.prevPos) } // First implements (base.InternalIterator).First. func (i *InterleavingIter) First() (*base.InternalKey, base.LazyValue) { + i.err = nil i.clearMask() i.disablePrefixMode() - i.pointKey, i.pointVal = i.pointIter.First() - i.pointKeyInterleaved = false - i.span = i.keyspanIter.First() - i.checkForwardBound(nil /* prefix */) + i.savePoint(i.pointIter.First()) + i.saveSpanForward(i.keyspanIter.First()) i.savedKeyspan() i.dir = +1 - return i.interleaveForward(i.lower, nil /* prefix */) + i.computeSmallestPos() + return i.yieldPosition(i.lower, i.nextPos) } // Last implements (base.InternalIterator).Last. func (i *InterleavingIter) Last() (*base.InternalKey, base.LazyValue) { + i.err = nil i.clearMask() i.disablePrefixMode() - i.pointKey, i.pointVal = i.pointIter.Last() - i.pointKeyInterleaved = false - i.span = i.keyspanIter.Last() - i.checkBackwardBound() + i.savePoint(i.pointIter.Last()) + i.saveSpanBackward(i.keyspanIter.Last()) i.savedKeyspan() i.dir = -1 - return i.interleaveBackward() + i.computeLargestPos() + return i.yieldPosition(i.lower, i.prevPos) } // Next implements (base.InternalIterator).Next. @@ -413,70 +440,42 @@ func (i *InterleavingIter) Next() (*base.InternalKey, base.LazyValue) { i.clearMask() } - // The existing point key (denoted below with *) is either the last - // key we returned (the current iterator position): - // points: x (y*) z - // or the upcoming point key in the backward direction if we just - // returned a span start boundary key: - // points: x* z - // spans: ([y-?)) - // direction. Either way, we must move to the next point key. - switch { - case i.pointKey == nil && i.lower == nil: - i.pointKey, i.pointVal = i.pointIter.First() - case i.pointKey == nil && i.lower != nil: - i.pointKey, i.pointVal = i.pointIter.SeekGE(i.lower, base.SeekGEFlagsNone) - default: - i.pointKey, i.pointVal = i.pointIter.Next() - } - i.pointKeyInterleaved = false - - if i.span == nil { - // There was no span in the reverse direction, but there may be - // a span in the forward direction. - i.span = i.keyspanIter.Next() - i.checkForwardBound(nil /* prefix */) - i.savedKeyspan() - } else { - // Regardless of the current iterator state, we mark any existing - // span as interleaved when switching to forward iteration, - // justified below. - // - // If the point key is the last key returned: - // pointIter : ... (y) z ... - // keyspanIter : ... ([x - )) ... - // ^ - // The span's start key must be ≤ the point key, otherwise we'd have - // interleaved the span's start key. From a forward-iteration - // perspective, the span's start key is in the past and should be - // considered already-interleaved. - // - // If the span start boundary key is the last key returned: - // pointIter : ... (x) z ... - // keyspanIter : ... ([y - )) ... - // ^ - // i.span.Start is the key we last returned during reverse - // iteration. From the perspective of forward-iteration, its start - // key was just visited. - i.keyspanInterleaved = true + // When switching directions, iterator state corresponding to the + // current iterator position (as indicated by i.pos) is already correct. + // However any state that has yet to be interleaved describes a position + // behind the current iterator position and needs to be updated to + // describe the position ahead of the current iterator position. + switch i.pos { + case posExhausted: + // Nothing to do. The below nextPos call will move both the point + // key and span to their next positions and return + // MIN(point,s.Start). + case posPointKey: + // If we're currently on a point key, the below nextPos will + // correctly Next the point key iterator to the next point key. + // Do we need to move the span forwards? If the current span lies + // entirely behind the current key (!i.withinSpan), then we + // need to move it to the first span in the forward direction. + if !i.withinSpan { + i.saveSpanForward(i.keyspanIter.Next()) + i.savedKeyspan() + } + case posKeyspanStart: + i.withinSpan = true + // Since we're positioned on a Span, the pointIter is positioned + // entirely behind the current iterator position. Reposition it + // ahead of the current iterator position. + i.savePoint(i.pointIter.Next()) + case posKeyspanEnd: + // Since we're positioned on a Span, the pointIter is positioned + // entirely behind of the current iterator position. Reposition it + // ahead the current iterator position. + i.savePoint(i.pointIter.Next()) } + // Fallthrough to calling i.nextPos. } - - // Refresh the point key if the current point key has already been - // interleaved. - if i.pointKeyInterleaved { - i.pointKey, i.pointVal = i.pointIter.Next() - i.pointKeyInterleaved = false - } - // If we already interleaved the current span start key, and the point key - // is ≥ the span's end key, move to the next span. - if i.keyspanInterleaved && i.pointKey != nil && i.span != nil && - i.cmp(i.pointKey.UserKey, i.span.End) >= 0 { - i.span = i.keyspanIter.Next() - i.checkForwardBound(nil /* prefix */) - i.savedKeyspan() - } - return i.interleaveForward(i.lower, nil /* prefix */) + i.nextPos() + return i.yieldPosition(i.lower, i.nextPos) } // NextPrefix implements (base.InternalIterator).NextPrefix. @@ -485,22 +484,24 @@ func (i *InterleavingIter) NextPrefix(succKey []byte) (*base.InternalKey, base.L panic("pebble: cannot switch directions with NextPrefix") } - // Refresh the point key if the current point key has already been - // interleaved, OR if the next uninterleaved point key has the old suffix - // (it's less than succKey). - if i.pointKeyInterleaved || (i.pointKey != nil && i.cmp(i.pointKey.UserKey, succKey) < 0) { - i.pointKey, i.pointVal = i.pointIter.NextPrefix(succKey) - i.pointKeyInterleaved = false - } - // If we already interleaved the current span start key, and the point key - // is ≥ the span's end key, move to the next span. - if i.keyspanInterleaved && i.pointKey != nil && i.span != nil && - i.cmp(i.pointKey.UserKey, i.span.End) >= 0 { - i.span = i.keyspanIter.Next() - i.checkForwardBound(nil) - i.savedKeyspan() + switch i.pos { + case posExhausted: + return nil, base.LazyValue{} + case posPointKey: + i.savePoint(i.pointIter.NextPrefix(succKey)) + if i.withinSpan { + if i.pointKey == nil || i.cmp(i.span.End, i.pointKey.UserKey) <= 0 { + i.pos = posKeyspanEnd + } else { + i.pos = posPointKey + } + } else { + i.computeSmallestPos() + } + case posKeyspanStart, posKeyspanEnd: + i.nextPos() } - return i.interleaveForward(i.lower, nil) + return i.yieldPosition(i.lower, i.nextPos) } // Prev implements (base.InternalIterator).Prev. @@ -516,18 +517,34 @@ func (i *InterleavingIter) Prev() (*base.InternalKey, base.LazyValue) { i.clearMask() } - if i.keyspanInterleaved { - // The current span's start key has already been interleaved in the - // forward direction. The start key may have been interleaved a - // while ago, or it might've been interleaved at the current - // iterator position. If it was interleaved a while ago, the current - // span is still relevant and we should not move the keyspan - // iterator. - // - // If it was just interleaved at the current iterator position, the - // span start was the last key returned to the user. We should - // prev past it so we don't return it again, with an exception. - // Consider span [a, z) and this sequence of iterator calls: + // When switching directions, iterator state corresponding to the + // current iterator position (as indicated by i.pos) is already correct. + // However any state that has yet to be interleaved describes a position + // ahead of the current iterator position and needs to be updated to + // describe the position behind the current iterator position. + switch i.pos { + case posExhausted: + // Nothing to do. The below prevPos call will move both the point + // key and span to previous positions and return MAX(point, s.End). + case posPointKey: + // If we're currently on a point key, the point iterator is in the + // right place and the call to prevPos will correctly Prev the point + // key iterator to the previous point key. Do we need to move the + // span backwards? If the current span lies entirely ahead of the + // current key (!i.withinSpan), then we need to move it to the first + // span in the reverse direction. + if !i.withinSpan { + i.saveSpanBackward(i.keyspanIter.Prev()) + i.savedKeyspan() + } + case posKeyspanStart: + // Since we're positioned on a Span, the pointIter is positioned + // entirely ahead of the current iterator position. Reposition it + // behind the current iterator position. + i.savePoint(i.pointIter.Prev()) + // Without considering truncation of spans to seek keys, the keyspan + // iterator is already in the right place. But consider span [a, z) + // and this sequence of iterator calls: // // SeekGE('c') = c.RANGEKEYSET#72057594037927935 // Prev() = a.RANGEKEYSET#72057594037927935 @@ -535,176 +552,232 @@ func (i *InterleavingIter) Prev() (*base.InternalKey, base.LazyValue) { // If the current span's start key was last surfaced truncated due // to a SeekGE or SeekPrefixGE call, then it's still relevant in the // reverse direction with an untruncated start key. - // - // We can determine whether the last key returned was a point key by - // checking i.pointKeyInterleaved, because every Next/Prev will - // advance the point iterator and reset pointKeyInterleaved if it - // was. - if i.pointKeyInterleaved || i.spanMarkerTruncated { - // The last returned key was a point key, OR a truncated span - // marker key. Don't move, but re-save the span because it - // should no longer be considered truncated or interleaved. - i.savedKeyspan() - } else { - // The last returned key is this key's start boundary, so Prev - // past it so we don't return it again. - i.span = i.keyspanIter.Prev() - i.checkBackwardBound() - i.savedKeyspan() + if i.spanMarkerTruncated { + // When we fallthrough to calling prevPos, we want to move to + // MAX(point, span.Start). We cheat here by claiming we're + // currently on the end boundary, so that we'll move on to the + // untruncated start key if necessary. + i.pos = posKeyspanEnd } - } else { - // If the current span's start key has not been interleaved, then - // the span's start key is greater than the current iterator - // position (denoted in parenthesis), and the current span's start - // key is ahead of our iterator position. Move it to the previous - // span: - // points: (x*) - // span: [y-z)* - i.span = i.keyspanIter.Prev() - i.checkBackwardBound() - i.savedKeyspan() + case posKeyspanEnd: + // Since we're positioned on a Span, the pointIter is positioned + // entirely ahead of the current iterator position. Reposition it + // behind the current iterator position. + i.savePoint(i.pointIter.Prev()) } - // The existing point key (denoted below with *) is either the last - // key we returned (the current iterator position): - // points: x (y*) z - // or the upcoming point key in the forward direction if we just - // returned a span start boundary key : - // points: x z* - // spans: ([y-?)) - // direction. Either way, we must move the point iterator backwards. - switch { - case i.pointKey == nil && i.upper == nil: - i.pointKey, i.pointVal = i.pointIter.Last() - case i.pointKey == nil && i.upper != nil: - i.pointKey, i.pointVal = i.pointIter.SeekLT(i.upper, base.SeekLTFlagsNone) - default: - i.pointKey, i.pointVal = i.pointIter.Prev() + if i.spanMarkerTruncated { + // Save the keyspan again to clear truncation. + i.savedKeyspan() } - i.pointKeyInterleaved = false + // Fallthrough to calling i.prevPos. } + i.prevPos() + return i.yieldPosition(i.lower, i.prevPos) +} - // Refresh the point key if we just returned the current point key. - if i.pointKeyInterleaved { - i.pointKey, i.pointVal = i.pointIter.Prev() - i.pointKeyInterleaved = false +// computeSmallestPos sets i.{pos,withinSpan} to: +// +// MIN(i.pointKey, i.span.Start) +func (i *InterleavingIter) computeSmallestPos() { + if i.err == nil { + if i.span != nil && (i.pointKey == nil || i.cmp(i.startKey(), i.pointKey.UserKey) <= 0) { + i.withinSpan = true + i.pos = posKeyspanStart + return + } + i.withinSpan = false + if i.pointKey != nil { + i.pos = posPointKey + return + } } - // Refresh the span if we just returned the span's start boundary key. - if i.keyspanInterleaved { - i.span = i.keyspanIter.Prev() - i.checkBackwardBound() - i.savedKeyspan() + i.pos = posExhausted +} + +// computeLargestPos sets i.{pos,withinSpan} to: +// +// MAX(i.pointKey, i.span.End) +func (i *InterleavingIter) computeLargestPos() { + if i.err == nil { + if i.span != nil && (i.pointKey == nil || i.cmp(i.span.End, i.pointKey.UserKey) > 0) { + i.withinSpan = true + i.pos = posKeyspanEnd + return + } + i.withinSpan = false + if i.pointKey != nil { + i.pos = posPointKey + return + } } - return i.interleaveBackward() + i.pos = posExhausted } -func (i *InterleavingIter) interleaveForward( - lowerBound []byte, prefix []byte, -) (*base.InternalKey, base.LazyValue) { - // This loop determines whether a point key or a span marker key should be - // interleaved on each iteration. If masking is disabled and the span is - // nonempty, this loop executes for exactly one iteration. If masking is - // enabled and a masked key is determined to be interleaved next, this loop - // continues until the interleaved key is unmasked. If a span's start key - // should be interleaved next, but the span is empty, the loop continues to - // the next key. - for { - // Check invariants. - if invariants.Enabled { - // INVARIANT: !pointKeyInterleaved - if i.pointKeyInterleaved { - panic("pebble: invariant violation: point key interleaved") +// nextPos advances the iterator one position in the forward direction. +func (i *InterleavingIter) nextPos() { + if invariants.Enabled { + defer func() { + if i.err != nil && i.pos != posExhausted { + panic(errors.AssertionFailedf("iterator has accumulated error but i.pos = %d", i.pos)) } - switch { - case i.span == nil: - case i.pointKey == nil: - default: - // INVARIANT: !keyspanInterleaved || pointKey < span.End - // The caller is responsible for advancing this span if it's already - // been interleaved and the span ends before the point key. - // Absolute positioning methods will never have already interleaved - // the span's start key, so only Next needs to handle the case where - // pointKey >= span.End. - if i.keyspanInterleaved && i.cmp(i.pointKey.UserKey, i.span.End) >= 0 { - panic("pebble: invariant violation: span interleaved, but point key >= span end") - } + }() + } + // NB: If i.err != nil or any of the positioning methods performed in this + // function result in i.err != nil, we must set i.pos = posExhausted. We + // perform this check explicitly here, but if any of the branches below + // advance either iterator, they must also check i.err and set posExhausted + // if necessary. + if i.err != nil { + i.pos = posExhausted + return + } + + switch i.pos { + case posExhausted: + i.savePoint(i.pointIter.Next()) + i.saveSpanForward(i.keyspanIter.Next()) + i.savedKeyspan() + i.computeSmallestPos() + case posPointKey: + i.savePoint(i.pointIter.Next()) + if i.err != nil { + i.pos = posExhausted + return + } + // If we're not currently within the span, we want to chose the + // MIN(pointKey,span.Start), which is exactly the calculation performed + // by computeSmallestPos. + if !i.withinSpan { + i.computeSmallestPos() + return + } + // i.withinSpan=true + // Since we previously were within the span, we want to choose the + // MIN(pointKey,span.End). + switch { + case i.span == nil: + panic("i.withinSpan=true and i.span=nil") + case i.pointKey == nil: + // Since i.withinSpan=true, we step onto the end boundary of the + // keyspan. + i.pos = posKeyspanEnd + default: + // i.withinSpan && i.pointKey != nil && i.span != nil + if i.cmp(i.span.End, i.pointKey.UserKey) <= 0 { + i.pos = posKeyspanEnd + } else { + i.pos = posPointKey } } + case posKeyspanStart: + // Either a point key or the span's end key comes next. + if i.pointKey != nil && i.cmp(i.pointKey.UserKey, i.span.End) < 0 { + i.pos = posPointKey + } else { + i.pos = posKeyspanEnd + } + case posKeyspanEnd: + i.saveSpanForward(i.keyspanIter.Next()) + i.savedKeyspan() + i.computeSmallestPos() + default: + panic(fmt.Sprintf("unexpected pos=%d", i.pos)) + } +} - // Interleave. +// prevPos advances the iterator one position in the reverse direction. +func (i *InterleavingIter) prevPos() { + if invariants.Enabled { + defer func() { + if i.err != nil && i.pos != posExhausted { + panic(errors.AssertionFailedf("iterator has accumulated error but i.pos = %d", i.pos)) + } + }() + } + // NB: If i.err != nil or any of the positioning methods performed in this + // function result in i.err != nil, we must set i.pos = posExhausted. We + // perform this check explicitly here, but if any of the branches below + // advance either iterator, they must also check i.err and set posExhausted + // if necessary. + if i.err != nil { + i.pos = posExhausted + return + } + + switch i.pos { + case posExhausted: + i.savePoint(i.pointIter.Prev()) + i.saveSpanBackward(i.keyspanIter.Prev()) + i.savedKeyspan() + i.computeLargestPos() + case posPointKey: + i.savePoint(i.pointIter.Prev()) + if i.err != nil { + i.pos = posExhausted + return + } + // If we're not currently covered by the span, we want to chose the + // MAX(pointKey,span.End), which is exactly the calculation performed + // by computeLargestPos. + if !i.withinSpan { + i.computeLargestPos() + return + } switch { case i.span == nil: - // If we're out of spans, just return the point key. - return i.yieldPointKey(false /* covered */) + panic("withinSpan=true, but i.span == nil") case i.pointKey == nil: - if i.pointKeyInterleaved { - panic("pebble: invariant violation: point key already interleaved") - } - // If we're out of point keys, we need to return a span marker. If - // the current span has already been interleaved, advance it. Since - // there are no more point keys, we don't need to worry about - // advancing past the current point key. - if i.keyspanInterleaved { - i.span = i.keyspanIter.Next() - i.checkForwardBound(prefix) - i.savedKeyspan() - if i.span == nil { - return i.yieldNil() - } + i.pos = posKeyspanEnd + default: + // i.withinSpan && i.pointKey != nil && i.span != nil + if i.cmp(i.span.Start, i.pointKey.UserKey) > 0 { + i.pos = posKeyspanStart + } else { + i.pos = posPointKey } - if i.span.Empty() { - i.keyspanInterleaved = true - continue + } + case posKeyspanStart: + i.saveSpanBackward(i.keyspanIter.Prev()) + i.savedKeyspan() + i.computeLargestPos() + case posKeyspanEnd: + // Either a point key or the span's start key is previous. + if i.pointKey != nil && i.cmp(i.pointKey.UserKey, i.span.Start) >= 0 { + i.pos = posPointKey + } else { + i.pos = posKeyspanStart + } + default: + panic(fmt.Sprintf("unexpected pos=%d", i.pos)) + } +} + +func (i *InterleavingIter) yieldPosition( + lowerBound []byte, advance func(), +) (*base.InternalKey, base.LazyValue) { + // This loop returns the first visible position in the current iteration + // direction. Some positions are not visible and skipped. For example, if + // masking is enabled and the iterator is positioned over a masked point + // key, this loop skips the position. If a span's start key should be + // interleaved next, but the span is empty, the loop continues to the next + // key. Currently, span end keys are also always skipped, and are used only + // for maintaining internal state. + for { + switch i.pos { + case posExhausted: + return i.yieldNil() + case posPointKey: + if i.pointKey == nil { + panic("i.pointKey is nil") } - return i.yieldSyntheticSpanMarker(lowerBound) - default: - if i.cmp(i.pointKey.UserKey, i.startKey()) >= 0 { - // The span start key lies before the point key. If we haven't - // interleaved it, we should. - if !i.keyspanInterleaved { - if i.span.Empty() { - if i.pointKey != nil && i.cmp(i.pointKey.UserKey, i.span.End) >= 0 { - // Advance the keyspan iterator, as just flipping - // keyspanInterleaved would likely trip up the invariant check - // above. - i.span = i.keyspanIter.Next() - i.checkForwardBound(prefix) - i.savedKeyspan() - } else { - i.keyspanInterleaved = true - } - continue - } - return i.yieldSyntheticSpanMarker(lowerBound) - } - // Otherwise, the span's start key is already interleaved and we - // need to return the point key. The current span necessarily - // must cover the point key: - // - // Since the span's start is less than or equal to the point - // key, the only way for this span to not cover the point would - // be if the span's end is less than or equal to the point. - // (For example span = [a, b), point key = c). - // - // However, the invariant at the beginning of the function - // guarantees that if: - // * we have both a point key and a span - // * and the span has already been interleaved - // => then the point key must be less than the span's end, and - // the point key must be covered by the current span. - - // The span covers the point key. If a SkipPoint hook is - // configured, ask it if we should skip this point key. - // - // But first, we may need to update the mask to the current span - // if we have stepped outside of the span last saved as a mask, - // so that the decision to skip is made with the correct - // knowledge of the covering span. - i.maybeUpdateMask(true /* covered */) - - if i.mask != nil && i.mask.SkipPoint(i.pointKey.UserKey) { - if i.prefix { + if i.mask != nil { + i.maybeUpdateMask() + if i.withinSpan && i.mask.SkipPoint(i.pointKey.UserKey) { + // The span covers the point key. If a SkipPoint hook is + // configured, ask it if we should skip this point key. + if i.prefix != nil { // During prefix-iteration node, once a point is masked, // all subsequent keys with the same prefix must also be // masked according to the key ordering. We can stop and @@ -721,126 +794,46 @@ func (i *InterleavingIter) interleaveForward( // TODO(jackson): If we thread a base.Comparer through to // InterleavingIter so that we have access to // ImmediateSuccessor, we could use NextPrefix. We'd need to - // tweak the SpanMask interface slightly, but it's probably - // worthwhile. - - i.pointKey, i.pointVal = i.pointIter.Next() - // We may have just invalidated the invariant that - // ensures the span's End is > the point key, so - // reestablish it before the next iteration. - if i.pointKey != nil && i.cmp(i.pointKey.UserKey, i.span.End) >= 0 { - i.span = i.keyspanIter.Next() - i.checkForwardBound(prefix) - i.savedKeyspan() - } + // tweak the SpanMask interface slightly. + + // Advance beyond the masked point key. + advance() continue } - - // Point key is unmasked but covered. - return i.yieldPointKey(true /* covered */) - } - return i.yieldPointKey(false /* covered */) - } - } -} - -func (i *InterleavingIter) interleaveBackward() (*base.InternalKey, base.LazyValue) { - // This loop determines whether a point key or a span's start key should be - // interleaved on each iteration. If masking is disabled and the span is - // nonempty, this loop executes for exactly one iteration. If masking is - // enabled and a masked key is determined to be interleaved next, this loop - // continues until the interleaved key is unmasked. If a span's start key - // should be interleaved next, but the span is empty, the loop continues to - // the next key. - for { - // Check invariants. - if invariants.Enabled { - // INVARIANT: !pointKeyInterleaved - if i.pointKeyInterleaved { - panic("pebble: invariant violation: point key interleaved") } - } - - // Interleave. - switch { - case i.span == nil: - // If we're out of spans, just return the point key. - return i.yieldPointKey(false /* covered */) - case i.pointKey == nil: - // If we're out of point keys, we need to return a span marker. + return i.yieldPointKey() + case posKeyspanEnd: + // Don't interleave end keys; just advance. + advance() + continue + case posKeyspanStart: + // Don't interleave an empty span. if i.span.Empty() { - i.span = i.keyspanIter.Prev() - i.checkBackwardBound() - i.savedKeyspan() + advance() continue } - return i.yieldSyntheticSpanMarker(i.lower) + return i.yieldSyntheticSpanMarker(lowerBound) default: - // If the span's start key is greater than the point key, return a - // marker for the span. - if i.cmp(i.startKey(), i.pointKey.UserKey) > 0 { - if i.span.Empty() { - i.span = i.keyspanIter.Prev() - i.checkBackwardBound() - i.savedKeyspan() - continue - } - return i.yieldSyntheticSpanMarker(i.lower) - } - // We have a span but it has not been interleaved and begins at a - // key equal to or before the current point key. The point key - // should be interleaved next, if it's not masked. - if i.cmp(i.pointKey.UserKey, i.span.End) < 0 { - // The span covers the point key. The point key might be masked - // too if masking is enabled. - // - // The span may have changed since the last time we updated the - // mask. Consider the following range-key masking scenario: - // - // |--------------) [b,d)@5 - // . c@4 . e@9 - // - // During reverse iteration when we step from e@9 to c@4, we - // enter the span [b,d)@5. Since end boundaries are not - // interleaved, the mask hasn't been updated with the span - // [b,d)@5 yet. We must update the mask before calling - // SkipPoint(c@4) to maintain the SpanMask contract and give the - // mask implementation an opportunity to build the state - // necessary to be able to determine whether [b,d)@5 masks c@4. - i.maybeUpdateMask(true /* covered */) - - // The span covers the point key. If a SkipPoint hook is - // configured, ask it if we should skip this point key. - if i.mask != nil && i.mask.SkipPoint(i.pointKey.UserKey) { - i.pointKey, i.pointVal = i.pointIter.Prev() - continue - } - - // Point key is unmasked but covered. - return i.yieldPointKey(true /* covered */) - } - return i.yieldPointKey(false /* covered */) + panic(fmt.Sprintf("unexpected interleavePos=%d", i.pos)) } } } // keyspanSeekGE seeks the keyspan iterator to the first span covering a key ≥ k. func (i *InterleavingIter) keyspanSeekGE(k []byte, prefix []byte) { - i.span = i.keyspanIter.SeekGE(k) - i.checkForwardBound(prefix) + i.saveSpanForward(i.keyspanIter.SeekGE(k)) i.savedKeyspan() } // keyspanSeekLT seeks the keyspan iterator to the last span covering a key < k. func (i *InterleavingIter) keyspanSeekLT(k []byte) { - i.span = i.keyspanIter.SeekLT(k) - i.checkBackwardBound() + i.saveSpanBackward(i.keyspanIter.SeekLT(k)) // The current span's start key is not guaranteed to be less than key, // because of the bounds enforcement. Consider the following example: // // Bounds are set to [d,e). The user performs a SeekLT(d). The // FragmentIterator.SeekLT lands on a span [b,f). This span has a start key - // less than d, as expected. Above, checkBackwardBound truncates the span to + // less than d, as expected. Above, saveSpanBackward truncates the span to // match the iterator's current bounds, modifying the span to [d,e), which // does not overlap the search space of [-∞, d). // @@ -852,12 +845,21 @@ func (i *InterleavingIter) keyspanSeekLT(k []byte) { i.savedKeyspan() } -func (i *InterleavingIter) checkForwardBound(prefix []byte) { +func (i *InterleavingIter) saveSpanForward(span *Span) { + i.span = span i.truncated = false i.truncatedSpan = Span{} if i.span == nil { + i.err = firstError(i.err, i.keyspanIter.Error()) return } + if invariants.Enabled { + if err := i.keyspanIter.Error(); err != nil { + panic(errors.WithSecondaryError( + errors.AssertionFailedf("pebble: %T keyspan iterator returned non-nil span %s while iter has error", i.keyspanIter, i.span), + err)) + } + } // Check the upper bound if we have one. if i.upper != nil && i.cmp(i.span.Start, i.upper) >= 0 { i.span = nil @@ -886,15 +888,15 @@ func (i *InterleavingIter) checkForwardBound(prefix []byte) { } // If this is a part of a SeekPrefixGE call, we may also need to truncate to // the prefix's bounds. - if prefix != nil { + if i.prefix != nil { if !i.truncated { i.truncated = true i.truncatedSpan = *i.span } - if i.cmp(prefix, i.truncatedSpan.Start) > 0 { - i.truncatedSpan.Start = prefix + if i.cmp(i.prefix, i.truncatedSpan.Start) > 0 { + i.truncatedSpan.Start = i.prefix } - i.nextPrefixBuf = i.comparer.ImmediateSuccessor(i.nextPrefixBuf[:0], prefix) + i.nextPrefixBuf = i.comparer.ImmediateSuccessor(i.nextPrefixBuf[:0], i.prefix) if i.truncated && i.cmp(i.nextPrefixBuf, i.truncatedSpan.End) < 0 { i.truncatedSpan.End = i.nextPrefixBuf } @@ -905,12 +907,22 @@ func (i *InterleavingIter) checkForwardBound(prefix []byte) { } } -func (i *InterleavingIter) checkBackwardBound() { +func (i *InterleavingIter) saveSpanBackward(span *Span) { + i.span = span i.truncated = false i.truncatedSpan = Span{} if i.span == nil { + i.err = firstError(i.err, i.keyspanIter.Error()) return } + if invariants.Enabled { + if err := i.keyspanIter.Error(); err != nil { + panic(errors.WithSecondaryError( + errors.AssertionFailedf("pebble: %T keyspan iterator returned non-nil span %s while iter has error", i.keyspanIter, i.span), + err)) + } + } + // Check the lower bound if we have one. if i.lower != nil && i.cmp(i.span.End, i.lower) <= 0 { i.span = nil @@ -943,15 +955,12 @@ func (i *InterleavingIter) checkBackwardBound() { } func (i *InterleavingIter) yieldNil() (*base.InternalKey, base.LazyValue) { - i.spanCoversKey = false + i.withinSpan = false i.clearMask() return i.verify(nil, base.LazyValue{}) } -func (i *InterleavingIter) yieldPointKey(covered bool) (*base.InternalKey, base.LazyValue) { - i.pointKeyInterleaved = true - i.spanCoversKey = covered - i.maybeUpdateMask(covered) +func (i *InterleavingIter) yieldPointKey() (*base.InternalKey, base.LazyValue) { return i.verify(i.pointKey, i.pointVal) } @@ -960,8 +969,6 @@ func (i *InterleavingIter) yieldSyntheticSpanMarker( ) (*base.InternalKey, base.LazyValue) { i.spanMarker.UserKey = i.startKey() i.spanMarker.Trailer = base.MakeTrailer(base.InternalKeySeqNumMax, i.span.Keys[0].Kind()) - i.keyspanInterleaved = true - i.spanCoversKey = true // Truncate the key we return to our lower bound if we have one. Note that // we use the lowerBound function parameter, not i.lower. The lowerBound @@ -992,13 +999,13 @@ func (i *InterleavingIter) yieldSyntheticSpanMarker( i.spanMarker.UserKey = i.keyBuf i.spanMarkerTruncated = true } - i.maybeUpdateMask(true /* covered */) + i.maybeUpdateMask() return i.verify(&i.spanMarker, base.LazyValue{}) } func (i *InterleavingIter) disablePrefixMode() { - if i.prefix { - i.prefix = false + if i.prefix != nil { + i.prefix = nil // Clear the existing span. It may not hold the true end bound of the // underlying span. i.span = nil @@ -1012,52 +1019,42 @@ func (i *InterleavingIter) verify( // production builds elide this entire function. if invariants.Enabled { switch { - case k != nil && !i.keyspanInterleaved && !i.pointKeyInterleaved: - panic("pebble: invariant violation: both keys marked as noninterleaved") - case i.dir == -1 && k != nil && i.keyspanInterleaved == i.pointKeyInterleaved: - // During reverse iteration, if we're returning a key, either the span's - // start key must have been interleaved OR the current point key value - // is being returned, not both. - // - // This invariant holds because in reverse iteration the start key of the - // span behaves like a point. Once the start key is interleaved, we move - // the keyspan iterator to the previous span. - panic(fmt.Sprintf("pebble: invariant violation: interleaving (point %t, span %t)", - i.pointKeyInterleaved, i.keyspanInterleaved)) case i.dir == -1 && i.spanMarkerTruncated: panic("pebble: invariant violation: truncated span key in reverse iteration") case k != nil && i.lower != nil && i.cmp(k.UserKey, i.lower) < 0: panic("pebble: invariant violation: key < lower bound") case k != nil && i.upper != nil && i.cmp(k.UserKey, i.upper) >= 0: panic("pebble: invariant violation: key ≥ upper bound") - case i.span != nil && k != nil && i.mask != nil && i.pointKeyInterleaved && - i.cmp(k.UserKey, i.span.Start) >= 0 && i.cmp(k.UserKey, i.span.End) < 0 && i.mask.SkipPoint(k.UserKey): - panic("pebble: invariant violation: point key eligible for skipping returned") + case i.err != nil && k != nil: + panic("pebble: invariant violation: accumulated error swallowed") + case i.err == nil && i.pointIter.Error() != nil: + panic("pebble: invariant violation: pointIter swallowed") + case i.err == nil && i.keyspanIter.Error() != nil: + panic("pebble: invariant violation: keyspanIter error swallowed") } } return k, v } func (i *InterleavingIter) savedKeyspan() { - i.keyspanInterleaved = false i.spanMarkerTruncated = false i.maskSpanChangedCalled = false } -// maybeUpdateMask updates the current mask, if a mask is configured and -// the mask hasn't been updated with the current keyspan yet. -func (i *InterleavingIter) maybeUpdateMask(covered bool) { - if i.mask != nil { - if !covered || i.span.Empty() { - i.clearMask() - } else if !i.maskSpanChangedCalled { - if i.truncated { - i.mask.SpanChanged(&i.truncatedSpan) - } else { - i.mask.SpanChanged(i.span) - } - i.maskSpanChangedCalled = true - } +// updateMask updates the current mask, if a mask is configured and the mask +// hasn't been updated with the current keyspan yet. +func (i *InterleavingIter) maybeUpdateMask() { + switch { + case i.mask == nil, i.maskSpanChangedCalled: + return + case !i.withinSpan || i.span.Empty(): + i.clearMask() + case i.truncated: + i.mask.SpanChanged(&i.truncatedSpan) + i.maskSpanChangedCalled = true + default: + i.mask.SpanChanged(i.span) + i.maskSpanChangedCalled = true } } @@ -1077,6 +1074,20 @@ func (i *InterleavingIter) startKey() []byte { return i.span.Start } +func (i *InterleavingIter) savePoint(key *base.InternalKey, value base.LazyValue) { + i.pointKey, i.pointVal = key, value + if key == nil { + i.err = firstError(i.err, i.pointIter.Error()) + } + if invariants.Enabled { + if err := i.pointIter.Error(); key != nil && err != nil { + panic(errors.WithSecondaryError( + errors.AssertionFailedf("pebble: %T point iterator returned non-nil key %q while iter has error", i.pointIter, key), + err)) + } + } +} + // Span returns the span covering the last key returned, if any. A span key is // considered to 'cover' a key if the key falls within the span's user key // bounds. The returned span is owned by the InterleavingIter. The caller is @@ -1084,13 +1095,12 @@ func (i *InterleavingIter) startKey() []byte { // // Span will never return an invalid or empty span. func (i *InterleavingIter) Span() *Span { - if !i.spanCoversKey || i.span.Empty() { + if !i.withinSpan || len(i.span.Keys) == 0 { return nil } else if i.truncated { return &i.truncatedSpan - } else { - return i.span } + return i.span } // SetBounds implements (base.InternalIterator).SetBounds. @@ -1100,6 +1110,11 @@ func (i *InterleavingIter) SetBounds(lower, upper []byte) { i.Invalidate() } +// SetContext implements (base.InternalIterator).SetContext. +func (i *InterleavingIter) SetContext(ctx context.Context) { + i.pointIter.SetContext(ctx) +} + // Invalidate invalidates the interleaving iterator's current position, clearing // its state. This prevents optimizations such as reusing the current span on // seek. @@ -1111,7 +1126,7 @@ func (i *InterleavingIter) Invalidate() { // Error implements (base.InternalIterator).Error. func (i *InterleavingIter) Error() error { - return firstError(i.pointIter.Error(), i.keyspanIter.Error()) + return i.err } // Close implements (base.InternalIterator).Close. diff --git a/vendor/github.com/cockroachdb/pebble/internal/keyspan/internal_iter_shim.go b/vendor/github.com/cockroachdb/pebble/internal/keyspan/internal_iter_shim.go index cf2adc3ff..bb9e37bdf 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/keyspan/internal_iter_shim.go +++ b/vendor/github.com/cockroachdb/pebble/internal/keyspan/internal_iter_shim.go @@ -4,7 +4,11 @@ package keyspan -import "github.com/cockroachdb/pebble/internal/base" +import ( + "context" + + "github.com/cockroachdb/pebble/internal/base" +) // InternalIteratorShim is a temporary iterator type used as a shim between // keyspan.MergingIter and base.InternalIterator. It's used temporarily for @@ -112,6 +116,9 @@ func (i *InternalIteratorShim) Close() error { func (i *InternalIteratorShim) SetBounds(lower, upper []byte) { } +// SetContext implements (base.InternalIterator).SetContext. +func (i *InternalIteratorShim) SetContext(_ context.Context) {} + // String implements fmt.Stringer. func (i *InternalIteratorShim) String() string { return i.miter.String() diff --git a/vendor/github.com/cockroachdb/pebble/internal/keyspan/iter.go b/vendor/github.com/cockroachdb/pebble/internal/keyspan/iter.go index 1b08126b2..7f8ceb8c2 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/keyspan/iter.go +++ b/vendor/github.com/cockroachdb/pebble/internal/keyspan/iter.go @@ -51,6 +51,8 @@ type FragmentIterator interface { Prev() *Span // Error returns any accumulated error. + // + // TODO(jackson): Lift errors into return values on the positioning methods. Error() error // Close closes the iterator and returns any accumulated error. Exhausting @@ -70,9 +72,6 @@ type SpanIterOptions struct { // RangeKeyFilters can be used to avoid scanning tables and blocks in tables // when iterating over range keys. RangeKeyFilters []base.BlockPropertyFilter - // Level specifies the level where this sstable is being read. Must be - // specified for foreign (i.e. shared not-created-by-this-instance) sstables. - Level manifest.Level } // Iter is an iterator over a set of fragmented spans. diff --git a/vendor/github.com/cockroachdb/pebble/internal/keyspan/transformer.go b/vendor/github.com/cockroachdb/pebble/internal/keyspan/transformer.go index e0152cf4d..b5e873551 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/keyspan/transformer.go +++ b/vendor/github.com/cockroachdb/pebble/internal/keyspan/transformer.go @@ -48,102 +48,3 @@ func VisibleTransform(snapshot uint64) Transformer { return nil }) } - -// TransformerIter is a FragmentIterator that applies a Transformer on all -// returned keys. Used for when a caller needs to apply a transformer on an -// iterator but does not otherwise need the mergingiter's merging ability. -type TransformerIter struct { - FragmentIterator - - // Transformer is applied on every Span returned by this iterator. - Transformer Transformer - // Comparer in use for this keyspace. - Compare base.Compare - - span Span - err error -} - -func (t *TransformerIter) applyTransform(span *Span) *Span { - t.span = Span{ - Start: t.span.Start[:0], - End: t.span.End[:0], - Keys: t.span.Keys[:0], - } - if err := t.Transformer.Transform(t.Compare, *span, &t.span); err != nil { - t.err = err - return nil - } - return &t.span -} - -// SeekGE implements the FragmentIterator interface. -func (t *TransformerIter) SeekGE(key []byte) *Span { - span := t.FragmentIterator.SeekGE(key) - if span == nil { - return nil - } - return t.applyTransform(span) -} - -// SeekLT implements the FragmentIterator interface. -func (t *TransformerIter) SeekLT(key []byte) *Span { - span := t.FragmentIterator.SeekLT(key) - if span == nil { - return nil - } - return t.applyTransform(span) -} - -// First implements the FragmentIterator interface. -func (t *TransformerIter) First() *Span { - span := t.FragmentIterator.First() - if span == nil { - return nil - } - return t.applyTransform(span) -} - -// Last implements the FragmentIterator interface. -func (t *TransformerIter) Last() *Span { - span := t.FragmentIterator.Last() - if span == nil { - return nil - } - return t.applyTransform(span) -} - -// Next implements the FragmentIterator interface. -func (t *TransformerIter) Next() *Span { - span := t.FragmentIterator.Next() - if span == nil { - return nil - } - return t.applyTransform(span) -} - -// Prev implements the FragmentIterator interface. -func (t *TransformerIter) Prev() *Span { - span := t.FragmentIterator.Prev() - if span == nil { - return nil - } - return t.applyTransform(span) -} - -// Error implements the FragmentIterator interface. -func (t *TransformerIter) Error() error { - if t.err != nil { - return t.err - } - return t.FragmentIterator.Error() -} - -// Close implements the FragmentIterator interface. -func (t *TransformerIter) Close() error { - err := t.FragmentIterator.Close() - if err != nil { - return err - } - return t.err -} diff --git a/vendor/github.com/cockroachdb/pebble/internal/keyspan/truncate.go b/vendor/github.com/cockroachdb/pebble/internal/keyspan/truncate.go index 97b448099..c0e609bda 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/keyspan/truncate.go +++ b/vendor/github.com/cockroachdb/pebble/internal/keyspan/truncate.go @@ -69,5 +69,5 @@ func Truncate( } return !out.Empty() && cmp(out.Start, out.End) < 0 - }) + }, cmp) } diff --git a/vendor/github.com/cockroachdb/pebble/internal/manifest/btree.go b/vendor/github.com/cockroachdb/pebble/internal/manifest/btree.go index 2af15a39f..10791922b 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/manifest/btree.go +++ b/vendor/github.com/cockroachdb/pebble/internal/manifest/btree.go @@ -6,6 +6,7 @@ package manifest import ( "bytes" + stdcmp "cmp" "fmt" "strings" "sync/atomic" @@ -80,14 +81,7 @@ func btreeCmpSpecificOrder(files []*FileMetadata) btreeCmp { if !aok || !bok { panic("btreeCmpSliceOrder called with unknown files") } - switch { - case ai < bi: - return -1 - case ai > bi: - return +1 - default: - return 0 - } + return stdcmp.Compare(ai, bi) } } @@ -195,7 +189,7 @@ func (n *node) incRef() { // new nodes pass contentsToo=false to preserve existing reference counts during // operations that should yield a net-zero change to descendant refcounts. // When a node is released, its contained files are dereferenced. -func (n *node) decRef(contentsToo bool, obsolete *[]*FileMetadata) { +func (n *node) decRef(contentsToo bool, obsolete *[]*FileBacking) { if n.ref.Add(-1) > 0 { // Other references remain. Can't free. return @@ -215,7 +209,13 @@ func (n *node) decRef(contentsToo bool, obsolete *[]*FileMetadata) { if obsolete == nil { panic(fmt.Sprintf("file metadata %s dereferenced to zero during tree mutation", f.FileNum)) } - *obsolete = append(*obsolete, f) + // Reference counting is performed on the FileBacking. In the case + // of a virtual sstable, this reference counting is performed on + // a FileBacking which is shared by every single virtual sstable + // with the same backing sstable. If the reference count hits 0, + // then we know that the FileBacking won't be required by any + // sstable in Pebble, and that the backing sstable can be deleted. + *obsolete = append(*obsolete, f.FileBacking) } } if !n.leaf { @@ -761,8 +761,8 @@ type btree struct { // Release dereferences and clears the root node of the btree, removing all // items from the btree. In doing so, it decrements contained file counts. -// It returns a slice of newly obsolete files, if any. -func (t *btree) Release() (obsolete []*FileMetadata) { +// It returns a slice of newly obsolete backing files, if any. +func (t *btree) Release() (obsolete []*FileBacking) { if t.root != nil { t.root.decRef(true /* contentsToo */, &obsolete) t.root = nil @@ -1132,15 +1132,11 @@ func cmpIter(a, b iterator) int { if af.n != bf.n { panic("nonmatching nodes during btree iterator comparison") } - switch { - case af.pos < bf.pos: - return -1 - case af.pos > bf.pos: - return +1 - default: - // Continue up both iterators' stacks (equivalently, down the - // B-Tree away from the root). + if v := stdcmp.Compare(af.pos, bf.pos); v != 0 { + return v } + // Otherwise continue up both iterators' stacks (equivalently, down the + // B-Tree away from the root). } if aok && bok { @@ -1149,24 +1145,20 @@ func cmpIter(a, b iterator) int { if an != bn { panic("nonmatching nodes during btree iterator comparison") } + if v := stdcmp.Compare(apos, bpos); v != 0 { + return v + } switch { - case apos < bpos: + case aok: + // a is positioned at a leaf child at this position and b is at an + // end sentinel state. return -1 - case apos > bpos: + case bok: + // b is positioned at a leaf child at this position and a is at an + // end sentinel state. return +1 default: - switch { - case aok: - // a is positioned at a leaf child at this position and b is at an - // end sentinel state. - return -1 - case bok: - // b is positioned at a leaf child at this position and a is at an - // end sentinel state. - return +1 - default: - return 0 - } + return 0 } } diff --git a/vendor/github.com/cockroachdb/pebble/internal/manifest/l0_sublevels.go b/vendor/github.com/cockroachdb/pebble/internal/manifest/l0_sublevels.go index 3646a034e..96b4ad6a0 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/manifest/l0_sublevels.go +++ b/vendor/github.com/cockroachdb/pebble/internal/manifest/l0_sublevels.go @@ -6,8 +6,10 @@ package manifest import ( "bytes" + stdcmp "cmp" "fmt" "math" + "slices" "sort" "strings" @@ -712,7 +714,7 @@ func (s *L0Sublevels) calculateFlushSplitKeys(flushSplitMaxBytes int64) { // InitCompactingFileInfo initializes internal flags relating to compacting // files. Must be called after sublevel initialization. // -// Requires DB.mu to be held. +// Requires DB.mu *and* the manifest lock to be held. func (s *L0Sublevels) InitCompactingFileInfo(inProgress []L0Compaction) { for i := range s.orderedIntervals { s.orderedIntervals[i].compactingFileCount = 0 @@ -735,6 +737,13 @@ func (s *L0Sublevels) InitCompactingFileInfo(inProgress []L0Compaction) { if !f.IsCompacting() { continue } + if invariants.Enabled { + if s.cmp(s.orderedIntervals[f.minIntervalIndex].startKey.key, f.Smallest.UserKey) != 0 || s.cmp(s.orderedIntervals[f.maxIntervalIndex+1].startKey.key, f.Largest.UserKey) != 0 { + panic(fmt.Sprintf("file %s has inconsistent L0 Sublevel interval bounds: %s-%s, %s-%s", f.FileNum, + s.orderedIntervals[f.minIntervalIndex].startKey.key, s.orderedIntervals[f.maxIntervalIndex+1].startKey.key, + f.Smallest.UserKey, f.Largest.UserKey)) + } + } for i := f.minIntervalIndex; i <= f.maxIntervalIndex; i++ { interval := &s.orderedIntervals[i] interval.compactingFileCount++ @@ -753,11 +762,11 @@ func (s *L0Sublevels) InitCompactingFileInfo(inProgress []L0Compaction) { for _, c := range inProgress { startIK := intervalKey{key: c.Smallest.UserKey, isLargest: false} endIK := intervalKey{key: c.Largest.UserKey, isLargest: !c.Largest.IsExclusiveSentinel()} - start := sort.Search(len(s.orderedIntervals), func(i int) bool { - return intervalKeyCompare(s.cmp, s.orderedIntervals[i].startKey, startIK) >= 0 + start, _ := slices.BinarySearchFunc(s.orderedIntervals, startIK, func(a fileInterval, b intervalKey) int { + return intervalKeyCompare(s.cmp, a.startKey, b) }) - end := sort.Search(len(s.orderedIntervals), func(i int) bool { - return intervalKeyCompare(s.cmp, s.orderedIntervals[i].startKey, endIK) >= 0 + end, _ := slices.BinarySearchFunc(s.orderedIntervals, endIK, func(a fileInterval, b intervalKey) int { + return intervalKeyCompare(s.cmp, a.startKey, b) }) for i := start; i < end && i < len(s.orderedIntervals); i++ { interval := &s.orderedIntervals[i] @@ -1040,8 +1049,8 @@ func (s *L0Sublevels) checkCompaction(c *L0CompactionFiles) error { if fileIntervalsByLevel[level].max > max { max = fileIntervalsByLevel[level].max } - index := sort.Search(len(s.levelFiles[level]), func(i int) bool { - return s.levelFiles[level][i].maxIntervalIndex >= min + index, _ := slices.BinarySearchFunc(s.levelFiles[level], min, func(a *FileMetadata, b int) int { + return stdcmp.Compare(a.maxIntervalIndex, b) }) // start := index for ; index < len(s.levelFiles[level]); index++ { @@ -1558,8 +1567,8 @@ func (s *L0Sublevels) baseCompactionUsingSeed( func (s *L0Sublevels) extendFiles( sl int, earliestUnflushedSeqNum uint64, cFiles *L0CompactionFiles, ) bool { - index := sort.Search(len(s.levelFiles[sl]), func(i int) bool { - return s.levelFiles[sl][i].maxIntervalIndex >= cFiles.minIntervalIndex + index, _ := slices.BinarySearchFunc(s.levelFiles[sl], cFiles.minIntervalIndex, func(a *FileMetadata, b int) int { + return stdcmp.Compare(a.maxIntervalIndex, b) }) for ; index < len(s.levelFiles[sl]); index++ { f := s.levelFiles[sl][index] diff --git a/vendor/github.com/cockroachdb/pebble/internal/manifest/level_metadata.go b/vendor/github.com/cockroachdb/pebble/internal/manifest/level_metadata.go index 3e1d26dea..d48e27790 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/manifest/level_metadata.go +++ b/vendor/github.com/cockroachdb/pebble/internal/manifest/level_metadata.go @@ -15,20 +15,28 @@ import ( // LevelMetadata contains metadata for all of the files within // a level of the LSM. type LevelMetadata struct { - level int - tree btree + level int + totalSize uint64 + // NumVirtual is the number of virtual sstables in the level. + NumVirtual uint64 + // VirtualSize is the size of the virtual sstables in the level. + VirtualSize uint64 + tree btree } // clone makes a copy of the level metadata, implicitly increasing the ref // count of every file contained within lm. func (lm *LevelMetadata) clone() LevelMetadata { return LevelMetadata{ - level: lm.level, - tree: lm.tree.Clone(), + level: lm.level, + totalSize: lm.totalSize, + NumVirtual: lm.NumVirtual, + VirtualSize: lm.VirtualSize, + tree: lm.tree.Clone(), } } -func (lm *LevelMetadata) release() (obsolete []*FileMetadata) { +func (lm *LevelMetadata) release() (obsolete []*FileBacking) { return lm.tree.Release() } @@ -40,6 +48,13 @@ func makeLevelMetadata(cmp Compare, level int, files []*FileMetadata) LevelMetad var lm LevelMetadata lm.level = level lm.tree, _ = makeBTree(bcmp, files) + for _, f := range files { + lm.totalSize += f.Size + if f.Virtual { + lm.NumVirtual++ + lm.VirtualSize += f.Size + } + } return lm } @@ -52,6 +67,27 @@ func makeBTree(cmp btreeCmp, files []*FileMetadata) (btree, LevelSlice) { return t, newLevelSlice(t.Iter()) } +func (lm *LevelMetadata) insert(f *FileMetadata) error { + if err := lm.tree.Insert(f); err != nil { + return err + } + lm.totalSize += f.Size + if f.Virtual { + lm.NumVirtual++ + lm.VirtualSize += f.Size + } + return nil +} + +func (lm *LevelMetadata) remove(f *FileMetadata) bool { + lm.totalSize -= f.Size + if f.Virtual { + lm.NumVirtual-- + lm.VirtualSize -= f.Size + } + return lm.tree.Delete(f) +} + // Empty indicates whether there are any files in the level. func (lm *LevelMetadata) Empty() bool { return lm.tree.Count() == 0 @@ -62,6 +98,11 @@ func (lm *LevelMetadata) Len() int { return lm.tree.Count() } +// Size returns the cumulative size of all the files within the level. +func (lm *LevelMetadata) Size() uint64 { + return lm.totalSize +} + // Iter constructs a LevelIterator over the entire level. func (lm *LevelMetadata) Iter() LevelIterator { return LevelIterator{iter: lm.tree.Iter()} @@ -280,6 +321,32 @@ func (ls *LevelSlice) SizeSum() uint64 { return sum } +// NumVirtual returns the number of virtual sstables in the level. Its runtime is +// linear in the length of the slice. +func (ls *LevelSlice) NumVirtual() uint64 { + var n uint64 + iter := ls.Iter() + for f := iter.First(); f != nil; f = iter.Next() { + if f.Virtual { + n++ + } + } + return n +} + +// VirtualSizeSum returns the sum of the sizes of the virtual sstables in the +// level. +func (ls *LevelSlice) VirtualSizeSum() uint64 { + var sum uint64 + iter := ls.Iter() + for f := iter.First(); f != nil; f = iter.Next() { + if f.Virtual { + sum += f.Size + } + } + return sum +} + // Reslice constructs a new slice backed by the same underlying level, with // new start and end positions. Reslice invokes the provided function, passing // two LevelIterators: one positioned to i's inclusive start and one diff --git a/vendor/github.com/cockroachdb/pebble/internal/manifest/version.go b/vendor/github.com/cockroachdb/pebble/internal/manifest/version.go index 8cacf142e..f1655c83c 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/manifest/version.go +++ b/vendor/github.com/cockroachdb/pebble/internal/manifest/version.go @@ -6,6 +6,7 @@ package manifest import ( "bytes" + stdcmp "cmp" "fmt" "sort" "strconv" @@ -49,6 +50,9 @@ type TableStats struct { // The number of point and range deletion entries in the table. NumDeletions uint64 // NumRangeKeySets is the total number of range key sets in the table. + // + // NB: If there's a chance that the sstable contains any range key sets, + // then NumRangeKeySets must be > 0. NumRangeKeySets uint64 // Estimate of the total disk space that may be dropped by this table's // point deletions by compacting them. @@ -169,22 +173,13 @@ type FileMetadata struct { // FileNum is the file number. // // INVARIANT: when !FileMetadata.Virtual, FileNum == FileBacking.DiskFileNum. - // - // TODO(bananabrick): Consider creating separate types for - // FileMetadata.FileNum and FileBacking.FileNum. FileNum is used both as - // an indentifier for the FileMetadata in Pebble, and also as a handle to - // perform reads and writes. We should ensure through types that - // FileMetadata.FileNum isn't used to perform reads, and that - // FileBacking.FileNum isn't used as an identifier for the FileMetadata. FileNum base.FileNum // Size is the size of the file, in bytes. Size is an approximate value for // virtual sstables. // - // INVARIANT: when !FileMetadata.Virtual, Size == FileBacking.Size. - // - // TODO(bananabrick): Size is currently used in metrics, and for many key - // Pebble level heuristics. Make sure that the heuristics will still work - // appropriately with an approximate value of size. + // INVARIANTS: + // - When !FileMetadata.Virtual, Size == FileBacking.Size. + // - Size should be non-zero. Size 0 virtual sstables must not be created. Size uint64 // File creation time in seconds since the epoch (1970-01-01 00:00:00 // UTC). For ingested sstables, this corresponds to the time the file was @@ -309,6 +304,7 @@ type PhysicalFileMeta struct { // The underlying file's size is stored in FileBacking.Size, though it could // also be estimated or could correspond to just the referenced portion of // a file (eg. if the file originated on another node). +// - Size must be > 0. // - SmallestSeqNum and LargestSeqNum are loose bounds for virtual sstables. // This means that all keys in the virtual sstable must have seqnums within // [SmallestSeqNum, LargestSeqNum], however there's no guarantee that there's @@ -871,30 +867,19 @@ func (m *FileMetadata) TableInfo() TableInfo { } } -func cmpUint64(a, b uint64) int { - switch { - case a < b: - return -1 - case a > b: - return +1 - default: - return 0 - } -} - func (m *FileMetadata) cmpSeqNum(b *FileMetadata) int { // NB: This is the same ordering that RocksDB uses for L0 files. // Sort first by largest sequence number. - if m.LargestSeqNum != b.LargestSeqNum { - return cmpUint64(m.LargestSeqNum, b.LargestSeqNum) + if v := stdcmp.Compare(m.LargestSeqNum, b.LargestSeqNum); v != 0 { + return v } // Then by smallest sequence number. - if m.SmallestSeqNum != b.SmallestSeqNum { - return cmpUint64(m.SmallestSeqNum, b.SmallestSeqNum) + if v := stdcmp.Compare(m.SmallestSeqNum, b.SmallestSeqNum); v != 0 { + return v } // Break ties by file number. - return cmpUint64(uint64(m.FileNum), uint64(b.FileNum)) + return stdcmp.Compare(m.FileNum, b.FileNum) } func (m *FileMetadata) lessSeqNum(b *FileMetadata) bool { @@ -1027,6 +1012,9 @@ func NewVersion( } else { v.Levels[l].tree.cmp = btreeCmpSmallestKey(cmp) } + for _, f := range files[l] { + v.Levels[l].totalSize += f.Size + } } if err := v.InitL0Sublevels(cmp, formatKey, flushSplitBytes); err != nil { panic(err) @@ -1206,12 +1194,7 @@ func (v *Version) Unref() { l := v.list l.mu.Lock() l.Remove(v) - obsolete := v.unrefFiles() - fileBacking := make([]*FileBacking, len(obsolete)) - for i, f := range obsolete { - fileBacking[i] = f.FileBacking - } - v.Deleted(fileBacking) + v.Deleted(v.unrefFiles()) l.mu.Unlock() } } @@ -1223,17 +1206,12 @@ func (v *Version) Unref() { func (v *Version) UnrefLocked() { if v.refs.Add(-1) == 0 { v.list.Remove(v) - obsolete := v.unrefFiles() - fileBacking := make([]*FileBacking, len(obsolete)) - for i, f := range obsolete { - fileBacking[i] = f.FileBacking - } - v.Deleted(fileBacking) + v.Deleted(v.unrefFiles()) } } -func (v *Version) unrefFiles() []*FileMetadata { - var obsolete []*FileMetadata +func (v *Version) unrefFiles() []*FileBacking { + var obsolete []*FileBacking for _, lm := range v.Levels { obsolete = append(obsolete, lm.release()...) } diff --git a/vendor/github.com/cockroachdb/pebble/internal/manifest/version_edit.go b/vendor/github.com/cockroachdb/pebble/internal/manifest/version_edit.go index d0b34220d..4c98de2a7 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/manifest/version_edit.go +++ b/vendor/github.com/cockroachdb/pebble/internal/manifest/version_edit.go @@ -7,10 +7,11 @@ package manifest import ( "bufio" "bytes" + stdcmp "cmp" "encoding/binary" "fmt" "io" - "sort" + "slices" "time" "github.com/cockroachdb/errors" @@ -94,7 +95,7 @@ type VersionEdit struct { // mutations that have not been flushed to an sstable. // // This is an optional field, and 0 represents it is not set. - MinUnflushedLogNum base.FileNum + MinUnflushedLogNum base.DiskFileNum // ObsoletePrevLogNum is a historic artifact from LevelDB that is not used by // Pebble, RocksDB, or even LevelDB. Its use in LevelDB was deprecated in @@ -104,7 +105,7 @@ type VersionEdit struct { // The next file number. A single counter is used to assign file numbers // for the WAL, MANIFEST, sstable, and OPTIONS files. - NextFileNum base.FileNum + NextFileNum uint64 // LastSeqNum is an upper bound on the sequence numbers that have been // assigned in flushed WALs. Unflushed WALs (that will be replayed during @@ -175,14 +176,14 @@ func (v *VersionEdit) Decode(r io.Reader) error { v.ComparerName = string(s) case tagLogNumber: - n, err := d.readFileNum() + n, err := d.readUvarint() if err != nil { return err } - v.MinUnflushedLogNum = n + v.MinUnflushedLogNum = base.DiskFileNum(n) case tagNextFileNumber: - n, err := d.readFileNum() + n, err := d.readUvarint() if err != nil { return err } @@ -471,11 +472,11 @@ func (v *VersionEdit) string(verbose bool, fmtKey base.FormatKey) string { for df := range v.DeletedFiles { entries = append(entries, df) } - sort.Slice(entries, func(i, j int) bool { - if entries[i].Level != entries[j].Level { - return entries[i].Level < entries[j].Level + slices.SortFunc(entries, func(a, b DeletedFileEntry) int { + if v := stdcmp.Compare(a.Level, b.Level); v != 0 { + return v } - return entries[i].FileNum < entries[j].FileNum + return stdcmp.Compare(a.FileNum, b.FileNum) }) for _, df := range entries { fmt.Fprintf(&buf, " deleted: L%d %s\n", df.Level, df.FileNum) @@ -783,6 +784,12 @@ func (b *BulkVersionEdit) Accumulate(ve *VersionEdit) error { b.AddedFileBacking = make(map[base.DiskFileNum]*FileBacking) } for _, fb := range ve.CreatedBackingTables { + if _, ok := b.AddedFileBacking[fb.DiskFileNum]; ok { + // There is already a FileBacking associated with fb.DiskFileNum. + // This should never happen. There must always be only one FileBacking + // associated with a backing sstable. + panic(fmt.Sprintf("pebble: duplicate file backing %s", fb.DiskFileNum.String())) + } b.AddedFileBacking[fb.DiskFileNum] = fb } @@ -846,6 +853,8 @@ func AccumulateIncompleteAndApplySingleVE( flushSplitBytes int64, readCompactionRate int64, backingStateMap map[base.DiskFileNum]*FileBacking, + addBackingFunc func(*FileBacking), + removeBackingFunc func(base.DiskFileNum), ) (_ *Version, zombies map[base.DiskFileNum]uint64, _ error) { if len(ve.RemovedBackingTables) != 0 { panic("pebble: invalid incomplete version edit") @@ -864,7 +873,7 @@ func AccumulateIncompleteAndApplySingleVE( } for _, s := range b.AddedFileBacking { - backingStateMap[s.DiskFileNum] = s + addBackingFunc(s) } for fileNum := range zombies { @@ -875,10 +884,9 @@ func AccumulateIncompleteAndApplySingleVE( ve.RemovedBackingTables = append( ve.RemovedBackingTables, fileNum, ) - delete(backingStateMap, fileNum) + removeBackingFunc(fileNum) } } - return v, zombies, nil } @@ -967,7 +975,7 @@ func (b *BulkVersionEdit) Apply( // level. for _, f := range deletedFilesMap { - if obsolete := v.Levels[level].tree.Delete(f); obsolete { + if obsolete := v.Levels[level].remove(f); obsolete { // Deleting a file from the B-Tree may decrement its // reference count. However, because we cloned the // previous level's B-Tree, this should never result in a @@ -976,7 +984,7 @@ func (b *BulkVersionEdit) Apply( return nil, err } if f.HasRangeKeys { - if obsolete := v.RangeKeyLevels[level].tree.Delete(f); obsolete { + if obsolete := v.RangeKeyLevels[level].remove(f); obsolete { // Deleting a file from the B-Tree may decrement its // reference count. However, because we cloned the // previous level's B-Tree, this should never result in a @@ -1011,8 +1019,8 @@ func (b *BulkVersionEdit) Apply( // Sort addedFiles by file number. This isn't necessary, but tests which // replay invalid manifests check the error output, and the error output // depends on the order in which files are added to the btree. - sort.Slice(addedFiles, func(i, j int) bool { - return addedFiles[i].FileNum < addedFiles[j].FileNum + slices.SortFunc(addedFiles, func(a, b *FileMetadata) int { + return stdcmp.Compare(a.FileNum, b.FileNum) }) var sm, la *FileMetadata @@ -1029,7 +1037,7 @@ func (b *BulkVersionEdit) Apply( f.AllowedSeeks.Store(allowedSeeks) f.InitAllowedSeeks = allowedSeeks - err := lm.tree.Insert(f) + err := lm.insert(f) // We're adding this file to the new version, so increment the // latest refs count. f.LatestRef() @@ -1037,7 +1045,7 @@ func (b *BulkVersionEdit) Apply( return nil, errors.Wrap(err, "pebble") } if f.HasRangeKeys { - err = lmRange.tree.Insert(f) + err = lmRange.insert(f) if err != nil { return nil, errors.Wrap(err, "pebble") } diff --git a/vendor/github.com/cockroachdb/pebble/internal/manual/manual_32bit.go b/vendor/github.com/cockroachdb/pebble/internal/manual/manual_32bit.go index 587308799..19369fa0c 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/manual/manual_32bit.go +++ b/vendor/github.com/cockroachdb/pebble/internal/manual/manual_32bit.go @@ -2,8 +2,8 @@ // of this source code is governed by a BSD-style license that can be found in // the LICENSE file. -//go:build 386 || amd64p32 || arm || armbe || mips || mipsle || mips64p32 || mips64p32le || ppc || sparc -// +build 386 amd64p32 arm armbe mips mipsle mips64p32 mips64p32le ppc sparc +//go:build 386 || amd64p32 || arm || armbe || ppc || sparc +// +build 386 amd64p32 arm armbe ppc sparc package manual diff --git a/vendor/github.com/cockroachdb/pebble/internal/manual/manual_mips.go b/vendor/github.com/cockroachdb/pebble/internal/manual/manual_mips.go new file mode 100644 index 000000000..08bb88082 --- /dev/null +++ b/vendor/github.com/cockroachdb/pebble/internal/manual/manual_mips.go @@ -0,0 +1,13 @@ +// Copyright 2020 The LevelDB-Go and Pebble 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 || mips64p32 || mips64p32le +// +build mips mipsle mips64p32 mips64p32le + +package manual + +const ( + // MaxArrayLen is a safe maximum length for slices on this architecture. + MaxArrayLen = 1 << 30 +) diff --git a/vendor/github.com/cockroachdb/pebble/internal/rangekey/coalesce.go b/vendor/github.com/cockroachdb/pebble/internal/rangekey/coalesce.go index c1208ca47..d1795e000 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/rangekey/coalesce.go +++ b/vendor/github.com/cockroachdb/pebble/internal/rangekey/coalesce.go @@ -6,7 +6,6 @@ package rangekey import ( "bytes" - "fmt" "math" "sort" @@ -213,8 +212,10 @@ func (ui *UserIteratorConfig) ShouldDefragment(equal base.Equal, a, b *keyspan.S b.Keys[i].Kind() != base.InternalKeyKindRangeKeySet) { panic("pebble: unexpected non-RangeKeySet during defragmentation") } - if i > 0 && (ui.comparer.Compare(a.Keys[i].Suffix, a.Keys[i-1].Suffix) < 0 || - ui.comparer.Compare(b.Keys[i].Suffix, b.Keys[i-1].Suffix) < 0) { + // Don't do a comparison with RangeKeyDeletes, as those will always sort + // to the end and have no suffix. + if i > 0 && ((a.Keys[i].Kind() != base.InternalKeyKindRangeKeyDelete && ui.comparer.Compare(a.Keys[i].Suffix, a.Keys[i-1].Suffix) < 0) || + (b.Keys[i].Kind() != base.InternalKeyKindRangeKeyDelete && ui.comparer.Compare(b.Keys[i].Suffix, b.Keys[i-1].Suffix) < 0)) { panic("pebble: range keys not ordered by suffix during defragmentation") } } @@ -368,78 +369,3 @@ func coalesce( } return nil } - -// ForeignSSTTransformer implements a keyspan.Transformer for range keys in -// foreign sstables (i.e. shared sstables not created by us). It is largely -// similar to the Transform function implemented in UserIteratorConfig in that -// it calls coalesce to remove range keys shadowed by other range keys, but also -// retains the range key that does the shadowing. In addition, it elides -// RangeKey unsets/dels in L6 as they are inapplicable when reading from a -// different Pebble instance. -type ForeignSSTTransformer struct { - Comparer *base.Comparer - Level int - sortBuf keyspan.KeysBySuffix -} - -// Transform implements the Transformer interface. -func (f *ForeignSSTTransformer) Transform( - cmp base.Compare, s keyspan.Span, dst *keyspan.Span, -) error { - // Apply shadowing of keys. - dst.Start = s.Start - dst.End = s.End - f.sortBuf = keyspan.KeysBySuffix{ - Cmp: cmp, - Keys: f.sortBuf.Keys[:0], - } - if err := coalesce(f.Comparer.Equal, &f.sortBuf, math.MaxUint64, s.Keys); err != nil { - return err - } - keys := f.sortBuf.Keys - dst.Keys = dst.Keys[:0] - for i := range keys { - seqNum := keys[i].SeqNum() - switch keys[i].Kind() { - case base.InternalKeyKindRangeKeySet: - if invariants.Enabled && len(dst.Keys) > 0 && cmp(dst.Keys[len(dst.Keys)-1].Suffix, keys[i].Suffix) > 0 { - panic("pebble: keys unexpectedly not in ascending suffix order") - } - switch f.Level { - case 5: - fallthrough - case 6: - if seqNum != base.SeqNumForLevel(f.Level) { - panic(fmt.Sprintf("pebble: expected range key iter to return seqnum %d, got %d", base.SeqNumForLevel(f.Level), seqNum)) - } - } - case base.InternalKeyKindRangeKeyUnset: - if invariants.Enabled && len(dst.Keys) > 0 && cmp(dst.Keys[len(dst.Keys)-1].Suffix, keys[i].Suffix) > 0 { - panic("pebble: keys unexpectedly not in ascending suffix order") - } - fallthrough - case base.InternalKeyKindRangeKeyDelete: - switch f.Level { - case 5: - // Emit this key. - if seqNum != base.SeqNumForLevel(f.Level) { - panic(fmt.Sprintf("pebble: expected range key iter to return seqnum %d, got %d", base.SeqNumForLevel(f.Level), seqNum)) - } - case 6: - // Skip this key, as foreign sstable in L6 do not need to emit range key - // unsets/dels as they do not apply to any other sstables. - continue - } - default: - return base.CorruptionErrorf("pebble: unrecognized range key kind %s", keys[i].Kind()) - } - dst.Keys = append(dst.Keys, keyspan.Key{ - Trailer: base.MakeTrailer(seqNum, keys[i].Kind()), - Suffix: keys[i].Suffix, - Value: keys[i].Value, - }) - } - // coalesce results in dst.Keys being sorted by Suffix. - dst.KeysOrder = keyspan.BySuffixAsc - return nil -} diff --git a/vendor/github.com/cockroachdb/pebble/internal/rawalloc/rawalloc_32bit.go b/vendor/github.com/cockroachdb/pebble/internal/rawalloc/rawalloc_32bit.go index 3edacea71..3112cc9eb 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/rawalloc/rawalloc_32bit.go +++ b/vendor/github.com/cockroachdb/pebble/internal/rawalloc/rawalloc_32bit.go @@ -12,8 +12,8 @@ // implied. See the License for the specific language governing // permissions and limitations under the License. -//go:build 386 || amd64p32 || arm || armbe || mips || mipsle || mips64p32 || mips64p32le || ppc || sparc -// +build 386 amd64p32 arm armbe mips mipsle mips64p32 mips64p32le ppc sparc +//go:build 386 || amd64p32 || arm || armbe || ppc || sparc +// +build 386 amd64p32 arm armbe ppc sparc package rawalloc diff --git a/vendor/github.com/cockroachdb/pebble/internal/rawalloc/rawalloc_mips.go b/vendor/github.com/cockroachdb/pebble/internal/rawalloc/rawalloc_mips.go new file mode 100644 index 000000000..55b45eb10 --- /dev/null +++ b/vendor/github.com/cockroachdb/pebble/internal/rawalloc/rawalloc_mips.go @@ -0,0 +1,22 @@ +// Copyright 2014 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +//go:build mips || mipsle || mips64p32 || mips64p32le +// +build mips mipsle mips64p32 mips64p32le + +package rawalloc + +const ( + maxArrayLen = 1 << 30 +) diff --git a/vendor/github.com/cockroachdb/pebble/internal/testkeys/testkeys.go b/vendor/github.com/cockroachdb/pebble/internal/testkeys/testkeys.go index 8ac89e2ee..f1b3a184d 100644 --- a/vendor/github.com/cockroachdb/pebble/internal/testkeys/testkeys.go +++ b/vendor/github.com/cockroachdb/pebble/internal/testkeys/testkeys.go @@ -14,23 +14,33 @@ package testkeys import ( "bytes" + "cmp" "fmt" "math" "strconv" "strings" "github.com/cockroachdb/pebble/internal/base" + "golang.org/x/exp/rand" ) const alpha = "abcdefghijklmnopqrstuvwxyz" const suffixDelim = '@' +var inverseAlphabet = make(map[byte]int64, len(alpha)) + +func init() { + for i := range alpha { + inverseAlphabet[alpha[i]] = int64(i) + } +} + // MaxSuffixLen is the maximum length of a suffix generated by this package. -var MaxSuffixLen = 1 + len(fmt.Sprintf("%d", math.MaxInt64)) +var MaxSuffixLen = 1 + len(fmt.Sprintf("%d", int64(math.MaxInt64))) // Comparer is the comparer for test keys generated by this package. -var Comparer *base.Comparer = &base.Comparer{ +var Comparer = &base.Comparer{ Compare: compare, Equal: func(a, b []byte) bool { return compare(a, b) == 0 }, AbbreviatedKey: func(k []byte) uint64 { @@ -123,20 +133,13 @@ func compareTimestamps(a, b []byte) int { if err != nil { panic(fmt.Sprintf("invalid test mvcc timestamp %q", b)) } - switch { - case ai < bi: - return +1 - case ai > bi: - return -1 - default: - return 0 - } + return cmp.Compare(bi, ai) } // Keyspace describes a finite keyspace of unsuffixed test keys. type Keyspace interface { // Count returns the number of keys that exist within this keyspace. - Count() int + Count() int64 // MaxLen returns the maximum length, in bytes, of a key within this // keyspace. This is only guaranteed to return an upper bound. @@ -144,20 +147,21 @@ type Keyspace interface { // Slice returns the sub-keyspace from index i, inclusive, to index j, // exclusive. The receiver is unmodified. - Slice(i, j int) Keyspace + Slice(i, j int64) Keyspace // EveryN returns a key space that includes 1 key for every N keys in the // original keyspace. The receiver is unmodified. - EveryN(n int) Keyspace + EveryN(n int64) Keyspace - key(buf []byte, i int) int + // key writes the i-th key to the buffer and returns the length. + key(buf []byte, i int64) int } // Divvy divides the provided keyspace into N equal portions, containing // disjoint keys evenly distributed across the keyspace. -func Divvy(ks Keyspace, n int) []Keyspace { +func Divvy(ks Keyspace, n int64) []Keyspace { ret := make([]Keyspace, n) - for i := 0; i < n; i++ { + for i := int64(0); i < n; i++ { ret[i] = ks.Slice(i, ks.Count()).EveryN(n) } return ret @@ -175,7 +179,7 @@ func Alpha(maxLength int) Keyspace { // KeyAt returns the i-th key within the keyspace with a suffix encoding the // timestamp t. -func KeyAt(k Keyspace, i int, t int) []byte { +func KeyAt(k Keyspace, i int64, t int64) []byte { b := make([]byte, k.MaxLen()+MaxSuffixLen) return b[:WriteKeyAt(b, k, i, t)] } @@ -183,20 +187,20 @@ func KeyAt(k Keyspace, i int, t int) []byte { // WriteKeyAt writes the i-th key within the keyspace to the buffer dst, with a // suffix encoding the timestamp t suffix. It returns the number of bytes // written. -func WriteKeyAt(dst []byte, k Keyspace, i int, t int) int { +func WriteKeyAt(dst []byte, k Keyspace, i int64, t int64) int { n := WriteKey(dst, k, i) n += WriteSuffix(dst[n:], t) return n } // Suffix returns the test keys suffix representation of timestamp t. -func Suffix(t int) []byte { +func Suffix(t int64) []byte { b := make([]byte, MaxSuffixLen) return b[:WriteSuffix(b, t)] } // SuffixLen returns the exact length of the given suffix when encoded. -func SuffixLen(t int) int { +func SuffixLen(t int64) int { // Begin at 1 for the '@' delimiter, 1 for a single digit. n := 2 t /= 10 @@ -208,42 +212,42 @@ func SuffixLen(t int) int { } // ParseSuffix returns the integer representation of the encoded suffix. -func ParseSuffix(s []byte) (int, error) { - return strconv.Atoi(strings.TrimPrefix(string(s), string(suffixDelim))) +func ParseSuffix(s []byte) (int64, error) { + return strconv.ParseInt(strings.TrimPrefix(string(s), string(suffixDelim)), 10, 64) } // WriteSuffix writes the test keys suffix representation of timestamp t to dst, // returning the number of bytes written. -func WriteSuffix(dst []byte, t int) int { +func WriteSuffix(dst []byte, t int64) int { dst[0] = suffixDelim n := 1 - n += len(strconv.AppendInt(dst[n:n], int64(t), 10)) + n += len(strconv.AppendInt(dst[n:n], t, 10)) return n } // Key returns the i-th unsuffixed key within the keyspace. -func Key(k Keyspace, i int) []byte { +func Key(k Keyspace, i int64) []byte { b := make([]byte, k.MaxLen()) return b[:k.key(b, i)] } // WriteKey writes the i-th unsuffixed key within the keyspace to the buffer dst. It // returns the number of bytes written. -func WriteKey(dst []byte, k Keyspace, i int) int { +func WriteKey(dst []byte, k Keyspace, i int64) int { return k.key(dst, i) } type alphabet struct { alphabet []byte maxLength int - headSkip int - tailSkip int - increment int + headSkip int64 + tailSkip int64 + increment int64 } -func (a alphabet) Count() int { +func (a alphabet) Count() int64 { // Calculate the total number of keys, ignoring the increment. - total := (keyCount(len(a.alphabet), a.maxLength) - a.headSkip - a.tailSkip) + total := keyCount(len(a.alphabet), a.maxLength) - a.headSkip - a.tailSkip // The increment dictates that we take every N keys, where N = a.increment. // Consider a total containing the 5 keys: @@ -263,20 +267,25 @@ func (a alphabet) MaxLen() int { return a.maxLength } -func (a alphabet) Slice(i, j int) Keyspace { +func (a alphabet) Slice(i, j int64) Keyspace { s := a s.headSkip += i s.tailSkip += a.Count() - j return s } -func (a alphabet) EveryN(n int) Keyspace { +func (a alphabet) EveryN(n int64) Keyspace { s := a s.increment *= n return s } -func keyCount(n, l int) int { +func keyCount(n, l int) int64 { + if n == 0 { + return 0 + } else if n == 1 { + return int64(l) + } // The number of representable keys in the keyspace is a function of the // length of the alphabet n and the max key length l. Consider how the // number of representable keys grows as l increases: @@ -286,10 +295,10 @@ func keyCount(n, l int) int { // l = 3: n + n^2 + n^3 // ... // Σ i=(1...l) n^i = n*(n^l - 1)/(n-1) - return (n * (int(math.Pow(float64(n), float64(l))) - 1)) / (n - 1) + return (int64(n) * (int64(math.Pow(float64(n), float64(l))) - 1)) / int64(n-1) } -func (a alphabet) key(buf []byte, idx int) int { +func (a alphabet) key(buf []byte, idx int64) int { // This function generates keys of length 1..maxKeyLength, pulling // characters from the alphabet. The idx determines which key to generate, // generating the i-th lexicographically next key. @@ -308,14 +317,14 @@ func (a alphabet) key(buf []byte, idx int) int { keyCount(len(a.alphabet), a.maxLength)) } -func generateAlphabetKey(buf, alphabet []byte, i, keyCount int) int { +func generateAlphabetKey(buf, alphabet []byte, i, keyCount int64) int { if keyCount == 0 || i > keyCount || i < 0 { return 0 } // Of the keyCount keys in the generative keyspace, how many are there // starting with a particular character? - keysPerCharacter := keyCount / len(alphabet) + keysPerCharacter := keyCount / int64(len(alphabet)) // Find the character that the key at index i starts with and set it. characterIdx := i / keysPerCharacter @@ -347,3 +356,149 @@ func generateAlphabetKey(buf, alphabet []byte, i, keyCount int) int { i = i - keysPerCharacter*characterIdx - 1 return 1 + generateAlphabetKey(buf[1:], alphabet, i, keysPerCharacter-1) } + +// computeAlphabetKeyIndex computes the inverse of generateAlphabetKey, +// returning the index of a particular key, given the provided alphabet and max +// length of a key. +// +// len(key) must be ≥ 1. +func computeAlphabetKeyIndex(key []byte, alphabet map[byte]int64, n int) int64 { + i, ok := alphabet[key[0]] + if !ok { + panic(fmt.Sprintf("unrecognized alphabet character %v", key[0])) + } + // How many keys exist that start with the preceding i characters? Each of + // the i characters themselves are a key, plus the count of all the keys + // with one less character for each. + ret := i + i*keyCount(len(alphabet), n-1) + if len(key) > 1 { + ret += 1 + computeAlphabetKeyIndex(key[1:], alphabet, n-1) + } + return ret +} + +func abs(a int64) int64 { + if a < 0 { + return -a + } + return a +} + +// RandomSeparator returns a random alphabetic key k such that a < k < b, +// pulling randomness from the provided random number generator. If dst is +// provided and the generated key fits within dst's capacity, the returned slice +// will use dst's memory. +// +// If a prefix P exists such that Prefix(a) < P < Prefix(b), the generated key +// will consist of the prefix P appended with the provided suffix. A zero suffix +// generates an unsuffixed key. If no such prefix P exists, RandomSeparator will +// try to find a key k with either Prefix(a) or Prefix(b) such that a < k < b, +// but the generated key will not use the provided suffix. Note that it's +// possible that no separator key exists (eg, a='a@2', b='a@1'), in which case +// RandomSeparator returns nil. +// +// If RandomSeparator generates a new prefix, the generated prefix will have +// length at most MAX(maxLength, len(Prefix(a)), len(Prefix(b))). +// +// RandomSeparator panics if a or b fails to decode. +func RandomSeparator(dst, a, b []byte, suffix int64, maxLength int, rng *rand.Rand) []byte { + if Comparer.Compare(a, b) >= 0 { + return nil + } + + // Determine both keys' logical prefixes and suffixes. + ai := Comparer.Split(a) + bi := Comparer.Split(b) + ap := a[:ai] + bp := b[:bi] + maxLength = max(maxLength, len(ap), len(bp)) + var as, bs int64 + var err error + if ai != len(a) { + as, err = ParseSuffix(a[ai:]) + if err != nil { + panic(fmt.Sprintf("failed to parse suffix of %q", a)) + } + } + if bi != len(b) { + bs, err = ParseSuffix(b[bi:]) + if err != nil { + panic(fmt.Sprintf("failed to parse suffix of %q", b)) + } + } + + apIdx := computeAlphabetKeyIndex(ap, inverseAlphabet, maxLength) + bpIdx := computeAlphabetKeyIndex(bp, inverseAlphabet, maxLength) + diff := bpIdx - apIdx + generatedIdx := bpIdx + if diff > 0 { + var add int64 = diff + 1 + var start int64 = apIdx + if as == 1 { + // There's no expressible key with prefix a greater than a@1. So, + // exclude ap. + start = apIdx + 1 + add = diff + } + if bs == 0 { + // No key with prefix b can sort before b@0. We don't want to pick b. + add-- + } + // We're allowing generated id to be in the range [start, start + add - 1]. + if start > start+add-1 { + return nil + } + // If we can generate a key which is actually in the middle of apIdx + // and bpIdx use it so that we don't have to bother about timestamps. + generatedIdx = rng.Int63n(add) + start + for diff > 1 && generatedIdx == apIdx || generatedIdx == bpIdx { + generatedIdx = rng.Int63n(add) + start + } + } + + switch { + case generatedIdx == apIdx && generatedIdx == bpIdx: + if abs(bs-as) <= 1 { + // There's no expressible suffix between the two, and there's no + // possible separator key. + return nil + } + // The key b is >= key a, but has the same prefix, so b must have the + // smaller timestamp, unless a has timestamp of 0. + // + // NB: The zero suffix (suffix-less) sorts before all other suffixes, so + // any suffix we generate will be greater than it. + if as == 0 { + // bs > as + suffix = bs + rng.Int63n(10) + 1 + } else { + // bs < as. + // Generate suffix in range [bs + 1, as - 1] + suffix = bs + 1 + rng.Int63n(as-bs-1) + } + case generatedIdx == apIdx: + // NB: The zero suffix (suffix-less) sorts before all other suffixes, so + // any suffix we generate will be greater than it. + if as == 0 && suffix == 0 { + suffix++ + } else if as != 0 && suffix >= as { + suffix = rng.Int63n(as) + } + case generatedIdx == bpIdx: + if suffix <= bs { + suffix = bs + rng.Int63n(10) + 1 + } + } + if sz := maxLength + SuffixLen(suffix); cap(dst) < sz { + dst = make([]byte, sz) + } else { + dst = dst[:cap(dst)] + } + var w int + if suffix == 0 { + w = WriteKey(dst, Alpha(maxLength), generatedIdx) + } else { + w = WriteKeyAt(dst, Alpha(maxLength), generatedIdx, suffix) + } + return dst[:w] +} diff --git a/vendor/github.com/cockroachdb/pebble/iterator.go b/vendor/github.com/cockroachdb/pebble/iterator.go index 40a99f8b6..831e31512 100644 --- a/vendor/github.com/cockroachdb/pebble/iterator.go +++ b/vendor/github.com/cockroachdb/pebble/iterator.go @@ -187,7 +187,9 @@ type Iterator struct { comparer base.Comparer iter internalIterator pointIter internalIterator + // Either readState or version is set, but not both. readState *readState + version *version // rangeKey holds iteration state specific to iteration over range keys. // The range key field may be nil if the Iterator has never been configured // to iterate over range keys. Its non-nilness cannot be used to determine @@ -300,6 +302,8 @@ type Iterator struct { // Used for an optimization in external iterators to reduce the number of // merging levels. forwardOnly bool + // batchOnlyIter is set to true for Batch.NewBatchOnlyIter. + batchOnlyIter bool // closePointIterOnce is set to true if this point iter can only be Close()d // once, _and_ closing i.iter and then i.pointIter would close i.pointIter // twice. This is necessary to track if the point iter is an internal iterator @@ -548,6 +552,21 @@ func (i *Iterator) findNextEntry(limit []byte) { return } + // If the user has configured a SkipPoint function, invoke it to see + // whether we should skip over the current user key. + if i.opts.SkipPoint != nil && key.Kind() != InternalKeyKindRangeKeySet && i.opts.SkipPoint(i.iterKey.UserKey) { + // NB: We could call nextUserKey, but in some cases the SkipPoint + // predicate function might be cheaper than nextUserKey's key copy + // and key comparison. This should be the case for MVCC suffix + // comparisons, for example. In the future, we could expand the + // SkipPoint interface to give the implementor more control over + // whether we skip over just the internal key, the user key, or even + // the key prefix. + i.stats.ForwardStepCount[InternalIterCall]++ + i.iterKey, i.iterValue = i.iter.Next() + continue + } + switch key.Kind() { case InternalKeyKindRangeKeySet: // Save the current key. @@ -617,6 +636,13 @@ func (i *Iterator) findNextEntry(limit []byte) { } func (i *Iterator) nextPointCurrentUserKey() bool { + // If the user has configured a SkipPoint function and the current user key + // would be skipped by it, there's no need to step forward looking for a + // point key. If we were to find one, it should be skipped anyways. + if i.opts.SkipPoint != nil && i.opts.SkipPoint(i.key) { + return false + } + i.pos = iterPosCurForward i.iterKey, i.iterValue = i.iter.Next() @@ -778,39 +804,41 @@ func (i *Iterator) maybeSampleRead() { func (i *Iterator) sampleRead() { var topFile *manifest.FileMetadata topLevel, numOverlappingLevels := numLevels, 0 - if mi, ok := i.iter.(*mergingIter); ok { - if len(mi.levels) > 1 { - mi.ForEachLevelIter(func(li *levelIter) bool { - l := manifest.LevelToInt(li.level) - if f := li.iterFile; f != nil { - var containsKey bool - if i.pos == iterPosNext || i.pos == iterPosCurForward || - i.pos == iterPosCurForwardPaused { - containsKey = i.cmp(f.SmallestPointKey.UserKey, i.key) <= 0 - } else if i.pos == iterPosPrev || i.pos == iterPosCurReverse || - i.pos == iterPosCurReversePaused { - containsKey = i.cmp(f.LargestPointKey.UserKey, i.key) >= 0 - } - // Do nothing if the current key is not contained in f's - // bounds. We could seek the LevelIterator at this level - // to find the right file, but the performance impacts of - // doing that are significant enough to negate the benefits - // of read sampling in the first place. See the discussion - // at: - // https://github.com/cockroachdb/pebble/pull/1041#issuecomment-763226492 - if containsKey { - numOverlappingLevels++ - if numOverlappingLevels >= 2 { - // Terminate the loop early if at least 2 overlapping levels are found. - return true - } - topLevel = l - topFile = f + mi := i.merging + if mi == nil { + return + } + if len(mi.levels) > 1 { + mi.ForEachLevelIter(func(li *levelIter) bool { + l := manifest.LevelToInt(li.level) + if f := li.iterFile; f != nil { + var containsKey bool + if i.pos == iterPosNext || i.pos == iterPosCurForward || + i.pos == iterPosCurForwardPaused { + containsKey = i.cmp(f.SmallestPointKey.UserKey, i.key) <= 0 + } else if i.pos == iterPosPrev || i.pos == iterPosCurReverse || + i.pos == iterPosCurReversePaused { + containsKey = i.cmp(f.LargestPointKey.UserKey, i.key) >= 0 + } + // Do nothing if the current key is not contained in f's + // bounds. We could seek the LevelIterator at this level + // to find the right file, but the performance impacts of + // doing that are significant enough to negate the benefits + // of read sampling in the first place. See the discussion + // at: + // https://github.com/cockroachdb/pebble/pull/1041#issuecomment-763226492 + if containsKey { + numOverlappingLevels++ + if numOverlappingLevels >= 2 { + // Terminate the loop early if at least 2 overlapping levels are found. + return true } + topLevel = l + topFile = f } - return false - }) - } + } + return false + }) } if topFile == nil || topLevel >= numLevels { return @@ -907,6 +935,26 @@ func (i *Iterator) findPrevEntry(limit []byte) { } } + // If the user has configured a SkipPoint function, invoke it to see + // whether we should skip over the current user key. + if i.opts.SkipPoint != nil && key.Kind() != InternalKeyKindRangeKeySet && i.opts.SkipPoint(key.UserKey) { + // NB: We could call prevUserKey, but in some cases the SkipPoint + // predicate function might be cheaper than prevUserKey's key copy + // and key comparison. This should be the case for MVCC suffix + // comparisons, for example. In the future, we could expand the + // SkipPoint interface to give the implementor more control over + // whether we skip over just the internal key, the user key, or even + // the key prefix. + i.stats.ReverseStepCount[InternalIterCall]++ + i.iterKey, i.iterValue = i.iter.Prev() + if limit != nil && i.iterKey != nil && i.cmp(limit, i.iterKey.UserKey) > 0 && !i.rangeKeyWithinLimit(limit) { + i.iterValidityState = IterAtLimit + i.pos = iterPosCurReversePaused + return + } + continue + } + switch key.Kind() { case InternalKeyKindRangeKeySet: // Range key start boundary markers are interleaved with the maximum @@ -944,12 +992,12 @@ func (i *Iterator) findPrevEntry(limit []byte) { // Compare with the limit. We could optimize by only checking when // we step to the previous user key, but detecting that requires a // comparison too. Note that this position may already passed a - // number of versions of this user key, but they are all deleted, - // so the fact that a subsequent Prev*() call will not see them is + // number of versions of this user key, but they are all deleted, so + // the fact that a subsequent Prev*() call will not see them is // harmless. Also note that this is the only place in the loop, - // other than the firstLoopIter case above, where we could step - // to a different user key and start processing it for returning - // to the caller. + // other than the firstLoopIter and SkipPoint cases above, where we + // could step to a different user key and start processing it for + // returning to the caller. if limit != nil && i.iterKey != nil && i.cmp(limit, i.iterKey.UserKey) > 0 && !i.rangeKeyWithinLimit(limit) { i.iterValidityState = IterAtLimit i.pos = iterPosCurReversePaused @@ -1760,7 +1808,8 @@ func (i *Iterator) internalNextPrefix(currKeyPrefixLen int) { i.iterKey, i.iterValue = i.iter.NextPrefix(i.prefixOrFullSeekKey) if invariants.Enabled && i.iterKey != nil { if iterKeyPrefixLen := i.split(i.iterKey.UserKey); i.cmp(i.iterKey.UserKey[:iterKeyPrefixLen], i.prefixOrFullSeekKey) < 0 { - panic("pebble: iter.NextPrefix did not advance beyond the current prefix") + panic(errors.AssertionFailedf("pebble: iter.NextPrefix did not advance beyond the current prefix: now at %q; expected to be geq %q", + i.iterKey, i.prefixOrFullSeekKey)) } } } @@ -2129,6 +2178,9 @@ func (i *Iterator) Value() []byte { // ValueAndErr returns the value, and any error encountered in extracting the value. // REQUIRES: i.Error()==nil and HasPointAndRange() returns true for hasPoint. +// +// The caller should not modify the contents of the returned slice, and its +// contents may change on the next call to Next. func (i *Iterator) ValueAndErr() ([]byte, error) { val, callerOwned, err := i.value.Value(i.lazyValueBuf) if err != nil { @@ -2159,7 +2211,13 @@ func (i *Iterator) RangeKeys() []RangeKeyData { // Valid returns true if the iterator is positioned at a valid key/value pair // and false otherwise. func (i *Iterator) Valid() bool { - return i.iterValidityState == IterValid && !i.requiresReposition + valid := i.iterValidityState == IterValid && !i.requiresReposition + if invariants.Enabled { + if err := i.Error(); valid && err != nil { + panic(errors.WithSecondaryError(errors.AssertionFailedf("pebble: iterator is valid with non-nil Error"), err)) + } + } + return valid } // Error returns any accumulated error. @@ -2224,6 +2282,10 @@ func (i *Iterator) Close() error { i.readState = nil } + if i.version != nil { + i.version.Unref() + } + for _, readers := range i.externalReaders { for _, r := range readers { err = firstError(err, r.Close()) @@ -2330,6 +2392,22 @@ func (i *Iterator) SetBounds(lower, upper []byte) { i.invalidate() } +// SetContext replaces the context provided at iterator creation, or the last +// one provided by SetContext. Even though iterators are expected to be +// short-lived, there are some cases where either (a) iterators are used far +// from the code that created them, (b) iterators are reused (while being +// short-lived) for processing different requests. For such scenarios, we +// allow the caller to replace the context. +func (i *Iterator) SetContext(ctx context.Context) { + i.ctx = ctx + i.iter.SetContext(ctx) + // If the iterator has an open point iterator that's not currently being + // used, propagate the new context to it. + if i.pointIter != nil && !i.opts.pointKeys() { + i.pointIter.SetContext(i.ctx) + } +} + // Initialization and changing of the bounds must call processBounds. // processBounds saves the bounds and computes derived state from those // bounds. @@ -2416,7 +2494,8 @@ func (i *Iterator) SetOptions(o *IterOptions) { // If either options specify block property filters for an iterator stack, // reconstruct it. if i.pointIter != nil && (closeBoth || len(o.PointKeyFilters) > 0 || len(i.opts.PointKeyFilters) > 0 || - o.RangeKeyMasking.Filter != nil || i.opts.RangeKeyMasking.Filter != nil) { + o.RangeKeyMasking.Filter != nil || i.opts.RangeKeyMasking.Filter != nil || o.SkipPoint != nil || + i.opts.SkipPoint != nil) { i.err = firstError(i.err, i.pointIter.Close()) i.pointIter = nil } @@ -2653,13 +2732,26 @@ func (i *Iterator) CloneWithContext(ctx context.Context, opts CloneOptions) (*It if opts.IterOptions == nil { opts.IterOptions = &i.opts } - + if i.batchOnlyIter { + return nil, errors.Errorf("cannot Clone a batch-only Iterator") + } readState := i.readState - if readState == nil { + vers := i.version + if readState == nil && vers == nil { return nil, errors.Errorf("cannot Clone a closed Iterator") } // i is already holding a ref, so there is no race with unref here. - readState.ref() + // + // TODO(bilal): If the underlying iterator was created on a snapshot, we could + // grab a reference to the current readState instead of reffing the original + // readState. This allows us to release references to some zombie sstables + // and memtables. + if readState != nil { + readState.ref() + } + if vers != nil { + vers.Ref() + } // Bundle various structures under a single umbrella in order to allocate // them together. buf := iterAllocPool.Get().(*iterAlloc) @@ -2671,6 +2763,7 @@ func (i *Iterator) CloneWithContext(ctx context.Context, opts CloneOptions) (*It merge: i.merge, comparer: i.comparer, readState: readState, + version: vers, keyBuf: buf.keyBuf, prefixOrFullSeekKey: buf.prefixOrFullSeekKey, boundsBuf: buf.boundsBuf, diff --git a/vendor/github.com/cockroachdb/pebble/level_checker.go b/vendor/github.com/cockroachdb/pebble/level_checker.go index 4cec440c3..2901c4559 100644 --- a/vendor/github.com/cockroachdb/pebble/level_checker.go +++ b/vendor/github.com/cockroachdb/pebble/level_checker.go @@ -345,7 +345,7 @@ func iterateAndCheckTombstones( type checkConfig struct { logger Logger - cmp Compare + comparer *Comparer readState *readState newIters tableNewIters seqNum uint64 @@ -354,6 +354,9 @@ type checkConfig struct { formatKey base.FormatKey } +// cmp is shorthand for comparer.Compare. +func (c *checkConfig) cmp(a, b []byte) int { return c.comparer.Compare(a, b) } + func checkRangeTombstones(c *checkConfig) error { var level int var tombstones []tombstoneWithLevel @@ -571,7 +574,7 @@ func (d *DB) CheckLevels(stats *CheckLevelsStats) error { checkConfig := &checkConfig{ logger: d.opts.Logger, - cmp: d.cmp, + comparer: d.opts.Comparer, readState: readState, newIters: d.newIters, seqNum: seqNum, @@ -639,7 +642,7 @@ func checkLevelsInternal(c *checkConfig) (err error) { manifestIter := current.L0SublevelFiles[sublevel].Iter() iterOpts := IterOptions{logger: c.logger} li := &levelIter{} - li.init(context.Background(), iterOpts, c.cmp, nil /* split */, c.newIters, manifestIter, + li.init(context.Background(), iterOpts, c.comparer, c.newIters, manifestIter, manifest.L0Sublevel(sublevel), internalIterOpts{}) li.initRangeDel(&mlevelAlloc[0].rangeDelIter) li.initBoundaryContext(&mlevelAlloc[0].levelIterBoundaryContext) @@ -653,7 +656,7 @@ func checkLevelsInternal(c *checkConfig) (err error) { iterOpts := IterOptions{logger: c.logger} li := &levelIter{} - li.init(context.Background(), iterOpts, c.cmp, nil /* split */, c.newIters, + li.init(context.Background(), iterOpts, c.comparer, c.newIters, current.Levels[level].Iter(), manifest.Level(level), internalIterOpts{}) li.initRangeDel(&mlevelAlloc[0].rangeDelIter) li.initBoundaryContext(&mlevelAlloc[0].levelIterBoundaryContext) diff --git a/vendor/github.com/cockroachdb/pebble/level_iter.go b/vendor/github.com/cockroachdb/pebble/level_iter.go index d10ec3948..0c26dbc39 100644 --- a/vendor/github.com/cockroachdb/pebble/level_iter.go +++ b/vendor/github.com/cockroachdb/pebble/level_iter.go @@ -37,8 +37,7 @@ type tableNewIters func( // for the rangedel iterator returned by tableNewIters. func tableNewRangeDelIter(ctx context.Context, newIters tableNewIters) keyspan.TableNewSpanIter { return func(file *manifest.FileMetadata, iterOptions keyspan.SpanIterOptions) (keyspan.FragmentIterator, error) { - iter, rangeDelIter, err := newIters( - ctx, file, &IterOptions{RangeKeyFilters: iterOptions.RangeKeyFilters, level: iterOptions.Level}, internalIterOpts{}) + iter, rangeDelIter, err := newIters(ctx, file, nil, internalIterOpts{}) if iter != nil { _ = iter.Close() } @@ -83,10 +82,11 @@ type levelIter struct { // short-lived (since they pin sstables), (b) plumbing a context into every // method is very painful, (c) they do not (yet) respect context // cancellation and are only used for tracing. - ctx context.Context - logger Logger - cmp Compare - split Split + ctx context.Context + logger Logger + comparer *Comparer + cmp Compare + split Split // The lower/upper bounds for iteration as specified at creation or the most // recent call to SetBounds. lower []byte @@ -241,25 +241,23 @@ var _ base.InternalIterator = (*levelIter)(nil) // newLevelIter returns a levelIter. It is permissible to pass a nil split // parameter if the caller is never going to call SeekPrefixGE. func newLevelIter( + ctx context.Context, opts IterOptions, - cmp Compare, - split Split, + comparer *Comparer, newIters tableNewIters, files manifest.LevelIterator, level manifest.Level, internalOpts internalIterOpts, ) *levelIter { l := &levelIter{} - l.init(context.Background(), opts, cmp, split, newIters, files, level, - internalOpts) + l.init(ctx, opts, comparer, newIters, files, level, internalOpts) return l } func (l *levelIter) init( ctx context.Context, opts IterOptions, - cmp Compare, - split Split, + comparer *Comparer, newIters tableNewIters, files manifest.LevelIterator, level manifest.Level, @@ -277,10 +275,12 @@ func (l *levelIter) init( l.tableOpts.PointKeyFilters = l.filtersBuf[:0:1] } l.tableOpts.UseL6Filters = opts.UseL6Filters + l.tableOpts.CategoryAndQoS = opts.CategoryAndQoS l.tableOpts.level = l.level l.tableOpts.snapshotForHideObsoletePoints = opts.snapshotForHideObsoletePoints - l.cmp = cmp - l.split = split + l.comparer = comparer + l.cmp = comparer.Compare + l.split = comparer.Split l.iterFile = nil l.newIters = newIters l.files = files @@ -798,7 +798,7 @@ func (l *levelIter) SeekPrefixGE( } return l.verify(l.largestBoundary, base.LazyValue{}) } - // It is possible that we are here because bloom filter matching failed. In + // It is possible that we are here because bloom filter matching failed. In // that case it is likely that all keys matching the prefix are wholly // within the current file and cannot be in the subsequent file. In that // case we don't want to go to the next file, since loading and seeking in @@ -806,7 +806,16 @@ func (l *levelIter) SeekPrefixGE( // next file will defeat the optimization for the next SeekPrefixGE that is // called with flags.TrySeekUsingNext(), since for sparse key spaces it is // likely that the next key will also be contained in the current file. - if n := l.split(l.iterFile.LargestPointKey.UserKey); l.cmp(prefix, l.iterFile.LargestPointKey.UserKey[:n]) < 0 { + var n int + if l.split != nil { + // If the split function is specified, calculate the prefix length accordingly. + n = l.split(l.iterFile.LargestPointKey.UserKey) + } else { + // If the split function is not specified, the entire key is used as the + // prefix. This case can occur when getIter uses SeekPrefixGE. + n = len(l.iterFile.LargestPointKey.UserKey) + } + if l.cmp(prefix, l.iterFile.LargestPointKey.UserKey[:n]) < 0 { return nil, base.LazyValue{} } return l.verify(l.skipEmptyFileForward()) @@ -1224,6 +1233,15 @@ func (l *levelIter) SetBounds(lower, upper []byte) { l.iter.SetBounds(l.tableOpts.LowerBound, l.tableOpts.UpperBound) } +func (l *levelIter) SetContext(ctx context.Context) { + l.ctx = ctx + if l.iter != nil { + // TODO(sumeer): this is losing the ctx = objiotracing.WithLevel(ctx, + // manifest.LevelToInt(opts.level)) that happens in table_cache.go. + l.iter.SetContext(ctx) + } +} + func (l *levelIter) String() string { if l.iterFile != nil { return fmt.Sprintf("%s: fileNum=%s", l.level, l.iter.String()) diff --git a/vendor/github.com/cockroachdb/pebble/mem_table.go b/vendor/github.com/cockroachdb/pebble/mem_table.go index 813652671..22d902eaf 100644 --- a/vendor/github.com/cockroachdb/pebble/mem_table.go +++ b/vendor/github.com/cockroachdb/pebble/mem_table.go @@ -15,6 +15,7 @@ import ( "github.com/cockroachdb/pebble/internal/arenaskl" "github.com/cockroachdb/pebble/internal/base" "github.com/cockroachdb/pebble/internal/keyspan" + "github.com/cockroachdb/pebble/internal/manual" "github.com/cockroachdb/pebble/internal/rangedel" "github.com/cockroachdb/pebble/internal/rangekey" ) @@ -84,7 +85,16 @@ type memTable struct { rangeKeys keySpanCache // The current logSeqNum at the time the memtable was created. This is // guaranteed to be less than or equal to any seqnum stored in the memtable. - logSeqNum uint64 + logSeqNum uint64 + releaseAccountingReservation func() +} + +func (m *memTable) free() { + if m != nil { + m.releaseAccountingReservation() + manual.Free(m.arenaBuf) + m.arenaBuf = nil + } } // memTableOptions holds configuration used when creating a memTable. All of @@ -92,9 +102,10 @@ type memTable struct { // which is used by tests. type memTableOptions struct { *Options - arenaBuf []byte - size int - logSeqNum uint64 + arenaBuf []byte + size int + logSeqNum uint64 + releaseAccountingReservation func() } func checkMemTable(obj interface{}) { @@ -109,16 +120,22 @@ func checkMemTable(obj interface{}) { // Options.MemTableSize is used instead. func newMemTable(opts memTableOptions) *memTable { opts.Options = opts.Options.EnsureDefaults() + m := new(memTable) + m.init(opts) + return m +} + +func (m *memTable) init(opts memTableOptions) { if opts.size == 0 { - opts.size = opts.MemTableSize + opts.size = int(opts.MemTableSize) } - - m := &memTable{ - cmp: opts.Comparer.Compare, - formatKey: opts.Comparer.FormatKey, - equal: opts.Comparer.Equal, - arenaBuf: opts.arenaBuf, - logSeqNum: opts.logSeqNum, + *m = memTable{ + cmp: opts.Comparer.Compare, + formatKey: opts.Comparer.FormatKey, + equal: opts.Comparer.Equal, + arenaBuf: opts.arenaBuf, + logSeqNum: opts.logSeqNum, + releaseAccountingReservation: opts.releaseAccountingReservation, } m.writerRefs.Store(1) m.tombstones = keySpanCache{ @@ -143,7 +160,6 @@ func newMemTable(opts memTableOptions) *memTable { m.rangeDelSkl.Reset(arena, m.cmp) m.rangeKeySkl.Reset(arena, m.cmp) m.reserved = arena.Size() - return m } func (m *memTable) writerRef() { @@ -153,7 +169,8 @@ func (m *memTable) writerRef() { } } -func (m *memTable) writerUnref() bool { +// writerUnref drops a ref on the memtable. Returns true if this was the last ref. +func (m *memTable) writerUnref() (wasLastRef bool) { switch v := m.writerRefs.Add(-1); { case v < 0: panic(fmt.Sprintf("pebble: inconsistent reference count: %d", v)) @@ -164,6 +181,7 @@ func (m *memTable) writerUnref() bool { } } +// readyForFlush is part of the flushable interface. func (m *memTable) readyForFlush() bool { return m.writerRefs.Load() == 0 } @@ -232,17 +250,19 @@ func (m *memTable) apply(batch *Batch, seqNum uint64) error { return nil } -// newIter returns an iterator that is unpositioned (Iterator.Valid() will -// return false). The iterator can be positioned via a call to SeekGE, -// SeekLT, First or Last. +// newIter is part of the flushable interface. It returns an iterator that is +// unpositioned (Iterator.Valid() will return false). The iterator can be +// positioned via a call to SeekGE, SeekLT, First or Last. func (m *memTable) newIter(o *IterOptions) internalIterator { return m.skl.NewIter(o.GetLowerBound(), o.GetUpperBound()) } +// newFlushIter is part of the flushable interface. func (m *memTable) newFlushIter(o *IterOptions, bytesFlushed *uint64) internalIterator { return m.skl.NewFlushIter(bytesFlushed) } +// newRangeDelIter is part of the flushable interface. func (m *memTable) newRangeDelIter(*IterOptions) keyspan.FragmentIterator { tombstones := m.tombstones.get() if tombstones == nil { @@ -251,6 +271,7 @@ func (m *memTable) newRangeDelIter(*IterOptions) keyspan.FragmentIterator { return keyspan.NewIter(m.cmp, tombstones) } +// newRangeKeyIter is part of the flushable interface. func (m *memTable) newRangeKeyIter(*IterOptions) keyspan.FragmentIterator { rangeKeys := m.rangeKeys.get() if rangeKeys == nil { @@ -259,6 +280,7 @@ func (m *memTable) newRangeKeyIter(*IterOptions) keyspan.FragmentIterator { return keyspan.NewIter(m.cmp, rangeKeys) } +// containsRangeKeys is part of the flushable interface. func (m *memTable) containsRangeKeys() bool { return m.rangeKeys.count.Load() > 0 } @@ -274,10 +296,12 @@ func (m *memTable) availBytes() uint32 { return a.Capacity() - m.reserved } +// inuseBytes is part of the flushable interface. func (m *memTable) inuseBytes() uint64 { return uint64(m.skl.Size() - memTableEmptySize) } +// totalBytes is part of the flushable interface. func (m *memTable) totalBytes() uint64 { return uint64(m.skl.Arena().Capacity()) } diff --git a/vendor/github.com/cockroachdb/pebble/merging_iter.go b/vendor/github.com/cockroachdb/pebble/merging_iter.go index 4e2426d88..a4341085c 100644 --- a/vendor/github.com/cockroachdb/pebble/merging_iter.go +++ b/vendor/github.com/cockroachdb/pebble/merging_iter.go @@ -6,6 +6,7 @@ package pebble import ( "bytes" + "context" "fmt" "runtime/debug" "unsafe" @@ -27,6 +28,10 @@ type mergingIterLevel struct { // iterKey and iterValue cache the current key and value iter are pointed at. iterKey *InternalKey iterValue base.LazyValue + // levelIter is non-nil if this level's iter is ultimately backed by a + // *levelIter. The handle in iter may have wrapped the levelIter with + // intermediary internalIterator implementations. + levelIter *levelIter // levelIterBoundaryContext's fields are set when using levelIter, in order // to surface sstable boundary keys and file-level context. See levelIter @@ -1354,6 +1359,12 @@ func (m *mergingIter) SetBounds(lower, upper []byte) { m.heap.clear() } +func (m *mergingIter) SetContext(ctx context.Context) { + for i := range m.levels { + m.levels[i].iter.SetContext(ctx) + } +} + func (m *mergingIter) DebugString() string { var buf bytes.Buffer sep := "" @@ -1371,9 +1382,9 @@ func (m *mergingIter) DebugString() string { } func (m *mergingIter) ForEachLevelIter(fn func(li *levelIter) bool) { - for _, iter := range m.levels { - if li, ok := iter.iter.(*levelIter); ok { - if done := fn(li); done { + for _, ml := range m.levels { + if ml.levelIter != nil { + if done := fn(ml.levelIter); done { break } } diff --git a/vendor/github.com/cockroachdb/pebble/metrics.go b/vendor/github.com/cockroachdb/pebble/metrics.go index ff17eac2c..0f1e32b2e 100644 --- a/vendor/github.com/cockroachdb/pebble/metrics.go +++ b/vendor/github.com/cockroachdb/pebble/metrics.go @@ -12,6 +12,7 @@ import ( "github.com/cockroachdb/pebble/internal/base" "github.com/cockroachdb/pebble/internal/cache" "github.com/cockroachdb/pebble/internal/humanize" + "github.com/cockroachdb/pebble/objstorage/objstorageprovider/sharedcache" "github.com/cockroachdb/pebble/record" "github.com/cockroachdb/pebble/sstable" "github.com/cockroachdb/redact" @@ -28,6 +29,11 @@ type FilterMetrics = sstable.FilterMetrics // comment in base. type ThroughputMetric = base.ThroughputMetric +// SecondaryCacheMetrics holds metrics for the persistent secondary cache +// that caches commonly accessed blocks from blob storage on a local +// file system. +type SecondaryCacheMetrics = sharedcache.Metrics + // LevelMetrics holds per-level metrics such as the number of files and total // size of the files, and compaction related metrics. type LevelMetrics struct { @@ -38,9 +44,14 @@ type LevelMetrics struct { Sublevels int32 // The total number of files in the level. NumFiles int64 + // The total number of virtual sstables in the level. + NumVirtualFiles uint64 // The total size in bytes of the files in the level. Size int64 - // The level's compaction score. + // The total size of the virtual sstables in the level. + VirtualSize uint64 + // The level's compaction score. This is the compensatedScoreRatio in the + // candidateLevelInfo. Score float64 // The number of incoming bytes from other levels read during // compactions. This excludes bytes moved and bytes ingested. For L0 this is @@ -71,6 +82,18 @@ type LevelMetrics struct { TablesIngested uint64 // The number of sstables moved to this level by a "move" compaction. TablesMoved uint64 + + MultiLevel struct { + // BytesInTop are the total bytes in a multilevel compaction coming from the top level. + BytesInTop uint64 + + // BytesIn, exclusively for multiLevel compactions. + BytesIn uint64 + + // BytesRead, exclusively for multilevel compactions. + BytesRead uint64 + } + // Additional contains misc additional metrics that are not always printed. Additional struct { // The sum of Properties.ValueBlocksSize for all the sstables in this @@ -88,6 +111,8 @@ type LevelMetrics struct { // Add updates the counter metrics for the level. func (m *LevelMetrics) Add(u *LevelMetrics) { m.NumFiles += u.NumFiles + m.NumVirtualFiles += u.NumVirtualFiles + m.VirtualSize += u.VirtualSize m.Size += u.Size m.BytesIn += u.BytesIn m.BytesIngested += u.BytesIngested @@ -99,6 +124,9 @@ func (m *LevelMetrics) Add(u *LevelMetrics) { m.TablesFlushed += u.TablesFlushed m.TablesIngested += u.TablesIngested m.TablesMoved += u.TablesMoved + m.MultiLevel.BytesInTop += u.MultiLevel.BytesInTop + m.MultiLevel.BytesRead += u.MultiLevel.BytesRead + m.MultiLevel.BytesIn += u.MultiLevel.BytesIn m.Additional.BytesWrittenDataBlocks += u.Additional.BytesWrittenDataBlocks m.Additional.BytesWrittenValueBlocks += u.Additional.BytesWrittenValueBlocks m.Additional.ValueBlocksSize += u.Additional.ValueBlocksSize @@ -124,14 +152,15 @@ type Metrics struct { Compact struct { // The total number of compactions, and per-compaction type counts. - Count int64 - DefaultCount int64 - DeleteOnlyCount int64 - ElisionOnlyCount int64 - MoveCount int64 - ReadCount int64 - RewriteCount int64 - MultiLevelCount int64 + Count int64 + DefaultCount int64 + DeleteOnlyCount int64 + ElisionOnlyCount int64 + MoveCount int64 + ReadCount int64 + RewriteCount int64 + MultiLevelCount int64 + CounterLevelCount int64 // An estimate of the number of bytes that need to be compacted for the LSM // to reach a stable state. EstimatedDebt uint64 @@ -184,7 +213,10 @@ type Metrics struct { // The count of memtables. Count int64 // The number of bytes present in zombie memtables which are no longer - // referenced by the current DB state but are still in use by an iterator. + // referenced by the current DB state. An unbounded number of memtables + // may be zombie if they're still in use by an iterator. One additional + // memtable may be zombie if it's no longer in use and waiting to be + // recycled. ZombieSize uint64 // The count of zombie memtables. ZombieCount int64 @@ -227,6 +259,10 @@ type Metrics struct { ZombieSize uint64 // The count of zombie tables. ZombieCount int64 + // The count of the backing sstables. + BackingTableCount uint64 + // The sum of the sizes of the all of the backing sstables. + BackingTableSize uint64 } TableCache CacheMetrics @@ -260,6 +296,10 @@ type Metrics struct { record.LogWriterMetrics } + CategoryStats []sstable.CategoryStatsAggregate + + SecondaryCacheMetrics SecondaryCacheMetrics + private struct { optionsFileSize uint64 manifestFileSize uint64 @@ -273,6 +313,13 @@ var ( prometheus.LinearBuckets(0.0, float64(time.Microsecond*100), 50), prometheus.ExponentialBucketsRange(float64(time.Millisecond*5), float64(10*time.Second), 50)..., ) + + // SecondaryCacheIOBuckets exported to enable exporting from package pebble to + // enable exporting metrics with below buckets in CRDB. + SecondaryCacheIOBuckets = sharedcache.IOBuckets + // SecondaryCacheChannelWriteBuckets exported to enable exporting from package + // pebble to enable exporting metrics with below buckets in CRDB. + SecondaryCacheChannelWriteBuckets = sharedcache.ChannelWriteBuckets ) // DiskSpaceUsage returns the total disk space used by the database in bytes, @@ -292,12 +339,25 @@ func (m *Metrics) DiskSpaceUsage() uint64 { return usageBytes } -func (m *Metrics) levelSizes() [numLevels]int64 { - var sizes [numLevels]int64 - for i := 0; i < len(sizes); i++ { - sizes[i] = m.Levels[i].Size +// NumVirtual is the number of virtual sstables in the latest version +// summed over every level in the lsm. +func (m *Metrics) NumVirtual() uint64 { + var n uint64 + for _, level := range m.Levels { + n += level.NumVirtualFiles + } + return n +} + +// VirtualSize is the sum of the sizes of the virtual sstables in the +// latest version. BackingTableSize - VirtualSize gives an estimate for +// the space amplification caused by not compacting virtual sstables. +func (m *Metrics) VirtualSize() uint64 { + var size uint64 + for _, level := range m.Levels { + size += level.VirtualSize } - return sizes + return size } // ReadAmp returns the current read amplification of the database. @@ -330,26 +390,28 @@ func (m *Metrics) Total() LevelMetrics { // String pretty-prints the metrics as below: // -// | | | | ingested | moved | written | | amp -// level | tables size val-bl | score | in | tables size | tables size | tables size | read | r w -// ------+---------------------+-------+-------+--------------+--------------+--------------+-------+--------- -// 0 | 101 102B 0B | 103.0 | 104B | 112 104B | 113 106B | 221 217B | 107B | 1 2.1 -// 1 | 201 202B 0B | 203.0 | 204B | 212 204B | 213 206B | 421 417B | 207B | 2 2.0 -// 2 | 301 302B 0B | 303.0 | 304B | 312 304B | 313 306B | 621 617B | 307B | 3 2.0 -// 3 | 401 402B 0B | 403.0 | 404B | 412 404B | 413 406B | 821 817B | 407B | 4 2.0 -// 4 | 501 502B 0B | 503.0 | 504B | 512 504B | 513 506B | 1.0K 1017B | 507B | 5 2.0 -// 5 | 601 602B 0B | 603.0 | 604B | 612 604B | 613 606B | 1.2K 1.2KB | 607B | 6 2.0 -// 6 | 701 702B 0B | - | 704B | 712 704B | 713 706B | 1.4K 1.4KB | 707B | 7 2.0 -// total | 2.8K 2.7KB 0B | - | 2.8KB | 2.9K 2.8KB | 2.9K 2.8KB | 5.7K 8.4KB | 2.8KB | 28 3.0 -// ----------------------------------------------------------------------------------------------------------- +// | | | | ingested | moved | written | | amp +// level | tables size val-bl vtables | score | in | tables size | tables size | tables size | read | r w +// ------+-----------------------------+-------+-------+--------------+--------------+--------------+-------+--------- +// 0 | 101 102B 0B 0 | 103.0 | 104B | 112 104B | 113 106B | 221 217B | 107B | 1 2.1 +// 1 | 201 202B 0B 0 | 203.0 | 204B | 212 204B | 213 206B | 421 417B | 207B | 2 2.0 +// 2 | 301 302B 0B 0 | 303.0 | 304B | 312 304B | 313 306B | 621 617B | 307B | 3 2.0 +// 3 | 401 402B 0B 0 | 403.0 | 404B | 412 404B | 413 406B | 821 817B | 407B | 4 2.0 +// 4 | 501 502B 0B 0 | 503.0 | 504B | 512 504B | 513 506B | 1.0K 1017B | 507B | 5 2.0 +// 5 | 601 602B 0B 0 | 603.0 | 604B | 612 604B | 613 606B | 1.2K 1.2KB | 607B | 6 2.0 +// 6 | 701 702B 0B 0 | - | 704B | 712 704B | 713 706B | 1.4K 1.4KB | 707B | 7 2.0 +// total | 2.8K 2.7KB 0B 0 | - | 2.8KB | 2.9K 2.8KB | 2.9K 2.8KB | 5.7K 8.4KB | 2.8KB | 28 3.0 +// ------------------------------------------------------------------------------------------------------------------- // WAL: 22 files (24B) in: 25B written: 26B (4% overhead) // Flushes: 8 // Compactions: 5 estimated debt: 6B in progress: 2 (7B) // default: 27 delete: 28 elision: 29 move: 30 read: 31 rewrite: 32 multi-level: 33 // MemTables: 12 (11B) zombie: 14 (13B) // Zombie tables: 16 (15B) +// Backing tables: 0 (0B) // Block cache: 2 entries (1B) hit rate: 42.9% // Table cache: 18 entries (17B) hit rate: 48.7% +// Secondary cache: 40 entries (40B) hit rate: 49.9% // Snapshots: 4 earliest seq num: 1024 // Table iters: 21 // Filter utility: 47.4% @@ -374,9 +436,25 @@ func (m *Metrics) SafeFormat(w redact.SafePrinter, _ rune) { // width specifiers. When the issue is fixed, we can convert these to // RedactableStrings. https://github.com/cockroachdb/redact/issues/17 - w.SafeString(" | | | | ingested | moved | written | | amp\n") - w.SafeString("level | tables size val-bl | score | in | tables size | tables size | tables size | read | r w\n") - w.SafeString("------+---------------------+-------+-------+--------------+--------------+--------------+-------+---------\n") + multiExists := m.Compact.MultiLevelCount > 0 + appendIfMulti := func(line redact.SafeString) { + if multiExists { + w.SafeString(line) + } + } + newline := func() { + w.SafeString("\n") + } + + w.SafeString(" | | | | ingested | moved | written | | amp") + appendIfMulti(" | multilevel") + newline() + w.SafeString("level | tables size val-bl vtables | score | in | tables size | tables size | tables size | read | r w") + appendIfMulti(" | top in read") + newline() + w.SafeString("------+-----------------------------+-------+-------+--------------+--------------+--------------+-------+---------") + appendIfMulti("-+------------------") + newline() // formatRow prints out a row of the table. formatRow := func(m *LevelMetrics, score float64) { @@ -399,10 +477,11 @@ func (m *Metrics) SafeFormat(w redact.SafePrinter, _ rune) { wampStr = fmt.Sprintf("%.1f", wamp) } - w.Printf("| %5s %6s %6s | %5s | %5s | %5s %6s | %5s %6s | %5s %6s | %5s | %3d %4s\n", + w.Printf("| %5s %6s %6s %7s | %5s | %5s | %5s %6s | %5s %6s | %5s %6s | %5s | %3d %4s", humanize.Count.Int64(m.NumFiles), humanize.Bytes.Int64(m.Size), humanize.Bytes.Uint64(m.Additional.ValueBlocksSize), + humanize.Count.Uint64(m.NumVirtualFiles), redact.Safe(scoreStr), humanize.Bytes.Uint64(m.BytesIn), humanize.Count.Uint64(m.TablesIngested), @@ -414,6 +493,14 @@ func (m *Metrics) SafeFormat(w redact.SafePrinter, _ rune) { humanize.Bytes.Uint64(m.BytesRead), redact.Safe(m.Sublevels), redact.Safe(wampStr)) + + if multiExists { + w.Printf(" | %5s %5s %5s", + humanize.Bytes.Uint64(m.MultiLevel.BytesInTop), + humanize.Bytes.Uint64(m.MultiLevel.BytesIn), + humanize.Bytes.Uint64(m.MultiLevel.BytesRead)) + } + newline() } var total LevelMetrics @@ -439,8 +526,9 @@ func (m *Metrics) SafeFormat(w redact.SafePrinter, _ rune) { w.SafeString("total ") formatRow(&total, math.NaN()) - w.SafeString("-----------------------------------------------------------------------------------------------------------\n") - + w.SafeString("-------------------------------------------------------------------------------------------------------------------") + appendIfMulti("--------------------") + newline() w.Printf("WAL: %d files (%s) in: %s written: %s (%.0f%% overhead)\n", redact.Safe(m.WAL.Files), humanize.Bytes.Uint64(m.WAL.Size), @@ -475,6 +563,13 @@ func (m *Metrics) SafeFormat(w redact.SafePrinter, _ rune) { redact.Safe(m.Table.ZombieCount), humanize.Bytes.Uint64(m.Table.ZombieSize)) + w.Printf("Backing tables: %d (%s)\n", + redact.Safe(m.Table.BackingTableCount), + humanize.Bytes.Uint64(m.Table.BackingTableSize)) + w.Printf("Virtual tables: %d (%s)\n", + redact.Safe(m.NumVirtual()), + humanize.Bytes.Uint64(m.VirtualSize())) + formatCacheMetrics := func(m *CacheMetrics, name redact.SafeString) { w.Printf("%s: %s entries (%s) hit rate: %.1f%%\n", name, @@ -485,6 +580,15 @@ func (m *Metrics) SafeFormat(w redact.SafePrinter, _ rune) { formatCacheMetrics(&m.BlockCache, "Block cache") formatCacheMetrics(&m.TableCache, "Table cache") + formatSharedCacheMetrics := func(w redact.SafePrinter, m *SecondaryCacheMetrics, name redact.SafeString) { + w.Printf("%s: %s entries (%s) hit rate: %.1f%%\n", + name, + humanize.Count.Int64(m.Count), + humanize.Bytes.Int64(m.Size), + redact.Safe(hitRate(m.ReadsWithFullHit, m.ReadsWithPartialHit+m.ReadsWithNoHit))) + } + formatSharedCacheMetrics(w, &m.SecondaryCacheMetrics, "Secondary cache") + w.Printf("Snapshots: %d earliest seq num: %d\n", redact.Safe(m.Snapshots.Count), redact.Safe(m.Snapshots.EarliestSeqNum)) @@ -508,3 +612,16 @@ func percent(numerator, denominator int64) float64 { } return 100 * float64(numerator) / float64(denominator) } + +// StringForTests is identical to m.String() on 64-bit platforms. It is used to +// provide a platform-independent result for tests. +func (m *Metrics) StringForTests() string { + mCopy := *m + if math.MaxInt == math.MaxInt32 { + // This is the difference in Sizeof(sstable.Reader{})) between 64 and 32 bit + // platforms. + const tableCacheSizeAdjustment = 212 + mCopy.TableCache.Size += mCopy.TableCache.Count * tableCacheSizeAdjustment + } + return redact.StringWithoutMarkers(&mCopy) +} diff --git a/vendor/github.com/cockroachdb/pebble/objstorage/objstorage.go b/vendor/github.com/cockroachdb/pebble/objstorage/objstorage.go index 267a82da7..3f78b4c4a 100644 --- a/vendor/github.com/cockroachdb/pebble/objstorage/objstorage.go +++ b/vendor/github.com/cockroachdb/pebble/objstorage/objstorage.go @@ -10,8 +10,10 @@ import ( "github.com/cockroachdb/errors" "github.com/cockroachdb/pebble/internal/base" + "github.com/cockroachdb/pebble/objstorage/objstorageprovider/sharedcache" "github.com/cockroachdb/pebble/objstorage/remote" "github.com/cockroachdb/pebble/vfs" + "github.com/cockroachdb/redact" ) // Readable is the handle for an object that is open for reading. @@ -166,6 +168,11 @@ func (c CreatorID) IsSet() bool { return c != 0 } func (c CreatorID) String() string { return fmt.Sprintf("%d", c) } +// SafeFormat implements redact.SafeFormatter. +func (c CreatorID) SafeFormat(w redact.SafePrinter, _ rune) { + w.Printf("%d", redact.SafeUint(c)) +} + // SharedCleanupMethod indicates the method for cleaning up unused shared objects. type SharedCleanupMethod uint8 @@ -268,10 +275,8 @@ type Provider interface { // Cannot be called if shared storage is not configured for the provider. SetCreatorID(creatorID CreatorID) error - // IsForeign returns whether this object is owned by a different node. Return - // value undefined if creator ID is not set yet, or if this object does not - // exist in this provider. - IsForeign(meta ObjectMetadata) bool + // IsSharedForeign returns whether this object is owned by a different node. + IsSharedForeign(meta ObjectMetadata) bool // RemoteObjectBacking encodes the remote object metadata for the given object. RemoteObjectBacking(meta *ObjectMetadata) (RemoteObjectBackingHandle, error) @@ -289,6 +294,10 @@ type Provider interface { // IsNotExistError indicates whether the error is known to report that a file or // directory does not exist. IsNotExistError(err error) bool + + // Metrics returns metrics about objstorage. Currently, it only returns metrics + // about the shared cache. + Metrics() sharedcache.Metrics } // RemoteObjectBacking encodes the metadata necessary to incorporate a shared diff --git a/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/provider.go b/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/provider.go index f739407a3..28cf57d17 100644 --- a/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/provider.go +++ b/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/provider.go @@ -5,10 +5,11 @@ package objstorageprovider import ( + "cmp" "context" "io" "os" - "sort" + "slices" "sync" "github.com/cockroachdb/errors" @@ -18,6 +19,7 @@ import ( "github.com/cockroachdb/pebble/objstorage" "github.com/cockroachdb/pebble/objstorage/objstorageprovider/objiotracing" "github.com/cockroachdb/pebble/objstorage/objstorageprovider/remoteobjcat" + "github.com/cockroachdb/pebble/objstorage/objstorageprovider/sharedcache" "github.com/cockroachdb/pebble/objstorage/remote" "github.com/cockroachdb/pebble/vfs" ) @@ -96,10 +98,10 @@ type Settings struct { Remote struct { StorageFactory remote.StorageFactory - // If CreateOnShared is true, sstables are created on remote storage using + // If CreateOnShared is non-zero, sstables are created on remote storage using // the CreateOnSharedLocator (when the PreferSharedStorage create option is // true). - CreateOnShared bool + CreateOnShared remote.CreateOnSharedStrategy CreateOnSharedLocator remote.Locator // CacheSizeBytes is the size of the on-disk block cache for objects @@ -143,7 +145,13 @@ func DefaultSettings(fs vfs.FS, dirName string) Settings { // Open creates the provider. func Open(settings Settings) (objstorage.Provider, error) { - return open(settings) + // Note: we can't just `return open(settings)` because in an error case we + // would return (*provider)(nil) which is not objstorage.Provider(nil). + p, err := open(settings) + if err != nil { + return nil, err + } + return p, nil } func open(settings Settings) (p *provider, _ error) { @@ -242,13 +250,13 @@ func (p *provider) Create( fileNum base.DiskFileNum, opts objstorage.CreateOptions, ) (w objstorage.Writable, meta objstorage.ObjectMetadata, err error) { - if opts.PreferSharedStorage && p.st.Remote.CreateOnShared { + if opts.PreferSharedStorage && p.st.Remote.CreateOnShared != remote.CreateOnSharedNone { w, meta, err = p.sharedCreate(ctx, fileType, fileNum, p.st.Remote.CreateOnSharedLocator, opts) } else { w, meta, err = p.vfsCreate(ctx, fileType, fileNum) } if err != nil { - err = errors.Wrapf(err, "creating object %s", errors.Safe(fileNum)) + err = errors.Wrapf(err, "creating object %s", fileNum) return nil, objstorage.ObjectMetadata{}, err } p.addMetadata(meta) @@ -285,7 +293,7 @@ func (p *provider) Remove(fileType base.FileType, fileNum base.DiskFileNum) erro // We want to be able to retry a Remove, so we keep the object in our list. // TODO(radu): we should mark the object as "zombie" and not allow any other // operations. - return errors.Wrapf(err, "removing object %s", errors.Safe(fileNum)) + return errors.Wrapf(err, "removing object %s", fileNum) } p.removeMetadata(fileNum) @@ -331,7 +339,7 @@ func (p *provider) LinkOrCopyFromLocal( dstFileNum base.DiskFileNum, opts objstorage.CreateOptions, ) (objstorage.ObjectMetadata, error) { - shared := opts.PreferSharedStorage && p.st.Remote.CreateOnShared + shared := opts.PreferSharedStorage && p.st.Remote.CreateOnShared != remote.CreateOnSharedNone if !shared && srcFS == p.st.FS { // Wrap the normal filesystem with one which wraps newly created files with // vfs.NewSyncingFile. @@ -397,13 +405,13 @@ func (p *provider) Lookup( return objstorage.ObjectMetadata{}, errors.Wrapf( os.ErrNotExist, "file %s (type %d) unknown to the objstorage provider", - errors.Safe(fileNum), errors.Safe(fileType), + fileNum, errors.Safe(fileType), ) } if meta.FileType != fileType { return objstorage.ObjectMetadata{}, errors.AssertionFailedf( "file %s type mismatch (known type %d, expected type %d)", - errors.Safe(fileNum), errors.Safe(meta.FileType), errors.Safe(fileType), + fileNum, errors.Safe(meta.FileType), errors.Safe(fileType), ) } return meta, nil @@ -433,12 +441,20 @@ func (p *provider) List() []objstorage.ObjectMetadata { for _, meta := range p.mu.knownObjects { res = append(res, meta) } - sort.Slice(res, func(i, j int) bool { - return res[i].DiskFileNum.FileNum() < res[j].DiskFileNum.FileNum() + slices.SortFunc(res, func(a, b objstorage.ObjectMetadata) int { + return cmp.Compare(a.DiskFileNum, b.DiskFileNum) }) return res } +// Metrics is part of the objstorage.Provider interface. +func (p *provider) Metrics() sharedcache.Metrics { + if p.remote.cache != nil { + return p.remote.cache.Metrics() + } + return sharedcache.Metrics{} +} + func (p *provider) addMetadata(meta objstorage.ObjectMetadata) { if invariants.Enabled { meta.AssertValid() diff --git a/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/remote.go b/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/remote.go index f8bd7a444..70fdfc78e 100644 --- a/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/remote.go +++ b/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/remote.go @@ -18,13 +18,18 @@ import ( "github.com/cockroachdb/pebble/objstorage/objstorageprovider/remoteobjcat" "github.com/cockroachdb/pebble/objstorage/objstorageprovider/sharedcache" "github.com/cockroachdb/pebble/objstorage/remote" + "github.com/cockroachdb/redact" ) // remoteSubsystem contains the provider fields related to remote storage. // All fields remain unset if remote storage is not configured. type remoteSubsystem struct { catalog *remoteobjcat.Catalog - cache *sharedcache.Cache + // catalogSyncMutex is used to correctly serialize two sharedSync operations. + // It must be acquired before the provider mutex. + catalogSyncMutex sync.Mutex + + cache *sharedcache.Cache // shared contains the fields relevant to shared objects, i.e. objects that // are created by Pebble and potentially shared between Pebble instances. @@ -150,12 +155,12 @@ func (p *provider) SetCreatorID(creatorID objstorage.CreatorID) error { return nil } -// IsForeign is part of the objstorage.Provider interface. -func (p *provider) IsForeign(meta objstorage.ObjectMetadata) bool { +// IsSharedForeign is part of the objstorage.Provider interface. +func (p *provider) IsSharedForeign(meta objstorage.ObjectMetadata) bool { if !p.remote.shared.initialized.Load() { return false } - return meta.IsRemote() && (meta.Remote.CustomObjectName != "" || meta.Remote.CreatorID != p.remote.shared.creatorID) + return meta.IsShared() && (meta.Remote.CreatorID != p.remote.shared.creatorID) } func (p *provider) remoteCheckInitialized() error { @@ -176,6 +181,12 @@ func (p *provider) sharedCheckInitialized() error { } func (p *provider) sharedSync() error { + // Serialize parallel sync operations. Note that ApplyBatch is already + // serialized internally, but we want to make sure they get called with + // batches in the right order. + p.remote.catalogSyncMutex.Lock() + defer p.remote.catalogSyncMutex.Unlock() + batch := func() remoteobjcat.Batch { p.mu.Lock() defer p.mu.Unlock() @@ -188,9 +199,9 @@ func (p *provider) sharedSync() error { return nil } - err := p.remote.catalog.ApplyBatch(batch) - if err != nil { - // We have to put back the batch (for the next Sync). + if err := p.remote.catalog.ApplyBatch(batch); err != nil { + // Put back the batch (for the next Sync), appending any operations that + // happened in the meantime. p.mu.Lock() defer p.mu.Unlock() batch.Append(p.mu.remote.catalogBatch) @@ -223,7 +234,7 @@ func (p *provider) sharedCreateRef(meta objstorage.ObjectMetadata) error { err = writer.Close() } if err != nil { - return errors.Wrapf(err, "creating marker object %q", refName) + return errors.Wrapf(err, "creating marker object %q", errors.Safe(refName)) } return nil } @@ -255,7 +266,7 @@ func (p *provider) sharedCreate( objName := remoteObjectName(meta) writer, err := storage.CreateObject(objName) if err != nil { - return nil, objstorage.ObjectMetadata{}, errors.Wrapf(err, "creating object %q", objName) + return nil, objstorage.ObjectMetadata{}, errors.Wrapf(err, "creating object %q", errors.Safe(objName)) } return &sharedWritable{ p: p, @@ -280,19 +291,19 @@ func (p *provider) remoteOpenForReading( if _, err := meta.Remote.Storage.Size(refName); err != nil { if meta.Remote.Storage.IsNotExistError(err) { if opts.MustExist { - p.st.Logger.Fatalf("marker object %q does not exist", refName) + p.st.Logger.Fatalf("marker object %q does not exist", errors.Safe(refName)) // TODO(radu): maybe list references for the object. } - return nil, errors.Errorf("marker object %q does not exist", refName) + return nil, errors.Errorf("marker object %q does not exist", errors.Safe(refName)) } - return nil, errors.Wrapf(err, "checking marker object %q", refName) + return nil, errors.Wrapf(err, "checking marker object %q", errors.Safe(refName)) } } objName := remoteObjectName(meta) reader, size, err := meta.Remote.Storage.ReadObject(ctx, objName) if err != nil { if opts.MustExist && meta.Remote.Storage.IsNotExistError(err) { - p.st.Logger.Fatalf("object %q does not exist", objName) + p.st.Logger.Fatalf("object %q does not exist", redact.SafeString(objName)) // TODO(radu): maybe list references for the object. } return nil, err diff --git a/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/remoteobjcat/catalog.go b/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/remoteobjcat/catalog.go index f9d22572a..4b0b67689 100644 --- a/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/remoteobjcat/catalog.go +++ b/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/remoteobjcat/catalog.go @@ -5,9 +5,10 @@ package remoteobjcat import ( + "cmp" "fmt" "io" - "sort" + "slices" "sync" "github.com/cockroachdb/errors" @@ -22,7 +23,7 @@ import ( // Catalog is used to manage the on-disk remote object catalog. // // The catalog file is a log of records, where each record is an encoded -// versionEdit. +// VersionEdit. type Catalog struct { fs vfs.FS dirname string @@ -114,8 +115,8 @@ func Open(fs vfs.FS, dirname string) (*Catalog, CatalogContents, error) { res.Objects = append(res.Objects, meta) } // Sort the objects so the function is deterministic. - sort.Slice(res.Objects, func(i, j int) bool { - return res.Objects[i].FileNum.FileNum() < res.Objects[j].FileNum.FileNum() + slices.SortFunc(res.Objects, func(a, b RemoteObjectMetadata) int { + return cmp.Compare(a.FileNum, b.FileNum) }) return c, res, nil } @@ -136,9 +137,9 @@ func (c *Catalog) SetCreatorID(id objstorage.CreatorID) error { return nil } - ve := versionEdit{CreatorID: id} + ve := VersionEdit{CreatorID: id} if err := c.writeToCatalogFileLocked(&ve); err != nil { - return errors.Wrapf(err, "pebble: could not write to remote object catalog: %v", err) + return errors.Wrapf(err, "pebble: could not write to remote object catalog") } c.mu.creatorID = id return nil @@ -165,7 +166,7 @@ func (c *Catalog) closeCatalogFile() error { // Batch is used to perform multiple object additions/deletions at once. type Batch struct { - ve versionEdit + ve VersionEdit } // AddObject adds a new object to the batch. @@ -218,37 +219,40 @@ func (c *Catalog) ApplyBatch(b Batch) error { c.mu.Lock() defer c.mu.Unlock() - // Add new objects before deleting any objects. This allows for cases where - // the same batch adds and deletes an object. - for _, meta := range b.ve.NewObjects { - if _, exists := c.mu.objects[meta.FileNum]; exists { - return errors.AssertionFailedf("adding existing object %s", meta.FileNum) + // Sanity checks. + toAdd := make(map[base.DiskFileNum]struct{}, len(b.ve.NewObjects)) + exists := func(n base.DiskFileNum) bool { + _, ok := c.mu.objects[n] + if !ok { + _, ok = toAdd[n] } + return ok } for _, meta := range b.ve.NewObjects { - c.mu.objects[meta.FileNum] = meta - } - removeAddedObjects := func() { - for i := range b.ve.NewObjects { - delete(c.mu.objects, b.ve.NewObjects[i].FileNum) + if exists(meta.FileNum) { + return errors.AssertionFailedf("adding existing object %s", meta.FileNum) } + toAdd[meta.FileNum] = struct{}{} } for _, n := range b.ve.DeletedObjects { - if _, exists := c.mu.objects[n]; !exists { - removeAddedObjects() + if !exists(n) { return errors.AssertionFailedf("deleting non-existent object %s", n) } } - // Apply the remainder of the batch to our current state. - for _, n := range b.ve.DeletedObjects { - delete(c.mu.objects, n) - } if err := c.writeToCatalogFileLocked(&b.ve); err != nil { - return errors.Wrapf(err, "pebble: could not write to remote object catalog: %v", err) + return errors.Wrapf(err, "pebble: could not write to remote object catalog") + } + + // Add new objects before deleting any objects. This allows for cases where + // the same batch adds and deletes an object. + for _, meta := range b.ve.NewObjects { + c.mu.objects[meta.FileNum] = meta + } + for _, n := range b.ve.DeletedObjects { + delete(c.mu.objects, n) } - b.Reset() return nil } @@ -272,29 +276,23 @@ func (c *Catalog) loadFromCatalogFile(filename string) error { return errors.Wrapf(err, "pebble: error when loading remote object catalog file %q", errors.Safe(filename)) } - var ve versionEdit - err = ve.Decode(r) - if err != nil { + var ve VersionEdit + if err := ve.Decode(r); err != nil { return errors.Wrapf(err, "pebble: error when loading remote object catalog file %q", errors.Safe(filename)) } // Apply the version edit to the current state. - if ve.CreatorID.IsSet() { - c.mu.creatorID = ve.CreatorID - } - for _, fileNum := range ve.DeletedObjects { - delete(c.mu.objects, fileNum) - } - for _, meta := range ve.NewObjects { - c.mu.objects[meta.FileNum] = meta + if err := ve.Apply(&c.mu.creatorID, c.mu.objects); err != nil { + return errors.Wrapf(err, "pebble: error when loading remote object catalog file %q", + errors.Safe(filename)) } } return nil } -// writeToCatalogFileLocked writes a versionEdit to the catalog file. +// writeToCatalogFileLocked writes a VersionEdit to the catalog file. // Creates a new file if this is the first write. -func (c *Catalog) writeToCatalogFileLocked(ve *versionEdit) error { +func (c *Catalog) writeToCatalogFileLocked(ve *VersionEdit) error { c.mu.rotationHelper.AddRecord(int64(len(ve.NewObjects) + len(ve.DeletedObjects))) snapshotSize := int64(len(c.mu.objects)) @@ -337,8 +335,8 @@ func (c *Catalog) createNewCatalogFileLocked() (outErr error) { } recWriter := record.NewWriter(file) err = func() error { - // Create a versionEdit that gets us from an empty catalog to the current state. - var ve versionEdit + // Create a VersionEdit that gets us from an empty catalog to the current state. + var ve VersionEdit ve.CreatorID = c.mu.creatorID ve.NewObjects = make([]RemoteObjectMetadata, 0, len(c.mu.objects)) for _, meta := range c.mu.objects { @@ -375,7 +373,7 @@ func (c *Catalog) createNewCatalogFileLocked() (outErr error) { return nil } -func writeRecord(ve *versionEdit, file vfs.File, recWriter *record.Writer) error { +func writeRecord(ve *VersionEdit, file vfs.File, recWriter *record.Writer) error { w, err := recWriter.Next() if err != nil { return err diff --git a/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/remoteobjcat/version_edit.go b/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/remoteobjcat/version_edit.go index a0423dca5..44552f5b6 100644 --- a/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/remoteobjcat/version_edit.go +++ b/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/remoteobjcat/version_edit.go @@ -11,15 +11,16 @@ import ( "github.com/cockroachdb/errors" "github.com/cockroachdb/pebble/internal/base" + "github.com/cockroachdb/pebble/internal/invariants" "github.com/cockroachdb/pebble/objstorage" "github.com/cockroachdb/pebble/objstorage/remote" ) -// versionEdit is a modification to the remote object state which can be encoded +// VersionEdit is a modification to the remote object state which can be encoded // into a record. // // TODO(radu): consider adding creation and deletion time for debugging purposes. -type versionEdit struct { +type VersionEdit struct { NewObjects []RemoteObjectMetadata DeletedObjects []base.DiskFileNum CreatorID objstorage.CreatorID @@ -69,7 +70,7 @@ func fileTypeToObjType(fileType base.FileType) (uint64, error) { } // Encode encodes an edit to the specified writer. -func (v *versionEdit) Encode(w io.Writer) error { +func (v *VersionEdit) Encode(w io.Writer) error { buf := make([]byte, 0, binary.MaxVarintLen64*(len(v.NewObjects)*10+len(v.DeletedObjects)*2+2)) for _, meta := range v.NewObjects { objType, err := fileTypeToObjType(meta.FileType) @@ -107,7 +108,7 @@ func (v *versionEdit) Encode(w io.Writer) error { } // Decode decodes an edit from the specified reader. -func (v *versionEdit) Decode(r io.Reader) error { +func (v *VersionEdit) Decode(r io.Reader) error { br, ok := r.(io.ByteReader) if !ok { br = bufio.NewReader(r) @@ -225,3 +226,29 @@ func decodeString(br io.ByteReader) (string, error) { } var errCorruptCatalog = base.CorruptionErrorf("pebble: corrupt remote object catalog") + +// Apply the version edit to a creator ID and a map of objects. +func (v *VersionEdit) Apply( + creatorID *objstorage.CreatorID, objects map[base.DiskFileNum]RemoteObjectMetadata, +) error { + if v.CreatorID.IsSet() { + *creatorID = v.CreatorID + } + for _, meta := range v.NewObjects { + if invariants.Enabled { + if _, exists := objects[meta.FileNum]; exists { + return errors.AssertionFailedf("version edit adds existing object %s", meta.FileNum) + } + } + objects[meta.FileNum] = meta + } + for _, fileNum := range v.DeletedObjects { + if invariants.Enabled { + if _, exists := objects[fileNum]; !exists { + return errors.AssertionFailedf("version edit deletes non-existent object %s", fileNum) + } + } + delete(objects, fileNum) + } + return nil +} diff --git a/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/shared_writable.go b/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/shared_writable.go index e4aecda69..5e8d45ad2 100644 --- a/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/shared_writable.go +++ b/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/shared_writable.go @@ -10,9 +10,16 @@ import ( "github.com/cockroachdb/pebble/objstorage" ) +// NewRemoteWritable creates an objstorage.Writable out of an io.WriteCloser. +func NewRemoteWritable(obj io.WriteCloser) objstorage.Writable { + return &sharedWritable{storageWriter: obj} +} + // sharedWritable is a very simple implementation of Writable on top of the // WriteCloser returned by remote.Storage.CreateObject. type sharedWritable struct { + // Either both p and meta must be unset / zero values, or both must be set. + // The case where both are unset is true only in tests. p *provider meta objstorage.ObjectMetadata storageWriter io.WriteCloser @@ -36,9 +43,11 @@ func (w *sharedWritable) Finish() error { } // Create the marker object. - if err := w.p.sharedCreateRef(w.meta); err != nil { - w.Abort() - return err + if w.p != nil { + if err := w.p.sharedCreateRef(w.meta); err != nil { + w.Abort() + return err + } } return nil } @@ -49,6 +58,8 @@ func (w *sharedWritable) Abort() { _ = w.storageWriter.Close() w.storageWriter = nil } - w.p.removeMetadata(w.meta.DiskFileNum) + if w.p != nil { + w.p.removeMetadata(w.meta.DiskFileNum) + } // TODO(radu): delete the object if it was created. } diff --git a/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/sharedcache/shared_cache.go b/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/sharedcache/shared_cache.go index 4985ea475..112e362c0 100644 --- a/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/sharedcache/shared_cache.go +++ b/vendor/github.com/cockroachdb/pebble/objstorage/objstorageprovider/sharedcache/shared_cache.go @@ -11,29 +11,98 @@ import ( "math/bits" "sync" "sync/atomic" + "time" "github.com/cockroachdb/errors" "github.com/cockroachdb/pebble/internal/base" "github.com/cockroachdb/pebble/internal/invariants" "github.com/cockroachdb/pebble/objstorage/remote" "github.com/cockroachdb/pebble/vfs" + "github.com/prometheus/client_golang/prometheus" +) + +// Exported to enable exporting from package pebble to enable +// exporting metrics with below buckets in CRDB. +var ( + IOBuckets = prometheus.ExponentialBucketsRange(float64(time.Millisecond*1), float64(10*time.Second), 50) + ChannelWriteBuckets = prometheus.ExponentialBucketsRange(float64(time.Microsecond*1), float64(10*time.Second), 50) ) // Cache is a persistent cache backed by a local filesystem. It is intended // to cache data that is in slower shared storage (e.g. S3), hence the // package name 'sharedcache'. type Cache struct { - shards []shard - logger base.Logger + shards []shard + writeWorkers writeWorkers bm blockMath shardingBlockSize int64 - // TODO(josh): Have a dedicated metrics struct. Right now, this - // is just for testing. - misses atomic.Int32 - - writeWorkers writeWorkers + logger base.Logger + metrics internalMetrics +} + +// Metrics is a struct containing metrics exported by the secondary cache. +// TODO(josh): Reconsider the set of metrics exported by the secondary cache +// before we release the secondary cache to users. We choose to export many metrics +// right now, so we learn a lot from the benchmarking we are doing over the 23.2 +// cycle. +type Metrics struct { + // The number of sstable bytes stored in the cache. + Size int64 + // The count of cache blocks in the cache (not sstable blocks). + Count int64 + + // The number of calls to ReadAt. + TotalReads int64 + // The number of calls to ReadAt that require reading data from 2+ shards. + MultiShardReads int64 + // The number of calls to ReadAt that require reading data from 2+ cache blocks. + MultiBlockReads int64 + // The number of calls to ReadAt where all data returned was read from the cache. + ReadsWithFullHit int64 + // The number of calls to ReadAt where some data returned was read from the cache. + ReadsWithPartialHit int64 + // The number of calls to ReadAt where no data returned was read from the cache. + ReadsWithNoHit int64 + + // The number of times a cache block was evicted from the cache. + Evictions int64 + // The number of times writing a cache block to the cache failed. + WriteBackFailures int64 + + // The latency of calls to get some data from the cache. + GetLatency prometheus.Histogram + // The latency of reads of a single cache block from disk. + DiskReadLatency prometheus.Histogram + // The latency of writing data to write back to the cache to a channel. + // Generally should be low, but if the channel is full, could be high. + QueuePutLatency prometheus.Histogram + // The latency of calls to put some data read from block storage into the cache. + PutLatency prometheus.Histogram + // The latency of writes of a single cache block to disk. + DiskWriteLatency prometheus.Histogram +} + +// See docs at Metrics. +type internalMetrics struct { + count atomic.Int64 + + totalReads atomic.Int64 + multiShardReads atomic.Int64 + multiBlockReads atomic.Int64 + readsWithFullHit atomic.Int64 + readsWithPartialHit atomic.Int64 + readsWithNoHit atomic.Int64 + + evictions atomic.Int64 + writeBackFailures atomic.Int64 + + getLatency prometheus.Histogram + diskReadLatency prometheus.Histogram + queuePutLatency prometheus.Histogram + putLatency prometheus.Histogram + diskWriteLatency prometheus.Histogram } const ( @@ -61,25 +130,36 @@ func Open( sizeBytes int64, numShards int, ) (*Cache, error) { - min := shardingBlockSize * int64(numShards) - if sizeBytes < min { - return nil, errors.Errorf("cache size %d lower than min %d", sizeBytes, min) + if minSize := shardingBlockSize * int64(numShards); sizeBytes < minSize { + // Up the size so that we have one block per shard. In practice, this should + // only happen in tests. + sizeBytes = minSize } - sc := &Cache{ + c := &Cache{ logger: logger, bm: makeBlockMath(blockSize), shardingBlockSize: shardingBlockSize, } - sc.shards = make([]shard, numShards) + c.shards = make([]shard, numShards) blocksPerShard := sizeBytes / int64(numShards) / int64(blockSize) - for i := range sc.shards { - if err := sc.shards[i].init(fs, fsDir, i, blocksPerShard, blockSize, shardingBlockSize); err != nil { + for i := range c.shards { + if err := c.shards[i].init(c, fs, fsDir, i, blocksPerShard, blockSize, shardingBlockSize); err != nil { return nil, err } } - sc.writeWorkers.Start(sc, numShards*writeWorkersPerShard) - return sc, nil + + c.writeWorkers.Start(c, numShards*writeWorkersPerShard) + + c.metrics.getLatency = prometheus.NewHistogram(prometheus.HistogramOpts{Buckets: IOBuckets}) + c.metrics.diskReadLatency = prometheus.NewHistogram(prometheus.HistogramOpts{Buckets: IOBuckets}) + c.metrics.putLatency = prometheus.NewHistogram(prometheus.HistogramOpts{Buckets: IOBuckets}) + c.metrics.diskWriteLatency = prometheus.NewHistogram(prometheus.HistogramOpts{Buckets: IOBuckets}) + + // Measures a channel write, so lower min. + c.metrics.queuePutLatency = prometheus.NewHistogram(prometheus.HistogramOpts{Buckets: ChannelWriteBuckets}) + + return c, nil } // Close closes the cache. Methods such as ReadAt should not be called after Close is @@ -97,6 +177,28 @@ func (c *Cache) Close() error { return retErr } +// Metrics return metrics for the cache. Callers should not mutate +// the returned histograms, which are pointer types. +func (c *Cache) Metrics() Metrics { + return Metrics{ + Count: c.metrics.count.Load(), + Size: c.metrics.count.Load() * int64(c.bm.BlockSize()), + TotalReads: c.metrics.totalReads.Load(), + MultiShardReads: c.metrics.multiShardReads.Load(), + MultiBlockReads: c.metrics.multiBlockReads.Load(), + ReadsWithFullHit: c.metrics.readsWithFullHit.Load(), + ReadsWithPartialHit: c.metrics.readsWithPartialHit.Load(), + ReadsWithNoHit: c.metrics.readsWithNoHit.Load(), + Evictions: c.metrics.evictions.Load(), + WriteBackFailures: c.metrics.writeBackFailures.Load(), + GetLatency: c.metrics.getLatency, + DiskReadLatency: c.metrics.diskReadLatency, + QueuePutLatency: c.metrics.queuePutLatency, + PutLatency: c.metrics.putLatency, + DiskWriteLatency: c.metrics.diskWriteLatency, + } +} + // ReadFlags contains options for Cache.ReadAt. type ReadFlags struct { // ReadOnly instructs ReadAt to not write any new data into the cache; it is @@ -115,6 +217,7 @@ func (c *Cache) ReadAt( objSize int64, flags ReadFlags, ) error { + c.metrics.totalReads.Add(1) if ofs >= objSize { if invariants.Enabled { panic(fmt.Sprintf("invalid ReadAt offset %v %v", ofs, objSize)) @@ -124,14 +227,22 @@ func (c *Cache) ReadAt( // TODO(radu): for compaction reads, we may not want to read from the cache at // all. { + start := time.Now() n, err := c.get(fileNum, p, ofs) + c.metrics.getLatency.Observe(float64(time.Since(start))) if err != nil { return err } if n == len(p) { // Everything was in cache! + c.metrics.readsWithFullHit.Add(1) return nil } + if n == 0 { + c.metrics.readsWithNoHit.Add(1) + } else { + c.metrics.readsWithPartialHit.Add(1) + } // Note this. The below code does not need the original ofs, as with the earlier // reading from the cache done, the relevant offset is ofs + int64(n). Same with p. @@ -145,8 +256,6 @@ func (c *Cache) ReadAt( } } - c.misses.Add(1) - if flags.ReadOnly { return objReader.ReadAt(ctx, p, ofs) } @@ -173,7 +282,10 @@ func (c *Cache) ReadAt( } copy(p, adjustedP[sizeOfOffAdjustment:]) + start := time.Now() c.writeWorkers.QueueWrite(fileNum, adjustedP, adjustedOfs) + c.metrics.queuePutLatency.Observe(float64(time.Since(start))) + return nil } @@ -188,6 +300,7 @@ func (c *Cache) get(fileNum base.DiskFileNum, p []byte, ofs int64) (n int, _ err // The data extent might cross shard boundaries, hence the loop. In the hot // path, max two iterations of this loop will be executed, since reads are sized // in units of sstable block size. + var multiShard bool for { shard := c.getShard(fileNum, ofs+int64(n)) cappedLen := len(p[n:]) @@ -208,6 +321,10 @@ func (c *Cache) get(fileNum base.DiskFileNum, p []byte, ofs int64) (n int, _ err return n, nil } // Data extent crosses shard boundary, continue with next shard. + if !multiShard { + c.metrics.multiShardReads.Add(1) + multiShard = true + } } } @@ -257,6 +374,7 @@ func (c *Cache) getShard(fileNum base.DiskFileNum, ofs int64) *shard { } type shard struct { + cache *Cache file vfs.File sizeInBlocks int64 bm blockMath @@ -311,9 +429,16 @@ const ( ) func (s *shard) init( - fs vfs.FS, fsDir string, shardIdx int, sizeInBlocks int64, blockSize int, shardingBlockSize int64, + cache *Cache, + fs vfs.FS, + fsDir string, + shardIdx int, + sizeInBlocks int64, + blockSize int, + shardingBlockSize int64, ) error { *s = shard{ + cache: cache, sizeInBlocks: sizeInBlocks, } if blockSize < 1024 || shardingBlockSize%int64(blockSize) != 0 { @@ -431,6 +556,7 @@ func (s *shard) get(fileNum base.DiskFileNum, p []byte, ofs int64) (n int, _ err // The data extent might cross cache block boundaries, hence the loop. In the hot // path, max two iterations of this loop will be executed, since reads are sized // in units of sstable block size. + var multiBlock bool for { k := logicalBlockID{ filenum: fileNum, @@ -469,11 +595,15 @@ func (s *shard) get(fileNum base.DiskFileNum, p []byte, ofs int64) (n int, _ err } if len(p[n:]) <= readSize { + start := time.Now() numRead, err := s.file.ReadAt(p[n:], readAt) + s.cache.metrics.diskReadLatency.Observe(float64(time.Since(start))) s.dropReadLock(cacheBlockIdx) return n + numRead, err } + start := time.Now() numRead, err := s.file.ReadAt(p[n:n+readSize], readAt) + s.cache.metrics.diskReadLatency.Observe(float64(time.Since(start))) s.dropReadLock(cacheBlockIdx) if err != nil { return 0, err @@ -481,6 +611,11 @@ func (s *shard) get(fileNum base.DiskFileNum, p []byte, ofs int64) (n int, _ err // Note that numRead == readSize, since we checked for an error above. n += numRead + + if !multiBlock { + s.cache.metrics.multiBlockReads.Add(1) + multiBlock = true + } } } @@ -526,8 +661,6 @@ func (s *shard) set(fileNum base.DiskFileNum, p []byte, ofs int64) error { continue } - // Determine cache block index by looking at the free list and randomly evicting if - // it is empty. var cacheBlockIdx cacheBlockIndex if s.mu.freeHead == invalidBlockIndex { if invariants.Enabled && s.mu.lruHead == invalidBlockIndex { @@ -550,9 +683,11 @@ func (s *shard) set(fileNum base.DiskFileNum, p []byte, ofs int64) error { return errors.New("no block to evict so skipping write to cache") } } + s.cache.metrics.evictions.Add(1) s.lruUnlink(cacheBlockIdx) delete(s.mu.where, s.mu.blocks[cacheBlockIdx].logical) } else { + s.cache.metrics.count.Add(1) cacheBlockIdx = s.freePop() } @@ -569,7 +704,9 @@ func (s *shard) set(fileNum base.DiskFileNum, p []byte, ofs int64) error { writeSize = len(p[n:]) } + start := time.Now() _, err := s.file.WriteAt(p[n:n+writeSize], writeAt) + s.cache.metrics.diskWriteLatency.Observe(float64(time.Since(start))) if err != nil { // Free the block. s.mu.Lock() @@ -729,10 +866,13 @@ func (w *writeWorkers) Start(c *Cache, numWorkers int) { } // TODO(radu): set() can perform multiple writes; perhaps each one // should be its own task. - if err := c.set(task.fileNum, task.p, task.offset); err != nil { - // TODO(radu): expose as metric. + start := time.Now() + err := c.set(task.fileNum, task.p, task.offset) + c.metrics.putLatency.Observe(float64(time.Since(start))) + if err != nil { + c.metrics.writeBackFailures.Add(1) // TODO(radu): throttle logs. - c.logger.Infof("writing back to cache after miss failed: %v", err) + c.logger.Errorf("writing back to cache after miss failed: %v", err) } } } diff --git a/vendor/github.com/cockroachdb/pebble/objstorage/remote/storage.go b/vendor/github.com/cockroachdb/pebble/objstorage/remote/storage.go index b0f8a76b7..891876441 100644 --- a/vendor/github.com/cockroachdb/pebble/objstorage/remote/storage.go +++ b/vendor/github.com/cockroachdb/pebble/objstorage/remote/storage.go @@ -7,6 +7,8 @@ package remote import ( "context" "io" + + "github.com/cockroachdb/redact" ) // Locator is an opaque string identifying a remote.Storage implementation. @@ -16,12 +18,53 @@ import ( // RemoteObjectBacking; they can also appear in error messages. type Locator string +// SafeFormat implements redact.SafeFormatter. +func (l Locator) SafeFormat(w redact.SafePrinter, _ rune) { + w.Printf("%s", redact.SafeString(l)) +} + // StorageFactory is used to return Storage implementations based on locators. A // Pebble store that uses shared storage is configured with a StorageFactory. type StorageFactory interface { CreateStorage(locator Locator) (Storage, error) } +// SharedLevelsStart denotes the highest (i.e. lowest numbered) level that will +// have sstables shared across Pebble instances when doing skip-shared +// iteration (see db.ScanInternal) or shared file ingestion (see +// db.IngestAndExcise). +const SharedLevelsStart = 5 + +// CreateOnSharedStrategy specifies what table files should be created on shared +// storage. For use with CreateOnShared in options. +type CreateOnSharedStrategy int + +const ( + // CreateOnSharedNone denotes no files being created on shared storage. + CreateOnSharedNone CreateOnSharedStrategy = iota + // CreateOnSharedLower denotes the creation of files in lower levels of the + // LSM (specifically, L5 and L6 as they're below SharedLevelsStart) on + // shared storage, and higher levels on local storage. + CreateOnSharedLower + // CreateOnSharedAll denotes the creation of all sstables on shared storage. + CreateOnSharedAll +) + +// ShouldCreateShared returns whether new table files at the specified level +// should be created on shared storage. +func ShouldCreateShared(strategy CreateOnSharedStrategy, level int) bool { + switch strategy { + case CreateOnSharedAll: + return true + case CreateOnSharedNone: + return false + case CreateOnSharedLower: + return level >= SharedLevelsStart + default: + panic("unexpected CreateOnSharedStrategy value") + } +} + // Storage is an interface for a blob storage driver. This is lower-level // than an FS-like interface, however FS/File-like abstractions can be built on // top of these methods. diff --git a/vendor/github.com/cockroachdb/pebble/open.go b/vendor/github.com/cockroachdb/pebble/open.go index ecdd9843c..09d223331 100644 --- a/vendor/github.com/cockroachdb/pebble/open.go +++ b/vendor/github.com/cockroachdb/pebble/open.go @@ -6,13 +6,14 @@ package pebble import ( "bytes" + "cmp" "context" "encoding/binary" "fmt" "io" "math" "os" - "sort" + "slices" "sync/atomic" "time" @@ -21,6 +22,7 @@ import ( "github.com/cockroachdb/pebble/internal/arenaskl" "github.com/cockroachdb/pebble/internal/base" "github.com/cockroachdb/pebble/internal/cache" + "github.com/cockroachdb/pebble/internal/constants" "github.com/cockroachdb/pebble/internal/invariants" "github.com/cockroachdb/pebble/internal/manifest" "github.com/cockroachdb/pebble/internal/manual" @@ -37,11 +39,23 @@ const ( // The max batch size is limited by the uint32 offsets stored in // internal/batchskl.node, DeferredBatchOp, and flushableBatchEntry. - maxBatchSize = 4 << 30 // 4 GB + // + // We limit the size to MaxUint32 (just short of 4GB) so that the exclusive + // end of an allocation fits in uint32. + // + // On 32-bit systems, slices are naturally limited to MaxInt (just short of + // 2GB). + maxBatchSize = constants.MaxUint32OrInt // The max memtable size is limited by the uint32 offsets stored in // internal/arenaskl.node, DeferredBatchOp, and flushableBatchEntry. - maxMemTableSize = 4 << 30 // 4 GB + // + // We limit the size to MaxUint32 (just short of 4GB) so that the exclusive + // end of an allocation fits in uint32. + // + // On 32-bit systems, slices are naturally limited to MaxInt (just short of + // 2GB). + maxMemTableSize = constants.MaxUint32OrInt ) // TableCacheSize can be used to determine the table @@ -76,7 +90,7 @@ func Open(dirname string, opts *Options) (db *DB, _ error) { // Open the database and WAL directories first. walDirname, dataDir, walDir, err := prepareAndOpenDirs(dirname, opts) if err != nil { - return nil, err + return nil, errors.Wrapf(err, "error opening database at %q", dirname) } defer func() { if db == nil { @@ -160,7 +174,7 @@ func Open(dirname string, opts *Options) (db *DB, _ error) { merge: opts.Merger.Merge, split: opts.Comparer.Split, abbreviatedKey: opts.Comparer.AbbreviatedKey, - largeBatchThreshold: (opts.MemTableSize - int(memTableEmptySize)) / 2, + largeBatchThreshold: (opts.MemTableSize - uint64(memTableEmptySize)) / 2, fileLock: fileLock, dataDir: dataDir, walDir: walDir, @@ -170,7 +184,6 @@ func Open(dirname string, opts *Options) (db *DB, _ error) { } d.mu.versions = &versionSet{} d.diskAvailBytes.Store(math.MaxUint64) - d.mu.versions.diskAvailBytes = d.getDiskAvailableBytesCached defer func() { // If an error or panic occurs during open, attempt to release the manually @@ -222,9 +235,10 @@ func Open(dirname string, opts *Options) (db *DB, _ error) { d.mu.compact.inProgress = make(map[*compaction]struct{}) d.mu.compact.noOngoingFlushStartTime = time.Now() d.mu.snapshots.init() - // logSeqNum is the next sequence number that will be assigned. Start - // assigning sequence numbers from base.SeqNumStart to leave room for reserved - // sequence numbers (see comments around SeqNumStart). + // logSeqNum is the next sequence number that will be assigned. + // Start assigning sequence numbers from base.SeqNumStart to leave + // room for reserved sequence numbers (see comments around + // SeqNumStart). d.mu.versions.logSeqNum.Store(base.SeqNumStart) d.mu.formatVers.vers.Store(uint64(formatVersion)) d.mu.formatVers.marker = formatVersionMarker @@ -247,7 +261,7 @@ func Open(dirname string, opts *Options) (db *DB, _ error) { } // Create the DB. - if err := d.mu.versions.create(jobID, dirname, opts, manifestMarker, setCurrent, &d.mu.Mutex); err != nil { + if err := d.mu.versions.create(jobID, dirname, opts, manifestMarker, setCurrent, d.FormatMajorVersion, &d.mu.Mutex); err != nil { return nil, err } } else { @@ -255,7 +269,7 @@ func Open(dirname string, opts *Options) (db *DB, _ error) { return nil, errors.Wrapf(ErrDBAlreadyExists, "dirname=%q", dirname) } // Load the version set. - if err := d.mu.versions.load(dirname, opts, manifestFileNum.FileNum(), manifestMarker, setCurrent, &d.mu.Mutex); err != nil { + if err := d.mu.versions.load(dirname, opts, manifestFileNum, manifestMarker, setCurrent, d.FormatMajorVersion, &d.mu.Mutex); err != nil { return nil, err } if opts.ErrorIfNotPristine { @@ -300,7 +314,7 @@ func Open(dirname string, opts *Options) (db *DB, _ error) { providerSettings.Remote.StorageFactory = opts.Experimental.RemoteStorage providerSettings.Remote.CreateOnShared = opts.Experimental.CreateOnShared providerSettings.Remote.CreateOnSharedLocator = opts.Experimental.CreateOnSharedLocator - providerSettings.Remote.CacheSizeBytes = opts.Experimental.SecondaryCacheSize + providerSettings.Remote.CacheSizeBytes = opts.Experimental.SecondaryCacheSizeBytes d.objProvider, err = objstorageprovider.Open(providerSettings) if err != nil { @@ -317,13 +331,15 @@ func Open(dirname string, opts *Options) (db *DB, _ error) { } tableCacheSize := TableCacheSize(opts.MaxOpenFiles) - d.tableCache = newTableCacheContainer(opts.TableCache, d.cacheID, d.objProvider, d.opts, tableCacheSize) + d.tableCache = newTableCacheContainer( + opts.TableCache, d.cacheID, d.objProvider, d.opts, tableCacheSize, + &sstable.CategoryStatsCollector{}) d.newIters = d.tableCache.newIters d.tableNewRangeKeyIter = d.tableCache.newRangeKeyIter // Replay any newer log files than the ones named in the manifest. type fileNumAndName struct { - num FileNum + num base.DiskFileNum name string } var logFiles []fileNumAndName @@ -337,14 +353,14 @@ func Open(dirname string, opts *Options) (db *DB, _ error) { // Don't reuse any obsolete file numbers to avoid modifying an // ingested sstable's original external file. - if d.mu.versions.nextFileNum <= fn.FileNum() { - d.mu.versions.nextFileNum = fn.FileNum() + 1 + if d.mu.versions.nextFileNum <= uint64(fn.FileNum()) { + d.mu.versions.nextFileNum = uint64(fn.FileNum()) + 1 } switch ft { case fileTypeLog: - if fn.FileNum() >= d.mu.versions.minUnflushedLogNum { - logFiles = append(logFiles, fileNumAndName{fn.FileNum(), filename}) + if fn >= d.mu.versions.minUnflushedLogNum { + logFiles = append(logFiles, fileNumAndName{fn, filename}) } if d.logRecycler.minRecycleLogNum <= fn.FileNum() { d.logRecycler.minRecycleLogNum = fn.FileNum() + 1 @@ -368,6 +384,15 @@ func Open(dirname string, opts *Options) (db *DB, _ error) { } } + // Ratchet d.mu.versions.nextFileNum ahead of all known objects in the + // objProvider. This avoids FileNum collisions with obsolete sstables. + objects := d.objProvider.List() + for _, obj := range objects { + if d.mu.versions.nextFileNum <= uint64(obj.DiskFileNum) { + d.mu.versions.nextFileNum = uint64(obj.DiskFileNum) + 1 + } + } + // Validate the most-recent OPTIONS file, if there is one. var strictWALTail bool if previousOptionsFilename != "" { @@ -378,8 +403,8 @@ func Open(dirname string, opts *Options) (db *DB, _ error) { } } - sort.Slice(logFiles, func(i, j int) bool { - return logFiles[i].num < logFiles[j].num + slices.SortFunc(logFiles, func(a, b fileNumAndName) int { + return cmp.Compare(a.num, b.num) }) var ve versionEdit @@ -401,7 +426,7 @@ func Open(dirname string, opts *Options) (db *DB, _ error) { if !d.opts.ReadOnly { // Create an empty .log file. - newLogNum := d.mu.versions.getNextFileNum() + newLogNum := d.mu.versions.getNextDiskFileNum() // This logic is slightly different than RocksDB's. Specifically, RocksDB // sets MinUnflushedLogNum to max-recovered-log-num + 1. We set it to the @@ -423,8 +448,8 @@ func Open(dirname string, opts *Options) (db *DB, _ error) { entry.readerUnrefLocked(true) } - newLogName := base.MakeFilepath(opts.FS, d.walDirname, fileTypeLog, newLogNum.DiskFileNum()) - d.mu.log.queue = append(d.mu.log.queue, fileInfo{fileNum: newLogNum.DiskFileNum(), fileSize: 0}) + newLogName := base.MakeFilepath(opts.FS, d.walDirname, fileTypeLog, newLogNum) + d.mu.log.queue = append(d.mu.log.queue, fileInfo{fileNum: newLogNum, fileSize: 0}) logFile, err := opts.FS.Create(newLogName) if err != nil { return nil, err @@ -475,7 +500,7 @@ func Open(dirname string, opts *Options) (db *DB, _ error) { if !d.opts.ReadOnly { // Write the current options to disk. - d.optionsFileNum = d.mu.versions.getNextFileNum().DiskFileNum() + d.optionsFileNum = d.mu.versions.getNextDiskFileNum() tmpPath := base.MakeFilepath(opts.FS, dirname, fileTypeTemp, d.optionsFileNum) optionsPath := base.MakeFilepath(opts.FS, dirname, fileTypeOptions, d.optionsFileNum) @@ -668,7 +693,12 @@ func GetVersion(dir string, fs vfs.FS) (string, error) { // d.mu must be held when calling this, but the mutex may be dropped and // re-acquired during the course of this method. func (d *DB) replayWAL( - jobID int, ve *versionEdit, fs vfs.FS, filename string, logNum FileNum, strictWALTail bool, + jobID int, + ve *versionEdit, + fs vfs.FS, + filename string, + logNum base.DiskFileNum, + strictWALTail bool, ) (toFlush flushableList, maxSeqNum uint64, err error) { file, err := fs.Open(filename) if err != nil { @@ -773,7 +803,8 @@ func (d *DB) replayWAL( // Specify Batch.db so that Batch.SetRepr will compute Batch.memTableSize // which is used below. - b = Batch{db: d} + b = Batch{} + b.db = d b.SetRepr(buf.Bytes()) seqNum := b.SeqNum() maxSeqNum = seqNum + uint64(b.Count()) @@ -895,7 +926,7 @@ func (d *DB) replayWAL( flushMem() // Make a copy of the data slice since it is currently owned by buf and will // be reused in the next iteration. - b.data = append([]byte(nil), b.data...) + b.data = slices.Clone(b.data) b.flushable = newFlushableBatch(&b, d.opts.Comparer) entry := d.newFlushableEntry(b.flushable, logNum, b.SeqNum()) // Disable memory accounting by adding a reader ref that will never be @@ -1093,10 +1124,14 @@ var ErrDBAlreadyExists = errors.New("pebble: database already exists") // Note that errors can be wrapped with more details; use errors.Is(). var ErrDBNotPristine = errors.New("pebble: database already exists and is not pristine") -func checkConsistency(v *manifest.Version, dirname string, objProvider objstorage.Provider) error { - var buf bytes.Buffer - var args []interface{} +// IsCorruptionError returns true if the given error indicates database +// corruption. +func IsCorruptionError(err error) bool { + return errors.Is(err, base.ErrCorruption) +} +func checkConsistency(v *manifest.Version, dirname string, objProvider objstorage.Provider) error { + var errs []error dedup := make(map[base.DiskFileNum]struct{}) for level, files := range v.Levels { iter := files.Iter() @@ -1108,34 +1143,29 @@ func checkConsistency(v *manifest.Version, dirname string, objProvider objstorag dedup[backingState.DiskFileNum] = struct{}{} fileNum := backingState.DiskFileNum fileSize := backingState.Size - // We allow foreign objects to have a mismatch between sizes. This is - // because we might skew the backing size stored by our objprovider - // to prevent us from over-prioritizing this file for compaction. + // We skip over remote objects; those are instead checked asynchronously + // by the table stats loading job. meta, err := objProvider.Lookup(base.FileTypeTable, fileNum) var size int64 if err == nil { - if objProvider.IsForeign(meta) { + if meta.IsRemote() { continue } size, err = objProvider.Size(meta) } if err != nil { - buf.WriteString("L%d: %s: %v\n") - args = append(args, errors.Safe(level), errors.Safe(fileNum), err) + errs = append(errs, errors.Wrapf(err, "L%d: %s", errors.Safe(level), fileNum)) continue } if size != int64(fileSize) { - buf.WriteString("L%d: %s: object size mismatch (%s): %d (disk) != %d (MANIFEST)\n") - args = append(args, errors.Safe(level), errors.Safe(fileNum), objProvider.Path(meta), - errors.Safe(size), errors.Safe(fileSize)) + errs = append(errs, errors.Errorf( + "L%d: %s: object size mismatch (%s): %d (disk) != %d (MANIFEST)", + errors.Safe(level), fileNum, objProvider.Path(meta), + errors.Safe(size), errors.Safe(fileSize))) continue } } } - - if buf.Len() == 0 { - return nil - } - return errors.Errorf(buf.String(), args...) + return errors.Join(errs...) } diff --git a/vendor/github.com/cockroachdb/pebble/options.go b/vendor/github.com/cockroachdb/pebble/options.go index ea89f9391..8a2c609ef 100644 --- a/vendor/github.com/cockroachdb/pebble/options.go +++ b/vendor/github.com/cockroachdb/pebble/options.go @@ -20,6 +20,7 @@ import ( "github.com/cockroachdb/pebble/internal/keyspan" "github.com/cockroachdb/pebble/internal/manifest" "github.com/cockroachdb/pebble/objstorage/remote" + "github.com/cockroachdb/pebble/rangekey" "github.com/cockroachdb/pebble/sstable" "github.com/cockroachdb/pebble/vfs" ) @@ -118,6 +119,16 @@ type IterOptions struct { // false to skip scanning. This function must be thread-safe since the same // function can be used by multiple iterators, if the iterator is cloned. TableFilter func(userProps map[string]string) bool + // SkipPoint may be used to skip over point keys that don't match an + // arbitrary predicate during iteration. If set, the Iterator invokes + // SkipPoint for keys encountered. If SkipPoint returns true, the iterator + // will skip the key without yielding it to the iterator operation in + // progress. + // + // SkipPoint must be a pure function and always return the same result when + // provided the same arguments. The iterator may call SkipPoint multiple + // times for the same user key. + SkipPoint func(userKey []byte) bool // PointKeyFilters can be used to avoid scanning tables and blocks in tables // when iterating over point keys. This slice represents an intersection // across all filters, i.e., all filters must indicate that the block is @@ -175,6 +186,9 @@ type IterOptions struct { // existing is not low or if we just expect a one-time Seek (where loading the // data block directly is better). UseL6Filters bool + // CategoryAndQoS is used for categorized iterator stats. This should not be + // changed by calling SetOptions. + sstable.CategoryAndQoS // Internal options. @@ -231,24 +245,36 @@ func (o *IterOptions) getLogger() Logger { } // SpanIterOptions creates a SpanIterOptions from this IterOptions. -func (o *IterOptions) SpanIterOptions(level manifest.Level) keyspan.SpanIterOptions { +func (o *IterOptions) SpanIterOptions() keyspan.SpanIterOptions { if o == nil { - return keyspan.SpanIterOptions{Level: level} + return keyspan.SpanIterOptions{} } return keyspan.SpanIterOptions{ RangeKeyFilters: o.RangeKeyFilters, - Level: level, } } // scanInternalOptions is similar to IterOptions, meant for use with // scanInternalIterator. type scanInternalOptions struct { + sstable.CategoryAndQoS IterOptions + visitPointKey func(key *InternalKey, value LazyValue, iterInfo IteratorLevel) error + visitRangeDel func(start, end []byte, seqNum uint64) error + visitRangeKey func(start, end []byte, keys []rangekey.Key) error + visitSharedFile func(sst *SharedSSTMeta) error + // skipSharedLevels skips levels that are shareable (level >= // sharedLevelStart). skipSharedLevels bool + + // includeObsoleteKeys specifies whether keys shadowed by newer internal keys + // are exposed. If false, only one internal key per user key is exposed. + includeObsoleteKeys bool + + // rateLimitFunc is used to limit the amount of bytes read per second. + rateLimitFunc func(key *InternalKey, value LazyValue) error } // RangeKeyMasking configures automatic hiding of point keys by range keys. A @@ -526,7 +552,12 @@ type Options struct { // concurrent compaction is added. This works "on top" of // L0CompactionConcurrency, so the higher of the count of compaction // concurrency slots as determined by the two options is chosen. - CompactionDebtConcurrency int + CompactionDebtConcurrency uint64 + + // IngestSplit, if it returns true, allows for ingest-time splitting of + // existing sstables into two virtual sstables to allow ingestion sstables to + // slot into a lower level than they otherwise would have. + IngestSplit func() bool // ReadCompactionRate controls the frequency of read triggered // compactions by adjusting `AllowedSeeks` in manifest.FileMetadata: @@ -591,10 +622,10 @@ type Options struct { // desired size of each level of the LSM. Defaults to 10. LevelMultiplier int - // MultiLevelCompactionHueristic determines whether to add an additional + // MultiLevelCompactionHeuristic determines whether to add an additional // level to a conventional two level compaction. If nil, a multilevel // compaction will never get triggered. - MultiLevelCompactionHueristic MultiLevelHeuristic + MultiLevelCompactionHeuristic MultiLevelHeuristic // MaxWriterConcurrency is used to indicate the maximum number of // compression workers the compression queue is allowed to use. If @@ -658,19 +689,20 @@ type Options struct { // allows ingestion of external files. RemoteStorage remote.StorageFactory - // If CreateOnShared is true, any new sstables are created on remote storage - // (using CreateOnSharedLocator). These sstables can be shared between - // different Pebble instances; the lifecycle of such objects is managed by - // the cluster. + // If CreateOnShared is non-zero, new sstables are created on remote storage + // (using CreateOnSharedLocator and with the appropriate + // CreateOnSharedStrategy). These sstables can be shared between different + // Pebble instances; the lifecycle of such objects is managed by the + // remote.Storage constructed by options.RemoteStorage. // // Can only be used when RemoteStorage is set (and recognizes // CreateOnSharedLocator). - CreateOnShared bool + CreateOnShared remote.CreateOnSharedStrategy CreateOnSharedLocator remote.Locator - // CacheSizeBytes is the size of the on-disk block cache for objects - // on shared storage. If it is 0, no cache is used. - SecondaryCacheSize int64 + // CacheSizeBytesBytes is the size of the on-disk block cache for objects + // on shared storage in bytes. If it is 0, no cache is used. + SecondaryCacheSizeBytes int64 } // Filters is a map from filter policy name to filter policy. It is used for @@ -785,12 +817,18 @@ type Options struct { // writing the contents of the old one in the // background. MemTableStopWritesThreshold places a hard limit on the size of // the queued MemTables. - MemTableSize int + // + // The default value is 4MB. + MemTableSize uint64 - // Hard limit on the size of queued of MemTables. Writes are stopped when the - // sum of the queued memtable sizes exceeds - // MemTableStopWritesThreshold*MemTableSize. This value should be at least 2 - // or writes will stop whenever a MemTable is being flushed. + // Hard limit on the number of queued of MemTables. Writes are stopped when + // the sum of the queued memtable sizes exceeds: + // MemTableStopWritesThreshold * MemTableSize. + // + // This value should be at least 2 or writes will stop whenever a MemTable is + // being flushed. + // + // The default value is 2. MemTableStopWritesThreshold int // Merger defines the associative merge operation to use for merging values @@ -922,6 +960,10 @@ type Options struct { // A private option to disable stats collection. disableTableStats bool + // testingAlwaysWaitForCleanup is set by some tests to force waiting for + // obsolete file deletion (to make events deterministic). + testingAlwaysWaitForCleanup bool + // fsCloser holds a closer that should be invoked after a DB using these // Options is closed. This is used to automatically stop the // long-running goroutine associated with the disk-health-checking FS. @@ -1033,7 +1075,7 @@ func (o *Options) EnsureDefaults() *Options { o.MaxOpenFiles = 1000 } if o.MemTableSize <= 0 { - o.MemTableSize = 4 << 20 + o.MemTableSize = 4 << 20 // 4 MB } if o.MemTableStopWritesThreshold <= 0 { o.MemTableStopWritesThreshold = 2 @@ -1074,8 +1116,8 @@ func (o *Options) EnsureDefaults() *Options { if o.Experimental.CPUWorkPermissionGranter == nil { o.Experimental.CPUWorkPermissionGranter = defaultCPUWorkGranter{} } - if o.Experimental.MultiLevelCompactionHueristic == nil { - o.Experimental.MultiLevelCompactionHueristic = NoMultiLevel{} + if o.Experimental.MultiLevelCompactionHeuristic == nil { + o.Experimental.MultiLevelCompactionHeuristic = WriteAmpHeuristic{} } o.initMaps() @@ -1215,6 +1257,8 @@ func (o *Options) String() string { fmt.Fprintf(&buf, " wal_bytes_per_sync=%d\n", o.WALBytesPerSync) fmt.Fprintf(&buf, " max_writer_concurrency=%d\n", o.Experimental.MaxWriterConcurrency) fmt.Fprintf(&buf, " force_writer_parallelism=%t\n", o.Experimental.ForceWriterParallelism) + fmt.Fprintf(&buf, " secondary_cache_size_bytes=%d\n", o.Experimental.SecondaryCacheSizeBytes) + fmt.Fprintf(&buf, " create_on_shared=%d\n", o.Experimental.CreateOnShared) // Private options. // @@ -1270,7 +1314,11 @@ func parseOptions(s string, fn func(section, key, value string) error) error { pos := strings.Index(line, "=") if pos < 0 { - return errors.Errorf("pebble: invalid key=value syntax: %s", errors.Safe(line)) + const maxLen = 50 + if len(line) > maxLen { + line = line[:maxLen-3] + "..." + } + return base.CorruptionErrorf("invalid key=value syntax: %q", errors.Safe(line)) } key := strings.TrimSpace(line[:pos]) @@ -1368,7 +1416,7 @@ func (o *Options) Parse(s string, hooks *ParseHooks) error { } } case "compaction_debt_concurrency": - o.Experimental.CompactionDebtConcurrency, err = strconv.Atoi(value) + o.Experimental.CompactionDebtConcurrency, err = strconv.ParseUint(value, 10, 64) case "delete_range_flush_delay": // NB: This is a deprecated serialization of the // `flush_delay_delete_range`. @@ -1433,7 +1481,7 @@ func (o *Options) Parse(s string, hooks *ParseHooks) error { case "max_open_files": o.MaxOpenFiles, err = strconv.Atoi(value) case "mem_table_size": - o.MemTableSize, err = strconv.Atoi(value) + o.MemTableSize, err = strconv.ParseUint(value, 10, 64) case "mem_table_stop_writes_threshold": o.MemTableStopWritesThreshold, err = strconv.Atoi(value) case "min_compaction_rate": @@ -1484,6 +1532,12 @@ func (o *Options) Parse(s string, hooks *ParseHooks) error { o.Experimental.MaxWriterConcurrency, err = strconv.Atoi(value) case "force_writer_parallelism": o.Experimental.ForceWriterParallelism, err = strconv.ParseBool(value) + case "secondary_cache_size_bytes": + o.Experimental.SecondaryCacheSizeBytes, err = strconv.ParseInt(value, 10, 64) + case "create_on_shared": + var createOnSharedInt int64 + createOnSharedInt, err = strconv.ParseInt(value, 10, 64) + o.Experimental.CreateOnShared = remote.CreateOnSharedStrategy(createOnSharedInt) default: if hooks != nil && hooks.SkipUnknown != nil && hooks.SkipUnknown(section+"."+key, value) { return nil diff --git a/vendor/github.com/cockroachdb/pebble/range_keys.go b/vendor/github.com/cockroachdb/pebble/range_keys.go index 6cd3e5875..e46b2bedf 100644 --- a/vendor/github.com/cockroachdb/pebble/range_keys.go +++ b/vendor/github.com/cockroachdb/pebble/range_keys.go @@ -5,6 +5,8 @@ package pebble import ( + "context" + "github.com/cockroachdb/pebble/internal/base" "github.com/cockroachdb/pebble/internal/invariants" "github.com/cockroachdb/pebble/internal/keyspan" @@ -35,53 +37,84 @@ func (i *Iterator) constructRangeKeyIter() { } } - // Next are the flushables: memtables and large batches. - for j := len(i.readState.memtables) - 1; j >= 0; j-- { - mem := i.readState.memtables[j] - // We only need to read from memtables which contain sequence numbers older - // than seqNum. - if logSeqNum := mem.logSeqNum; logSeqNum >= i.seqNum { - continue + if !i.batchOnlyIter { + // Next are the flushables: memtables and large batches. + if i.readState != nil { + for j := len(i.readState.memtables) - 1; j >= 0; j-- { + mem := i.readState.memtables[j] + // We only need to read from memtables which contain sequence numbers older + // than seqNum. + if logSeqNum := mem.logSeqNum; logSeqNum >= i.seqNum { + continue + } + if rki := mem.newRangeKeyIter(&i.opts); rki != nil { + i.rangeKey.iterConfig.AddLevel(rki) + } + } } - if rki := mem.newRangeKeyIter(&i.opts); rki != nil { - i.rangeKey.iterConfig.AddLevel(rki) + + current := i.version + if current == nil { + current = i.readState.current } - } + // Next are the file levels: L0 sub-levels followed by lower levels. - current := i.readState.current - // Next are the file levels: L0 sub-levels followed by lower levels. - // - // Add file-specific iterators for L0 files containing range keys. This is less - // efficient than using levelIters for sublevels of L0 files containing - // range keys, but range keys are expected to be sparse anyway, reducing the - // cost benefit of maintaining a separate L0Sublevels instance for range key - // files and then using it here. - // - // NB: We iterate L0's files in reverse order. They're sorted by - // LargestSeqNum ascending, and we need to add them to the merging iterator - // in LargestSeqNum descending to preserve the merging iterator's invariants - // around Key Trailer order. - iter := current.RangeKeyLevels[0].Iter() - for f := iter.Last(); f != nil; f = iter.Prev() { - spanIter, err := i.newIterRangeKey(f, i.opts.SpanIterOptions(manifest.Level(0))) - if err != nil { - i.rangeKey.iterConfig.AddLevel(&errorKeyspanIter{err: err}) - continue + // Add file-specific iterators for L0 files containing range keys. We + // maintain a separate manifest.LevelMetadata for each level containing only + // files that contain range keys, however we don't compute a separate + // L0Sublevels data structure too. + // + // We first use L0's LevelMetadata to peek and see whether L0 contains any + // range keys at all. If it does, we create a range key level iterator per + // level that contains range keys using the information from L0Sublevels. + // Some sublevels may not contain any range keys, and we need to iterate + // through the fileMetadata to determine that. Since L0's file count should + // not significantly exceed ~1000 files (see L0CompactionFileThreshold), + // this should be okay. + if !current.RangeKeyLevels[0].Empty() { + // L0 contains at least 1 file containing range keys. + // Add level iterators for the L0 sublevels, iterating from newest to + // oldest. + for j := len(current.L0SublevelFiles) - 1; j >= 0; j-- { + iter := current.L0SublevelFiles[j].Iter() + if !containsAnyRangeKeys(iter) { + continue + } + + li := i.rangeKey.iterConfig.NewLevelIter() + li.Init( + i.opts.SpanIterOptions(), + i.cmp, + i.newIterRangeKey, + iter.Filter(manifest.KeyTypeRange), + manifest.L0Sublevel(j), + manifest.KeyTypeRange, + ) + i.rangeKey.iterConfig.AddLevel(li) + } + } + + // Add level iterators for the non-empty non-L0 levels. + for level := 1; level < len(current.RangeKeyLevels); level++ { + if current.RangeKeyLevels[level].Empty() { + continue + } + li := i.rangeKey.iterConfig.NewLevelIter() + spanIterOpts := i.opts.SpanIterOptions() + li.Init(spanIterOpts, i.cmp, i.newIterRangeKey, current.RangeKeyLevels[level].Iter(), + manifest.Level(level), manifest.KeyTypeRange) + i.rangeKey.iterConfig.AddLevel(li) } - i.rangeKey.iterConfig.AddLevel(spanIter) } +} - // Add level iterators for the non-empty non-L0 levels. - for level := 1; level < len(current.RangeKeyLevels); level++ { - if current.RangeKeyLevels[level].Empty() { - continue +func containsAnyRangeKeys(iter manifest.LevelIterator) bool { + for f := iter.First(); f != nil; f = iter.Next() { + if f.HasRangeKeys { + return true } - li := i.rangeKey.iterConfig.NewLevelIter() - spanIterOpts := i.opts.SpanIterOptions(manifest.Level(level)) - li.Init(spanIterOpts, i.cmp, i.newIterRangeKey, current.RangeKeyLevels[level].Iter(), - manifest.Level(level), manifest.KeyTypeRange) - i.rangeKey.iterConfig.AddLevel(li) } + return false } // Range key masking @@ -365,24 +398,24 @@ func (m *rangeKeyMasking) Intersects(prop []byte) (bool, error) { // KeyIsWithinLowerBound implements the limitedBlockPropertyFilter interface // defined in the sstable package. It's used to restrict the masking block // property filter to only applying within the bounds of the active range key. -func (m *rangeKeyMasking) KeyIsWithinLowerBound(ik *InternalKey) bool { +func (m *rangeKeyMasking) KeyIsWithinLowerBound(key []byte) bool { // Invariant: m.maskSpan != nil // - // The provided `ik` is an inclusive lower bound of the block we're + // The provided `key` is an inclusive lower bound of the block we're // considering skipping. - return m.cmp(m.maskSpan.Start, ik.UserKey) <= 0 + return m.cmp(m.maskSpan.Start, key) <= 0 } // KeyIsWithinUpperBound implements the limitedBlockPropertyFilter interface // defined in the sstable package. It's used to restrict the masking block // property filter to only applying within the bounds of the active range key. -func (m *rangeKeyMasking) KeyIsWithinUpperBound(ik *InternalKey) bool { +func (m *rangeKeyMasking) KeyIsWithinUpperBound(key []byte) bool { // Invariant: m.maskSpan != nil // - // The provided `ik` is an *inclusive* upper bound of the block we're + // The provided `key` is an *inclusive* upper bound of the block we're // considering skipping, so the range key's end must be strictly greater // than the block bound for the block to be within bounds. - return m.cmp(m.maskSpan.End, ik.UserKey) > 0 + return m.cmp(m.maskSpan.End, key) > 0 } // lazyCombinedIter implements the internalIterator interface, wrapping a @@ -511,7 +544,11 @@ func (i *lazyCombinedIter) initCombinedIteration( // Initialize the Iterator's interleaving iterator. i.parent.rangeKey.iiter.Init( &i.parent.comparer, i.parent.pointIter, i.parent.rangeKey.rangeKeyIter, - &i.parent.rangeKeyMasking, i.parent.opts.LowerBound, i.parent.opts.UpperBound) + keyspan.InterleavingIterOpts{ + Mask: &i.parent.rangeKeyMasking, + LowerBound: i.parent.opts.LowerBound, + UpperBound: i.parent.opts.UpperBound, + }) // Set the parent's primary iterator to point to the combined, interleaving // iterator that's now initialized with our current state. @@ -658,6 +695,14 @@ func (i *lazyCombinedIter) SetBounds(lower, upper []byte) { i.pointIter.SetBounds(lower, upper) } +func (i *lazyCombinedIter) SetContext(ctx context.Context) { + if i.combinedIterState.initialized { + i.parent.rangeKey.iiter.SetContext(ctx) + return + } + i.pointIter.SetContext(ctx) +} + func (i *lazyCombinedIter) String() string { if i.combinedIterState.initialized { return i.parent.rangeKey.iiter.String() diff --git a/vendor/github.com/cockroachdb/pebble/rangekey/rangekey.go b/vendor/github.com/cockroachdb/pebble/rangekey/rangekey.go index efe7dad38..93e7fbe18 100644 --- a/vendor/github.com/cockroachdb/pebble/rangekey/rangekey.go +++ b/vendor/github.com/cockroachdb/pebble/rangekey/rangekey.go @@ -11,6 +11,9 @@ import ( "github.com/cockroachdb/pebble/sstable" ) +// Fragmenter exports the keyspan.Fragmenter type. +type Fragmenter = keyspan.Fragmenter + // Key exports the keyspan.Key type. type Key = keyspan.Key diff --git a/vendor/github.com/cockroachdb/pebble/record/log_writer.go b/vendor/github.com/cockroachdb/pebble/record/log_writer.go index 4aa5d2d24..3b1fa775f 100644 --- a/vendor/github.com/cockroachdb/pebble/record/log_writer.go +++ b/vendor/github.com/cockroachdb/pebble/record/log_writer.go @@ -323,7 +323,9 @@ var blockPool = sync.Pool{ } // NewLogWriter returns a new LogWriter. -func NewLogWriter(w io.Writer, logNum base.FileNum, logWriterConfig LogWriterConfig) *LogWriter { +func NewLogWriter( + w io.Writer, logNum base.DiskFileNum, logWriterConfig LogWriterConfig, +) *LogWriter { c, _ := w.(io.Closer) s, _ := w.(syncer) r := &LogWriter{ @@ -739,9 +741,7 @@ func (w *LogWriter) emitFragment(n int, p []byte) (remainingP []byte) { if blockSize-b.written.Load() < recyclableHeaderSize { // There is no room for another fragment in the block, so fill the // remaining bytes with zeros and queue the block for flushing. - for i := b.written.Load(); i < blockSize; i++ { - b.buf[i] = 0 - } + clear(b.buf[b.written.Load():]) w.queueBlock() } return p[r:] diff --git a/vendor/github.com/cockroachdb/pebble/record/record.go b/vendor/github.com/cockroachdb/pebble/record/record.go index 9b42a4c51..7b6d52589 100644 --- a/vendor/github.com/cockroachdb/pebble/record/record.go +++ b/vendor/github.com/cockroachdb/pebble/record/record.go @@ -187,7 +187,7 @@ type Reader struct { // NewReader returns a new reader. If the file contains records encoded using // the recyclable record format, then the log number in those records must // match the specified logNum. -func NewReader(r io.Reader, logNum base.FileNum) *Reader { +func NewReader(r io.Reader, logNum base.DiskFileNum) *Reader { return &Reader{ r: r, logNum: uint32(logNum), @@ -549,9 +549,7 @@ func (w *Writer) Next() (io.Writer, error) { // Check if there is room in the block for the header. if w.j > blockSize { // Fill in the rest of the block with zeroes. - for k := w.i; k < blockSize; k++ { - w.buf[k] = 0 - } + clear(w.buf[w.i:]) w.writeBlock() if w.err != nil { return nil, w.err diff --git a/vendor/github.com/cockroachdb/pebble/scan_internal.go b/vendor/github.com/cockroachdb/pebble/scan_internal.go index 747a981fb..6993bce4d 100644 --- a/vendor/github.com/cockroachdb/pebble/scan_internal.go +++ b/vendor/github.com/cockroachdb/pebble/scan_internal.go @@ -7,7 +7,6 @@ package pebble import ( "context" "fmt" - "sync" "github.com/cockroachdb/errors" "github.com/cockroachdb/pebble/internal/base" @@ -15,14 +14,14 @@ import ( "github.com/cockroachdb/pebble/internal/keyspan" "github.com/cockroachdb/pebble/internal/manifest" "github.com/cockroachdb/pebble/objstorage" - "github.com/cockroachdb/pebble/rangekey" + "github.com/cockroachdb/pebble/objstorage/remote" "github.com/cockroachdb/pebble/sstable" ) const ( // In skip-shared iteration mode, keys in levels sharedLevelsStart and greater // (i.e. lower in the LSM) are skipped. - sharedLevelsStart = 5 + sharedLevelsStart = remote.SharedLevelsStart ) // ErrInvalidSkipSharedIteration is returned by ScanInternal if it was called @@ -92,57 +91,25 @@ func (s *SharedSSTMeta) cloneFromFileMeta(f *fileMetadata) { } } +type sharedByLevel []SharedSSTMeta + +func (s sharedByLevel) Len() int { return len(s) } +func (s sharedByLevel) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s sharedByLevel) Less(i, j int) bool { return s[i].Level < s[j].Level } + type pcIterPos int const ( pcIterPosCur pcIterPos = iota pcIterPosNext - pcIterPosPrev ) -// pointCollapsingSSTIterator implements sstable.Iterator while composing -// pointCollapsingIterator. -type pointCollapsingSSTIterator struct { - pointCollapsingIterator - childIter sstable.Iterator -} - -var pcSSTIterPool = sync.Pool{ - New: func() interface{} { - return &pointCollapsingSSTIterator{} - }, -} - -// MaybeFilteredKeys implements the sstable.Iterator interface. -func (p *pointCollapsingSSTIterator) MaybeFilteredKeys() bool { - return p.childIter.MaybeFilteredKeys() -} - -// SetCloseHook implements the sstable.Iterator interface. -func (p *pointCollapsingSSTIterator) SetCloseHook(fn func(i sstable.Iterator) error) { - p.childIter.SetCloseHook(fn) -} - -// Close implements the sstable.Iterator interface. -func (p *pointCollapsingSSTIterator) Close() error { - err := p.pointCollapsingIterator.Close() - p.pointCollapsingIterator = pointCollapsingIterator{} - p.childIter = nil - pcSSTIterPool.Put(p) - return err -} - // pointCollapsingIterator is an internalIterator that collapses point keys and -// returns at most one point internal key for each user key. Merges are merged, -// sets are emitted as-is, and SingleDeletes are collapsed with the next point -// key, however we don't guarantee that we generate and return a SetWithDel if -// a set shadows a del. Point keys deleted by rangedels are also considered shadowed and not -// exposed. +// returns at most one point internal key for each user key. Merges and +// SingleDels are not supported and result in a panic if encountered. Point keys +// deleted by rangedels are considered shadowed and not exposed. // -// TODO(bilal): Implement the unimplemented internalIterator methods below. -// Currently this iterator only supports the forward iteration case necessary -// for scanInternal, however foreign sstable iterators will also need to use this -// or a simplified version of this. +// Only used in ScanInternal to return at most one internal key per user key. type pointCollapsingIterator struct { iter keyspan.InterleavingIter pos pcIterPos @@ -163,28 +130,19 @@ type pointCollapsingIterator struct { // - If pos == pcIterPosCur, iterKey is pointing to an `iter`-owned current // key, and savedKey is either undefined or pointing to a version of the // current key owned by this iterator (i.e. backed by savedKeyBuf). - // - if pos == pcIterPosPrev, iterKey is pointing to the key before - // p.savedKey. p.savedKey is treated as the current key and is owned by - // this iterator, while p.iterKey is the previous key that is the current - // position of the child iterator. savedKey InternalKey savedKeyBuf []byte - // elideRangeDeletes ignores range deletes returned by the interleaving - // iterator if true. - elideRangeDeletes bool // Value at the current iterator position, at iterKey. iterValue base.LazyValue - // Saved value backed by valueBuf, if set. Used in reverse iteration, and - // for merges. - savedValue base.LazyValue - // Used for Merge keys only. - valueMerger ValueMerger - valueBuf []byte // If fixedSeqNum is non-zero, all emitted points are verified to have this // fixed sequence number. fixedSeqNum uint64 } +func (p *pointCollapsingIterator) Span() *keyspan.Span { + return p.iter.Span() +} + // SeekPrefixGE implements the InternalIterator interface. func (p *pointCollapsingIterator) SeekPrefixGE( prefix, key []byte, flags base.SeekGEFlags, @@ -215,20 +173,12 @@ func (p *pointCollapsingIterator) SeekGE( func (p *pointCollapsingIterator) SeekLT( key []byte, flags base.SeekLTFlags, ) (*base.InternalKey, base.LazyValue) { - p.resetKey() - p.iterKey, p.iterValue = p.iter.SeekLT(key, flags) - p.pos = pcIterPosCur - if p.iterKey == nil { - return nil, base.LazyValue{} - } - return p.findPrevEntry() + panic("unimplemented") } func (p *pointCollapsingIterator) resetKey() { p.savedKey.UserKey = p.savedKeyBuf[:0] p.savedKey.Trailer = 0 - p.valueMerger = nil - p.valueBuf = p.valueBuf[:0] p.iterKey = nil p.pos = pcIterPosCur } @@ -246,22 +196,6 @@ func (p *pointCollapsingIterator) verifySeqNum(key *base.InternalKey) *base.Inte return key } -// finishAndReturnMerge finishes off the valueMerger and returns the saved key. -func (p *pointCollapsingIterator) finishAndReturnMerge() (*base.InternalKey, base.LazyValue) { - value, closer, err := p.valueMerger.Finish(true /* includesBase */) - if err != nil { - p.err = err - return nil, base.LazyValue{} - } - p.valueBuf = append(p.valueBuf[:0], value...) - if closer != nil { - _ = closer.Close() - } - p.valueMerger = nil - val := base.MakeInPlaceValue(p.valueBuf) - return p.verifySeqNum(&p.savedKey), val -} - // findNextEntry is called to return the next key. p.iter must be positioned at the // start of the first user key we are interested in. func (p *pointCollapsingIterator) findNextEntry() (*base.InternalKey, base.LazyValue) { @@ -272,22 +206,13 @@ func (p *pointCollapsingIterator) findNextEntry() (*base.InternalKey, base.LazyV // NB: p.savedKey is either the current key (iff p.iterKey == firstKey), // or the previous key. if !firstIteration && !p.comparer.Equal(p.iterKey.UserKey, p.savedKey.UserKey) { - if p.valueMerger != nil { - if p.savedKey.Kind() != InternalKeyKindMerge { - panic(fmt.Sprintf("expected key %s to have MERGE kind", p.iterKey)) - } - p.pos = pcIterPosNext - return p.finishAndReturnMerge() - } p.saveKey() continue } firstIteration = false if s := p.iter.Span(); s != nil && s.CoversAt(p.seqNum, p.iterKey.SeqNum()) { // All future keys for this user key must be deleted. - if p.valueMerger != nil { - return p.finishAndReturnMerge() - } else if p.savedKey.Kind() == InternalKeyKindSingleDelete { + if p.savedKey.Kind() == InternalKeyKindSingleDelete { panic("cannot process singledel key in point collapsing iterator") } // Fast forward to the next user key. @@ -323,58 +248,9 @@ func (p *pointCollapsingIterator) findNextEntry() (*base.InternalKey, base.LazyV // Panic, as this iterator is not expected to observe single deletes. panic("cannot process singledel key in point collapsing iterator") case InternalKeyKindMerge: - if p.valueMerger == nil { - // Set up merger. This is the first Merge key encountered. - value, callerOwned, err := p.iterValue.Value(p.valueBuf[:0]) - if err != nil { - p.err = err - return nil, base.LazyValue{} - } - if !callerOwned { - p.valueBuf = append(p.valueBuf[:0], value...) - } else { - p.valueBuf = value - } - p.valueMerger, err = p.merge(p.iterKey.UserKey, p.valueBuf) - if err != nil { - p.err = err - return nil, base.LazyValue{} - } - p.saveKey() - p.iterKey, p.iterValue = p.iter.Next() - continue - } - switch p.iterKey.Kind() { - case InternalKeyKindSet, InternalKeyKindMerge, InternalKeyKindSetWithDelete: - // Merge into key. - value, callerOwned, err := p.iterValue.Value(p.valueBuf[:0]) - if err != nil { - p.err = err - return nil, base.LazyValue{} - } - if !callerOwned { - p.valueBuf = append(p.valueBuf[:0], value...) - } else { - p.valueBuf = value - } - if err := p.valueMerger.MergeOlder(value); err != nil { - p.err = err - return nil, base.LazyValue{} - } - } - if p.iterKey.Kind() != InternalKeyKindMerge { - p.savedKey.SetKind(p.iterKey.Kind()) - p.pos = pcIterPosCur - return p.finishAndReturnMerge() - } - p.iterKey, p.iterValue = p.iter.Next() + // Panic, as this iterator is not expected to observe merges. + panic("cannot process merge key in point collapsing iterator") case InternalKeyKindRangeDelete: - if p.elideRangeDeletes { - // Skip this range delete, and process any point after it. - p.iterKey, p.iterValue = p.iter.Next() - p.saveKey() - continue - } // These are interleaved by the interleaving iterator ahead of all points. // We should pass them as-is, but also account for any points ahead of // them. @@ -384,121 +260,10 @@ func (p *pointCollapsingIterator) findNextEntry() (*base.InternalKey, base.LazyV panic(fmt.Sprintf("unexpected kind: %d", p.iterKey.Kind())) } } - if p.valueMerger != nil { - p.pos = pcIterPosNext - return p.finishAndReturnMerge() - } p.resetKey() return nil, base.LazyValue{} } -// findPrevEntry finds the relevant point key to return for the previous user key -// (i.e. in reverse iteration). Requires that the iterator is already positioned -// at the first-in-reverse (i.e. rightmost / largest) internal key encountered -// for that user key. -func (p *pointCollapsingIterator) findPrevEntry() (*base.InternalKey, base.LazyValue) { - if p.iterKey == nil { - p.pos = pcIterPosCur - return nil, base.LazyValue{} - } - - p.saveKey() - firstIteration := true - for p.iterKey != nil { - if !firstIteration && !p.comparer.Equal(p.iterKey.UserKey, p.savedKey.UserKey) { - p.pos = pcIterPosPrev - return p.verifySeqNum(&p.savedKey), p.savedValue - } - firstIteration = false - if s := p.iter.Span(); s != nil && s.CoversAt(p.seqNum, p.iterKey.SeqNum()) { - // Skip this key. - p.iterKey, p.iterValue = p.iter.Prev() - p.saveKey() - continue - } - switch p.iterKey.Kind() { - case InternalKeyKindSet, InternalKeyKindDelete, InternalKeyKindSetWithDelete: - // Instead of calling saveKey(), we take advantage of the invariant that - // p.savedKey.UserKey == p.iterKey.UserKey (otherwise we'd have gone into - // the !p.comparer.Equal(p.iterKey.UserKey, p.savedKey.UserKey) case at - // the top of this for loop). That allows us to just save the trailer - // and move on. - if invariants.Enabled && !p.comparer.Equal(p.iterKey.UserKey, p.savedKey.UserKey) { - panic("unexpected inequality between p.iterKey and p.savedKey") - } - p.savedKey.Trailer = p.iterKey.Trailer - // Copy value into p.savedValue. - value, callerOwned, err := p.iterValue.Value(p.valueBuf[:0]) - if err != nil { - p.err = err - return nil, base.LazyValue{} - } - if !callerOwned { - p.valueBuf = append(p.valueBuf[:0], value...) - } else { - p.valueBuf = value - } - p.valueMerger = nil - p.savedValue = base.MakeInPlaceValue(p.valueBuf) - p.iterKey, p.iterValue = p.iter.Prev() - continue - case InternalKeyKindSingleDelete: - // Panic, as this iterator is not expected to observe single deletes. - panic("cannot process singledel key in point collapsing iterator") - case InternalKeyKindMerge: - panic("cannot process merge key in point collapsing iterator in reverse iteration") - case InternalKeyKindRangeDelete: - if p.elideRangeDeletes { - // Skip this range delete, and process any point before it. - p.iterKey, p.iterValue = p.iter.Prev() - continue - } - // These are interleaved by the interleaving iterator behind all points. - if p.savedKey.Kind() != InternalKeyKindRangeDelete { - // If the previous key was not a rangedel, we need to return it. Pretend that we're at the - // previous user key (i.e. with p.pos = pcIterPosPrev) even if we're not, so on the next - // Prev() we encounter and return this rangedel. For now return the point ahead of - // this range del (if any). - p.pos = pcIterPosPrev - return p.verifySeqNum(&p.savedKey), p.savedValue - } - // We take advantage of the fact that a Prev() *on* a RangeDel iterKey - // always takes us to a different user key, so on the next iteration - // we will fall into the !p.comparer.Equal(p.iterKey.UserKey, p.savedKey.UserKey) - // case. - // - // Instead of calling saveKey(), we take advantage of the invariant that - // p.savedKey.UserKey == p.iterKey.UserKey (otherwise we'd have gone into - // the !p.comparer.Equal(p.iterKey.UserKey, p.savedKey.UserKey) case at - // the top of this for loop). That allows us to just save the trailer - // and move on. - if invariants.Enabled && !p.comparer.Equal(p.iterKey.UserKey, p.savedKey.UserKey) { - panic("unexpected inequality between p.iterKey and p.savedKey") - } - p.savedKey.Trailer = p.iterKey.Trailer - // Copy value into p.savedValue. - value, callerOwned, err := p.iterValue.Value(p.valueBuf[:0]) - if err != nil { - p.err = err - return nil, base.LazyValue{} - } - if !callerOwned { - p.valueBuf = append(p.valueBuf[:0], value...) - } else { - p.valueBuf = value - } - p.valueMerger = nil - p.savedValue = base.MakeInPlaceValue(p.valueBuf) - p.iterKey, p.iterValue = p.iter.Prev() - continue - default: - panic(fmt.Sprintf("unexpected kind: %d", p.iterKey.Kind())) - } - } - p.pos = pcIterPosPrev - return p.verifySeqNum(&p.savedKey), p.savedValue -} - // First implements the InternalIterator interface. func (p *pointCollapsingIterator) First() (*base.InternalKey, base.LazyValue) { p.resetKey() @@ -512,13 +277,7 @@ func (p *pointCollapsingIterator) First() (*base.InternalKey, base.LazyValue) { // Last implements the InternalIterator interface. func (p *pointCollapsingIterator) Last() (*base.InternalKey, base.LazyValue) { - p.resetKey() - p.iterKey, p.iterValue = p.iter.Last() - p.pos = pcIterPosCur - if p.iterKey == nil { - return nil, base.LazyValue{} - } - return p.findPrevEntry() + panic("unimplemented") } func (p *pointCollapsingIterator) saveKey() { @@ -533,33 +292,9 @@ func (p *pointCollapsingIterator) saveKey() { // Next implements the InternalIterator interface. func (p *pointCollapsingIterator) Next() (*base.InternalKey, base.LazyValue) { switch p.pos { - case pcIterPosPrev: - p.saveKey() - if p.iterKey != nil && p.iterKey.Kind() == InternalKeyKindRangeDelete && !p.elideRangeDeletes { - p.iterKey, p.iterValue = p.iter.Next() - p.pos = pcIterPosCur - } else { - // Fast forward to the next user key. - key, val := p.iter.Next() - // p.iterKey.SeqNum() >= key.SeqNum() is an optimization that allows us to - // use p.iterKey.SeqNum() < key.SeqNum() as a sign that the user key has - // changed, without needing to do the full key comparison. - for key != nil && p.savedKey.SeqNum() >= key.SeqNum() && - p.comparer.Equal(p.savedKey.UserKey, key.UserKey) { - key, val = p.iter.Next() - } - if key == nil { - // There are no keys to return. - p.resetKey() - return nil, base.LazyValue{} - } - p.iterKey, p.iterValue = key, val - p.pos = pcIterPosCur - } - fallthrough case pcIterPosCur: p.saveKey() - if p.iterKey != nil && p.iterKey.Kind() == InternalKeyKindRangeDelete && !p.elideRangeDeletes { + if p.iterKey != nil && p.iterKey.Kind() == InternalKeyKindRangeDelete { // Step over the interleaved range delete and process the very next // internal key, even if it's at the same user key. This is because a // point for that user key has not been returned yet. @@ -593,56 +328,12 @@ func (p *pointCollapsingIterator) Next() (*base.InternalKey, base.LazyValue) { // NextPrefix implements the InternalIterator interface. func (p *pointCollapsingIterator) NextPrefix(succKey []byte) (*base.InternalKey, base.LazyValue) { - // TODO(bilal): Implement this optimally. It'll be similar to SeekGE, except we'll call - // the child iterator's NextPrefix, and have some special logic in case pos - // is pcIterPosNext. - return p.SeekGE(succKey, base.SeekGEFlagsNone) + panic("unimplemented") } // Prev implements the InternalIterator interface. func (p *pointCollapsingIterator) Prev() (*base.InternalKey, base.LazyValue) { - switch p.pos { - case pcIterPosNext: - // Rewind backwards to the previous iter key. - p.saveKey() - key, val := p.iter.Prev() - for key != nil && p.savedKey.SeqNum() <= key.SeqNum() && - p.comparer.Equal(p.savedKey.UserKey, key.UserKey) { - if key.Kind() == InternalKeyKindRangeDelete && !p.elideRangeDeletes { - // We need to pause at this range delete and return it as-is, as "cur" - // is referencing the point key after it, not the range delete. - break - } - key, val = p.iter.Prev() - } - p.iterKey = key - p.iterValue = val - p.pos = pcIterPosCur - fallthrough - case pcIterPosCur: - p.saveKey() - key, val := p.iter.Prev() - for key != nil && p.savedKey.SeqNum() <= key.SeqNum() && - p.comparer.Equal(p.savedKey.UserKey, key.UserKey) { - if key.Kind() == InternalKeyKindRangeDelete && !p.elideRangeDeletes { - // We need to pause at this range delete and return it as-is, as "cur" - // is referencing the point key after it, not the range delete. - break - } - key, val = p.iter.Prev() - } - p.iterKey = key - p.iterValue = val - p.pos = pcIterPosCur - case pcIterPosPrev: - // Do nothing. - p.pos = pcIterPosCur - } - if p.iterKey == nil { - p.resetKey() - return nil, base.LazyValue{} - } - return p.findPrevEntry() + panic("unimplemented") } // Error implements the InternalIterator interface. @@ -664,6 +355,10 @@ func (p *pointCollapsingIterator) SetBounds(lower, upper []byte) { p.iter.SetBounds(lower, upper) } +func (p *pointCollapsingIterator) SetContext(ctx context.Context) { + p.iter.SetContext(ctx) +} + // String implements the InternalIterator interface. func (p *pointCollapsingIterator) String() string { return p.iter.String() @@ -671,6 +366,32 @@ func (p *pointCollapsingIterator) String() string { var _ internalIterator = &pointCollapsingIterator{} +// IteratorLevelKind is used to denote whether the current ScanInternal iterator +// is unknown, belongs to a flushable, or belongs to an LSM level type. +type IteratorLevelKind int8 + +const ( + // IteratorLevelUnknown indicates an unknown LSM level. + IteratorLevelUnknown IteratorLevelKind = iota + // IteratorLevelLSM indicates an LSM level. + IteratorLevelLSM + // IteratorLevelFlushable indicates a flushable (i.e. memtable). + IteratorLevelFlushable +) + +// IteratorLevel is used with scanInternalIterator to surface additional iterator-specific info where possible. +// Note: this is struct is only provided for point keys. +type IteratorLevel struct { + Kind IteratorLevelKind + // FlushableIndex indicates the position within the flushable queue of this level. + // Only valid if kind == IteratorLevelFlushable. + FlushableIndex int + // The level within the LSM. Only valid if Kind == IteratorLevelLSM. + Level int + // Sublevel is only valid if Kind == IteratorLevelLSM and Level == 0. + Sublevel int +} + // scanInternalIterator is an iterator that returns all internal keys, including // tombstones. For instance, an InternalKeyKindDelete would be returned as an // InternalKeyKindDelete instead of the iterator skipping over to the next key. @@ -684,19 +405,24 @@ var _ internalIterator = &pointCollapsingIterator{} // *must* return the range delete as well as the range key unset/delete that did // the shadowing. type scanInternalIterator struct { + ctx context.Context + db *DB opts scanInternalOptions comparer *base.Comparer merge Merge iter internalIterator readState *readState + version *version rangeKey *iteratorRangeKeyState - pointKeyIter pointCollapsingIterator + pointKeyIter internalIterator iterKey *InternalKey iterValue LazyValue alloc *iterAlloc newIters tableNewIters newIterRangeKey keyspan.TableNewSpanIter seqNum uint64 + iterLevels []IteratorLevel + mergingIter *mergingIter // boundsBuf holds two buffers used to store the lower and upper bounds. // Whenever the InternalIterator's bounds change, the new bounds are copied @@ -754,7 +480,7 @@ func (d *DB) truncateSharedFile( ) defer rangeDelIter.Close() } - rangeKeyIter, err := d.tableNewRangeKeyIter(file, keyspan.SpanIterOptions{Level: manifest.Level(level)}) + rangeKeyIter, err := d.tableNewRangeKeyIter(file, keyspan.SpanIterOptions{}) if err != nil { return nil, false, err } @@ -877,15 +603,9 @@ func (d *DB) truncateSharedFile( } func scanInternalImpl( - ctx context.Context, - lower, upper []byte, - iter *scanInternalIterator, - visitPointKey func(key *InternalKey, value LazyValue) error, - visitRangeDel func(start, end []byte, seqNum uint64) error, - visitRangeKey func(start, end []byte, keys []rangekey.Key) error, - visitSharedFile func(sst *SharedSSTMeta) error, + ctx context.Context, lower, upper []byte, iter *scanInternalIterator, opts *scanInternalOptions, ) error { - if visitSharedFile != nil && (lower == nil || upper == nil) { + if opts.visitSharedFile != nil && (lower == nil || upper == nil) { panic("lower and upper bounds must be specified in skip-shared iteration mode") } // Before starting iteration, check if any files in levels sharedLevelsStart @@ -894,15 +614,18 @@ func scanInternalImpl( // of keys. For files that are shared, call visitSharedFile with a truncated // version of that file. cmp := iter.comparer.Compare - db := iter.readState.db - provider := db.objProvider + provider := iter.db.ObjProvider() seqNum := iter.seqNum - if visitSharedFile != nil { + current := iter.version + if current == nil { + current = iter.readState.current + } + if opts.visitSharedFile != nil { if provider == nil { panic("expected non-nil Provider in skip-shared iteration mode") } for level := sharedLevelsStart; level < numLevels; level++ { - files := iter.readState.current.Levels[level].Iter() + files := current.Levels[level].Iter() for f := files.SeekGE(cmp, lower); f != nil && cmp(f.Smallest.UserKey, upper) < 0; f = files.Next() { var objMeta objstorage.ObjectMetadata var err error @@ -918,14 +641,14 @@ func scanInternalImpl( } var sst *SharedSSTMeta var skip bool - sst, skip, err = iter.readState.db.truncateSharedFile(ctx, lower, upper, level, f, objMeta) + sst, skip, err = iter.db.truncateSharedFile(ctx, lower, upper, level, f, objMeta) if err != nil { return err } if skip { continue } - if err = visitSharedFile(sst); err != nil { + if err = opts.visitSharedFile(sst); err != nil { return err } } @@ -935,21 +658,40 @@ func scanInternalImpl( for valid := iter.seekGE(lower); valid && iter.error() == nil; valid = iter.next() { key := iter.unsafeKey() + if opts.rateLimitFunc != nil { + if err := opts.rateLimitFunc(key, iter.lazyValue()); err != nil { + return err + } + } + switch key.Kind() { case InternalKeyKindRangeKeyDelete, InternalKeyKindRangeKeyUnset, InternalKeyKindRangeKeySet: - span := iter.unsafeSpan() - if err := visitRangeKey(span.Start, span.End, span.Keys); err != nil { - return err + if opts.visitRangeKey != nil { + span := iter.unsafeSpan() + if err := opts.visitRangeKey(span.Start, span.End, span.Keys); err != nil { + return err + } } case InternalKeyKindRangeDelete: - rangeDel := iter.unsafeRangeDel() - if err := visitRangeDel(rangeDel.Start, rangeDel.End, rangeDel.LargestSeqNum()); err != nil { - return err + if opts.visitRangeDel != nil { + rangeDel := iter.unsafeRangeDel() + if err := opts.visitRangeDel(rangeDel.Start, rangeDel.End, rangeDel.LargestSeqNum()); err != nil { + return err + } } default: - val := iter.lazyValue() - if err := visitPointKey(key, val); err != nil { - return err + if opts.visitPointKey != nil { + var info IteratorLevel + if len(iter.mergingIter.heap.items) > 0 { + mergingIterIdx := iter.mergingIter.heap.items[0].index + info = iter.iterLevels[mergingIterIdx] + } else { + info = IteratorLevel{Kind: IteratorLevelUnknown} + } + val := iter.lazyValue() + if err := opts.visitPointKey(key, val, info); err != nil { + return err + } } } } @@ -958,7 +700,9 @@ func scanInternalImpl( } // constructPointIter constructs a merging iterator and sets i.iter to it. -func (i *scanInternalIterator) constructPointIter(memtables flushableList, buf *iterAlloc) { +func (i *scanInternalIterator) constructPointIter( + categoryAndQoS sstable.CategoryAndQoS, memtables flushableList, buf *iterAlloc, +) { // Merging levels and levels from iterAlloc. mlevels := buf.mlevels[:0] levels := buf.levels[:0] @@ -969,9 +713,13 @@ func (i *scanInternalIterator) constructPointIter(memtables flushableList, buf * numMergingLevels := len(memtables) numLevelIters := 0 - current := i.readState.current + current := i.version + if current == nil { + current = i.readState.current + } numMergingLevels += len(current.L0SublevelFiles) numLevelIters += len(current.L0SublevelFiles) + for level := 1; level < len(current.Levels); level++ { if current.Levels[level].Empty() { continue @@ -994,35 +742,43 @@ func (i *scanInternalIterator) constructPointIter(memtables flushableList, buf * rangeDelIters := make([]keyspan.FragmentIterator, 0, numMergingLevels) rangeDelLevels := make([]keyspan.LevelIter, 0, numLevelIters) + i.iterLevels = make([]IteratorLevel, numMergingLevels) + mlevelsIndex := 0 + // Next are the memtables. for j := len(memtables) - 1; j >= 0; j-- { mem := memtables[j] mlevels = append(mlevels, mergingIterLevel{ iter: mem.newIter(&i.opts.IterOptions), }) + i.iterLevels[mlevelsIndex] = IteratorLevel{ + Kind: IteratorLevelFlushable, + FlushableIndex: j, + } + mlevelsIndex++ if rdi := mem.newRangeDelIter(&i.opts.IterOptions); rdi != nil { rangeDelIters = append(rangeDelIters, rdi) } } // Next are the file levels: L0 sub-levels followed by lower levels. - mlevelsIndex := len(mlevels) levelsIndex := len(levels) mlevels = mlevels[:numMergingLevels] levels = levels[:numLevelIters] rangeDelLevels = rangeDelLevels[:numLevelIters] i.opts.IterOptions.snapshotForHideObsoletePoints = i.seqNum + i.opts.IterOptions.CategoryAndQoS = categoryAndQoS addLevelIterForFiles := func(files manifest.LevelIterator, level manifest.Level) { li := &levels[levelsIndex] rli := &rangeDelLevels[levelsIndex] li.init( - context.Background(), i.opts.IterOptions, i.comparer.Compare, i.comparer.Split, i.newIters, files, level, + i.ctx, i.opts.IterOptions, i.comparer, i.newIters, files, level, internalIterOpts{}) li.initBoundaryContext(&mlevels[mlevelsIndex].levelIterBoundaryContext) mlevels[mlevelsIndex].iter = li rli.Init(keyspan.SpanIterOptions{RangeKeyFilters: i.opts.RangeKeyFilters}, - i.comparer.Compare, tableNewRangeDelIter(context.Background(), i.newIters), files, level, + i.comparer.Compare, tableNewRangeDelIter(i.ctx, i.newIters), files, level, manifest.KeyTypePoint) rangeDelIters = append(rangeDelIters, rli) @@ -1030,12 +786,14 @@ func (i *scanInternalIterator) constructPointIter(memtables flushableList, buf * mlevelsIndex++ } - // Add level iterators for the L0 sublevels, iterating from newest to - // oldest. - for i := len(current.L0SublevelFiles) - 1; i >= 0; i-- { - addLevelIterForFiles(current.L0SublevelFiles[i].Iter(), manifest.L0Sublevel(i)) + for j := len(current.L0SublevelFiles) - 1; j >= 0; j-- { + i.iterLevels[mlevelsIndex] = IteratorLevel{ + Kind: IteratorLevelLSM, + Level: 0, + Sublevel: j, + } + addLevelIterForFiles(current.L0SublevelFiles[j].Iter(), manifest.L0Sublevel(j)) } - // Add level iterators for the non-empty non-L0 levels. for level := 1; level < numLevels; level++ { if current.Levels[level].Empty() { @@ -1044,18 +802,35 @@ func (i *scanInternalIterator) constructPointIter(memtables flushableList, buf * if i.opts.skipSharedLevels && level >= sharedLevelsStart { continue } + i.iterLevels[mlevelsIndex] = IteratorLevel{Kind: IteratorLevelLSM, Level: level} addLevelIterForFiles(current.Levels[level].Iter(), manifest.Level(level)) } + buf.merging.init(&i.opts.IterOptions, &InternalIteratorStats{}, i.comparer.Compare, i.comparer.Split, mlevels...) buf.merging.snapshot = i.seqNum rangeDelMiter.Init(i.comparer.Compare, keyspan.VisibleTransform(i.seqNum), new(keyspan.MergingBuffers), rangeDelIters...) - i.pointKeyIter = pointCollapsingIterator{ - comparer: i.comparer, - merge: i.merge, - seqNum: i.seqNum, + + if i.opts.includeObsoleteKeys { + iiter := &keyspan.InterleavingIter{} + iiter.Init(i.comparer, &buf.merging, &rangeDelMiter, + keyspan.InterleavingIterOpts{ + LowerBound: i.opts.LowerBound, + UpperBound: i.opts.UpperBound, + }) + i.pointKeyIter = iiter + } else { + pcIter := &pointCollapsingIterator{ + comparer: i.comparer, + merge: i.merge, + seqNum: i.seqNum, + } + pcIter.iter.Init(i.comparer, &buf.merging, &rangeDelMiter, keyspan.InterleavingIterOpts{ + LowerBound: i.opts.LowerBound, + UpperBound: i.opts.UpperBound, + }) + i.pointKeyIter = pcIter } - i.pointKeyIter.iter.Init(i.comparer, &buf.merging, &rangeDelMiter, nil /* mask */, i.opts.LowerBound, i.opts.UpperBound) - i.iter = &i.pointKeyIter + i.iter = i.pointKeyIter } // constructRangeKeyIter constructs the range-key iterator stack, populating @@ -1071,19 +846,24 @@ func (i *scanInternalIterator) constructRangeKeyIter() { &i.rangeKey.rangeKeyBuffers.internal) // Next are the flushables: memtables and large batches. - for j := len(i.readState.memtables) - 1; j >= 0; j-- { - mem := i.readState.memtables[j] - // We only need to read from memtables which contain sequence numbers older - // than seqNum. - if logSeqNum := mem.logSeqNum; logSeqNum >= i.seqNum { - continue - } - if rki := mem.newRangeKeyIter(&i.opts.IterOptions); rki != nil { - i.rangeKey.iterConfig.AddLevel(rki) + if i.readState != nil { + for j := len(i.readState.memtables) - 1; j >= 0; j-- { + mem := i.readState.memtables[j] + // We only need to read from memtables which contain sequence numbers older + // than seqNum. + if logSeqNum := mem.logSeqNum; logSeqNum >= i.seqNum { + continue + } + if rki := mem.newRangeKeyIter(&i.opts.IterOptions); rki != nil { + i.rangeKey.iterConfig.AddLevel(rki) + } } } - current := i.readState.current + current := i.version + if current == nil { + current = i.readState.current + } // Next are the file levels: L0 sub-levels followed by lower levels. // // Add file-specific iterators for L0 files containing range keys. This is less @@ -1098,7 +878,7 @@ func (i *scanInternalIterator) constructRangeKeyIter() { // around Key Trailer order. iter := current.RangeKeyLevels[0].Iter() for f := iter.Last(); f != nil; f = iter.Prev() { - spanIter, err := i.newIterRangeKey(f, i.opts.SpanIterOptions(manifest.Level(0))) + spanIter, err := i.newIterRangeKey(f, i.opts.SpanIterOptions()) if err != nil { i.rangeKey.iterConfig.AddLevel(&errorKeyspanIter{err: err}) continue @@ -1115,7 +895,7 @@ func (i *scanInternalIterator) constructRangeKeyIter() { continue } li := i.rangeKey.iterConfig.NewLevelIter() - spanIterOpts := i.opts.SpanIterOptions(manifest.Level(level)) + spanIterOpts := i.opts.SpanIterOptions() li.Init(spanIterOpts, i.comparer.Compare, i.newIterRangeKey, current.RangeKeyLevels[level].Iter(), manifest.Level(level), manifest.KeyTypeRange) i.rangeKey.iterConfig.AddLevel(li) @@ -1145,7 +925,10 @@ func (i *scanInternalIterator) lazyValue() LazyValue { // unsafeRangeDel returns a range key span. Behaviour undefined if UnsafeKey returns // a non-rangedel kind. func (i *scanInternalIterator) unsafeRangeDel() *keyspan.Span { - return i.pointKeyIter.iter.Span() + type spanInternalIterator interface { + Span() *keyspan.Span + } + return i.pointKeyIter.(spanInternalIterator).Span() } // unsafeSpan returns a range key span. Behaviour undefined if UnsafeKey returns @@ -1171,7 +954,12 @@ func (i *scanInternalIterator) close() error { if err := i.iter.Close(); err != nil { return err } - i.readState.unref() + if i.readState != nil { + i.readState.unref() + } + if i.version != nil { + i.version.Unref() + } if i.rangeKey != nil { i.rangeKey.PrepareForReuse() *i.rangeKey = iteratorRangeKeyState{ diff --git a/vendor/github.com/cockroachdb/pebble/snapshot.go b/vendor/github.com/cockroachdb/pebble/snapshot.go index 6617cce5f..31536b34a 100644 --- a/vendor/github.com/cockroachdb/pebble/snapshot.go +++ b/vendor/github.com/cockroachdb/pebble/snapshot.go @@ -8,16 +8,30 @@ import ( "context" "io" "math" + "sync" + "sync/atomic" + "time" + "github.com/cockroachdb/errors" + "github.com/cockroachdb/pebble/internal/invariants" "github.com/cockroachdb/pebble/rangekey" + "github.com/cockroachdb/pebble/sstable" ) +// ErrSnapshotExcised is returned from WaitForFileOnlySnapshot if an excise +// overlapping with one of the EventuallyFileOnlySnapshot's KeyRanges gets +// applied before the transition of that EFOS to a file-only snapshot. +var ErrSnapshotExcised = errors.New("pebble: snapshot excised before conversion to file-only snapshot") + // Snapshot provides a read-only point-in-time view of the DB state. type Snapshot struct { // The db the snapshot was created from. db *DB seqNum uint64 + // Set if part of an EventuallyFileOnlySnapshot. + efos *EventuallyFileOnlySnapshot + // The list the snapshot is linked into. list *snapshotList @@ -44,17 +58,19 @@ func (s *Snapshot) Get(key []byte) ([]byte, io.Closer, error) { // NewIter returns an iterator that is unpositioned (Iterator.Valid() will // return false). The iterator can be positioned via a call to SeekGE, // SeekLT, First or Last. -func (s *Snapshot) NewIter(o *IterOptions) *Iterator { +func (s *Snapshot) NewIter(o *IterOptions) (*Iterator, error) { return s.NewIterWithContext(context.Background(), o) } // NewIterWithContext is like NewIter, and additionally accepts a context for // tracing. -func (s *Snapshot) NewIterWithContext(ctx context.Context, o *IterOptions) *Iterator { +func (s *Snapshot) NewIterWithContext(ctx context.Context, o *IterOptions) (*Iterator, error) { if s.db == nil { panic(ErrClosed) } - return s.db.newIter(ctx, nil /* batch */, s, o) + return s.db.newIter(ctx, nil /* batch */, newIterOpts{ + snapshot: snapshotIterOpts{seqNum: s.seqNum}, + }, o), nil } // ScanInternal scans all internal keys within the specified bounds, truncating @@ -65,8 +81,9 @@ func (s *Snapshot) NewIterWithContext(ctx context.Context, o *IterOptions) *Iter // point keys deleted by range dels and keys masked by range keys. func (s *Snapshot) ScanInternal( ctx context.Context, + categoryAndQoS sstable.CategoryAndQoS, lower, upper []byte, - visitPointKey func(key *InternalKey, value LazyValue) error, + visitPointKey func(key *InternalKey, value LazyValue, iterInfo IteratorLevel) error, visitRangeDel func(start, end []byte, seqNum uint64) error, visitRangeKey func(start, end []byte, keys []rangekey.Key) error, visitSharedFile func(sst *SharedSSTMeta) error, @@ -74,28 +91,29 @@ func (s *Snapshot) ScanInternal( if s.db == nil { panic(ErrClosed) } - iter := s.db.newInternalIter(s, &scanInternalOptions{ + scanInternalOpts := &scanInternalOptions{ + CategoryAndQoS: categoryAndQoS, + visitPointKey: visitPointKey, + visitRangeDel: visitRangeDel, + visitRangeKey: visitRangeKey, + visitSharedFile: visitSharedFile, + skipSharedLevels: visitSharedFile != nil, IterOptions: IterOptions{ KeyTypes: IterKeyTypePointsAndRanges, LowerBound: lower, UpperBound: upper, }, - skipSharedLevels: visitSharedFile != nil, - }) + } + + iter := s.db.newInternalIter(ctx, snapshotIterOpts{seqNum: s.seqNum}, scanInternalOpts) defer iter.close() - return scanInternalImpl(ctx, lower, upper, iter, visitPointKey, visitRangeDel, visitRangeKey, visitSharedFile) + return scanInternalImpl(ctx, lower, upper, iter, scanInternalOpts) } -// Close closes the snapshot, releasing its resources. Close must be called. -// Failure to do so will result in a tiny memory leak and a large leak of -// resources on disk due to the entries the snapshot is preventing from being -// deleted. -func (s *Snapshot) Close() error { - if s.db == nil { - panic(ErrClosed) - } - s.db.mu.Lock() +// closeLocked is similar to Close(), except it requires that db.mu be held +// by the caller. +func (s *Snapshot) closeLocked() error { s.db.mu.snapshots.remove(s) // If s was the previous earliest snapshot, we might be able to reclaim @@ -103,11 +121,26 @@ func (s *Snapshot) Close() error { if e := s.db.mu.snapshots.earliest(); e > s.seqNum { s.db.maybeScheduleCompactionPicker(pickElisionOnly) } - s.db.mu.Unlock() s.db = nil return nil } +// Close closes the snapshot, releasing its resources. Close must be called. +// Failure to do so will result in a tiny memory leak and a large leak of +// resources on disk due to the entries the snapshot is preventing from being +// deleted. +// +// d.mu must NOT be held by the caller. +func (s *Snapshot) Close() error { + db := s.db + if db == nil { + panic(ErrClosed) + } + db.mu.Lock() + defer db.mu.Unlock() + return s.closeLocked() +} + type snapshotList struct { root Snapshot } @@ -175,3 +208,347 @@ func (l *snapshotList) remove(s *Snapshot) { s.prev = nil // avoid memory leaks s.list = nil // avoid memory leaks } + +// EventuallyFileOnlySnapshot (aka EFOS) provides a read-only point-in-time view +// of the database state, similar to Snapshot. An EventuallyFileOnlySnapshot +// induces less write amplification than Snapshot, at the cost of increased space +// amplification. While a Snapshot may increase write amplification across all +// flushes and compactions for the duration of its lifetime, an +// EventuallyFileOnlySnapshot only incurs that cost for flushes/compactions if +// memtables at the time of EFOS instantiation contained keys that the EFOS is +// interested in (i.e. its protectedRanges). In that case, the EFOS prevents +// elision of keys visible to it, similar to a Snapshot, until those memtables +// are flushed, and once that happens, the "EventuallyFileOnlySnapshot" +// transitions to a file-only snapshot state in which it pins zombies sstables +// like an open Iterator would, without pinning any memtables. Callers that can +// tolerate the increased space amplification of pinning zombie sstables until +// the snapshot is closed may prefer EventuallyFileOnlySnapshots for their +// reduced write amplification. Callers that desire the benefits of the file-only +// state that requires no pinning of memtables should call +// `WaitForFileOnlySnapshot()` (and possibly re-mint an EFOS if it returns +// ErrSnapshotExcised) before relying on the EFOS to keep producing iterators +// with zero write-amp and zero pinning of memtables in memory. +// +// EventuallyFileOnlySnapshots interact with the IngestAndExcise operation in +// subtle ways. No new iterators can be created once +// EventuallyFileOnlySnapshot.excised is set to true. +type EventuallyFileOnlySnapshot struct { + mu struct { + // NB: If both this mutex and db.mu are being grabbed, db.mu should be + // grabbed _before_ grabbing this one. + sync.Mutex + + // Either the snap field is set below, or the version is set at any given + // point of time. If a snapshot is referenced, this is not a file-only + // snapshot yet, and if a version is set (and ref'd) this is a file-only + // snapshot. + + // The wrapped regular snapshot, if not a file-only snapshot yet. + snap *Snapshot + // The wrapped version reference, if a file-only snapshot. + vers *version + } + + // Key ranges to watch for an excise on. + protectedRanges []KeyRange + // excised, if true, signals that the above ranges were excised during the + // lifetime of this snapshot. + excised atomic.Bool + + // The db the snapshot was created from. + db *DB + seqNum uint64 + + closed chan struct{} +} + +func (d *DB) makeEventuallyFileOnlySnapshot( + keyRanges []KeyRange, internalKeyRanges []internalKeyRange, +) *EventuallyFileOnlySnapshot { + isFileOnly := true + + d.mu.Lock() + defer d.mu.Unlock() + seqNum := d.mu.versions.visibleSeqNum.Load() + // Check if any of the keyRanges overlap with a memtable. + for i := range d.mu.mem.queue { + mem := d.mu.mem.queue[i] + if ingestMemtableOverlaps(d.cmp, mem, internalKeyRanges) { + isFileOnly = false + break + } + } + es := &EventuallyFileOnlySnapshot{ + db: d, + seqNum: seqNum, + protectedRanges: keyRanges, + closed: make(chan struct{}), + } + if isFileOnly { + es.mu.vers = d.mu.versions.currentVersion() + es.mu.vers.Ref() + } else { + s := &Snapshot{ + db: d, + seqNum: seqNum, + } + s.efos = es + es.mu.snap = s + d.mu.snapshots.pushBack(s) + } + return es +} + +// Transitions this EventuallyFileOnlySnapshot to a file-only snapshot. Requires +// earliestUnflushedSeqNum and vers to correspond to the same Version from the +// current or a past acquisition of db.mu. vers must have been Ref()'d before +// that mutex was released, if it was released. +// +// NB: The caller is expected to check for es.excised before making this +// call. +// +// d.mu must be held when calling this method. +func (es *EventuallyFileOnlySnapshot) transitionToFileOnlySnapshot(vers *version) error { + es.mu.Lock() + select { + case <-es.closed: + vers.UnrefLocked() + es.mu.Unlock() + return ErrClosed + default: + } + if es.mu.snap == nil { + es.mu.Unlock() + panic("pebble: tried to transition an eventually-file-only-snapshot twice") + } + // The caller has already called Ref() on vers. + es.mu.vers = vers + // NB: The callers should have already done a check of es.excised. + oldSnap := es.mu.snap + es.mu.snap = nil + es.mu.Unlock() + return oldSnap.closeLocked() +} + +// hasTransitioned returns true if this EFOS has transitioned to a file-only +// snapshot. +func (es *EventuallyFileOnlySnapshot) hasTransitioned() bool { + es.mu.Lock() + defer es.mu.Unlock() + return es.mu.vers != nil +} + +// waitForFlush waits for a flush on any memtables that need to be flushed +// before this EFOS can transition to a file-only snapshot. If this EFOS is +// waiting on a flush of the mutable memtable, it forces a rotation within +// `dur` duration. For immutable memtables, it schedules a flush and waits for +// it to finish. +func (es *EventuallyFileOnlySnapshot) waitForFlush(ctx context.Context, dur time.Duration) error { + es.db.mu.Lock() + defer es.db.mu.Unlock() + + earliestUnflushedSeqNum := es.db.getEarliestUnflushedSeqNumLocked() + for earliestUnflushedSeqNum < es.seqNum { + select { + case <-es.closed: + return ErrClosed + case <-ctx.Done(): + return ctx.Err() + default: + } + // Check if the current mutable memtable contains keys less than seqNum. + // If so, rotate it. + if es.db.mu.mem.mutable.logSeqNum < es.seqNum && dur.Nanoseconds() > 0 { + es.db.maybeScheduleDelayedFlush(es.db.mu.mem.mutable, dur) + } else { + // Find the last memtable that contains seqNums less than es.seqNum, + // and force a flush on it. + var mem *flushableEntry + for i := range es.db.mu.mem.queue { + if es.db.mu.mem.queue[i].logSeqNum < es.seqNum { + mem = es.db.mu.mem.queue[i] + } + } + mem.flushForced = true + es.db.maybeScheduleFlush() + } + es.db.mu.compact.cond.Wait() + + earliestUnflushedSeqNum = es.db.getEarliestUnflushedSeqNumLocked() + } + if es.excised.Load() { + return ErrSnapshotExcised + } + return nil +} + +// WaitForFileOnlySnapshot blocks the calling goroutine until this snapshot +// has been converted into a file-only snapshot (i.e. all memtables containing +// keys < seqNum are flushed). A duration can be passed in, and if nonzero, +// a delayed flush will be scheduled at that duration if necessary. +// +// Idempotent; can be called multiple times with no side effects. +func (es *EventuallyFileOnlySnapshot) WaitForFileOnlySnapshot( + ctx context.Context, dur time.Duration, +) error { + if es.hasTransitioned() { + return nil + } + + if err := es.waitForFlush(ctx, dur); err != nil { + return err + } + + if invariants.Enabled { + // Since we aren't returning an error, we _must_ have transitioned to a + // file-only snapshot by now. + if !es.hasTransitioned() { + panic("expected EFOS to have transitioned to file-only snapshot after flush") + } + } + return nil +} + +// Close closes the file-only snapshot and releases all referenced resources. +// Not idempotent. +func (es *EventuallyFileOnlySnapshot) Close() error { + close(es.closed) + es.db.mu.Lock() + defer es.db.mu.Unlock() + es.mu.Lock() + defer es.mu.Unlock() + + if es.mu.snap != nil { + if err := es.mu.snap.closeLocked(); err != nil { + return err + } + } + if es.mu.vers != nil { + es.mu.vers.UnrefLocked() + } + return nil +} + +// Get implements the Reader interface. +func (es *EventuallyFileOnlySnapshot) Get(key []byte) (value []byte, closer io.Closer, err error) { + // TODO(jackson): Use getInternal. + iter, err := es.NewIter(nil) + if err != nil { + return nil, nil, err + } + var valid bool + if es.db.opts.Comparer.Split != nil { + valid = iter.SeekPrefixGE(key) + } else { + valid = iter.SeekGE(key) + } + if !valid { + if err = firstError(iter.Error(), iter.Close()); err != nil { + return nil, nil, err + } + return nil, nil, ErrNotFound + } + if !es.db.equal(iter.Key(), key) { + return nil, nil, firstError(iter.Close(), ErrNotFound) + } + return iter.Value(), iter, nil +} + +// NewIter returns an iterator that is unpositioned (Iterator.Valid() will +// return false). The iterator can be positioned via a call to SeekGE, +// SeekLT, First or Last. +func (es *EventuallyFileOnlySnapshot) NewIter(o *IterOptions) (*Iterator, error) { + return es.NewIterWithContext(context.Background(), o) +} + +// NewIterWithContext is like NewIter, and additionally accepts a context for +// tracing. +func (es *EventuallyFileOnlySnapshot) NewIterWithContext( + ctx context.Context, o *IterOptions, +) (*Iterator, error) { + select { + case <-es.closed: + panic(ErrClosed) + default: + } + + es.mu.Lock() + defer es.mu.Unlock() + if es.mu.vers != nil { + sOpts := snapshotIterOpts{seqNum: es.seqNum, vers: es.mu.vers} + return es.db.newIter(ctx, nil /* batch */, newIterOpts{snapshot: sOpts}, o), nil + } + + if es.excised.Load() { + return nil, ErrSnapshotExcised + } + sOpts := snapshotIterOpts{seqNum: es.seqNum} + iter := es.db.newIter(ctx, nil /* batch */, newIterOpts{snapshot: sOpts}, o) + + // If excised is true, then keys relevant to the snapshot might not be + // present in the readState being used by the iterator. Error out. + if es.excised.Load() { + iter.Close() + return nil, ErrSnapshotExcised + } + return iter, nil +} + +// ScanInternal scans all internal keys within the specified bounds, truncating +// any rangedels and rangekeys to those bounds. For use when an external user +// needs to be aware of all internal keys that make up a key range. +// +// See comment on db.ScanInternal for the behaviour that can be expected of +// point keys deleted by range dels and keys masked by range keys. +func (es *EventuallyFileOnlySnapshot) ScanInternal( + ctx context.Context, + categoryAndQoS sstable.CategoryAndQoS, + lower, upper []byte, + visitPointKey func(key *InternalKey, value LazyValue, iterInfo IteratorLevel) error, + visitRangeDel func(start, end []byte, seqNum uint64) error, + visitRangeKey func(start, end []byte, keys []rangekey.Key) error, + visitSharedFile func(sst *SharedSSTMeta) error, +) error { + if es.db == nil { + panic(ErrClosed) + } + if es.excised.Load() { + return ErrSnapshotExcised + } + var sOpts snapshotIterOpts + es.mu.Lock() + if es.mu.vers != nil { + sOpts = snapshotIterOpts{ + seqNum: es.seqNum, + vers: es.mu.vers, + } + } else { + sOpts = snapshotIterOpts{ + seqNum: es.seqNum, + } + } + es.mu.Unlock() + opts := &scanInternalOptions{ + CategoryAndQoS: categoryAndQoS, + IterOptions: IterOptions{ + KeyTypes: IterKeyTypePointsAndRanges, + LowerBound: lower, + UpperBound: upper, + }, + visitPointKey: visitPointKey, + visitRangeDel: visitRangeDel, + visitRangeKey: visitRangeKey, + visitSharedFile: visitSharedFile, + skipSharedLevels: visitSharedFile != nil, + } + iter := es.db.newInternalIter(ctx, sOpts, opts) + defer iter.close() + + // If excised is true, then keys relevant to the snapshot might not be + // present in the readState being used by the iterator. Error out. + if es.excised.Load() { + return ErrSnapshotExcised + } + + return scanInternalImpl(ctx, lower, upper, iter, opts) +} diff --git a/vendor/github.com/cockroachdb/pebble/sstable/block.go b/vendor/github.com/cockroachdb/pebble/sstable/block.go index cbd2e5ce6..9634d2d9d 100644 --- a/vendor/github.com/cockroachdb/pebble/sstable/block.go +++ b/vendor/github.com/cockroachdb/pebble/sstable/block.go @@ -5,6 +5,7 @@ package sstable import ( + "context" "encoding/binary" "unsafe" @@ -688,8 +689,11 @@ func (i *blockIter) getFirstUserKey() []byte { // SeekGE implements internalIterator.SeekGE, as documented in the pebble // package. func (i *blockIter) SeekGE(key []byte, flags base.SeekGEFlags) (*InternalKey, base.LazyValue) { - i.clearCache() + if invariants.Enabled && i.isDataInvalidated() { + panic(errors.AssertionFailedf("invalidated blockIter used")) + } + i.clearCache() // Find the index of the smallest restart point whose key is > the key // sought; index will be numRestarts if there is no such restart point. i.offset = 0 @@ -818,8 +822,11 @@ func (i *blockIter) SeekPrefixGE( // SeekLT implements internalIterator.SeekLT, as documented in the pebble // package. func (i *blockIter) SeekLT(key []byte, flags base.SeekLTFlags) (*InternalKey, base.LazyValue) { - i.clearCache() + if invariants.Enabled && i.isDataInvalidated() { + panic(errors.AssertionFailedf("invalidated blockIter used")) + } + i.clearCache() // Find the index of the smallest restart point whose key is >= the key // sought; index will be numRestarts if there is no such restart point. i.offset = 0 @@ -986,6 +993,10 @@ func (i *blockIter) SeekLT(key []byte, flags base.SeekLTFlags) (*InternalKey, ba // First implements internalIterator.First, as documented in the pebble // package. func (i *blockIter) First() (*InternalKey, base.LazyValue) { + if invariants.Enabled && i.isDataInvalidated() { + panic(errors.AssertionFailedf("invalidated blockIter used")) + } + i.offset = 0 if !i.valid() { return nil, base.LazyValue{} @@ -1015,6 +1026,10 @@ func decodeRestart(b []byte) int32 { // Last implements internalIterator.Last, as documented in the pebble package. func (i *blockIter) Last() (*InternalKey, base.LazyValue) { + if invariants.Enabled && i.isDataInvalidated() { + panic(errors.AssertionFailedf("invalidated blockIter used")) + } + // Seek forward from the last restart point. i.offset = decodeRestart(i.data[i.restarts+4*(i.numRestarts-1):]) if !i.valid() { @@ -1526,6 +1541,8 @@ func (i *blockIter) SetBounds(lower, upper []byte) { panic("pebble: SetBounds unimplemented") } +func (i *blockIter) SetContext(_ context.Context) {} + func (i *blockIter) valid() bool { return i.offset >= 0 && i.offset < i.restarts } diff --git a/vendor/github.com/cockroachdb/pebble/sstable/block_property.go b/vendor/github.com/cockroachdb/pebble/sstable/block_property.go index 9bec5294d..f3a46ca60 100644 --- a/vendor/github.com/cockroachdb/pebble/sstable/block_property.go +++ b/vendor/github.com/cockroachdb/pebble/sstable/block_property.go @@ -189,13 +189,13 @@ type BoundLimitedBlockPropertyFilter interface { // indicates that the filter may be used to filter blocks that exclusively // contain keys ≥ `key`, so long as the blocks' keys also satisfy the upper // bound. - KeyIsWithinLowerBound(key *InternalKey) bool + KeyIsWithinLowerBound(key []byte) bool // KeyIsWithinUpperBound tests whether the provided internal key falls // within the current upper bound of the filter. A true return value // indicates that the filter may be used to filter blocks that exclusively // contain keys ≤ `key`, so long as the blocks' keys also satisfy the lower // bound. - KeyIsWithinUpperBound(key *InternalKey) bool + KeyIsWithinUpperBound(key []byte) bool } // BlockIntervalCollector is a helper implementation of BlockPropertyCollector diff --git a/vendor/github.com/cockroachdb/pebble/sstable/category_stats.go b/vendor/github.com/cockroachdb/pebble/sstable/category_stats.go new file mode 100644 index 000000000..bb2154d0e --- /dev/null +++ b/vendor/github.com/cockroachdb/pebble/sstable/category_stats.go @@ -0,0 +1,172 @@ +// Copyright 2018 The LevelDB-Go and Pebble Authors. All rights reserved. Use +// of this source code is governed by a BSD-style license that can be found in +// the LICENSE file. + +package sstable + +import ( + "cmp" + "slices" + "sync" + + "github.com/cockroachdb/errors" + "github.com/cockroachdb/redact" +) + +// Category is a user-understandable string, where stats are aggregated for +// each category. The cardinality of this should be low, say < 20. The prefix +// "pebble-" is reserved for internal Pebble categories. +// +// Examples of categories that can be useful in the CockroachDB context are: +// sql-user, sql-stats, raft, rangefeed, mvcc-gc, range-snapshot. +type Category string + +// QoSLevel describes whether the read is latency-sensitive or not. Each +// category must map to a single QoSLevel. While category strings are opaque +// to Pebble, the QoSLevel may be internally utilized in Pebble to better +// optimize future reads. +type QoSLevel int + +const ( + // LatencySensitiveQoSLevel is the default when QoSLevel is not specified, + // and represents reads that are latency-sensitive. + LatencySensitiveQoSLevel QoSLevel = iota + // NonLatencySensitiveQoSLevel represents reads that are not + // latency-sensitive. + NonLatencySensitiveQoSLevel +) + +// SafeFormat implements the redact.SafeFormatter interface. +func (q QoSLevel) SafeFormat(p redact.SafePrinter, verb rune) { + switch q { + case LatencySensitiveQoSLevel: + p.Printf("latency") + case NonLatencySensitiveQoSLevel: + p.Printf("non-latency") + default: + p.Printf("") + } +} + +// StringToQoSForTesting returns the QoSLevel for the string, or panics if the +// string is not known. +func StringToQoSForTesting(s string) QoSLevel { + switch s { + case "latency": + return LatencySensitiveQoSLevel + case "non-latency": + return NonLatencySensitiveQoSLevel + } + panic(errors.AssertionFailedf("unknown QoS %s", s)) +} + +// CategoryAndQoS specifies both the Category and the QoSLevel. +type CategoryAndQoS struct { + Category + QoSLevel +} + +// CategoryStats provides stats about a category of reads. +type CategoryStats struct { + // BlockBytes is the bytes in the loaded blocks. If the block was + // compressed, this is the compressed bytes. Currently, only the index + // blocks, data blocks containing points, and filter blocks are included. + // Additionally, value blocks read after the corresponding iterator is + // closed are not included. + BlockBytes uint64 + // BlockBytesInCache is the subset of BlockBytes that were in the block + // cache. + BlockBytesInCache uint64 +} + +func (s *CategoryStats) aggregate(a CategoryStats) { + s.BlockBytes += a.BlockBytes + s.BlockBytesInCache += a.BlockBytesInCache +} + +// CategoryStatsAggregate is the aggregate for the given category. +type CategoryStatsAggregate struct { + Category + QoSLevel + CategoryStats +} + +type categoryStatsWithMu struct { + mu sync.Mutex + // Protected by mu. + stats CategoryStatsAggregate +} + +// CategoryStatsCollector collects and aggregates the stats per category. +type CategoryStatsCollector struct { + // mu protects additions to statsMap. + mu sync.Mutex + // Category => categoryStatsWithMu. + statsMap sync.Map +} + +func (c *CategoryStatsCollector) reportStats( + category Category, qosLevel QoSLevel, stats CategoryStats, +) { + v, ok := c.statsMap.Load(category) + if !ok { + c.mu.Lock() + v, _ = c.statsMap.LoadOrStore(category, &categoryStatsWithMu{ + stats: CategoryStatsAggregate{Category: category, QoSLevel: qosLevel}, + }) + c.mu.Unlock() + } + aggStats := v.(*categoryStatsWithMu) + aggStats.mu.Lock() + aggStats.stats.CategoryStats.aggregate(stats) + aggStats.mu.Unlock() +} + +// GetStats returns the aggregated stats. +func (c *CategoryStatsCollector) GetStats() []CategoryStatsAggregate { + var stats []CategoryStatsAggregate + c.statsMap.Range(func(_, v any) bool { + aggStats := v.(*categoryStatsWithMu) + aggStats.mu.Lock() + s := aggStats.stats + aggStats.mu.Unlock() + if len(s.Category) == 0 { + s.Category = "_unknown" + } + stats = append(stats, s) + return true + }) + slices.SortFunc(stats, func(a, b CategoryStatsAggregate) int { + return cmp.Compare(a.Category, b.Category) + }) + return stats +} + +// iterStatsAccumulator is a helper for a sstable iterator to accumulate +// stats, which are reported to the CategoryStatsCollector when the +// accumulator is closed. +type iterStatsAccumulator struct { + Category + QoSLevel + stats CategoryStats + collector *CategoryStatsCollector +} + +func (accum *iterStatsAccumulator) init( + categoryAndQoS CategoryAndQoS, collector *CategoryStatsCollector, +) { + accum.Category = categoryAndQoS.Category + accum.QoSLevel = categoryAndQoS.QoSLevel + accum.collector = collector +} + +func (accum *iterStatsAccumulator) reportStats(blockBytes, blockBytesInCache uint64) { + accum.stats.BlockBytes += blockBytes + accum.stats.BlockBytesInCache += blockBytesInCache +} + +func (accum *iterStatsAccumulator) close() { + if accum.collector != nil { + accum.collector.reportStats(accum.Category, accum.QoSLevel, accum.stats) + } +} diff --git a/vendor/github.com/cockroachdb/pebble/sstable/format.go b/vendor/github.com/cockroachdb/pebble/sstable/format.go index a42ed7c39..82310a55b 100644 --- a/vendor/github.com/cockroachdb/pebble/sstable/format.go +++ b/vendor/github.com/cockroachdb/pebble/sstable/format.go @@ -25,8 +25,9 @@ const ( TableFormatPebblev2 // Range keys. TableFormatPebblev3 // Value blocks. TableFormatPebblev4 // DELSIZED tombstones. + NumTableFormats - TableFormatMax = TableFormatPebblev4 + TableFormatMax = NumTableFormats - 1 ) // TableFormatPebblev4, in addition to DELSIZED, introduces the use of diff --git a/vendor/github.com/cockroachdb/pebble/sstable/layout.go b/vendor/github.com/cockroachdb/pebble/sstable/layout.go index bff1e3019..8c375741d 100644 --- a/vendor/github.com/cockroachdb/pebble/sstable/layout.go +++ b/vendor/github.com/cockroachdb/pebble/sstable/layout.go @@ -6,10 +6,12 @@ package sstable import ( "bytes" + "cmp" "context" "encoding/binary" "fmt" "io" + "slices" "sort" "unsafe" @@ -86,10 +88,9 @@ func (l *Layout) Describe( } } - sort.Slice(blocks, func(i, j int) bool { - return blocks[i].Offset < blocks[j].Offset + slices.SortFunc(blocks, func(a, b block) int { + return cmp.Compare(a.Offset, b.Offset) }) - for i := range blocks { b := &blocks[i] fmt.Fprintf(w, "%10d %s (%d)\n", b.Offset, b.name, b.Length) @@ -144,7 +145,7 @@ func (l *Layout) Describe( } h, err := r.readBlock( - context.Background(), b.BlockHandle, nil /* transform */, nil /* readHandle */, nil /* stats */, nil /* buffer pool */) + context.Background(), b.BlockHandle, nil /* transform */, nil /* readHandle */, nil /* stats */, nil /* iterStats */, nil /* buffer pool */) if err != nil { fmt.Fprintf(w, " [err: %s]\n", err) continue diff --git a/vendor/github.com/cockroachdb/pebble/sstable/properties.go b/vendor/github.com/cockroachdb/pebble/sstable/properties.go index 004d14ad3..6b224d62a 100644 --- a/vendor/github.com/cockroachdb/pebble/sstable/properties.go +++ b/vendor/github.com/cockroachdb/pebble/sstable/properties.go @@ -25,10 +25,20 @@ var propBoolFalse = []byte{'0'} var propOffsetTagMap = make(map[uintptr]string) -func init() { - t := reflect.TypeOf(Properties{}) +func generateTagMaps(t reflect.Type) { for i := 0; i < t.NumField(); i++ { f := t.Field(i) + if f.Type.Kind() == reflect.Struct { + if tag := f.Tag.Get("prop"); i == 0 && tag == "pebble.embbeded_common_properties" { + // CommonProperties struct embedded in Properties. Note that since + // CommonProperties is placed at the top of properties we can use + // the offsets of the fields within CommonProperties to determine + // the offsets of those fields within Properties. + generateTagMaps(f.Type) + continue + } + panic("pebble: unknown struct type in Properties") + } if tag := f.Tag.Get("prop"); tag != "" { switch f.Type.Kind() { case reflect.Bool: @@ -44,10 +54,75 @@ func init() { } } +func init() { + t := reflect.TypeOf(Properties{}) + generateTagMaps(t) +} + +// CommonProperties holds properties for either a virtual or a physical sstable. This +// can be used by code which doesn't care to make the distinction between physical +// and virtual sstables properties. +// +// For virtual sstables, fields are constructed through extrapolation upon virtual +// reader construction. See MakeVirtualReader for implementation details. +// +// NB: The values of these properties can affect correctness. For example, +// if NumRangeKeySets == 0, but the sstable actually contains range keys, then +// the iterators will behave incorrectly. +type CommonProperties struct { + // The number of entries in this table. + NumEntries uint64 `prop:"rocksdb.num.entries"` + // Total raw key size. + RawKeySize uint64 `prop:"rocksdb.raw.key.size"` + // Total raw value size. + RawValueSize uint64 `prop:"rocksdb.raw.value.size"` + // Total raw key size of point deletion tombstones. This value is comparable + // to RawKeySize. + RawPointTombstoneKeySize uint64 `prop:"pebble.raw.point-tombstone.key.size"` + // Sum of the raw value sizes carried by point deletion tombstones + // containing size estimates. See the DeleteSized key kind. This value is + // comparable to Raw{Key,Value}Size. + RawPointTombstoneValueSize uint64 `prop:"pebble.raw.point-tombstone.value.size"` + // The number of point deletion entries ("tombstones") in this table that + // carry a size hint indicating the size of the value the tombstone deletes. + NumSizedDeletions uint64 `prop:"pebble.num.deletions.sized"` + // The number of deletion entries in this table, including both point and + // range deletions. + NumDeletions uint64 `prop:"rocksdb.deleted.keys"` + // The number of range deletions in this table. + NumRangeDeletions uint64 `prop:"rocksdb.num.range-deletions"` + // The number of RANGEKEYDELs in this table. + NumRangeKeyDels uint64 `prop:"pebble.num.range-key-dels"` + // The number of RANGEKEYSETs in this table. + NumRangeKeySets uint64 `prop:"pebble.num.range-key-sets"` + // Total size of value blocks and value index block. Only serialized if > 0. + ValueBlocksSize uint64 `prop:"pebble.value-blocks.size"` +} + +// String is only used for testing purposes. +func (c *CommonProperties) String() string { + var buf bytes.Buffer + v := reflect.ValueOf(*c) + loaded := make(map[uintptr]struct{}) + writeProperties(loaded, v, &buf) + return buf.String() +} + +// NumPointDeletions is the number of point deletions in the sstable. For virtual +// sstables, this is an estimate. +func (c *CommonProperties) NumPointDeletions() uint64 { + return c.NumDeletions - c.NumRangeDeletions +} + // Properties holds the sstable property values. The properties are // automatically populated during sstable creation and load from the properties // meta block when an sstable is opened. type Properties struct { + // CommonProperties needs to be at the top of the Properties struct so that the + // offsets of the fields in CommonProperties match the offsets of the embedded + // fields of CommonProperties in Properties. + CommonProperties `prop:"pebble.embbeded_common_properties"` + // The name of the comparer used in this table. ComparerName string `prop:"rocksdb.comparator"` // The compression algorithm used to compress blocks. @@ -81,22 +156,8 @@ type Properties struct { MergerName string `prop:"rocksdb.merge.operator"` // The number of blocks in this table. NumDataBlocks uint64 `prop:"rocksdb.num.data.blocks"` - // The number of deletion entries in this table, including both point and - // range deletions. - NumDeletions uint64 `prop:"rocksdb.deleted.keys"` - // The number of point deletion entries ("tombstones") in this table that - // carry a size hint indicating the size of the value the tombstone deletes. - NumSizedDeletions uint64 `prop:"pebble.num.deletions.sized"` - // The number of entries in this table. - NumEntries uint64 `prop:"rocksdb.num.entries"` // The number of merge operands in the table. NumMergeOperands uint64 `prop:"rocksdb.merge.operands"` - // The number of range deletions in this table. - NumRangeDeletions uint64 `prop:"rocksdb.num.range-deletions"` - // The number of RANGEKEYDELs in this table. - NumRangeKeyDels uint64 `prop:"pebble.num.range-key-dels"` - // The number of RANGEKEYSETs in this table. - NumRangeKeySets uint64 `prop:"pebble.num.range-key-sets"` // The number of RANGEKEYUNSETs in this table. NumRangeKeyUnsets uint64 `prop:"pebble.num.range-key-unsets"` // The number of value blocks in this table. Only serialized if > 0. @@ -111,21 +172,10 @@ type Properties struct { // A comma separated list of names of the property collectors used in this // table. PropertyCollectorNames string `prop:"rocksdb.property.collectors"` - // Total raw key size. - RawKeySize uint64 `prop:"rocksdb.raw.key.size"` - // Total raw key size of point deletion tombstones. This value is comparable - // to RawKeySize. - RawPointTombstoneKeySize uint64 `prop:"pebble.raw.point-tombstone.key.size"` - // Sum of the raw value sizes carried by point deletion tombstones - // containing size estimates. See the DeleteSized key kind. This value is - // comparable to Raw{Key,Value}Size. - RawPointTombstoneValueSize uint64 `prop:"pebble.raw.point-tombstone.value.size"` // Total raw rangekey key size. RawRangeKeyKeySize uint64 `prop:"pebble.raw.range-key.key.size"` // Total raw rangekey value size. RawRangeKeyValueSize uint64 `prop:"pebble.raw.range-key.value.size"` - // Total raw value size. - RawValueSize uint64 `prop:"rocksdb.raw.value.size"` // The total number of keys in this table that were pinned by open snapshots. SnapshotPinnedKeys uint64 `prop:"pebble.num.snapshot-pinned-keys"` // The cumulative bytes of keys in this table that were pinned by @@ -138,8 +188,6 @@ type Properties struct { TopLevelIndexSize uint64 `prop:"rocksdb.top-level.index.size"` // User collected properties. UserProperties map[string]string - // Total size of value blocks and value index block. Only serialized if > 0. - ValueBlocksSize uint64 `prop:"pebble.value-blocks.size"` // If filtering is enabled, was the filter created on the whole key. WholeKeyFiltering bool `prop:"rocksdb.block.based.table.whole.key.filtering"` @@ -160,12 +208,15 @@ func (p *Properties) NumRangeKeys() uint64 { return p.NumRangeKeyDels + p.NumRangeKeySets + p.NumRangeKeyUnsets } -func (p *Properties) String() string { - var buf bytes.Buffer - v := reflect.ValueOf(*p) +func writeProperties(loaded map[uintptr]struct{}, v reflect.Value, buf *bytes.Buffer) { vt := v.Type() for i := 0; i < v.NumField(); i++ { ft := vt.Field(i) + if ft.Type.Kind() == reflect.Struct { + // Embedded struct within the properties. + writeProperties(loaded, v.Field(i), buf) + continue + } tag := ft.Tag.Get("prop") if tag == "" { continue @@ -175,25 +226,33 @@ func (p *Properties) String() string { // TODO(peter): Use f.IsZero() when we can rely on go1.13. if zero := reflect.Zero(f.Type()); zero.Interface() == f.Interface() { // Skip printing of zero values which were not loaded from disk. - if _, ok := p.Loaded[ft.Offset]; !ok { + if _, ok := loaded[ft.Offset]; !ok { continue } } - fmt.Fprintf(&buf, "%s: ", tag) + fmt.Fprintf(buf, "%s: ", tag) switch ft.Type.Kind() { case reflect.Bool: - fmt.Fprintf(&buf, "%t\n", f.Bool()) + fmt.Fprintf(buf, "%t\n", f.Bool()) case reflect.Uint32: - fmt.Fprintf(&buf, "%d\n", f.Uint()) + fmt.Fprintf(buf, "%d\n", f.Uint()) case reflect.Uint64: - fmt.Fprintf(&buf, "%d\n", f.Uint()) + fmt.Fprintf(buf, "%d\n", f.Uint()) case reflect.String: - fmt.Fprintf(&buf, "%s\n", f.String()) + fmt.Fprintf(buf, "%s\n", f.String()) default: panic("not reached") } } +} + +func (p *Properties) String() string { + var buf bytes.Buffer + v := reflect.ValueOf(*p) + writeProperties(p.Loaded, v, &buf) + + // Write the UserProperties. keys := make([]string, 0, len(p.UserProperties)) for key := range p.UserProperties { keys = append(keys, key) @@ -217,7 +276,7 @@ func (p *Properties) load( for valid := i.First(); valid; valid = i.Next() { if f, ok := propTagMap[string(i.Key().UserKey)]; ok { p.Loaded[f.Offset] = struct{}{} - field := v.FieldByIndex(f.Index) + field := v.FieldByName(f.Name) switch f.Type.Kind() { case reflect.Bool: field.SetBool(bytes.Equal(i.Value(), propBoolTrue)) diff --git a/vendor/github.com/cockroachdb/pebble/sstable/reader.go b/vendor/github.com/cockroachdb/pebble/sstable/reader.go index 109022710..14b728e4b 100644 --- a/vendor/github.com/cockroachdb/pebble/sstable/reader.go +++ b/vendor/github.com/cockroachdb/pebble/sstable/reader.go @@ -6,11 +6,12 @@ package sstable import ( "bytes" + "cmp" "context" "encoding/binary" "io" "os" - "sort" + "slices" "time" "github.com/cespare/xxhash/v2" @@ -174,6 +175,32 @@ func init() { private.SSTableRawTombstonesOpt = rawTombstonesOpt{} } +// CommonReader abstracts functionality over a Reader or a VirtualReader. This +// can be used by code which doesn't care to distinguish between a reader and a +// virtual reader. +type CommonReader interface { + NewRawRangeKeyIter() (keyspan.FragmentIterator, error) + NewRawRangeDelIter() (keyspan.FragmentIterator, error) + NewIterWithBlockPropertyFiltersAndContextEtc( + ctx context.Context, lower, upper []byte, + filterer *BlockPropertiesFilterer, + hideObsoletePoints, useFilterBlock bool, + stats *base.InternalIteratorStats, + categoryAndQoS CategoryAndQoS, + statsCollector *CategoryStatsCollector, + rp ReaderProvider, + ) (Iterator, error) + NewCompactionIter( + bytesIterated *uint64, + categoryAndQoS CategoryAndQoS, + statsCollector *CategoryStatsCollector, + rp ReaderProvider, + bufferPool *BufferPool, + ) (Iterator, error) + EstimateDiskUsage(start, end []byte) (uint64, error) + CommonProperties() *CommonProperties +} + // Reader is a table reader. type Reader struct { readable objstorage.Readable @@ -236,12 +263,13 @@ func (r *Reader) NewIterWithBlockPropertyFilters( filterer *BlockPropertiesFilterer, useFilterBlock bool, stats *base.InternalIteratorStats, + categoryAndQoS CategoryAndQoS, + statsCollector *CategoryStatsCollector, rp ReaderProvider, ) (Iterator, error) { return r.newIterWithBlockPropertyFiltersAndContext( - context.Background(), - lower, upper, filterer, false, useFilterBlock, stats, rp, nil, - ) + context.Background(), lower, upper, filterer, false, useFilterBlock, stats, + categoryAndQoS, statsCollector, rp, nil) } // NewIterWithBlockPropertyFiltersAndContextEtc is similar to @@ -257,11 +285,13 @@ func (r *Reader) NewIterWithBlockPropertyFiltersAndContextEtc( filterer *BlockPropertiesFilterer, hideObsoletePoints, useFilterBlock bool, stats *base.InternalIteratorStats, + categoryAndQoS CategoryAndQoS, + statsCollector *CategoryStatsCollector, rp ReaderProvider, ) (Iterator, error) { return r.newIterWithBlockPropertyFiltersAndContext( - ctx, lower, upper, filterer, hideObsoletePoints, useFilterBlock, stats, rp, nil, - ) + ctx, lower, upper, filterer, hideObsoletePoints, useFilterBlock, stats, categoryAndQoS, + statsCollector, rp, nil) } // TryAddBlockPropertyFilterForHideObsoletePoints is expected to be called @@ -287,6 +317,8 @@ func (r *Reader) newIterWithBlockPropertyFiltersAndContext( hideObsoletePoints bool, useFilterBlock bool, stats *base.InternalIteratorStats, + categoryAndQoS CategoryAndQoS, + statsCollector *CategoryStatsCollector, rp ReaderProvider, v *virtualState, ) (Iterator, error) { @@ -295,7 +327,8 @@ func (r *Reader) newIterWithBlockPropertyFiltersAndContext( // until the final iterator closes. if r.Properties.IndexType == twoLevelIndex { i := twoLevelIterPool.Get().(*twoLevelIterator) - err := i.init(ctx, r, v, lower, upper, filterer, useFilterBlock, hideObsoletePoints, stats, rp, nil /* bufferPool */) + err := i.init(ctx, r, v, lower, upper, filterer, useFilterBlock, hideObsoletePoints, stats, + categoryAndQoS, statsCollector, rp, nil /* bufferPool */) if err != nil { return nil, err } @@ -303,7 +336,8 @@ func (r *Reader) newIterWithBlockPropertyFiltersAndContext( } i := singleLevelIterPool.Get().(*singleLevelIterator) - err := i.init(ctx, r, v, lower, upper, filterer, useFilterBlock, hideObsoletePoints, stats, rp, nil /* bufferPool */) + err := i.init(ctx, r, v, lower, upper, filterer, useFilterBlock, hideObsoletePoints, stats, + categoryAndQoS, statsCollector, rp, nil /* bufferPool */) if err != nil { return nil, err } @@ -317,20 +351,29 @@ func (r *Reader) newIterWithBlockPropertyFiltersAndContext( func (r *Reader) NewIter(lower, upper []byte) (Iterator, error) { return r.NewIterWithBlockPropertyFilters( lower, upper, nil, true /* useFilterBlock */, nil, /* stats */ - TrivialReaderProvider{Reader: r}) + CategoryAndQoS{}, nil /*statsCollector */, TrivialReaderProvider{Reader: r}) } // NewCompactionIter returns an iterator similar to NewIter but it also increments // the number of bytes iterated. If an error occurs, NewCompactionIter cleans up // after itself and returns a nil iterator. func (r *Reader) NewCompactionIter( - bytesIterated *uint64, rp ReaderProvider, bufferPool *BufferPool, + bytesIterated *uint64, + categoryAndQoS CategoryAndQoS, + statsCollector *CategoryStatsCollector, + rp ReaderProvider, + bufferPool *BufferPool, ) (Iterator, error) { - return r.newCompactionIter(bytesIterated, rp, nil, bufferPool) + return r.newCompactionIter(bytesIterated, categoryAndQoS, statsCollector, rp, nil, bufferPool) } func (r *Reader) newCompactionIter( - bytesIterated *uint64, rp ReaderProvider, v *virtualState, bufferPool *BufferPool, + bytesIterated *uint64, + categoryAndQoS CategoryAndQoS, + statsCollector *CategoryStatsCollector, + rp ReaderProvider, + v *virtualState, + bufferPool *BufferPool, ) (Iterator, error) { if r.Properties.IndexType == twoLevelIndex { i := twoLevelIterPool.Get().(*twoLevelIterator) @@ -338,7 +381,7 @@ func (r *Reader) newCompactionIter( context.Background(), r, v, nil /* lower */, nil /* upper */, nil, false /* useFilter */, false, /* hideObsoletePoints */ - nil /* stats */, rp, bufferPool, + nil /* stats */, categoryAndQoS, statsCollector, rp, bufferPool, ) if err != nil { return nil, err @@ -353,7 +396,7 @@ func (r *Reader) newCompactionIter( err := i.init( context.Background(), r, v, nil /* lower */, nil, /* upper */ nil, false /* useFilter */, false, /* hideObsoletePoints */ - nil /* stats */, rp, bufferPool, + nil /* stats */, categoryAndQoS, statsCollector, rp, bufferPool, ) if err != nil { return nil, err @@ -375,7 +418,7 @@ func (r *Reader) NewRawRangeDelIter() (keyspan.FragmentIterator, error) { if r.rangeDelBH.Length == 0 { return nil, nil } - h, err := r.readRangeDel(nil /* stats */) + h, err := r.readRangeDel(nil /* stats */, nil /* iterStats */) if err != nil { return nil, err } @@ -396,7 +439,7 @@ func (r *Reader) NewRawRangeKeyIter() (keyspan.FragmentIterator, error) { if r.rangeKeyBH.Length == 0 { return nil, nil } - h, err := r.readRangeKey(nil /* stats */) + h, err := r.readRangeKey(nil /* stats */, nil /* iterStats */) if err != nil { return nil, err } @@ -419,27 +462,31 @@ func (i *rangeKeyFragmentBlockIter) Close() error { } func (r *Reader) readIndex( - ctx context.Context, stats *base.InternalIteratorStats, + ctx context.Context, stats *base.InternalIteratorStats, iterStats *iterStatsAccumulator, ) (bufferHandle, error) { ctx = objiotracing.WithBlockType(ctx, objiotracing.MetadataBlock) - return r.readBlock(ctx, r.indexBH, nil, nil, stats, nil /* buffer pool */) + return r.readBlock(ctx, r.indexBH, nil, nil, stats, iterStats, nil /* buffer pool */) } func (r *Reader) readFilter( - ctx context.Context, stats *base.InternalIteratorStats, + ctx context.Context, stats *base.InternalIteratorStats, iterStats *iterStatsAccumulator, ) (bufferHandle, error) { ctx = objiotracing.WithBlockType(ctx, objiotracing.FilterBlock) - return r.readBlock(ctx, r.filterBH, nil /* transform */, nil /* readHandle */, stats, nil /* buffer pool */) + return r.readBlock(ctx, r.filterBH, nil /* transform */, nil /* readHandle */, stats, iterStats, nil /* buffer pool */) } -func (r *Reader) readRangeDel(stats *base.InternalIteratorStats) (bufferHandle, error) { +func (r *Reader) readRangeDel( + stats *base.InternalIteratorStats, iterStats *iterStatsAccumulator, +) (bufferHandle, error) { ctx := objiotracing.WithBlockType(context.Background(), objiotracing.MetadataBlock) - return r.readBlock(ctx, r.rangeDelBH, r.rangeDelTransform, nil /* readHandle */, stats, nil /* buffer pool */) + return r.readBlock(ctx, r.rangeDelBH, r.rangeDelTransform, nil /* readHandle */, stats, iterStats, nil /* buffer pool */) } -func (r *Reader) readRangeKey(stats *base.InternalIteratorStats) (bufferHandle, error) { +func (r *Reader) readRangeKey( + stats *base.InternalIteratorStats, iterStats *iterStatsAccumulator, +) (bufferHandle, error) { ctx := objiotracing.WithBlockType(context.Background(), objiotracing.MetadataBlock) - return r.readBlock(ctx, r.rangeKeyBH, nil /* transform */, nil /* readHandle */, stats, nil /* buffer pool */) + return r.readBlock(ctx, r.rangeKeyBH, nil /* transform */, nil /* readHandle */, stats, iterStats, nil /* buffer pool */) } func checkChecksum( @@ -500,6 +547,7 @@ func (r *Reader) readBlock( transform blockTransform, readHandle objstorage.ReadHandle, stats *base.InternalIteratorStats, + iterStats *iterStatsAccumulator, bufferPool *BufferPool, ) (handle bufferHandle, _ error) { if h := r.opts.Cache.Get(r.cacheID, r.fileNum, bh.Offset); h.Get() != nil { @@ -511,6 +559,9 @@ func (r *Reader) readBlock( stats.BlockBytes += bh.Length stats.BlockBytesInCache += bh.Length } + if iterStats != nil { + iterStats.reportStats(bh.Length, bh.Length) + } // This block is already in the cache; return a handle to existing vlaue // in the cache. return bufferHandle{h: h}, nil @@ -609,6 +660,9 @@ func (r *Reader) readBlock( if stats != nil { stats.BlockBytes += bh.Length } + if iterStats != nil { + iterStats.reportStats(bh.Length, 0) + } if decompressed.buf.Valid() { return bufferHandle{b: decompressed.buf}, nil } @@ -674,7 +728,8 @@ func (r *Reader) readMetaindex(metaindexBH BlockHandle) error { defer r.metaBufferPool.Release() b, err := r.readBlock( - context.Background(), metaindexBH, nil /* transform */, nil /* readHandle */, nil /* stats */, &r.metaBufferPool) + context.Background(), metaindexBH, nil /* transform */, nil /* readHandle */, nil, /* stats */ + nil /* iterStats */, &r.metaBufferPool) if err != nil { return err } @@ -717,7 +772,8 @@ func (r *Reader) readMetaindex(metaindexBH BlockHandle) error { if bh, ok := meta[metaPropertiesName]; ok { b, err = r.readBlock( - context.Background(), bh, nil /* transform */, nil /* readHandle */, nil /* stats */, nil /* buffer pool */) + context.Background(), bh, nil /* transform */, nil /* readHandle */, nil, /* stats */ + nil /* iterStats */, nil /* buffer pool */) if err != nil { return err } @@ -790,7 +846,7 @@ func (r *Reader) Layout() (*Layout, error) { Format: r.tableFormat, } - indexH, err := r.readIndex(context.Background(), nil) + indexH, err := r.readIndex(context.Background(), nil, nil) if err != nil { return nil, err } @@ -823,7 +879,7 @@ func (r *Reader) Layout() (*Layout, error) { l.Index = append(l.Index, indexBH.BlockHandle) subIndex, err := r.readBlock(context.Background(), indexBH.BlockHandle, - nil /* transform */, nil /* readHandle */, nil /* stats */, nil /* buffer pool */) + nil /* transform */, nil /* readHandle */, nil /* stats */, nil /* iterStats */, nil /* buffer pool */) if err != nil { return nil, err } @@ -846,7 +902,7 @@ func (r *Reader) Layout() (*Layout, error) { } } if r.valueBIH.h.Length != 0 { - vbiH, err := r.readBlock(context.Background(), r.valueBIH.h, nil, nil, nil, nil /* buffer pool */) + vbiH, err := r.readBlock(context.Background(), r.valueBIH.h, nil, nil, nil, nil, nil /* buffer pool */) if err != nil { return nil, err } @@ -901,8 +957,8 @@ func (r *Reader) ValidateBlockChecksums() error { // Sorting by offset ensures we are performing a sequential scan of the // file. - sort.Slice(blocks, func(i, j int) bool { - return blocks[i].Offset < blocks[j].Offset + slices.SortFunc(blocks, func(a, b BlockHandle) int { + return cmp.Compare(a.Offset, b.Offset) }) // Check all blocks sequentially. Make use of read-ahead, given we are @@ -917,7 +973,7 @@ func (r *Reader) ValidateBlockChecksums() error { } // Read the block, which validates the checksum. - h, err := r.readBlock(context.Background(), bh, nil, rh, nil, nil /* buffer pool */) + h, err := r.readBlock(context.Background(), bh, nil, rh, nil, nil /* iterStats */, nil /* buffer pool */) if err != nil { return err } @@ -927,6 +983,11 @@ func (r *Reader) ValidateBlockChecksums() error { return nil } +// CommonProperties implemented the CommonReader interface. +func (r *Reader) CommonProperties() *CommonProperties { + return &r.Properties.CommonProperties +} + // EstimateDiskUsage returns the total size of data blocks overlapping the range // `[start, end]`. Even if a data block partially overlaps, or we cannot // determine overlap due to abbreviated index keys, the full data block size is @@ -947,7 +1008,7 @@ func (r *Reader) EstimateDiskUsage(start, end []byte) (uint64, error) { return 0, r.err } - indexH, err := r.readIndex(context.Background(), nil) + indexH, err := r.readIndex(context.Background(), nil, nil) if err != nil { return 0, err } @@ -980,7 +1041,7 @@ func (r *Reader) EstimateDiskUsage(start, end []byte) (uint64, error) { return 0, errCorruptIndexEntry } startIdxBlock, err := r.readBlock(context.Background(), startIdxBH.BlockHandle, - nil /* transform */, nil /* readHandle */, nil /* stats */, nil /* buffer pool */) + nil /* transform */, nil /* readHandle */, nil /* stats */, nil /* iterStats */, nil /* buffer pool */) if err != nil { return 0, err } @@ -1001,7 +1062,7 @@ func (r *Reader) EstimateDiskUsage(start, end []byte) (uint64, error) { return 0, errCorruptIndexEntry } endIdxBlock, err := r.readBlock(context.Background(), - endIdxBH.BlockHandle, nil /* transform */, nil /* readHandle */, nil /* stats */, nil /* buffer pool */) + endIdxBH.BlockHandle, nil /* transform */, nil /* readHandle */, nil /* stats */, nil /* iterStats */, nil /* buffer pool */) if err != nil { return 0, err } diff --git a/vendor/github.com/cockroachdb/pebble/sstable/reader_iter_single_lvl.go b/vendor/github.com/cockroachdb/pebble/sstable/reader_iter_single_lvl.go index 4fd22bad6..60af84055 100644 --- a/vendor/github.com/cockroachdb/pebble/sstable/reader_iter_single_lvl.go +++ b/vendor/github.com/cockroachdb/pebble/sstable/reader_iter_single_lvl.go @@ -52,8 +52,18 @@ type singleLevelIterator struct { vbRHPrealloc objstorageprovider.PreallocatedReadHandle err error closeHook func(i Iterator) error - stats *base.InternalIteratorStats - bufferPool *BufferPool + // stats and iterStats are slightly different. stats is a shared struct + // supplied from the outside, and represents stats for the whole iterator + // tree and can be reset from the outside (e.g. when the pebble.Iterator is + // being reused). It is currently only provided when the iterator tree is + // rooted at pebble.Iterator. iterStats is this sstable iterator's private + // stats that are reported to a CategoryStatsCollector when this iterator is + // closed. More paths are instrumented with this as the + // CategoryStatsCollector needed for this is provided by the + // tableCacheContainer (which is more universally used). + stats *base.InternalIteratorStats + iterStats iterStatsAccumulator + bufferPool *BufferPool // boundsCmp and positionedUsingLatestBounds are for optimizing iteration // that uses multiple adjacent bounds. The seek after setting a new bound @@ -174,13 +184,16 @@ func (i *singleLevelIterator) init( filterer *BlockPropertiesFilterer, useFilter, hideObsoletePoints bool, stats *base.InternalIteratorStats, + categoryAndQoS CategoryAndQoS, + statsCollector *CategoryStatsCollector, rp ReaderProvider, bufferPool *BufferPool, ) error { if r.err != nil { return r.err } - indexH, err := r.readIndex(ctx, stats) + i.iterStats.init(categoryAndQoS, statsCollector) + indexH, err := r.readIndex(ctx, stats, &i.iterStats) if err != nil { return err } @@ -218,7 +231,6 @@ func (i *singleLevelIterator) init( // separated to their callers, they can put this valueBlockReader into a // sync.Pool. i.vbReader = &valueBlockReader{ - ctx: ctx, bpOpen: i, rp: rp, vbih: r.valueBIH, @@ -302,6 +314,12 @@ func disableBoundsOpt(bound []byte, ptr uintptr) bool { return bound[len(bound)-1]&byte(1) == 0 && simpleHash == 0 } +// ensureBoundsOptDeterminism provides a facility for disabling of the bounds +// optimizations performed by disableBoundsOpt for tests that require +// deterministic iterator behavior. Some unit tests examine internal iterator +// state and require this behavior to be deterministic. +var ensureBoundsOptDeterminism bool + // SetBounds implements internalIterator.SetBounds, as documented in the pebble // package. Note that the upper field is exclusive. func (i *singleLevelIterator) SetBounds(lower, upper []byte) { @@ -320,12 +338,14 @@ func (i *singleLevelIterator) SetBounds(lower, upper []byte) { if i.positionedUsingLatestBounds { if i.upper != nil && lower != nil && i.cmp(i.upper, lower) <= 0 { i.boundsCmp = +1 - if invariants.Enabled && disableBoundsOpt(lower, uintptr(unsafe.Pointer(i))) { + if invariants.Enabled && !ensureBoundsOptDeterminism && + disableBoundsOpt(lower, uintptr(unsafe.Pointer(i))) { i.boundsCmp = 0 } } else if i.lower != nil && upper != nil && i.cmp(upper, i.lower) <= 0 { i.boundsCmp = -1 - if invariants.Enabled && disableBoundsOpt(upper, uintptr(unsafe.Pointer(i))) { + if invariants.Enabled && !ensureBoundsOptDeterminism && + disableBoundsOpt(upper, uintptr(unsafe.Pointer(i))) { i.boundsCmp = 0 } } @@ -339,6 +359,10 @@ func (i *singleLevelIterator) SetBounds(lower, upper []byte) { i.blockUpper = nil } +func (i *singleLevelIterator) SetContext(ctx context.Context) { + i.ctx = ctx +} + // loadBlock loads the block at the current index position and leaves i.data // unpositioned. If unsuccessful, it sets i.err to any error encountered, which // may be nil if we have simply exhausted the entire table. @@ -387,7 +411,8 @@ func (i *singleLevelIterator) loadBlock(dir int8) loadBlockResult { // blockIntersects } ctx := objiotracing.WithBlockType(i.ctx, objiotracing.DataBlock) - block, err := i.reader.readBlock(ctx, i.dataBH, nil /* transform */, i.dataRH, i.stats, i.bufferPool) + block, err := i.reader.readBlock( + ctx, i.dataBH, nil /* transform */, i.dataRH, i.stats, &i.iterStats, i.bufferPool) if err != nil { i.err = err return loadBlockFailed @@ -405,10 +430,10 @@ func (i *singleLevelIterator) loadBlock(dir int8) loadBlockResult { // readBlockForVBR implements the blockProviderWhenOpen interface for use by // the valueBlockReader. func (i *singleLevelIterator) readBlockForVBR( - ctx context.Context, h BlockHandle, stats *base.InternalIteratorStats, + h BlockHandle, stats *base.InternalIteratorStats, ) (bufferHandle, error) { - ctx = objiotracing.WithBlockType(ctx, objiotracing.ValueBlock) - return i.reader.readBlock(ctx, h, nil, i.vbRH, stats, i.bufferPool) + ctx := objiotracing.WithBlockType(i.ctx, objiotracing.ValueBlock) + return i.reader.readBlock(ctx, h, nil, i.vbRH, stats, &i.iterStats, i.bufferPool) } // resolveMaybeExcluded is invoked when the block-property filterer has found @@ -438,7 +463,7 @@ func (i *singleLevelIterator) resolveMaybeExcluded(dir int8) intersectsResult { // need. if dir > 0 { // Forward iteration. - if i.bpfs.boundLimitedFilter.KeyIsWithinUpperBound(i.index.Key()) { + if i.bpfs.boundLimitedFilter.KeyIsWithinUpperBound(i.index.Key().UserKey) { return blockExcluded } return blockIntersects @@ -467,7 +492,7 @@ func (i *singleLevelIterator) resolveMaybeExcluded(dir int8) intersectsResult { // there's a two-level index, it could potentially provide a lower // bound, but the code refactoring necessary to read it doesn't seem // worth the payoff. We fall through to loading the block. - } else if i.bpfs.boundLimitedFilter.KeyIsWithinLowerBound(peekKey) { + } else if i.bpfs.boundLimitedFilter.KeyIsWithinLowerBound(peekKey.UserKey) { // The lower-bound on the original block falls within the filter's // bounds, and we can skip the block (after restoring our current index // position). @@ -774,7 +799,7 @@ func (i *singleLevelIterator) seekPrefixGE( i.lastBloomFilterMatched = false // Check prefix bloom filter. var dataH bufferHandle - dataH, i.err = i.reader.readFilter(i.ctx, i.stats) + dataH, i.err = i.reader.readFilter(i.ctx, i.stats, &i.iterStats) if i.err != nil { i.data.invalidate() return nil, base.LazyValue{} @@ -1349,6 +1374,7 @@ func firstError(err0, err1 error) error { // Close implements internalIterator.Close, as documented in the pebble // package. func (i *singleLevelIterator) Close() error { + i.iterStats.close() var err error if i.closeHook != nil { err = firstError(err, i.closeHook(i)) diff --git a/vendor/github.com/cockroachdb/pebble/sstable/reader_iter_two_lvl.go b/vendor/github.com/cockroachdb/pebble/sstable/reader_iter_two_lvl.go index ce98fe8e3..8c4f4c450 100644 --- a/vendor/github.com/cockroachdb/pebble/sstable/reader_iter_two_lvl.go +++ b/vendor/github.com/cockroachdb/pebble/sstable/reader_iter_two_lvl.go @@ -32,6 +32,7 @@ func (i *twoLevelIterator) loadIndex(dir int8) loadBlockResult { // Ensure the index data block iterators are invalidated even if loading of // the index fails. i.data.invalidate() + i.index.invalidate() if !i.topLevelIndex.valid() { i.index.offset = 0 i.index.restarts = 0 @@ -59,7 +60,8 @@ func (i *twoLevelIterator) loadIndex(dir int8) loadBlockResult { // blockIntersects } ctx := objiotracing.WithBlockType(i.ctx, objiotracing.MetadataBlock) - indexBlock, err := i.reader.readBlock(ctx, bhp.BlockHandle, nil /* transform */, nil /* readHandle */, i.stats, i.bufferPool) + indexBlock, err := i.reader.readBlock( + ctx, bhp.BlockHandle, nil /* transform */, nil /* readHandle */, i.stats, &i.iterStats, i.bufferPool) if err != nil { i.err = err return loadBlockFailed @@ -93,7 +95,7 @@ func (i *twoLevelIterator) resolveMaybeExcluded(dir int8) intersectsResult { // are ≤ topLevelIndex.Key(). For forward iteration, this is all we need. if dir > 0 { // Forward iteration. - if i.bpfs.boundLimitedFilter.KeyIsWithinUpperBound(i.topLevelIndex.Key()) { + if i.bpfs.boundLimitedFilter.KeyIsWithinUpperBound(i.topLevelIndex.Key().UserKey) { return blockExcluded } return blockIntersects @@ -122,7 +124,7 @@ func (i *twoLevelIterator) resolveMaybeExcluded(dir int8) intersectsResult { // we knew the lower bound for the entire table, it could provide a // lower bound, but the code refactoring necessary to read it doesn't // seem worth the payoff. We fall through to loading the block. - } else if i.bpfs.boundLimitedFilter.KeyIsWithinLowerBound(peekKey) { + } else if i.bpfs.boundLimitedFilter.KeyIsWithinLowerBound(peekKey.UserKey) { // The lower-bound on the original index block falls within the filter's // bounds, and we can skip the block (after restoring our current // top-level index position). @@ -144,13 +146,16 @@ func (i *twoLevelIterator) init( filterer *BlockPropertiesFilterer, useFilter, hideObsoletePoints bool, stats *base.InternalIteratorStats, + categoryAndQoS CategoryAndQoS, + statsCollector *CategoryStatsCollector, rp ReaderProvider, bufferPool *BufferPool, ) error { if r.err != nil { return r.err } - topLevelIndexH, err := r.readIndex(ctx, stats) + i.iterStats.init(categoryAndQoS, statsCollector) + topLevelIndexH, err := r.readIndex(ctx, stats, &i.iterStats) if err != nil { return err } @@ -180,7 +185,6 @@ func (i *twoLevelIterator) init( if r.tableFormat >= TableFormatPebblev3 { if r.Properties.NumValueBlocks > 0 { i.vbReader = &valueBlockReader{ - ctx: ctx, bpOpen: i, rp: rp, vbih: r.valueBIH, @@ -259,8 +263,16 @@ func (i *twoLevelIterator) SeekGE( // the position of the two-level index iterator without remembering the // previous value of maybeFilteredKeys. + // We fall into the slow path if i.index.isDataInvalidated() even if the + // top-level iterator is already positioned correctly and all other + // conditions are met. An alternative structure could reuse topLevelIndex's + // current position and reload the index block to which it points. Arguably, + // an index block load is expensive and the index block may still be earlier + // than the index block containing the sought key, resulting in a wasteful + // block load. + var dontSeekWithinSingleLevelIter bool - if i.topLevelIndex.isDataInvalidated() || !i.topLevelIndex.valid() || err != nil || + if i.topLevelIndex.isDataInvalidated() || !i.topLevelIndex.valid() || i.index.isDataInvalidated() || err != nil || (i.boundsCmp <= 0 && !flags.TrySeekUsingNext()) || i.cmp(key, i.topLevelIndex.Key().UserKey) > 0 { // Slow-path: need to position the topLevelIndex. @@ -412,7 +424,7 @@ func (i *twoLevelIterator) SeekPrefixGE( } i.lastBloomFilterMatched = false var dataH bufferHandle - dataH, i.err = i.reader.readFilter(i.ctx, i.stats) + dataH, i.err = i.reader.readFilter(i.ctx, i.stats, &i.iterStats) if i.err != nil { i.data.invalidate() return nil, base.LazyValue{} @@ -447,8 +459,16 @@ func (i *twoLevelIterator) SeekPrefixGE( // not reuse the position of the two-level index iterator without // remembering the previous value of maybeFilteredKeysTwoLevel. + // We fall into the slow path if i.index.isDataInvalidated() even if the + // top-level iterator is already positioned correctly and all other + // conditions are met. An alternative structure could reuse topLevelIndex's + // current position and reload the index block to which it points. Arguably, + // an index block load is expensive and the index block may still be earlier + // than the index block containing the sought key, resulting in a wasteful + // block load. + var dontSeekWithinSingleLevelIter bool - if i.topLevelIndex.isDataInvalidated() || !i.topLevelIndex.valid() || err != nil || + if i.topLevelIndex.isDataInvalidated() || !i.topLevelIndex.valid() || i.index.isDataInvalidated() || err != nil || (i.boundsCmp <= 0 && !flags.TrySeekUsingNext()) || i.cmp(key, i.topLevelIndex.Key().UserKey) > 0 { // Slow-path: need to position the topLevelIndex. @@ -919,6 +939,7 @@ func (i *twoLevelIterator) skipBackward() (*InternalKey, base.LazyValue) { // Close implements internalIterator.Close, as documented in the pebble // package. func (i *twoLevelIterator) Close() error { + i.iterStats.close() var err error if i.closeHook != nil { err = firstError(err, i.closeHook(i)) diff --git a/vendor/github.com/cockroachdb/pebble/sstable/reader_virtual.go b/vendor/github.com/cockroachdb/pebble/sstable/reader_virtual.go index 0580dac1d..2653b5748 100644 --- a/vendor/github.com/cockroachdb/pebble/sstable/reader_virtual.go +++ b/vendor/github.com/cockroachdb/pebble/sstable/reader_virtual.go @@ -22,13 +22,7 @@ import ( type VirtualReader struct { vState virtualState reader *Reader - Properties struct { - // RawKeySize, RawValueSize are set upon construction of a - // VirtualReader. The values of the fields is extrapolated. See - // MakeVirtualReader for implementation details. - RawKeySize uint64 - RawValueSize uint64 - } + Properties CommonProperties } // Lightweight virtual sstable state which can be passed to sstable iterators. @@ -39,6 +33,10 @@ type virtualState struct { Compare Compare } +func ceilDiv(a, b uint64) uint64 { + return (a + b - 1) / b +} + // MakeVirtualReader is used to contruct a reader which can read from virtual // sstables. func MakeVirtualReader(reader *Reader, meta manifest.VirtualFileMeta) VirtualReader { @@ -57,19 +55,34 @@ func MakeVirtualReader(reader *Reader, meta manifest.VirtualFileMeta) VirtualRea reader: reader, } - v.Properties.RawKeySize = - (reader.Properties.RawKeySize * meta.Size) / meta.FileBacking.Size - v.Properties.RawValueSize = - (reader.Properties.RawValueSize * meta.Size) / meta.FileBacking.Size - + v.Properties.RawKeySize = ceilDiv(reader.Properties.RawKeySize*meta.Size, meta.FileBacking.Size) + v.Properties.RawValueSize = ceilDiv(reader.Properties.RawValueSize*meta.Size, meta.FileBacking.Size) + v.Properties.NumEntries = ceilDiv(reader.Properties.NumEntries*meta.Size, meta.FileBacking.Size) + v.Properties.NumDeletions = ceilDiv(reader.Properties.NumDeletions*meta.Size, meta.FileBacking.Size) + v.Properties.NumRangeDeletions = ceilDiv(reader.Properties.NumRangeDeletions*meta.Size, meta.FileBacking.Size) + v.Properties.NumRangeKeyDels = ceilDiv(reader.Properties.NumRangeKeyDels*meta.Size, meta.FileBacking.Size) + + // Note that we rely on NumRangeKeySets for correctness. If the sstable may + // contain range keys, then NumRangeKeySets must be > 0. ceilDiv works because + // meta.Size will not be 0 for virtual sstables. + v.Properties.NumRangeKeySets = ceilDiv(reader.Properties.NumRangeKeySets*meta.Size, meta.FileBacking.Size) + v.Properties.ValueBlocksSize = ceilDiv(reader.Properties.ValueBlocksSize*meta.Size, meta.FileBacking.Size) + v.Properties.NumSizedDeletions = ceilDiv(reader.Properties.NumSizedDeletions*meta.Size, meta.FileBacking.Size) + v.Properties.RawPointTombstoneKeySize = ceilDiv(reader.Properties.RawPointTombstoneKeySize*meta.Size, meta.FileBacking.Size) + v.Properties.RawPointTombstoneValueSize = ceilDiv(reader.Properties.RawPointTombstoneValueSize*meta.Size, meta.FileBacking.Size) return v } // NewCompactionIter is the compaction iterator function for virtual readers. func (v *VirtualReader) NewCompactionIter( - bytesIterated *uint64, rp ReaderProvider, bufferPool *BufferPool, + bytesIterated *uint64, + categoryAndQoS CategoryAndQoS, + statsCollector *CategoryStatsCollector, + rp ReaderProvider, + bufferPool *BufferPool, ) (Iterator, error) { - return v.reader.newCompactionIter(bytesIterated, rp, &v.vState, bufferPool) + return v.reader.newCompactionIter( + bytesIterated, categoryAndQoS, statsCollector, rp, &v.vState, bufferPool) } // NewIterWithBlockPropertyFiltersAndContextEtc wraps @@ -82,11 +95,19 @@ func (v *VirtualReader) NewIterWithBlockPropertyFiltersAndContextEtc( filterer *BlockPropertiesFilterer, hideObsoletePoints, useFilterBlock bool, stats *base.InternalIteratorStats, + categoryAndQoS CategoryAndQoS, + statsCollector *CategoryStatsCollector, rp ReaderProvider, ) (Iterator, error) { return v.reader.newIterWithBlockPropertyFiltersAndContext( - ctx, lower, upper, filterer, hideObsoletePoints, useFilterBlock, stats, rp, &v.vState, - ) + ctx, lower, upper, filterer, hideObsoletePoints, useFilterBlock, stats, + categoryAndQoS, statsCollector, rp, &v.vState) +} + +// ValidateBlockChecksumsOnBacking will call ValidateBlockChecksumsOnBacking on the underlying reader. +// Note that block checksum validation is NOT restricted to virtual sstable bounds. +func (v *VirtualReader) ValidateBlockChecksumsOnBacking() error { + return v.reader.ValidateBlockChecksums() } // NewRawRangeDelIter wraps Reader.NewRawRangeDelIter. @@ -181,3 +202,8 @@ func (v *VirtualReader) EstimateDiskUsage(start, end []byte) (uint64, error) { _, f, l := v.vState.constrainBounds(start, end, true /* endInclusive */) return v.reader.EstimateDiskUsage(f, l) } + +// CommonProperties implements the CommonReader interface. +func (v *VirtualReader) CommonProperties() *CommonProperties { + return &v.Properties +} diff --git a/vendor/github.com/cockroachdb/pebble/sstable/table.go b/vendor/github.com/cockroachdb/pebble/sstable/table.go index 040efafd6..2f36f3076 100644 --- a/vendor/github.com/cockroachdb/pebble/sstable/table.go +++ b/vendor/github.com/cockroachdb/pebble/sstable/table.go @@ -406,18 +406,14 @@ func (f footer) encode(buf []byte) []byte { switch magic, version := f.format.AsTuple(); magic { case levelDBMagic: buf = buf[:levelDBFooterLen] - for i := range buf { - buf[i] = 0 - } + clear(buf) n := encodeBlockHandle(buf[0:], f.metaindexBH) encodeBlockHandle(buf[n:], f.indexBH) copy(buf[len(buf)-len(levelDBMagic):], levelDBMagic) case rocksDBMagic, pebbleDBMagic: buf = buf[:rocksDBFooterLen] - for i := range buf { - buf[i] = 0 - } + clear(buf) switch f.checksum { case ChecksumTypeNone: buf[0] = byte(ChecksumTypeNone) diff --git a/vendor/github.com/cockroachdb/pebble/sstable/value_block.go b/vendor/github.com/cockroachdb/pebble/sstable/value_block.go index 447348bf5..ff8b05cf4 100644 --- a/vendor/github.com/cockroachdb/pebble/sstable/value_block.go +++ b/vendor/github.com/cockroachdb/pebble/sstable/value_block.go @@ -726,7 +726,7 @@ func (ukb *UserKeyPrefixBound) IsEmpty() bool { type blockProviderWhenOpen interface { readBlockForVBR( - ctx context.Context, h BlockHandle, stats *base.InternalIteratorStats, + h BlockHandle, stats *base.InternalIteratorStats, ) (bufferHandle, error) } @@ -747,13 +747,21 @@ func (bpwc *blockProviderWhenClosed) close() { } func (bpwc blockProviderWhenClosed) readBlockForVBR( - ctx context.Context, h BlockHandle, stats *base.InternalIteratorStats, + h BlockHandle, stats *base.InternalIteratorStats, ) (bufferHandle, error) { - ctx = objiotracing.WithBlockType(ctx, objiotracing.ValueBlock) + // This is rare, since most block reads happen when the corresponding + // sstable iterator is open. So we are willing to sacrifice a proper context + // for tracing. + // + // TODO(sumeer): consider fixing this. See + // https://github.com/cockroachdb/pebble/pull/3065#issue-1991175365 for an + // alternative. + ctx := objiotracing.WithBlockType(context.Background(), objiotracing.ValueBlock) // TODO(jackson,sumeer): Consider whether to use a buffer pool in this case. // The bpwc is not allowed to outlive the iterator tree, so it cannot // outlive the buffer pool. - return bpwc.r.readBlock(ctx, h, nil, nil, stats, nil /* buffer pool */) + return bpwc.r.readBlock( + ctx, h, nil, nil, stats, nil /* iterStats */, nil /* buffer pool */) } // ReaderProvider supports the implementation of blockProviderWhenClosed. @@ -783,7 +791,6 @@ func (trp TrivialReaderProvider) Close() {} // blocks. It is used when the sstable was written with // Properties.ValueBlocksAreEnabled. type valueBlockReader struct { - ctx context.Context bpOpen blockProviderWhenOpen rp ReaderProvider vbih valueBlocksIndexHandle @@ -883,9 +890,7 @@ func (r *valueBlockReader) doValueMangling(v []byte) []byte { // property P1 only requires the valueBlockReader to maintain the memory of // one fetched value. if rand.Intn(2) == 0 { - for i := range r.bufToMangle { - r.bufToMangle[i] = 0 - } + clear(r.bufToMangle) } // Store the current value in a new buffer for future mangling. r.bufToMangle = append([]byte(nil), v...) @@ -896,7 +901,7 @@ func (r *valueBlockReader) getValueInternal(handle []byte, valLen int32) (val [] vh := decodeRemainingValueHandle(handle) vh.valueLen = uint32(valLen) if r.vbiBlock == nil { - ch, err := r.bpOpen.readBlockForVBR(r.ctx, r.vbih.h, r.stats) + ch, err := r.bpOpen.readBlockForVBR(r.vbih.h, r.stats) if err != nil { return nil, err } @@ -908,7 +913,7 @@ func (r *valueBlockReader) getValueInternal(handle []byte, valLen int32) (val [] if err != nil { return nil, err } - vbCacheHandle, err := r.bpOpen.readBlockForVBR(r.ctx, vbh, r.stats) + vbCacheHandle, err := r.bpOpen.readBlockForVBR(vbh, r.stats) if err != nil { return nil, err } diff --git a/vendor/github.com/cockroachdb/pebble/table_cache.go b/vendor/github.com/cockroachdb/pebble/table_cache.go index 444b9250b..f72458628 100644 --- a/vendor/github.com/cockroachdb/pebble/table_cache.go +++ b/vendor/github.com/cockroachdb/pebble/table_cache.go @@ -9,7 +9,6 @@ import ( "context" "fmt" "io" - "math" "runtime/debug" "runtime/pprof" "sync" @@ -22,7 +21,6 @@ import ( "github.com/cockroachdb/pebble/internal/keyspan" "github.com/cockroachdb/pebble/internal/manifest" "github.com/cockroachdb/pebble/internal/private" - "github.com/cockroachdb/pebble/internal/rangekey" "github.com/cockroachdb/pebble/objstorage" "github.com/cockroachdb/pebble/objstorage/objstorageprovider/objiotracing" "github.com/cockroachdb/pebble/sstable" @@ -65,11 +63,12 @@ type tableCacheOpts struct { // track of leaked iterators on a per-db level. iterCount *atomic.Int32 - loggerAndTracer LoggerAndTracer - cacheID uint64 - objProvider objstorage.Provider - opts sstable.ReaderOptions - filterMetrics *sstable.FilterMetricsTracker + loggerAndTracer LoggerAndTracer + cacheID uint64 + objProvider objstorage.Provider + opts sstable.ReaderOptions + filterMetrics *sstable.FilterMetricsTracker + sstStatsCollector *sstable.CategoryStatsCollector } // tableCacheContainer contains the table cache and @@ -85,7 +84,12 @@ type tableCacheContainer struct { // newTableCacheContainer will panic if the underlying cache in the table cache // doesn't match Options.Cache. func newTableCacheContainer( - tc *TableCache, cacheID uint64, objProvider objstorage.Provider, opts *Options, size int, + tc *TableCache, + cacheID uint64, + objProvider objstorage.Provider, + opts *Options, + size int, + sstStatsCollector *sstable.CategoryStatsCollector, ) *tableCacheContainer { // We will release a ref to table cache acquired here when tableCacheContainer.close is called. if tc != nil { @@ -107,6 +111,7 @@ func newTableCacheContainer( t.dbOpts.opts = opts.MakeReaderOptions() t.dbOpts.filterMetrics = &sstable.FilterMetricsTracker{} t.dbOpts.iterCount = new(atomic.Int32) + t.dbOpts.sstStatsCollector = sstStatsCollector return t } @@ -196,6 +201,30 @@ func (c *tableCacheContainer) estimateSize( return size, nil } +func createCommonReader(v *tableCacheValue, file *fileMetadata) sstable.CommonReader { + // TODO(bananabrick): We suffer an allocation if file is a virtual sstable. + var cr sstable.CommonReader = v.reader + if file.Virtual { + virtualReader := sstable.MakeVirtualReader( + v.reader, file.VirtualMeta(), + ) + cr = &virtualReader + } + return cr +} + +func (c *tableCacheContainer) withCommonReader( + meta *fileMetadata, fn func(sstable.CommonReader) error, +) error { + s := c.tableCache.getShard(meta.FileBacking.DiskFileNum) + v := s.findNode(meta, &c.dbOpts) + defer s.unrefValue(v) + if v.err != nil { + return v.err + } + return fn(createCommonReader(v, meta)) +} + func (c *tableCacheContainer) withReader(meta physicalMeta, fn func(*sstable.Reader) error) error { s := c.tableCache.getShard(meta.FileBacking.DiskFileNum) v := s.findNode(meta.FileMetadata, &c.dbOpts) @@ -434,24 +463,8 @@ func (c *tableCacheShard) newIters( return nil, nil, err } - type iterCreator interface { - NewRawRangeDelIter() (keyspan.FragmentIterator, error) - NewIterWithBlockPropertyFiltersAndContextEtc(ctx context.Context, lower, upper []byte, filterer *sstable.BlockPropertiesFilterer, hideObsoletePoints, useFilterBlock bool, stats *base.InternalIteratorStats, rp sstable.ReaderProvider) (sstable.Iterator, error) - NewCompactionIter( - bytesIterated *uint64, - rp sstable.ReaderProvider, - bufferPool *sstable.BufferPool, - ) (sstable.Iterator, error) - } - - // TODO(bananabrick): We suffer an allocation if file is a virtual sstable. - var ic iterCreator = v.reader - if file.Virtual { - virtualReader := sstable.MakeVirtualReader( - v.reader, file.VirtualMeta(), - ) - ic = &virtualReader - } + // Note: This suffers an allocation for virtual sstables. + cr := createCommonReader(v, file) provider := dbOpts.objProvider // Check if this file is a foreign file. @@ -462,29 +475,7 @@ func (c *tableCacheShard) newIters( // NB: range-del iterator does not maintain a reference to the table, nor // does it need to read from it after creation. - var rangeDelIter keyspan.FragmentIterator - if provider.IsForeign(objMeta) { - if opts == nil { - panic("unexpected nil opts when reading foreign file") - } - if !file.Virtual { - // Foreign sstables must be virtual by definition. - panic(fmt.Sprintf("sstable is foreign but not virtual: %s", file.FileNum)) - } - switch manifest.LevelToInt(opts.level) { - case 5: - rangeDelIter, err = ic.NewRawRangeDelIter() - case 6: - // Let rangeDelIter remain nil. We don't need to return rangedels from - // this file as they will not apply to any other files. For the purpose - // of collapsing rangedels within this file, we create another rangeDelIter - // below for use with the interleaving iter. - default: - panic(fmt.Sprintf("unexpected level for foreign sstable: %d", manifest.LevelToInt(opts.level))) - } - } else { - rangeDelIter, err = ic.NewRawRangeDelIter() - } + rangeDelIter, err := cr.NewRawRangeDelIter() if err != nil { c.unrefValue(v) return nil, nil, err @@ -521,12 +512,24 @@ func (c *tableCacheShard) newIters( rp = &tableCacheShardReaderProvider{c: c, file: file, dbOpts: dbOpts} } + if provider.IsSharedForeign(objMeta) { + if tableFormat < sstable.TableFormatPebblev4 { + return nil, nil, errors.New("pebble: shared foreign sstable has a lower table format than expected") + } + hideObsoletePoints = true + } + var categoryAndQoS sstable.CategoryAndQoS + if opts != nil { + categoryAndQoS = opts.CategoryAndQoS + } if internalOpts.bytesIterated != nil { - iter, err = ic.NewCompactionIter(internalOpts.bytesIterated, rp, internalOpts.bufferPool) + iter, err = cr.NewCompactionIter( + internalOpts.bytesIterated, categoryAndQoS, dbOpts.sstStatsCollector, rp, + internalOpts.bufferPool) } else { - iter, err = ic.NewIterWithBlockPropertyFiltersAndContextEtc( + iter, err = cr.NewIterWithBlockPropertyFiltersAndContextEtc( ctx, opts.GetLowerBound(), opts.GetUpperBound(), filterer, hideObsoletePoints, useFilter, - internalOpts.stats, rp) + internalOpts.stats, categoryAndQoS, dbOpts.sstStatsCollector, rp) } if err != nil { if rangeDelIter != nil { @@ -538,35 +541,6 @@ func (c *tableCacheShard) newIters( // NB: v.closeHook takes responsibility for calling unrefValue(v) here. Take // care to avoid introducing an allocation here by adding a closure. iter.SetCloseHook(v.closeHook) - if provider.IsForeign(objMeta) { - // NB: IsForeign() guarantees IsShared, so opts must not be nil as we've - // already panicked on the nil case above. - pointKeySeqNum := base.SeqNumForLevel(manifest.LevelToInt(opts.level)) - pcIter := pointCollapsingIterator{ - comparer: dbOpts.opts.Comparer, - merge: dbOpts.opts.Merge, - seqNum: math.MaxUint64, - elideRangeDeletes: true, - fixedSeqNum: pointKeySeqNum, - } - // Open a second rangedel iter. This is solely for the interleaving iter to - // be able to efficiently delete covered range deletes. We don't need to fix - // the sequence number in this iter, as these range deletes will not be - // exposed to anything other than the interleaving iter and - // pointCollapsingIter. - rangeDelIter, err := v.reader.NewRawRangeDelIter() - if err != nil { - c.unrefValue(v) - return nil, nil, err - } - if rangeDelIter == nil { - rangeDelIter = emptyKeyspanIter - } - pcIter.iter.Init(dbOpts.opts.Comparer, iter, rangeDelIter, nil /* mask */, opts.LowerBound, opts.UpperBound) - pcSSTIter := pcSSTIterPool.Get().(*pointCollapsingSSTIterator) - *pcSSTIter = pointCollapsingSSTIterator{pointCollapsingIterator: pcIter, childIter: iter} - iter = pcSSTIter - } c.iterCount.Add(1) dbOpts.iterCount.Add(1) @@ -636,29 +610,6 @@ func (c *tableCacheShard) newRangeKeyIter( return emptyKeyspanIter, nil } - objMeta, err := dbOpts.objProvider.Lookup(fileTypeTable, file.FileBacking.DiskFileNum) - if err != nil { - return nil, err - } - if dbOpts.objProvider.IsForeign(objMeta) { - if opts.Level == 0 { - panic("unexpected zero level when reading foreign file") - } - transform := &rangekey.ForeignSSTTransformer{ - Comparer: dbOpts.opts.Comparer, - Level: manifest.LevelToInt(opts.Level), - } - if iter == nil { - iter = emptyKeyspanIter - } - transformIter := &keyspan.TransformerIter{ - FragmentIterator: iter, - Transformer: transform, - Compare: dbOpts.opts.Comparer.Compare, - } - return transformIter, nil - } - return iter, nil } @@ -784,7 +735,27 @@ func (c *tableCacheShard) unrefValue(v *tableCacheValue) { // findNode returns the node for the table with the given file number, creating // that node if it didn't already exist. The caller is responsible for // decrementing the returned node's refCount. -func (c *tableCacheShard) findNode(meta *fileMetadata, dbOpts *tableCacheOpts) *tableCacheValue { +func (c *tableCacheShard) findNode( + meta *fileMetadata, dbOpts *tableCacheOpts, +) (v *tableCacheValue) { + // Loading a file before its global sequence number is known (eg, + // during ingest before entering the commit pipeline) can pollute + // the cache with incorrect state. In invariant builds, verify + // that the global sequence number of the returned reader matches. + if invariants.Enabled { + defer func() { + if v.reader != nil && meta.LargestSeqNum == meta.SmallestSeqNum && + v.reader.Properties.GlobalSeqNum != meta.SmallestSeqNum { + panic(errors.AssertionFailedf("file %s loaded from table cache with the wrong global sequence number %d", + meta, v.reader.Properties.GlobalSeqNum)) + } + }() + } + if refs := meta.Refs(); refs <= 0 { + panic(errors.AssertionFailedf("attempting to load file %s with refs=%d from table cache", + meta, refs)) + } + // Fast-path for a hit in the cache. c.mu.RLock() key := tableCacheKey{dbOpts.cacheID, meta.FileBacking.DiskFileNum} @@ -792,7 +763,7 @@ func (c *tableCacheShard) findNode(meta *fileMetadata, dbOpts *tableCacheOpts) * // Fast-path hit. // // The caller is responsible for decrementing the refCount. - v := n.value + v = n.value v.refCount.Add(1) c.mu.RUnlock() n.referenced.Store(true) @@ -819,7 +790,7 @@ func (c *tableCacheShard) findNode(meta *fileMetadata, dbOpts *tableCacheOpts) * // Slow-path hit of a hot or cold node. // // The caller is responsible for decrementing the refCount. - v := n.value + v = n.value v.refCount.Add(1) n.referenced.Store(true) c.hits.Add(1) @@ -843,7 +814,7 @@ func (c *tableCacheShard) findNode(meta *fileMetadata, dbOpts *tableCacheOpts) * c.misses.Add(1) - v := &tableCacheValue{ + v = &tableCacheValue{ loaded: make(chan struct{}), } v.refCount.Store(2) @@ -1118,10 +1089,8 @@ func (v *tableCacheValue) load(loadInfo loadInfo, c *tableCacheShard, dbOpts *ta v.err = errors.Wrapf( err, "pebble: backing file %s error", errors.Safe(loadInfo.backingFileNum.FileNum())) } - if v.err == nil { - if loadInfo.smallestSeqNum == loadInfo.largestSeqNum { - v.reader.Properties.GlobalSeqNum = loadInfo.largestSeqNum - } + if v.err == nil && loadInfo.smallestSeqNum == loadInfo.largestSeqNum { + v.reader.Properties.GlobalSeqNum = loadInfo.largestSeqNum } if v.err != nil { c.mu.Lock() diff --git a/vendor/github.com/cockroachdb/pebble/table_stats.go b/vendor/github.com/cockroachdb/pebble/table_stats.go index f20dbf7af..8b3e02bc9 100644 --- a/vendor/github.com/cockroachdb/pebble/table_stats.go +++ b/vendor/github.com/cockroachdb/pebble/table_stats.go @@ -8,6 +8,7 @@ import ( "fmt" "math" + "github.com/cockroachdb/errors" "github.com/cockroachdb/pebble/internal/base" "github.com/cockroachdb/pebble/internal/keyspan" "github.com/cockroachdb/pebble/internal/manifest" @@ -186,14 +187,9 @@ func (d *DB) loadNewFileStats( continue } - if nf.Meta.Virtual { - // cannot load virtual table stats - continue - } - stats, newHints, err := d.loadTableStats( rs.current, nf.Level, - nf.Meta.PhysicalMeta(), + nf.Meta, ) if err != nil { d.opts.EventListener.BackgroundError(err) @@ -219,15 +215,10 @@ func (d *DB) scanReadStateTableStats( ) ([]collectedStats, []deleteCompactionHint, bool) { moreRemain := false var hints []deleteCompactionHint + sizesChecked := make(map[base.DiskFileNum]struct{}) for l, levelMetadata := range rs.current.Levels { iter := levelMetadata.Iter() for f := iter.First(); f != nil; f = iter.Next() { - if f.Virtual { - // TODO(bananabrick): Support stats collection for virtual - // sstables. - continue - } - // NB: We're not holding d.mu which protects f.Stats, but only the // active stats collection job updates f.Stats for active files, // and we ensure only one goroutine runs it at a time through @@ -236,11 +227,6 @@ func (d *DB) scanReadStateTableStats( if f.StatsValid() { continue } - // TODO(bilal): Remove this guard when table stats collection is - // implemented for virtual sstables. - if f.Virtual { - continue - } // Limit how much work we do per read state. The older the read // state is, the higher the likelihood files are no longer being @@ -252,8 +238,43 @@ func (d *DB) scanReadStateTableStats( return fill, hints, moreRemain } + // If the file is remote and not SharedForeign, we should check if its size + // matches. This is because checkConsistency skips over remote files. + // SharedForeign files are skipped as their sizes are allowed to have a + // mismatch; the size stored in the FileBacking is just the part of the + // file that is referenced by this Pebble instance, not the size of the + // whole object. + objMeta, err := d.objProvider.Lookup(fileTypeTable, f.FileBacking.DiskFileNum) + if err != nil { + // Set `moreRemain` so we'll try again. + moreRemain = true + d.opts.EventListener.BackgroundError(err) + continue + } + if _, ok := sizesChecked[f.FileBacking.DiskFileNum]; !ok && objMeta.IsRemote() && + !d.objProvider.IsSharedForeign(objMeta) { + + size, err := d.objProvider.Size(objMeta) + fileSize := f.FileBacking.Size + if err != nil { + moreRemain = true + d.opts.EventListener.BackgroundError(err) + continue + } + if size != int64(fileSize) { + err := errors.Errorf( + "during consistency check in loadTableStats: L%d: %s: object size mismatch (%s): %d (provider) != %d (MANIFEST)", + errors.Safe(l), f.FileNum, d.objProvider.Path(objMeta), + errors.Safe(size), errors.Safe(fileSize)) + d.opts.EventListener.BackgroundError(err) + d.opts.Logger.Fatalf("%s", err) + } + + sizesChecked[f.FileBacking.DiskFileNum] = struct{}{} + } + stats, newHints, err := d.loadTableStats( - rs.current, l, f.PhysicalMeta(), + rs.current, l, f, ) if err != nil { // Set `moreRemain` so we'll try again. @@ -271,25 +292,22 @@ func (d *DB) scanReadStateTableStats( return fill, hints, moreRemain } -// loadTableStats currently only supports stats collection for physical -// sstables. -// -// TODO(bananabrick): Support stats collection for virtual sstables. func (d *DB) loadTableStats( - v *version, level int, meta physicalMeta, + v *version, level int, meta *fileMetadata, ) (manifest.TableStats, []deleteCompactionHint, error) { var stats manifest.TableStats var compactionHints []deleteCompactionHint - err := d.tableCache.withReader( - meta, func(r *sstable.Reader) (err error) { - stats.NumEntries = r.Properties.NumEntries - stats.NumDeletions = r.Properties.NumDeletions - if r.Properties.NumPointDeletions() > 0 { - if err = d.loadTablePointKeyStats(r, v, level, meta, &stats); err != nil { + err := d.tableCache.withCommonReader( + meta, func(r sstable.CommonReader) (err error) { + props := r.CommonProperties() + stats.NumEntries = props.NumEntries + stats.NumDeletions = props.NumDeletions + if props.NumPointDeletions() > 0 { + if err = d.loadTablePointKeyStats(props, v, level, meta, &stats); err != nil { return } } - if r.Properties.NumRangeDeletions > 0 || r.Properties.NumRangeKeyDels > 0 { + if props.NumRangeDeletions > 0 || props.NumRangeKeyDels > 0 { if compactionHints, err = d.loadTableRangeDelStats( r, v, level, meta, &stats, ); err != nil { @@ -299,8 +317,8 @@ func (d *DB) loadTableStats( // TODO(travers): Once we have real-world data, consider collecting // additional stats that may provide improved heuristics for compaction // picking. - stats.NumRangeKeySets = r.Properties.NumRangeKeySets - stats.ValueBlocksSize = r.Properties.ValueBlocksSize + stats.NumRangeKeySets = props.NumRangeKeySets + stats.ValueBlocksSize = props.ValueBlocksSize return }) if err != nil { @@ -312,7 +330,11 @@ func (d *DB) loadTableStats( // loadTablePointKeyStats calculates the point key statistics for the given // table. The provided manifest.TableStats are updated. func (d *DB) loadTablePointKeyStats( - r *sstable.Reader, v *version, level int, meta physicalMeta, stats *manifest.TableStats, + props *sstable.CommonProperties, + v *version, + level int, + meta *fileMetadata, + stats *manifest.TableStats, ) error { // TODO(jackson): If the file has a wide keyspace, the average // value size beneath the entire file might not be representative @@ -320,21 +342,21 @@ func (d *DB) loadTablePointKeyStats( // We could write the ranges of 'clusters' of point tombstones to // a sstable property and call averageValueSizeBeneath for each of // these narrower ranges to improve the estimate. - avgValLogicalSize, compressionRatio, err := d.estimateSizesBeneath(v, level, meta) + avgValLogicalSize, compressionRatio, err := d.estimateSizesBeneath(v, level, meta, props) if err != nil { return err } stats.PointDeletionsBytesEstimate = - pointDeletionsBytesEstimate(meta.Size, &r.Properties, avgValLogicalSize, compressionRatio) + pointDeletionsBytesEstimate(meta.Size, props, avgValLogicalSize, compressionRatio) return nil } // loadTableRangeDelStats calculates the range deletion and range key deletion // statistics for the given table. func (d *DB) loadTableRangeDelStats( - r *sstable.Reader, v *version, level int, meta physicalMeta, stats *manifest.TableStats, + r sstable.CommonReader, v *version, level int, meta *fileMetadata, stats *manifest.TableStats, ) ([]deleteCompactionHint, error) { - iter, err := newCombinedDeletionKeyspanIter(d.opts.Comparer, r, meta.FileMetadata) + iter, err := newCombinedDeletionKeyspanIter(d.opts.Comparer, r, meta) if err != nil { return nil, err } @@ -423,7 +445,7 @@ func (d *DB) loadTableRangeDelStats( hintType: hintType, start: make([]byte, len(start)), end: make([]byte, len(end)), - tombstoneFile: meta.FileMetadata, + tombstoneFile: meta, tombstoneLevel: level, tombstoneLargestSeqNum: s.LargestSeqNum(), tombstoneSmallestSeqNum: s.SmallestSeqNum(), @@ -437,12 +459,21 @@ func (d *DB) loadTableRangeDelStats( } func (d *DB) estimateSizesBeneath( - v *version, level int, meta physicalMeta, + v *version, level int, meta *fileMetadata, fileProps *sstable.CommonProperties, ) (avgValueLogicalSize, compressionRatio float64, err error) { // Find all files in lower levels that overlap with meta, // summing their value sizes and entry counts. - file := meta.FileMetadata + file := meta var fileSum, keySum, valSum, entryCount uint64 + // Include the file itself. This is important because in some instances, the + // computed compression ratio is applied to the tombstones contained within + // `meta` itself. If there are no files beneath `meta` in the LSM, we would + // calculate a compression ratio of 0 which is not accurate for the file's + // own tombstones. + fileSum += file.Size + entryCount += fileProps.NumEntries + keySum += fileProps.RawKeySize + valSum += fileProps.RawValueSize addPhysicalTableStats := func(r *sstable.Reader) (err error) { fileSum += file.Size @@ -459,15 +490,6 @@ func (d *DB) estimateSizesBeneath( return nil } - // Include the file itself. This is important because in some instances, the - // computed compression ratio is applied to the tombstones contained within - // `meta` itself. If there are no files beneath `meta` in the LSM, we would - // calculate a compression ratio of 0 which is not accurate for the file's - // own tombstones. - if err = d.tableCache.withReader(meta, addPhysicalTableStats); err != nil { - return 0, 0, err - } - for l := level + 1; l < numLevels; l++ { overlaps := v.Overlaps(l, d.cmp, meta.Smallest.UserKey, meta.Largest.UserKey, meta.Largest.IsExclusiveSentinel()) @@ -637,8 +659,9 @@ func maybeSetStatsFromProperties(meta physicalMeta, props *sstable.Properties) b // doesn't require any additional IO and since the number of point // deletions in the file is low, the error introduced by this crude // estimate is expected to be small. - avgValSize, compressionRatio := estimatePhysicalSizes(meta.Size, props) - pointEstimate = pointDeletionsBytesEstimate(meta.Size, props, avgValSize, compressionRatio) + commonProps := &props.CommonProperties + avgValSize, compressionRatio := estimatePhysicalSizes(meta.Size, commonProps) + pointEstimate = pointDeletionsBytesEstimate(meta.Size, commonProps, avgValSize, compressionRatio) } meta.Stats.NumEntries = props.NumEntries @@ -652,7 +675,7 @@ func maybeSetStatsFromProperties(meta physicalMeta, props *sstable.Properties) b } func pointDeletionsBytesEstimate( - fileSize uint64, props *sstable.Properties, avgValLogicalSize, compressionRatio float64, + fileSize uint64, props *sstable.CommonProperties, avgValLogicalSize, compressionRatio float64, ) (estimate uint64) { if props.NumEntries == 0 { return 0 @@ -675,7 +698,7 @@ func pointDeletionsBytesEstimate( // tombstones' encoded values. // // For un-sized point tombstones (DELs), we estimate assuming that each - // point tombstone on average covers 1 key and using average vaue sizes. + // point tombstone on average covers 1 key and using average value sizes. // This is almost certainly an overestimate, but that's probably okay // because point tombstones can slow range iterations even when they don't // cover a key. @@ -739,7 +762,7 @@ func pointDeletionsBytesEstimate( } func estimatePhysicalSizes( - fileSize uint64, props *sstable.Properties, + fileSize uint64, props *sstable.CommonProperties, ) (avgValLogicalSize, compressionRatio float64) { // RawKeySize and RawValueSize are uncompressed totals. Scale according to // the data size to account for compression, index blocks and metadata @@ -812,7 +835,7 @@ func estimatePhysicalSizes( // corresponding to the largest and smallest sequence numbers encountered across // the range deletes and range keys deletes that comprised the merged spans. func newCombinedDeletionKeyspanIter( - comparer *base.Comparer, r *sstable.Reader, m *fileMetadata, + comparer *base.Comparer, cr sstable.CommonReader, m *fileMetadata, ) (keyspan.FragmentIterator, error) { // The range del iter and range key iter are each wrapped in their own // defragmenting iter. For each iter, abutting spans can always be merged. @@ -874,7 +897,7 @@ func newCombinedDeletionKeyspanIter( }) mIter.Init(comparer.Compare, transform, new(keyspan.MergingBuffers)) - iter, err := r.NewRawRangeDelIter() + iter, err := cr.NewRawRangeDelIter() if err != nil { return nil, err } @@ -891,7 +914,7 @@ func newCombinedDeletionKeyspanIter( mIter.AddLevel(iter) } - iter, err = r.NewRawRangeKeyIter() + iter, err = cr.NewRawRangeKeyIter() if err != nil { return nil, err } @@ -908,7 +931,7 @@ func newCombinedDeletionKeyspanIter( out.Keys = append(out.Keys, k) } return len(out.Keys) > 0 - }) + }, comparer.Compare) dIter := &keyspan.DefragmentingIter{} dIter.Init(comparer, iter, equal, reducer, new(keyspan.DefragmentingBuffers)) iter = dIter diff --git a/vendor/github.com/cockroachdb/pebble/version_set.go b/vendor/github.com/cockroachdb/pebble/version_set.go index e85774c07..25a6ee921 100644 --- a/vendor/github.com/cockroachdb/pebble/version_set.go +++ b/vendor/github.com/cockroachdb/pebble/version_set.go @@ -8,7 +8,6 @@ import ( "bytes" "fmt" "io" - "math" "sync" "sync/atomic" @@ -61,12 +60,11 @@ type versionSet struct { // Immutable fields. dirname string // Set to DB.mu. - mu *sync.Mutex - opts *Options - fs vfs.FS - cmp Compare - cmpName string - diskAvailBytes func() uint64 + mu *sync.Mutex + opts *Options + fs vfs.FS + cmp Compare + cmpName string // Dynamic base level allows the dynamic base level computation to be // disabled. Used by tests which want to create specific LSM structures. dynamicBaseLevel bool @@ -88,33 +86,38 @@ type versionSet struct { // still referenced by an inuse iterator. zombieTables map[base.DiskFileNum]uint64 // filenum -> size - // fileBackingMap is a map for the FileBacking which is supporting virtual - // sstables in the latest version. Once the file backing is backing no - // virtual sstables in the latest version, it is removed from this map and - // the corresponding state is added to the zombieTables map. Note that we - // don't keep track of file backing which supports a virtual sstable - // which is not in the latest version. - // - // fileBackingMap is protected by the versionSet.logLock. It's populated + // backingState is protected by the versionSet.logLock. It's populated // during Open in versionSet.load, but it's not used concurrently during // load. - fileBackingMap map[base.DiskFileNum]*fileBacking + backingState struct { + // fileBackingMap is a map for the FileBacking which is supporting virtual + // sstables in the latest version. Once the file backing is backing no + // virtual sstables in the latest version, it is removed from this map and + // the corresponding state is added to the zombieTables map. Note that we + // don't keep track of file backing which supports a virtual sstable + // which is not in the latest version. + fileBackingMap map[base.DiskFileNum]*fileBacking + // fileBackingSize is the sum of the sizes of the fileBackings in the + // fileBackingMap. + fileBackingSize uint64 + } // minUnflushedLogNum is the smallest WAL log file number corresponding to // mutations that have not been flushed to an sstable. - minUnflushedLogNum FileNum + minUnflushedLogNum base.DiskFileNum - // The next file number. A single counter is used to assign file numbers - // for the WAL, MANIFEST, sstable, and OPTIONS files. - nextFileNum FileNum + // The next file number. A single counter is used to assign file + // numbers for the WAL, MANIFEST, sstable, and OPTIONS files. + nextFileNum uint64 // The current manifest file number. - manifestFileNum FileNum + manifestFileNum base.DiskFileNum manifestMarker *atomicfs.Marker - manifestFile vfs.File - manifest *record.Writer - setCurrent func(FileNum) error + manifestFile vfs.File + manifest *record.Writer + setCurrent func(base.DiskFileNum) error + getFormatMajorVersion func() FormatMajorVersion writing bool writerCond sync.Cond @@ -126,7 +129,8 @@ func (vs *versionSet) init( dirname string, opts *Options, marker *atomicfs.Marker, - setCurrent func(FileNum) error, + setCurrent func(base.DiskFileNum) error, + getFMV func() FormatMajorVersion, mu *sync.Mutex, ) { vs.dirname = dirname @@ -140,13 +144,12 @@ func (vs *versionSet) init( vs.versions.Init(mu) vs.obsoleteFn = vs.addObsoleteLocked vs.zombieTables = make(map[base.DiskFileNum]uint64) - vs.fileBackingMap = make(map[base.DiskFileNum]*fileBacking) + vs.backingState.fileBackingMap = make(map[base.DiskFileNum]*fileBacking) + vs.backingState.fileBackingSize = 0 vs.nextFileNum = 1 vs.manifestMarker = marker vs.setCurrent = setCurrent - if vs.diskAvailBytes == nil { - vs.diskAvailBytes = func() uint64 { return math.MaxUint64 } - } + vs.getFormatMajorVersion = getFMV } // create creates a version set for a fresh DB. @@ -155,19 +158,19 @@ func (vs *versionSet) create( dirname string, opts *Options, marker *atomicfs.Marker, - setCurrent func(FileNum) error, + setCurrent func(base.DiskFileNum) error, + getFormatMajorVersion func() FormatMajorVersion, mu *sync.Mutex, ) error { - vs.init(dirname, opts, marker, setCurrent, mu) + vs.init(dirname, opts, marker, setCurrent, getFormatMajorVersion, mu) newVersion := &version{} vs.append(newVersion) var err error - vs.picker = newCompactionPicker(newVersion, vs.opts, nil, vs.metrics.levelSizes(), vs.diskAvailBytes) - + vs.picker = newCompactionPicker(newVersion, vs.opts, nil) // Note that a "snapshot" version edit is written to the manifest when it is // created. - vs.manifestFileNum = vs.getNextFileNum() + vs.manifestFileNum = vs.getNextDiskFileNum() err = vs.createManifest(vs.dirname, vs.manifestFileNum, vs.minUnflushedLogNum, vs.nextFileNum) if err == nil { if err = vs.manifest.Flush(); err != nil { @@ -188,7 +191,7 @@ func (vs *versionSet) create( vs.opts.EventListener.ManifestCreated(ManifestCreateInfo{ JobID: jobID, - Path: base.MakeFilepath(vs.fs, vs.dirname, fileTypeManifest, vs.manifestFileNum.DiskFileNum()), + Path: base.MakeFilepath(vs.fs, vs.dirname, fileTypeManifest, vs.manifestFileNum), FileNum: vs.manifestFileNum, Err: err, }) @@ -202,15 +205,16 @@ func (vs *versionSet) create( func (vs *versionSet) load( dirname string, opts *Options, - manifestFileNum FileNum, + manifestFileNum base.DiskFileNum, marker *atomicfs.Marker, - setCurrent func(FileNum) error, + setCurrent func(base.DiskFileNum) error, + getFormatMajorVersion func() FormatMajorVersion, mu *sync.Mutex, ) error { - vs.init(dirname, opts, marker, setCurrent, mu) + vs.init(dirname, opts, marker, setCurrent, getFormatMajorVersion, mu) vs.manifestFileNum = manifestFileNum - manifestPath := base.MakeFilepath(opts.FS, dirname, fileTypeManifest, vs.manifestFileNum.DiskFileNum()) + manifestPath := base.MakeFilepath(opts.FS, dirname, fileTypeManifest, vs.manifestFileNum) manifestFilename := opts.FS.PathBase(manifestPath) // Read the versionEdits in the manifest file. @@ -296,11 +300,11 @@ func (vs *versionSet) load( // Populate the fileBackingMap and the FileBacking for virtual sstables since // we have finished version edit accumulation. for _, s := range bve.AddedFileBacking { - vs.fileBackingMap[s.DiskFileNum] = s + vs.addFileBacking(s) } for _, fileNum := range bve.RemovedFileBacking { - delete(vs.fileBackingMap, fileNum) + vs.removeFileBacking(fileNum) } newVersion, err := bve.Apply( @@ -320,7 +324,7 @@ func (vs *versionSet) load( l.Size = int64(files.SizeSum()) } - vs.picker = newCompactionPicker(newVersion, vs.opts, nil, vs.metrics.levelSizes(), vs.diskAvailBytes) + vs.picker = newCompactionPicker(newVersion, vs.opts, nil) return nil } @@ -363,6 +367,26 @@ func (vs *versionSet) logUnlock() { vs.writerCond.Signal() } +// Only call if the DiskFileNum doesn't exist in the fileBackingMap. +func (vs *versionSet) addFileBacking(backing *manifest.FileBacking) { + _, ok := vs.backingState.fileBackingMap[backing.DiskFileNum] + if ok { + panic("pebble: trying to add an existing file backing") + } + vs.backingState.fileBackingMap[backing.DiskFileNum] = backing + vs.backingState.fileBackingSize += backing.Size +} + +// Only call if the the DiskFileNum exists in the fileBackingMap. +func (vs *versionSet) removeFileBacking(dfn base.DiskFileNum) { + backing, ok := vs.backingState.fileBackingMap[dfn] + if !ok { + panic("pebble: trying to remove an unknown file backing") + } + delete(vs.backingState.fileBackingMap, dfn) + vs.backingState.fileBackingSize -= backing.Size +} + // logAndApply logs the version edit to the manifest, applies the version edit // to the current version, and installs the new version. // @@ -387,7 +411,7 @@ func (vs *versionSet) logAndApply( if ve.MinUnflushedLogNum != 0 { if ve.MinUnflushedLogNum < vs.minUnflushedLogNum || - vs.nextFileNum <= ve.MinUnflushedLogNum { + vs.nextFileNum <= uint64(ve.MinUnflushedLogNum) { panic(fmt.Sprintf("pebble: inconsistent versionEdit minUnflushedLogNum %d", ve.MinUnflushedLogNum)) } @@ -472,10 +496,10 @@ func (vs *versionSet) logAndApply( if sizeExceeded && !requireRotation { requireRotation = vs.rotationHelper.ShouldRotate(nextSnapshotFilecount) } - var newManifestFileNum FileNum + var newManifestFileNum base.DiskFileNum var prevManifestFileSize uint64 if requireRotation { - newManifestFileNum = vs.getNextFileNum() + newManifestFileNum = vs.getNextDiskFileNum() prevManifestFileSize = uint64(vs.manifest.Size()) } @@ -490,13 +514,13 @@ func (vs *versionSet) logAndApply( defer vs.mu.Lock() var err error - if vs.opts.FormatMajorVersion < ExperimentalFormatVirtualSSTables && len(ve.CreatedBackingTables) > 0 { + if vs.getFormatMajorVersion() < FormatVirtualSSTables && len(ve.CreatedBackingTables) > 0 { return errors.AssertionFailedf("MANIFEST cannot contain virtual sstable records due to format major version") } newVersion, zombies, err = manifest.AccumulateIncompleteAndApplySingleVE( ve, currentVersion, vs.cmp, vs.opts.Comparer.FormatKey, vs.opts.FlushSplitBytes, vs.opts.Experimental.ReadCompactionRate, - vs.fileBackingMap, + vs.backingState.fileBackingMap, vs.addFileBacking, vs.removeFileBacking, ) if err != nil { return errors.Wrap(err, "MANIFEST apply failed") @@ -506,7 +530,7 @@ func (vs *versionSet) logAndApply( if err := vs.createManifest(vs.dirname, newManifestFileNum, minUnflushedLogNum, nextFileNum); err != nil { vs.opts.EventListener.ManifestCreated(ManifestCreateInfo{ JobID: jobID, - Path: base.MakeFilepath(vs.fs, vs.dirname, fileTypeManifest, newManifestFileNum.DiskFileNum()), + Path: base.MakeFilepath(vs.fs, vs.dirname, fileTypeManifest, newManifestFileNum), FileNum: newManifestFileNum, Err: err, }) @@ -540,7 +564,7 @@ func (vs *versionSet) logAndApply( } vs.opts.EventListener.ManifestCreated(ManifestCreateInfo{ JobID: jobID, - Path: base.MakeFilepath(vs.fs, vs.dirname, fileTypeManifest, newManifestFileNum.DiskFileNum()), + Path: base.MakeFilepath(vs.fs, vs.dirname, fileTypeManifest, newManifestFileNum), FileNum: newManifestFileNum, }) } @@ -581,7 +605,7 @@ func (vs *versionSet) logAndApply( if newManifestFileNum != 0 { if vs.manifestFileNum != 0 { vs.obsoleteManifests = append(vs.obsoleteManifests, fileInfo{ - fileNum: vs.manifestFileNum.DiskFileNum(), + fileNum: vs.manifestFileNum, fileSize: prevManifestFileSize, }) } @@ -593,30 +617,46 @@ func (vs *versionSet) logAndApply( } for i := range vs.metrics.Levels { l := &vs.metrics.Levels[i] + l.NumFiles = int64(newVersion.Levels[i].Len()) + l.NumVirtualFiles = newVersion.Levels[i].NumVirtual + l.VirtualSize = newVersion.Levels[i].VirtualSize + l.Size = int64(newVersion.Levels[i].Size()) + l.Sublevels = 0 if l.NumFiles > 0 { l.Sublevels = 1 } if invariants.Enabled { - if count := int64(newVersion.Levels[i].Len()); l.NumFiles != count { - vs.opts.Logger.Fatalf("versionSet metrics L%d NumFiles = %d, actual count = %d", i, l.NumFiles, count) - } levelFiles := newVersion.Levels[i].Slice() if size := int64(levelFiles.SizeSum()); l.Size != size { vs.opts.Logger.Fatalf("versionSet metrics L%d Size = %d, actual size = %d", i, l.Size, size) } + if nVirtual := levelFiles.NumVirtual(); nVirtual != l.NumVirtualFiles { + vs.opts.Logger.Fatalf( + "versionSet metrics L%d NumVirtual = %d, actual NumVirtual = %d", + i, l.NumVirtualFiles, nVirtual, + ) + } + if vSize := levelFiles.VirtualSizeSum(); vSize != l.VirtualSize { + vs.opts.Logger.Fatalf( + "versionSet metrics L%d Virtual size = %d, actual size = %d", + i, l.VirtualSize, vSize, + ) + } } } vs.metrics.Levels[0].Sublevels = int32(len(newVersion.L0SublevelFiles)) - vs.picker = newCompactionPicker(newVersion, vs.opts, inProgress, vs.metrics.levelSizes(), vs.diskAvailBytes) + vs.picker = newCompactionPicker(newVersion, vs.opts, inProgress) if !vs.dynamicBaseLevel { vs.picker.forceBaseLevel1() } return nil } -func (vs *versionSet) incrementCompactions(kind compactionKind, extraLevels []*compactionLevel) { +func (vs *versionSet) incrementCompactions( + kind compactionKind, extraLevels []*compactionLevel, pickerMetrics compactionPickerMetrics, +) { switch kind { case compactionKindDefault: vs.metrics.Compact.Count++ @@ -656,10 +696,10 @@ func (vs *versionSet) incrementCompactionBytes(numBytes int64) { // createManifest creates a manifest file that contains a snapshot of vs. func (vs *versionSet) createManifest( - dirname string, fileNum, minUnflushedLogNum, nextFileNum FileNum, + dirname string, fileNum, minUnflushedLogNum base.DiskFileNum, nextFileNum uint64, ) (err error) { var ( - filename = base.MakeFilepath(vs.fs, dirname, fileTypeManifest, fileNum.DiskFileNum()) + filename = base.MakeFilepath(vs.fs, dirname, fileTypeManifest, fileNum) manifestFile vfs.File manifest *record.Writer ) @@ -734,16 +774,22 @@ func (vs *versionSet) createManifest( return nil } -func (vs *versionSet) markFileNumUsed(fileNum FileNum) { - if vs.nextFileNum <= fileNum { - vs.nextFileNum = fileNum + 1 +func (vs *versionSet) markFileNumUsed(fileNum base.DiskFileNum) { + if vs.nextFileNum <= uint64(fileNum) { + vs.nextFileNum = uint64(fileNum + 1) } } -func (vs *versionSet) getNextFileNum() FileNum { +func (vs *versionSet) getNextFileNum() base.FileNum { + x := vs.nextFileNum + vs.nextFileNum++ + return base.FileNum(x) +} + +func (vs *versionSet) getNextDiskFileNum() base.DiskFileNum { x := vs.nextFileNum vs.nextFileNum++ - return x + return base.DiskFileNum(x) } func (vs *versionSet) append(v *version) { @@ -835,17 +881,17 @@ func (vs *versionSet) updateObsoleteTableMetricsLocked() { func setCurrentFunc( vers FormatMajorVersion, marker *atomicfs.Marker, fs vfs.FS, dirname string, dir vfs.File, -) func(FileNum) error { +) func(base.DiskFileNum) error { if vers < formatVersionedManifestMarker { // Pebble versions before `formatVersionedManifestMarker` used // the CURRENT file to signal which MANIFEST is current. Ignore // the filename read during LocateMarker. - return func(manifestFileNum FileNum) error { - if err := setCurrentFile(dirname, fs, manifestFileNum.DiskFileNum()); err != nil { + return func(manifestFileNum base.DiskFileNum) error { + if err := setCurrentFile(dirname, fs, manifestFileNum); err != nil { return err } if err := dir.Sync(); err != nil { - // This is a panic here, rather than higher in the call + // This is a panic here, rather than higher in the call // stack, for parity with the atomicfs.Marker behavior. // A panic is always necessary because failed Syncs are // unrecoverable. @@ -857,9 +903,11 @@ func setCurrentFunc( return setCurrentFuncMarker(marker, fs, dirname) } -func setCurrentFuncMarker(marker *atomicfs.Marker, fs vfs.FS, dirname string) func(FileNum) error { - return func(manifestFileNum FileNum) error { - return marker.Move(base.MakeFilename(fileTypeManifest, manifestFileNum.DiskFileNum())) +func setCurrentFuncMarker( + marker *atomicfs.Marker, fs vfs.FS, dirname string, +) func(base.DiskFileNum) error { + return func(manifestFileNum base.DiskFileNum) error { + return marker.Move(base.MakeFilename(fileTypeManifest, manifestFileNum)) } } diff --git a/vendor/github.com/cockroachdb/pebble/vfs/disk_health.go b/vendor/github.com/cockroachdb/pebble/vfs/disk_health.go index 9ce7b7121..3df4017b1 100644 --- a/vendor/github.com/cockroachdb/pebble/vfs/disk_health.go +++ b/vendor/github.com/cockroachdb/pebble/vfs/disk_health.go @@ -13,7 +13,6 @@ import ( "sync/atomic" "time" - "github.com/cockroachdb/pebble/internal/invariants" "github.com/cockroachdb/redact" ) @@ -136,7 +135,7 @@ type diskHealthCheckingFile struct { // NB: this packing scheme is not persisted, and is therefore safe to adjust // across process boundaries. lastWritePacked atomic.Uint64 - createTime time.Time + createTimeNanos int64 } // newDiskHealthCheckingFile instantiates a new diskHealthCheckingFile, with the @@ -152,8 +151,8 @@ func newDiskHealthCheckingFile( diskSlowThreshold: diskSlowThreshold, tickInterval: defaultTickInterval, - stopper: make(chan struct{}), - createTime: time.Now(), + stopper: make(chan struct{}), + createTimeNanos: time.Now().UnixNano(), } } @@ -179,7 +178,7 @@ func (d *diskHealthCheckingFile) startTicker() { continue } delta, writeSize, op := unpack(packed) - lastWrite := d.createTime.Add(delta) + lastWrite := time.Unix(0, d.createTimeNanos+delta.Nanoseconds()) now := time.Now() if lastWrite.Add(d.diskSlowThreshold).Before(now) { // diskSlowThreshold was exceeded. Call the passed-in @@ -215,7 +214,7 @@ func (d *diskHealthCheckingFile) ReadAt(p []byte, off int64) (int, error) { func (d *diskHealthCheckingFile) Write(p []byte) (n int, err error) { d.timeDiskOp(OpTypeWrite, int64(len(p)), func() { n, err = d.file.Write(p) - }) + }, time.Now().UnixNano()) return n, err } @@ -223,7 +222,7 @@ func (d *diskHealthCheckingFile) Write(p []byte) (n int, err error) { func (d *diskHealthCheckingFile) WriteAt(p []byte, ofs int64) (n int, err error) { d.timeDiskOp(OpTypeWrite, int64(len(p)), func() { n, err = d.file.WriteAt(p, ofs) - }) + }, time.Now().UnixNano()) return n, err } @@ -242,7 +241,7 @@ func (d *diskHealthCheckingFile) Prefetch(offset, length int64) error { func (d *diskHealthCheckingFile) Preallocate(off, n int64) (err error) { d.timeDiskOp(OpTypePreallocate, n, func() { err = d.file.Preallocate(off, n) - }) + }, time.Now().UnixNano()) return err } @@ -255,7 +254,7 @@ func (d *diskHealthCheckingFile) Stat() (os.FileInfo, error) { func (d *diskHealthCheckingFile) Sync() (err error) { d.timeDiskOp(OpTypeSync, 0, func() { err = d.file.Sync() - }) + }, time.Now().UnixNano()) return err } @@ -263,7 +262,7 @@ func (d *diskHealthCheckingFile) Sync() (err error) { func (d *diskHealthCheckingFile) SyncData() (err error) { d.timeDiskOp(OpTypeSyncData, 0, func() { err = d.file.SyncData() - }) + }, time.Now().UnixNano()) return err } @@ -271,7 +270,7 @@ func (d *diskHealthCheckingFile) SyncData() (err error) { func (d *diskHealthCheckingFile) SyncTo(length int64) (fullSync bool, err error) { d.timeDiskOp(OpTypeSyncTo, length, func() { fullSync, err = d.file.SyncTo(length) - }) + }, time.Now().UnixNano()) return fullSync, err } @@ -279,28 +278,26 @@ func (d *diskHealthCheckingFile) SyncTo(length int64) (fullSync bool, err error) // monitoring goroutine, in case it exceeds one of the slow disk durations. // opType should always be set. writeSizeInBytes should be set if the write // operation is sized. If not, it should be set to zero. -func (d *diskHealthCheckingFile) timeDiskOp(opType OpType, writeSizeInBytes int64, op func()) { +// +// The start time is taken as a parameter in the form of nanoseconds since the +// unix epoch so that it appears in stack traces during crashes (if GOTRACEBACK +// is set appropriately), aiding postmortem debugging. +func (d *diskHealthCheckingFile) timeDiskOp( + opType OpType, writeSizeInBytes int64, op func(), startNanos int64, +) { if d == nil { op() return } - delta := time.Since(d.createTime) + delta := time.Duration(startNanos - d.createTimeNanos) packed := pack(delta, writeSizeInBytes, opType) - if invariants.Enabled { - if !d.lastWritePacked.CompareAndSwap(0, packed) { - panic("concurrent write operations detected on file") - } - } else { - d.lastWritePacked.Store(packed) + if d.lastWritePacked.Swap(packed) != 0 { + panic("concurrent write operations detected on file") } defer func() { - if invariants.Enabled { - if !d.lastWritePacked.CompareAndSwap(packed, 0) { - panic("concurrent write operations detected on file") - } - } else { - d.lastWritePacked.Store(0) + if d.lastWritePacked.Swap(0) != packed { + panic("concurrent write operations detected on file") } }() op() @@ -361,7 +358,7 @@ type diskHealthCheckingDir struct { func (d *diskHealthCheckingDir) Sync() (err error) { d.fs.timeFilesystemOp(d.name, OpTypeSync, func() { err = d.File.Sync() - }) + }, time.Now().UnixNano()) return err } @@ -495,7 +492,17 @@ func WithDiskHealthChecks( return fs, fs } -func (d *diskHealthCheckingFS) timeFilesystemOp(name string, opType OpType, op func()) { +// timeFilesystemOp executes the provided closure, which should perform a +// singular filesystem operation of a type matching opType on the named file. It +// records the provided start time such that the long-lived disk-health checking +// goroutine can observe if the operation is blocked for an inordinate time. +// +// The start time is taken as a parameter in the form of nanoseconds since the +// unix epoch so that it appears in stack traces during crashes (if GOTRACEBACK +// is set appropriately), aiding postmortem debugging. +func (d *diskHealthCheckingFS) timeFilesystemOp( + name string, opType OpType, op func(), startNanos int64, +) { if d == nil { op() return @@ -524,7 +531,6 @@ func (d *diskHealthCheckingFS) timeFilesystemOp(name string, opType OpType, op f d.startTickerLocked() } - startNanos := time.Now().UnixNano() for i := 0; i < len(d.mu.inflight); i++ { if d.mu.inflight[i].startNanos.Load() == 0 { // This slot is not in use. Claim it. @@ -644,7 +650,7 @@ func (d *diskHealthCheckingFS) Create(name string) (File, error) { var err error d.timeFilesystemOp(name, OpTypeCreate, func() { f, err = d.fs.Create(name) - }) + }, time.Now().UnixNano()) if err != nil { return f, err } @@ -674,7 +680,7 @@ func (d *diskHealthCheckingFS) Link(oldname, newname string) error { var err error d.timeFilesystemOp(newname, OpTypeLink, func() { err = d.fs.Link(oldname, newname) - }) + }, time.Now().UnixNano()) return err } @@ -693,7 +699,7 @@ func (d *diskHealthCheckingFS) MkdirAll(dir string, perm os.FileMode) error { var err error d.timeFilesystemOp(dir, OpTypeMkdirAll, func() { err = d.fs.MkdirAll(dir, perm) - }) + }, time.Now().UnixNano()) return err } @@ -742,7 +748,7 @@ func (d *diskHealthCheckingFS) Remove(name string) error { var err error d.timeFilesystemOp(name, OpTypeRemove, func() { err = d.fs.Remove(name) - }) + }, time.Now().UnixNano()) return err } @@ -751,7 +757,7 @@ func (d *diskHealthCheckingFS) RemoveAll(name string) error { var err error d.timeFilesystemOp(name, OpTypeRemoveAll, func() { err = d.fs.RemoveAll(name) - }) + }, time.Now().UnixNano()) return err } @@ -760,7 +766,7 @@ func (d *diskHealthCheckingFS) Rename(oldname, newname string) error { var err error d.timeFilesystemOp(newname, OpTypeRename, func() { err = d.fs.Rename(oldname, newname) - }) + }, time.Now().UnixNano()) return err } @@ -770,7 +776,7 @@ func (d *diskHealthCheckingFS) ReuseForWrite(oldname, newname string) (File, err var err error d.timeFilesystemOp(newname, OpTypeReuseForWrite, func() { f, err = d.fs.ReuseForWrite(oldname, newname) - }) + }, time.Now().UnixNano()) if err != nil { return f, err } diff --git a/vendor/github.com/cockroachdb/pebble/vfs/mem_fs.go b/vendor/github.com/cockroachdb/pebble/vfs/mem_fs.go index bb9440a0d..7ccd8e71d 100644 --- a/vendor/github.com/cockroachdb/pebble/vfs/mem_fs.go +++ b/vendor/github.com/cockroachdb/pebble/vfs/mem_fs.go @@ -10,10 +10,12 @@ import ( "io" "os" "path" + "slices" "sort" "strings" "sync" "sync/atomic" + "syscall" "time" "github.com/cockroachdb/errors" @@ -78,6 +80,11 @@ type MemFS struct { mu sync.Mutex root *memNode + // lockFiles holds a map of open file locks. Presence in this map indicates + // a file lock is currently held. Keys are strings holding the path of the + // locked file. The stored value is untyped and unused; only presence of + // the key within the map is significant. + lockedFiles sync.Map strict bool ignoreSyncs bool // Windows has peculiar semantics with respect to hard links and deleting @@ -457,9 +464,31 @@ func (y *MemFS) MkdirAll(dirname string, perm os.FileMode) error { // Lock implements FS.Lock. func (y *MemFS) Lock(fullname string) (io.Closer, error) { // FS.Lock excludes other processes, but other processes cannot see this - // process' memory. We translate Lock into Create so that have the normal - // detection of non-existent directory paths. - return y.Create(fullname) + // process' memory. However some uses (eg, Cockroach tests) may open and + // close the same MemFS-backed database multiple times. We want mutual + // exclusion in this case too. See cockroachdb/cockroach#110645. + _, loaded := y.lockedFiles.Swap(fullname, nil /* the value itself is insignificant */) + if loaded { + // This file lock has already been acquired. On unix, this results in + // either EACCES or EAGAIN so we mimic. + return nil, syscall.EAGAIN + } + // Otherwise, we successfully acquired the lock. Locks are visible in the + // parent directory listing, and they also must be created under an existent + // directory. Create the path so that we have the normal detection of + // non-existent directory paths, and make the lock visible when listing + // directory entries. + f, err := y.Create(fullname) + if err != nil { + // "Release" the lock since we failed. + y.lockedFiles.Delete(fullname) + return nil, err + } + return &memFileLock{ + y: y, + f: f, + fullname: fullname, + }, nil } // List implements FS.List. @@ -625,7 +654,7 @@ func (f *memNode) resetToSyncedState() { } } else { f.mu.Lock() - f.mu.data = append([]byte(nil), f.mu.syncedData...) + f.mu.data = slices.Clone(f.mu.syncedData) f.mu.Unlock() } } @@ -759,7 +788,7 @@ func (f *memFile) Sync() error { } } else { f.n.mu.Lock() - f.n.mu.syncedData = append([]byte(nil), f.n.mu.data...) + f.n.mu.syncedData = slices.Clone(f.n.mu.data) f.n.mu.Unlock() } } @@ -787,3 +816,18 @@ func (f *memFile) Fd() uintptr { func (f *memFile) Flush() error { return nil } + +type memFileLock struct { + y *MemFS + f File + fullname string +} + +func (l *memFileLock) Close() error { + if l.y == nil { + return nil + } + l.y.lockedFiles.Delete(l.fullname) + l.y = nil + return l.f.Close() +} diff --git a/vendor/github.com/cockroachdb/redact/README.md b/vendor/github.com/cockroachdb/redact/README.md index 38c248af3..d04fd2c76 100644 --- a/vendor/github.com/cockroachdb/redact/README.md +++ b/vendor/github.com/cockroachdb/redact/README.md @@ -1,5 +1,9 @@ # redact Utilities to redact Go strings for confidentiality -Godoc link: https://pkg.go.dev/github.com/cockroachdb/redact?tab=doc +![Build Status](https://github.com/cockroachdb/redact/actions/workflows/ci.yaml/badge.svg?branch=master) +[![Go Reference](https://pkg.go.dev/badge/github.com/cockroachdb/redact.svg)](https://pkg.go.dev/github.com/cockroachdb/redact) +Some explanations about how this is used in e.g. CockroachDB: + +https://wiki.crdb.io/wiki/spaces/CRDB/pages/1824817806/Log+and+error+redactability diff --git a/vendor/github.com/cockroachdb/redact/api.go b/vendor/github.com/cockroachdb/redact/api.go index 3ed2e486d..2c8eba6a1 100644 --- a/vendor/github.com/cockroachdb/redact/api.go +++ b/vendor/github.com/cockroachdb/redact/api.go @@ -14,22 +14,23 @@ package redact -import "fmt" +import ( + "fmt" + "reflect" + + "github.com/cockroachdb/redact/builder" + i "github.com/cockroachdb/redact/interfaces" + b "github.com/cockroachdb/redact/internal/buffer" + fw "github.com/cockroachdb/redact/internal/fmtforward" + m "github.com/cockroachdb/redact/internal/markers" + w "github.com/cockroachdb/redact/internal/redact" + ifmt "github.com/cockroachdb/redact/internal/rfmt" +) // SafeFormatter is implemented by object types that want to separate // safe and non-safe information when printed out by a Printf-like // formatter. -type SafeFormatter interface { - // SafeFormat is like the Format method of fmt.Formatter, except - // that it operates using a SafePrinter instead of a fmt.State for - // output. - // - // The verb argument is the control character that defines - // the formatting mode in the surrounding Printf call. - // For example, if this method is called to format %03d, - // the verb is 'd'. - SafeFormat(s SafePrinter, verb rune) -} +type SafeFormatter = i.SafeFormatter // SafeValue is a marker interface to be implemented by types that // alias base Go types and whose natural representation via Printf is @@ -48,17 +49,13 @@ type SafeFormatter interface { // collect all the types that implement this interface, as well as all // uses of this type, and produce a report. Changes to this report // should receive maximal amount of scrutiny during code reviews. -type SafeValue interface { - SafeValue() -} +type SafeValue = i.SafeValue // SafeMessager is an alternative to SafeFormatter used in previous // versions of CockroachDB. // NB: this interface is obsolete. Use SafeFormatter instead. // TODO(knz): Remove this. -type SafeMessager interface { - SafeMessage() string -} +type SafeMessager = i.SafeMessager // SafePrinter is a stateful helper that abstracts an output stream in // the context of printf-like formatting, but with the ability to @@ -67,60 +64,112 @@ type SafeMessager interface { // This package provides one implementation of this using marker // delimiters for unsafe data, see markers.go. We would like to aim // for alternate implementations to generate more structured formats. -type SafePrinter interface { - // SafePrinter inherits fmt.State to access format flags, however - // calls to fmt.State's underlying Write() as unsafe. - fmt.State - - // SafePrinter provides the SafeWriter interface. - SafeWriter -} +type SafePrinter = i.SafePrinter // SafeWriter provides helper functions for use in implementations of // SafeFormatter, to format mixes of safe and unsafe strings. -type SafeWriter interface { - // SafeString emits a safe string. - SafeString(SafeString) +type SafeWriter = i.SafeWriter - // SafeRune emits a safe rune. - SafeRune(SafeRune) +// SafeString represents a string that is not a sensitive value. +type SafeString = i.SafeString - // Print emits its arguments separated by spaces. - // For each argument it dynamically checks for the SafeFormatter or - // SafeValue interface and either use that, or mark the argument - // payload as unsafe. - Print(args ...interface{}) +// SafeInt represents an integer that is not a sensitive value. +type SafeInt = i.SafeInt - // For printf, a linter checks that the format string is - // a constant literal, so the implementation can assume it's always - // safe. - Printf(format string, arg ...interface{}) +// SafeUint represents an integer that is not a sensitive value. +type SafeUint = i.SafeUint - // UnsafeString writes an unsafe string. - UnsafeString(string) +// SafeFloat represents a floating-point value that is not a sensitive value. +type SafeFloat = i.SafeFloat - // UnsafeByte writes an unsafe byte. - UnsafeByte(byte) +// SafeRune aliases rune. See the explanation for SafeString. +type SafeRune = i.SafeRune - // UnsafeBytes writes an unsafe byte slice. - UnsafeBytes([]byte) +// RedactableString is a string that contains a mix of safe and unsafe +// bits of data, but where it is known that unsafe bits are enclosed +// by redaction markers ‹ and ›, and occurrences of the markers +// inside the original data items have been escaped. +// +// Instances of RedactableString should not be constructed directly; +// instead use the facilities from print.go (Sprint, Sprintf) +// or the methods below. +type RedactableString = m.RedactableString - // UnsafeRune writes an unsafe rune. - UnsafeRune(rune) +// RedactableBytes is like RedactableString but is a byte slice. +// +// Instances of RedactableBytes should not be constructed directly; +// instead use the facilities from print.go (Sprint, Sprintf) +// or the methods below. +type RedactableBytes = m.RedactableBytes + +// StartMarker returns the start delimiter for an unsafe string. +func StartMarker() []byte { return m.StartMarker() } + +// EndMarker returns the end delimiter for an unsafe string. +func EndMarker() []byte { return m.EndMarker() } + +// RedactedMarker returns the special string used by Redact. +func RedactedMarker() []byte { return m.RedactedMarker() } + +// EscapeMarkers escapes the special delimiters from the provided +// byte slice. +func EscapeMarkers(s []byte) []byte { return m.EscapeMarkers(s) } + +// EscapeBytes escapes markers inside the given byte slice and encloses +// the entire byte slice between redaction markers. +// EscapeBytes escapes markers inside the given byte slice and encloses +// the entire byte slice between redaction markers. +func EscapeBytes(s []byte) RedactableBytes { return ifmt.EscapeBytes(s) } + +// ManualBuffer is a variable-sized buffer of bytes with +// Write methods. Writes are escaped in different ways +// depending on the output mode. +// Note: This type is only meant for "advanced" usage. +// For most common uses, consider using StringBuilder instead. +type ManualBuffer = b.Buffer + +// Unsafe turns any value that would otherwise be considered safe, +// into an unsafe value. +func Unsafe(a interface{}) interface{} { return w.Unsafe(a) } + +// Safe turns any value into an object that is considered as safe by +// the formatter. +// +// This is provided as an “escape hatch” for cases where the other +// interfaces and conventions fail. Increased usage of this mechanism +// should be taken as a signal that a new abstraction is missing. +// The implementation is also slow. +func Safe(a interface{}) SafeValue { return w.Safe(a) } + +// RegisterRedactErrorFn registers an error redaction function for use +// during automatic redaction by this package. +// Provided e.g. by cockroachdb/errors. +func RegisterRedactErrorFn(fn func(err error, p i.SafePrinter, verb rune)) { + ifmt.RegisterRedactErrorFn(fn) } -// SafeString aliases string. This is not meant to be used directly; -// the type definition ensures that SafePrinter's SafeString method -// can only take constant string literals as arguments. Typically, a -// Go linter would ensure that ConstantString is never used to cast a -// value. -type SafeString string - -// SafeValue makes SafeString a SafeValue. -func (SafeString) SafeValue() {} - -// SafeRune aliases rune. See the explanation for SafeString. -type SafeRune rune +// MakeFormat is a helper for use by implementations of the +// SafeFormatter interface. It reproduces the format currently active +// in fmt.State and verb. This is provided because Go's standard +// fmt.State does not make the original format string available to us. +// +// If the return value justV is true, then the current state +// was found to be %v exactly; in that case the caller +// can avoid a full-blown Printf call and use just Print instead +// to take a shortcut. +func MakeFormat(s fmt.State, verb rune) (justV bool, format string) { + return fw.MakeFormat(s, verb) +} -// SafeValue makes SafeRune a SafeValue. -func (SafeRune) SafeValue() {} +// StringBuilder accumulates strings with optional redaction markers. +// +// It implements io.Writer but marks direct writes as redactable. +// To distinguish safe and unsafe bits, it also implements the SafeWriter +// interface. +type StringBuilder = builder.StringBuilder + +// RegisterSafeType registers a data type to always be considered safe +// during the production of redactable strings. +func RegisterSafeType(t reflect.Type) { + ifmt.RegisterSafeType(t) +} diff --git a/vendor/github.com/cockroachdb/redact/builder.go b/vendor/github.com/cockroachdb/redact/builder/builder.go similarity index 53% rename from vendor/github.com/cockroachdb/redact/builder.go rename to vendor/github.com/cockroachdb/redact/builder/builder.go index 664da26a1..9c0ae29ca 100644 --- a/vendor/github.com/cockroachdb/redact/builder.go +++ b/vendor/github.com/cockroachdb/redact/builder/builder.go @@ -12,13 +12,15 @@ // implied. See the License for the specific language governing // permissions and limitations under the License. -package redact +package builder import ( - "bytes" "fmt" "io" - "unicode/utf8" + + i "github.com/cockroachdb/redact/interfaces" + ib "github.com/cockroachdb/redact/internal/buffer" + ifmt "github.com/cockroachdb/redact/internal/rfmt" ) // StringBuilder accumulates strings with optional redaction markers. @@ -27,26 +29,14 @@ import ( // To distinguish safe and unsafe bits, it also implements the SafeWriter // interface. type StringBuilder struct { - // we use bytes.Buffer internally to simplify the implementation of - // the SafeWriter interface. - buf bytes.Buffer + ib.Buffer } -// String returns the accumulated string, with redaction markers stripped out. -// To obtain the redactable string, call RedactableString(). -func (b StringBuilder) String() string { return b.RedactableString().StripMarkers() } - var _ fmt.Stringer = StringBuilder{} var _ fmt.Stringer = (*StringBuilder)(nil) -// RedactableString returns the accumulated string, including redaction markers. -func (b StringBuilder) RedactableString() RedactableString { return RedactableString(b.buf.String()) } - -// RedactableBytes returns the accumulated bytes, including redaction markers. -func (b StringBuilder) RedactableBytes() RedactableBytes { return RedactableBytes(b.buf.Bytes()) } - // SafeFormat implements SafeFormatter. -func (b StringBuilder) SafeFormat(p SafePrinter, _ rune) { +func (b StringBuilder) SafeFormat(p i.SafePrinter, _ rune) { // We only support the %v / %s natural print here. // Go supports other formatting verbs for strings: %x/%X/%q. // @@ -64,20 +54,8 @@ func (b StringBuilder) SafeFormat(p SafePrinter, _ rune) { p.Print(b.RedactableString()) } -var _ SafeFormatter = StringBuilder{} -var _ SafeFormatter = (*StringBuilder)(nil) - -// Len returns the number of accumulated bytes, including redaction -// markers; b.Len() == len(b.RedactableString()). -func (b *StringBuilder) Len() int { return b.buf.Len() } - -// Cap returns the capacity of the builder's underlying byte slice. It is the -// total space allocated for the string being built and includes any bytes -// already written. -func (b *StringBuilder) Cap() int { return b.buf.Cap() } - -// Reset resets the Builder to be empty. -func (b *StringBuilder) Reset() { b.buf.Reset() } +var _ i.SafeFormatter = StringBuilder{} +var _ i.SafeFormatter = (*StringBuilder)(nil) // StringBuilder implements io.Writer. // Direct Write() calls are considered unsafe. @@ -85,65 +63,93 @@ var _ io.Writer = (*StringBuilder)(nil) // Write implements the io.Writer interface. func (b *StringBuilder) Write(s []byte) (int, error) { - b.UnsafeBytes(s) - return len(s), nil + b.SetMode(ib.UnsafeEscaped) + return b.Buffer.Write(s) +} + +// WriteString shadows the ib.Buffer.WriteString method. +func (b *StringBuilder) WriteString(s string) (int, error) { + b.SetMode(ib.UnsafeEscaped) + return b.Buffer.WriteString(s) +} + +// WriteByte shadows the ib.Buffer.WriteByte method. +func (b *StringBuilder) WriteByte(c byte) error { + b.SetMode(ib.UnsafeEscaped) + return b.Buffer.WriteByte(c) +} + +// WriteRune shadows the ib.Buffer.WriteRune method. +func (b *StringBuilder) WriteRune(r rune) error { + b.SetMode(ib.UnsafeEscaped) + return b.Buffer.WriteRune(r) } // StringBuilder implements SafeWriter. -var _ SafeWriter = (*StringBuilder)(nil) +var _ i.SafeWriter = (*StringBuilder)(nil) // Print is part of the SafeWriter interface. func (b *StringBuilder) Print(args ...interface{}) { - _, _ = Fprint(&b.buf, args...) + b.SetMode(ib.PreRedactable) + _, _ = ifmt.Fprint(&b.Buffer, args...) } // Printf is part of the SafeWriter interface. func (b *StringBuilder) Printf(format string, args ...interface{}) { - _, _ = Fprintf(&b.buf, format, args...) + b.SetMode(ib.PreRedactable) + _, _ = ifmt.Fprintf(&b.Buffer, format, args...) } // SafeString is part of the SafeWriter interface. -func (b *StringBuilder) SafeString(s SafeString) { - w := escapeWriter{w: &b.buf, enclose: false} - _, _ = w.Write([]byte(s)) +func (b *StringBuilder) SafeString(s i.SafeString) { + b.SetMode(ib.SafeEscaped) + _, _ = b.Buffer.WriteString(string(s)) +} + +// SafeInt is part of the SafeWriter interface. +func (b *StringBuilder) SafeInt(s i.SafeInt) { + b.SetMode(ib.SafeEscaped) + _, _ = ifmt.Fprintf(&b.Buffer, "%d", s) +} + +// SafeUint is part of the SafeWriter interface. +func (b *StringBuilder) SafeUint(s i.SafeUint) { + b.SetMode(ib.SafeEscaped) + _, _ = ifmt.Fprintf(&b.Buffer, "%d", s) +} + +// SafeFloat is part of the SafeWriter interface. +func (b *StringBuilder) SafeFloat(s i.SafeFloat) { + b.SetMode(ib.SafeEscaped) + _, _ = ifmt.Fprintf(&b.Buffer, "%v", s) } // SafeRune is part of the SafeWriter interface. -func (b *StringBuilder) SafeRune(s SafeRune) { - if s == startRedactable || s == endRedactable { - s = escapeMark - } - _, _ = b.buf.WriteRune(rune(s)) +func (b *StringBuilder) SafeRune(s i.SafeRune) { + b.SetMode(ib.SafeEscaped) + _ = b.Buffer.WriteRune(rune(s)) } // UnsafeString is part of the SafeWriter interface. func (b *StringBuilder) UnsafeString(s string) { - w := escapeWriter{w: &b.buf, enclose: true, strip: true} - _, _ = w.Write([]byte(s)) + b.SetMode(ib.UnsafeEscaped) + _, _ = b.Buffer.WriteString(s) } // UnsafeRune is part of the SafeWriter interface. func (b *StringBuilder) UnsafeRune(s rune) { - _, _ = b.buf.WriteRune(startRedactable) - b.SafeRune(SafeRune(s)) - _, _ = b.buf.WriteRune(endRedactable) + b.SetMode(ib.UnsafeEscaped) + _ = b.Buffer.WriteRune(s) } // UnsafeByte is part of the SafeWriter interface. func (b *StringBuilder) UnsafeByte(s byte) { - _, _ = b.buf.WriteRune(startRedactable) - if s >= utf8.RuneSelf || - s == startRedactableBytes[0] || s == endRedactableBytes[0] { - // Unsafe byte. Escape it. - _, _ = b.buf.Write(escapeBytes) - } else { - _ = b.buf.WriteByte(s) - } - _, _ = b.buf.WriteRune(endRedactable) + b.SetMode(ib.UnsafeEscaped) + _ = b.Buffer.WriteByte(s) } // UnsafeBytes is part of the SafeWriter interface. func (b *StringBuilder) UnsafeBytes(s []byte) { - w := escapeWriter{w: &b.buf, enclose: true, strip: true} - _, _ = w.Write(s) + b.SetMode(ib.UnsafeEscaped) + _, _ = b.Buffer.Write(s) } diff --git a/vendor/github.com/cockroachdb/redact/interfaces/interfaces.go b/vendor/github.com/cockroachdb/redact/interfaces/interfaces.go new file mode 100644 index 000000000..20fec2ebc --- /dev/null +++ b/vendor/github.com/cockroachdb/redact/interfaces/interfaces.go @@ -0,0 +1,149 @@ +// Copyright 2021 The Cockroach 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 interfaces + +import "fmt" + +// SafeFormatter is implemented by object types that want to separate +// safe and non-safe information when printed out by a Printf-like +// formatter. +type SafeFormatter interface { + // SafeFormat is like the Format method of fmt.Formatter, except + // that it operates using a SafePrinter instead of a fmt.State for + // output. + // + // The verb argument is the control character that defines + // the formatting mode in the surrounding Printf call. + // For example, if this method is called to format %03d, + // the verb is 'd'. + SafeFormat(s SafePrinter, verb rune) +} + +// SafePrinter is a stateful helper that abstracts an output stream in +// the context of printf-like formatting, but with the ability to +// separate safe and unsafe bits of data. +// +// This package provides one implementation of this using marker +// delimiters for unsafe data, see markers.go. We would like to aim +// for alternate implementations to generate more structured formats. +type SafePrinter interface { + // SafePrinter inherits fmt.State to access format flags, however + // calls to fmt.State's underlying Write() as unsafe. + fmt.State + + // SafePrinter provides the SafeWriter interface. + SafeWriter +} + +// SafeWriter provides helper functions for use in implementations of +// SafeFormatter, to format mixes of safe and unsafe strings. +type SafeWriter interface { + // SafeString emits a safe string. + SafeString(SafeString) + + // SafeInt emits a safe integer. + SafeInt(SafeInt) + + // SafeUint emits a safe unsigned integer. + SafeUint(SafeUint) + + // SafeFloat emits a safe floating-point value. + SafeFloat(SafeFloat) + + // SafeRune emits a safe rune. + SafeRune(SafeRune) + + // Print emits its arguments separated by spaces. + // For each argument it dynamically checks for the SafeFormatter or + // SafeValue interface and either use that, or mark the argument + // payload as unsafe. + Print(args ...interface{}) + + // For printf, a linter checks that the format string is + // a constant literal, so the implementation can assume it's always + // safe. + Printf(format string, arg ...interface{}) + + // UnsafeString writes an unsafe string. + UnsafeString(string) + + // UnsafeByte writes an unsafe byte. + UnsafeByte(byte) + + // UnsafeBytes writes an unsafe byte slice. + UnsafeBytes([]byte) + + // UnsafeRune writes an unsafe rune. + UnsafeRune(rune) +} + +// SafeString represents a string that is not a sensitive value. +type SafeString string + +// SafeValue makes SafeString a SafeValue. +func (SafeString) SafeValue() {} + +// SafeInt represents an integer that is not a sensitive value. +type SafeInt int64 + +// SafeValue makes SafeInt a SafeValue. +func (SafeInt) SafeValue() {} + +// SafeUint represents an integer that is not a sensitive value. +type SafeUint uint64 + +// SafeValue makes SafeUint a SafeValue. +func (SafeUint) SafeValue() {} + +// SafeFloat represents a floating-point value that is not a sensitive value. +type SafeFloat float64 + +// SafeValue makes SafeFloat a SafeValue. +func (SafeFloat) SafeValue() {} + +// SafeRune aliases rune. See the explanation for SafeString. +type SafeRune rune + +// SafeValue makes SafeRune a SafeValue. +func (SafeRune) SafeValue() {} + +// SafeValue is a marker interface to be implemented by types that +// alias base Go types and whose natural representation via Printf is +// always safe for reporting. +// +// This is recognized by the SafePrinter interface as an alternative +// to SafeFormatter. +// +// It is provided to decorate "leaf" Go types, such as aliases to int. +// +// Typically, a linter enforces that a type can only implement this +// interface if it aliases a base go type. More complex types should +// implement SafeFormatter instead. +// +// It is advised to build an automatic process during builds to +// collect all the types that implement this interface, as well as all +// uses of this type, and produce a report. Changes to this report +// should receive maximal amount of scrutiny during code reviews. +type SafeValue interface { + SafeValue() +} + +// SafeMessager is an alternative to SafeFormatter used in previous +// versions of CockroachDB. +// NB: this interface is obsolete. Use SafeFormatter instead. +// TODO(knz): Remove this. +type SafeMessager = interface { + SafeMessage() string +} diff --git a/vendor/github.com/cockroachdb/redact/internal/buffer/buffer.go b/vendor/github.com/cockroachdb/redact/internal/buffer/buffer.go new file mode 100644 index 000000000..387e2548a --- /dev/null +++ b/vendor/github.com/cockroachdb/redact/internal/buffer/buffer.go @@ -0,0 +1,351 @@ +// Copyright 2021 The Cockroach 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 buffer + +import ( + "bytes" + origFmt "fmt" + "unicode/utf8" + "unsafe" + + "github.com/cockroachdb/redact/internal/escape" + m "github.com/cockroachdb/redact/internal/markers" +) + +// Buffer is a variable-sized buffer of bytes with a +// Write method. Writes are escaped in different ways +// depending on the output mode. +type Buffer struct { + buf []byte + validUntil int // exclusive upper bound of data that's already validated + mode OutputMode + markerOpen bool +} + +// OutputMode determines how writes are processed in the Buffer. +type OutputMode int + +const ( + // UnsafeEscaped says that written data is unsafe for reporting, + // so it should be enclosed in redaction markers, + // and may contain redaction markers itself, and so it should be escaped. + UnsafeEscaped OutputMode = iota + // SafeEscaped says that written data is safe for reporting + // (should not be enclosed in redaction markers) but may itself + // contain redaction markers, and so it should be escaped. + SafeEscaped + // SafeRaw says that written data is safe for reporting + // (should not be enclosed in redaction markers) and is + // guaranteed not to contain redaction markers, so it + // needs not be escaped. + SafeRaw + // PreRedactable says that written data already contains a mixed + // of safe and unsafe information with suitably placed redaction markers, + // and so should be inlined. + PreRedactable = SafeRaw +) + +// RedactableBytes returns the bytes in the buffer. +func (b Buffer) RedactableBytes() m.RedactableBytes { + // NB: we're dependent on the fact this is a copy of the original + // buffer. The finalize() method should not be called + // in a conceputally read-only accessor like RedactableBytes(). + b.finalize() + return m.RedactableBytes(b.buf) +} + +// RedactableString returns the bytes in the buffer. +func (b Buffer) RedactableString() m.RedactableString { + // NB: we're dependent on the fact this is a copy of the original + // buffer. The finalize() method should not be called + // in a conceputally read-only accessor like RedactableString(). + b.finalize() + return m.RedactableString(b.buf) +} + +// String implemens fmt.Stringer. +func (b Buffer) String() string { + // NB: we're dependent on the fact this is a copy of the original + // buffer. The finalize() method should not be called + // in a conceputally read-only accessor like String(). + b.finalize() + return m.RedactableString(b.buf).StripMarkers() +} + +// TakeRedactableBytes returns the buffer +// contents and reinitializes the buffer. This saves +// a memory allocation compared to RedactableBytes(). +func (b *Buffer) TakeRedactableBytes() m.RedactableBytes { + b.finalize() + r := b.buf + b.buf = nil + b.validUntil = 0 + b.mode = UnsafeEscaped + return m.RedactableBytes(r) +} + +// TakeRedactableString returns the buffer +// contents and reinitializes the buffer. This saves +// a memory allocation compared to RedactableString(). +func (b *Buffer) TakeRedactableString() m.RedactableString { + if b == nil { + // Special case, useful in debugging. + return "" + } + b.finalize() + r := *(*m.RedactableString)(unsafe.Pointer(&b.buf)) + b.buf = nil + b.validUntil = 0 + b.mode = UnsafeEscaped + return r +} + +// Len returns the number of bytes in the buffer. +func (b *Buffer) Len() int { + copy := *b + copy.finalize() + return len(copy.buf) +} + +// Cap returns the capacity of the buffer's underlying byte slice, +// that is, the total space allocated for the buffer's data. +func (b *Buffer) Cap() int { + return cap(b.buf) +} + +// Write appends the contents of p to the buffer, growing the buffer as +// needed. The return value n is the length of p; err is always nil. If the +// buffer becomes too large, Write will panic with ErrTooLarge. +func (b *Buffer) Write(p []byte) (n int, err error) { + b.startWrite() + m, ok := b.tryGrowByReslice(len(p)) + if !ok { + m = b.grow(len(p)) + } + return copy(b.buf[m:], p), nil +} + +// WriteString appends the contents of s to the buffer, growing the buffer as +// needed. The return value n is the length of s; err is always nil. If the +// buffer becomes too large, WriteString will panic with ErrTooLarge. +func (b *Buffer) WriteString(s string) (n int, err error) { + b.startWrite() + m, ok := b.tryGrowByReslice(len(s)) + if !ok { + m = b.grow(len(s)) + } + return copy(b.buf[m:], s), nil +} + +// WriteByte emits a single byte. +func (b *Buffer) WriteByte(s byte) error { + b.startWrite() + if b.mode == UnsafeEscaped && + (s >= utf8.RuneSelf || + s == m.StartS[0] || s == m.EndS[0]) { + // Unsafe byte. Escape it. + _, err := b.WriteString(m.EscapeMarkS) + return err + } + m, ok := b.tryGrowByReslice(1) + if !ok { + m = b.grow(1) + } + b.buf[m] = s + return nil +} + +// WriteRune emits a single rune. +func (b *Buffer) WriteRune(s rune) error { + b.startWrite() + l := utf8.RuneLen(s) + m, ok := b.tryGrowByReslice(l) + if !ok { + m = b.grow(l) + } + _ = utf8.EncodeRune(b.buf[m:], s) + return nil +} + +// finalize ensures that all the buffer is properly +// marked. +func (b *Buffer) finalize() { + if b.mode == SafeRaw { + b.validUntil = len(b.buf) + } else { + b.escapeToEnd(b.mode == UnsafeEscaped /* breakNewLines */) + } + if b.markerOpen { + b.endRedactable() + b.validUntil = len(b.buf) + } +} + +// endRedactable adds the closing redaction marker. +func (b *Buffer) endRedactable() { + if len(b.buf) == 0 { + return + } + if bytes.HasSuffix(b.buf, m.StartBytes) { + // Special case: remove a trailing open marker and call it a day. + b.buf = b.buf[:len(b.buf)-m.StartLen] + } else { + p, ok := b.tryGrowByReslice(m.EndLen) + if !ok { + p = b.grow(m.EndLen) + } + copy(b.buf[p:], m.EndS) + } + b.markerOpen = false +} + +func (b *Buffer) startWrite() { + if b.mode == UnsafeEscaped && !b.markerOpen { + b.startRedactable() + b.validUntil = len(b.buf) + } +} + +// endRedactable adds the closing redaction marker. +func (b *Buffer) startRedactable() { + if bytes.HasSuffix(b.buf, m.EndBytes) { + // Special case: remove a trailing closing marker and call it a day. + b.buf = b.buf[:len(b.buf)-m.EndLen] + } else { + p, ok := b.tryGrowByReslice(len(m.StartS)) + if !ok { + p = b.grow(len(m.StartS)) + } + copy(b.buf[p:], m.StartS) + } + b.markerOpen = true +} + +// escapeToEnd escapes occurrences of redaction markers in +// b.buf[b.validUntil:] and advances b.validUntil until the end. +func (b *Buffer) escapeToEnd(breakNewLines bool) { + b.buf = escape.InternalEscapeBytes(b.buf, b.validUntil, breakNewLines, false /* trim */) + b.validUntil = len(b.buf) +} + +// GetMode retrieves the output mode. +func (b *Buffer) GetMode() OutputMode { + return b.mode +} + +// SetMode changes the output mode. +func (b *Buffer) SetMode(newMode OutputMode) { + if b.mode == newMode { + // noop + return + } + if b.mode == UnsafeEscaped || b.mode == SafeEscaped { + b.escapeToEnd(b.mode == UnsafeEscaped /* breakNewLines */) + } + if b.markerOpen { + b.endRedactable() + } + b.validUntil = len(b.buf) + b.mode = newMode +} + +// Reset resets the buffer to be empty, +// but it retains the underlying storage for use by future writes. +// It also resets the output mode to UnsafeEscaped. +func (b *Buffer) Reset() { + b.buf = b.buf[:0] + b.validUntil = 0 + b.mode = UnsafeEscaped + b.markerOpen = false +} + +// tryGrowByReslice is a inlineable version of grow for the fast-case where the +// internal buffer only needs to be resliced. +// It returns the index where bytes should be written and whether it succeeded. +func (b *Buffer) tryGrowByReslice(n int) (int, bool) { + if l := len(b.buf); n <= cap(b.buf)-l { + b.buf = b.buf[:l+n] + return l, true + } + return 0, false +} + +// grow grows the buffer to guarantee space for n more bytes. +// It returns the index where bytes should be written. +// If the buffer can't grow it will panic with ErrTooLarge. +func (b *Buffer) grow(n int) int { + m := len(b.buf) + // Try to grow by means of a reslice. + if i, ok := b.tryGrowByReslice(n); ok { + return i + } + if b.buf == nil && n <= smallBufferSize { + b.buf = make([]byte, n, smallBufferSize) + return 0 + } + c := cap(b.buf) + const maxInt = int(^uint(0) >> 1) + if n <= c/2-m { + // let capacity get twice as large. + } else if c > maxInt-c-n { + panic(ErrTooLarge) + } else { + // Not enough space anywhere, we need to allocate. + buf := makeSlice(2*c + n) + copy(buf, b.buf) + b.buf = buf + } + b.buf = b.buf[:m+n] + return m +} + +// Grow grows the buffer's capacity, if necessary, to guarantee space for +// another n bytes. After Grow(n), at least n bytes can be written to the +// buffer without another allocation. +// If n is negative, Grow will panic. +// If the buffer can't grow it will panic with ErrTooLarge. +func (b *Buffer) Grow(n int) { + if n < 0 { + panic(origFmt.Errorf("redact.Buffer.Grow: negative count")) + } + m := b.grow(n) + b.buf = b.buf[:m] +} + +// clone is used in tests. +func (b *Buffer) clone() *Buffer { + c := *b + c.buf = append([]byte(nil), b.buf...) + return &c +} + +// makeSlice allocates a slice of size n. If the allocation fails, it panics +// with ErrTooLarge. +func makeSlice(n int) []byte { + // If the make fails, give a known error. + defer func() { + if recover() != nil { + panic(ErrTooLarge) + } + }() + return make([]byte, n) +} + +// ErrTooLarge is passed to panic if memory cannot be allocated to +// store data in a buffer. +var ErrTooLarge = origFmt.Errorf("redact.Buffer: too large") + +// smallBufferSize is an initial allocation minimal capacity. +const smallBufferSize = 64 diff --git a/vendor/github.com/cockroachdb/redact/internal/escape/escape.go b/vendor/github.com/cockroachdb/redact/internal/escape/escape.go new file mode 100644 index 000000000..1fc67063a --- /dev/null +++ b/vendor/github.com/cockroachdb/redact/internal/escape/escape.go @@ -0,0 +1,137 @@ +// Copyright 2020 The Cockroach 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 escape + +import ( + "bytes" + "unicode/utf8" + + m "github.com/cockroachdb/redact/internal/markers" +) + +// InternalEscapeBytes escapes redaction markers in the provided buf +// starting at the location startLoc. +// The bytes before startLoc are considered safe (already escaped). +// +// If breakNewLines is set, a closing redaction marker +// is placed before sequences of one or more newline characters, +// and an open redaction marker is placed afterwards. +// +// If strip is set, final newlines and spaces are trimmed from the +// output. +func InternalEscapeBytes(b []byte, startLoc int, breakNewLines, strip bool) (res []byte) { + // Note: we use len(...RedactableS) and not len(...RedactableBytes) + // because the ...S variant is a compile-time constant so this + // accelerates the loops below. + start, ls := m.StartBytes, len(m.StartS) + end, le := m.EndBytes, len(m.EndS) + escape := m.EscapeMarkBytes + + // Trim final newlines/spaces, for convenience. + if strip { + end := len(b) + for i := end - 1; i >= startLoc; i-- { + if b[i] == '\n' || b[i] == ' ' { + end = i + } else { + break + } + } + b = b[:end] + } + + // res is the output slice. In the common case where there is + // nothing to escape, the input slice is returned directly + // and no allocation takes place. + res = b + // copied is true if and only if `res` is a copy of `b`. It only + // turns to true if the loop below finds something to escape. + copied := false + // k is the index in b up to (and excluding) the byte which we've + // already copied into res (if copied=true). + k := 0 + + for i := startLoc; i < len(b); i++ { + if breakNewLines && b[i] == '\n' { + if !copied { + // We only allocate an output slice when we know we definitely + // need it. + res = make([]byte, 0, len(b)) + copied = true + } + res = append(res, b[k:i]...) + // Either add an end marker, or elide a start marker immediately prior. + if bytes.HasSuffix(res, start) { + res = res[:len(res)-ls] + } else { + res = append(res, end...) + } + // Advance to the last newline character. We want to forward + // them all in a single call to doWrite, for performance. + lastNewLine := i + for lastNewLine < len(b) && b[lastNewLine] == '\n' { + lastNewLine++ + } + res = append(res, b[i:lastNewLine]...) + res = append(res, start...) + k = lastNewLine + i = lastNewLine - 1 + } else + // Ensure that occurrences of the delimiter inside the string get + // escaped. + // Reminder: ls and le are likely greater than 1, as we are scanning + // utf-8 encoded delimiters (the utf-8 encoding is multibyte). + if i+ls <= len(b) && bytes.Equal(b[i:i+ls], start) { + if !copied { + // We only allocate an output slice when we know we definitely + // need it. + res = make([]byte, 0, len(b)+len(escape)) + copied = true + } + res = append(res, b[k:i]...) + res = append(res, escape...) + // Advance the counters by the length (in bytes) of the delimiter. + k = i + ls + i += ls - 1 /* -1 because we have i++ at the end of every iteration */ + } else if i+le <= len(b) && bytes.Equal(b[i:i+le], end) { + if !copied { + // See the comment above about res allocation. + res = make([]byte, 0, len(b)+len(escape)) + copied = true + } + res = append(res, b[k:i]...) + res = append(res, escape...) + // Advance the counters by the length (in bytes) of the delimiter. + k = i + le + i += le - 1 /* -1 because we have i++ at the end of every iteration */ + } + } + // If the string terminates with an invalid utf-8 sequence, we + // want to avoid a run-in with a subsequent redaction marker. + if r, s := utf8.DecodeLastRune(b); s == 1 && r == utf8.RuneError { + if !copied { + // See the comment above about res allocation. + res = make([]byte, 0, len(b)+len(escape)) + copied = true + } + res = append(res, b[k:]...) + res = append(res, escape...) + k = len(b) + } + if copied { + res = append(res, b[k:]...) + } + return +} diff --git a/vendor/github.com/cockroachdb/redact/make_format.go b/vendor/github.com/cockroachdb/redact/internal/fmtforward/make_format.go similarity index 87% rename from vendor/github.com/cockroachdb/redact/make_format.go rename to vendor/github.com/cockroachdb/redact/internal/fmtforward/make_format.go index e088b9379..bb66923e8 100644 --- a/vendor/github.com/cockroachdb/redact/make_format.go +++ b/vendor/github.com/cockroachdb/redact/internal/fmtforward/make_format.go @@ -12,7 +12,7 @@ // implied. See the License for the specific language governing // permissions and limitations under the License. -package redact +package fmtforward import ( "fmt" @@ -21,7 +21,10 @@ import ( "strings" ) -func reproducePrintf(w io.Writer, s fmt.State, verb rune, arg interface{}) { +// ReproducePrintf calls fmt.Print/fmt.Printf on the argument +// based on the details present in the fmt.State and +// writes to the io.Writer. +func ReproducePrintf(w io.Writer, s fmt.State, verb rune, arg interface{}) { justV, revFmt := MakeFormat(s, verb) if justV { // Common case, avoids generating then parsing the format again. @@ -31,8 +34,7 @@ func reproducePrintf(w io.Writer, s fmt.State, verb rune, arg interface{}) { } } -// MakeFormat is a helper for use by implementations of the -// SafeFormatter interface. It reproduces the format currently active +// MakeFormat reproduces the format currently active // in fmt.State and verb. This is provided because Go's standard // fmt.State does not make the original format string available to us. // diff --git a/vendor/github.com/cockroachdb/redact/internal/hooks.go b/vendor/github.com/cockroachdb/redact/internal/hooks.go deleted file mode 100644 index 246e600de..000000000 --- a/vendor/github.com/cockroachdb/redact/internal/hooks.go +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2020 The Cockroach 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 fmt - -// printArg overrides the original implementation by redirecting the -// call to a substitute function in the printer, if available. -func (p *pp) printArg(a interface{}, verb rune) { - if p.printArgSubstituteFn != nil { - p.substituteState = p.printArgSubstituteFn(p, a, verb) - } else { - p.printArgOrig(a, verb) - } -} - -// InternalPrinter exposes pp to the redact package. -type InternalPrinter = pp - -// InternalBuffer exposes buffer to the redact package. -type InternalBuffer = buffer - -// NewInternalPrinter exposes pp allocation to the redact package. -func NewInternalPrinter() *InternalPrinter { return newPrinter() } - -// SetHook connects an outer printer to the inner printer. -func SetHook( - p *InternalPrinter, fn func(p *InternalPrinter, arg interface{}, verb rune) (newState int), -) { - p.printArgSubstituteFn = fn -} - -// Free exposes pp deallocation to the redact package. -func Free(p *InternalPrinter) { - p.substituteState = 0 - p.printArgSubstituteFn = nil - p.free() -} - -// Buf exposes the string buffer to the redact package. -func Buf(p *InternalPrinter) []byte { return []byte(p.buf) } - -// GetState exposes the state to the redact package. -func GetState(p *InternalPrinter) int { - return p.substituteState -} - -// SetState exposes the string buffer to the redact package. -func SetState(p *InternalPrinter, b []byte) { - p.buf = buffer(b) - p.substituteState = len(p.buf) -} - -// Append adds bytes to the buffer. -func Append(p *InternalPrinter, b []byte) { p.buf.write(b) } - -// PrintArg exposes the printArgOrig() method to the redact package. -func PrintArg(p *InternalPrinter, a interface{}, verb rune) { p.printArgOrig(a, verb) } - -// DoPrint exposes the doPrint() method to the redact package. -func DoPrint(p *InternalPrinter, a []interface{}) { p.doPrint(a) } - -// DoPrintf exposes the doPrintf() method to the redact package. -func DoPrintf(p *InternalPrinter, format string, a []interface{}) { p.doPrintf(format, a) } - -// SetCollectError enables wrapped error collection. -func SetCollectError(p *InternalPrinter) { p.wrapErrs = true } - -// CollectingError exposes wrapped error collection. -func CollectingError(p *InternalPrinter) bool { return p.wrapErrs } - -// WrappedError retrieves the wrapped error if found. -func WrappedError(p *InternalPrinter) error { return p.wrappedErr } diff --git a/vendor/github.com/cockroachdb/redact/internal/markers/constants.go b/vendor/github.com/cockroachdb/redact/internal/markers/constants.go new file mode 100644 index 000000000..f062f7ea8 --- /dev/null +++ b/vendor/github.com/cockroachdb/redact/internal/markers/constants.go @@ -0,0 +1,40 @@ +// Copyright 2020 The Cockroach 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 markers + +import "regexp" + +// Internal constants. +const ( + Start = '‹' + StartS = string(Start) + StartLen = len(StartS) + End = '›' + EndS = string(End) + EndLen = len(EndS) + EscapeMark = '?' + EscapeMarkS = string(EscapeMark) + RedactedS = StartS + "×" + EndS +) + +// Internal variables. +var ( + StartBytes = []byte(StartS) + EndBytes = []byte(EndS) + EscapeMarkBytes = []byte(EscapeMarkS) + RedactedBytes = []byte(RedactedS) + ReStripSensitive = regexp.MustCompile(StartS + "[^" + StartS + EndS + "]*" + EndS) + ReStripMarkers = regexp.MustCompile("[" + StartS + EndS + "]") +) diff --git a/vendor/github.com/cockroachdb/redact/markers.go b/vendor/github.com/cockroachdb/redact/internal/markers/markers.go similarity index 75% rename from vendor/github.com/cockroachdb/redact/markers.go rename to vendor/github.com/cockroachdb/redact/internal/markers/markers.go index 7b719183d..f6bfa10df 100644 --- a/vendor/github.com/cockroachdb/redact/markers.go +++ b/vendor/github.com/cockroachdb/redact/internal/markers/markers.go @@ -12,9 +12,9 @@ // implied. See the License for the specific language governing // permissions and limitations under the License. -package redact +package markers -import "bytes" +import i "github.com/cockroachdb/redact/interfaces" // RedactableString is a string that contains a mix of safe and unsafe // bits of data, but where it is known that unsafe bits are enclosed @@ -30,13 +30,13 @@ type RedactableString string // RedactableString. This returns an unsafe string where all safe and // unsafe bits are mixed together. func (s RedactableString) StripMarkers() string { - return reStripMarkers.ReplaceAllString(string(s), "") + return ReStripMarkers.ReplaceAllString(string(s), "") } // Redact replaces all occurrences of unsafe substrings by the // “Redacted” marker, ‹×›. The result string is still safe. func (s RedactableString) Redact() RedactableString { - return RedactableString(reStripSensitive.ReplaceAllString(string(s), redactedS)) + return RedactableString(ReStripSensitive.ReplaceAllString(string(s), RedactedS)) } // ToBytes converts the string to a byte slice. @@ -45,7 +45,7 @@ func (s RedactableString) ToBytes() RedactableBytes { } // SafeFormat formats the redactable safely. -func (s RedactableString) SafeFormat(sp SafePrinter, _ rune) { +func (s RedactableString) SafeFormat(sp i.SafePrinter, _ rune) { // As per annotateArgs() in markers_internal_print.go, // we consider the redactable string not further formattable. sp.Print(s) @@ -62,13 +62,13 @@ type RedactableBytes []byte // RedactableBytes. This returns an unsafe string where all safe and // unsafe bits are mixed together. func (s RedactableBytes) StripMarkers() []byte { - return reStripMarkers.ReplaceAll([]byte(s), nil) + return ReStripMarkers.ReplaceAll([]byte(s), nil) } // Redact replaces all occurrences of unsafe substrings by the // “Redacted” marker, ‹×›. func (s RedactableBytes) Redact() RedactableBytes { - return RedactableBytes(reStripSensitive.ReplaceAll(s, redactedBytes)) + return RedactableBytes(ReStripSensitive.ReplaceAll(s, RedactedBytes)) } // ToString converts the byte slice to a string. @@ -77,33 +77,23 @@ func (s RedactableBytes) ToString() RedactableString { } // SafeFormat formats the redactable safely. -func (s RedactableBytes) SafeFormat(sp SafePrinter, _ rune) { +func (s RedactableBytes) SafeFormat(sp i.SafePrinter, _ rune) { // As per annotateArgs() in markers_internal_print.go, // we consider the redactable bytes not further formattable. sp.Print(s) } -// EscapeBytes escapes markers inside the given byte slice and encloses -// the entire byte slice between redaction markers. -func EscapeBytes(s []byte) RedactableBytes { - var buf bytes.Buffer - buf.Grow(len(s) + len(startRedactableS) + len(endRedactableS)) - e := escapeWriter{w: &buf, enclose: true, strip: false} - _, _ = e.Write(s) - return RedactableBytes(buf.Bytes()) -} - // StartMarker returns the start delimiter for an unsafe string. -func StartMarker() []byte { return startRedactableBytes } +func StartMarker() []byte { return []byte(StartS) } // EndMarker returns the end delimiter for an unsafe string. -func EndMarker() []byte { return endRedactableBytes } +func EndMarker() []byte { return []byte(EndS) } // RedactedMarker returns the special string used by Redact. -func RedactedMarker() []byte { return redactedBytes } +func RedactedMarker() []byte { return []byte(RedactedS) } // EscapeMarkers escapes the special delimiters from the provided // byte slice. func EscapeMarkers(s []byte) []byte { - return reStripMarkers.ReplaceAll(s, escapeBytes) + return ReStripMarkers.ReplaceAll(s, EscapeMarkBytes) } diff --git a/vendor/github.com/cockroachdb/redact/internal/print.go.diff b/vendor/github.com/cockroachdb/redact/internal/print.go.diff deleted file mode 100644 index 4451b4b10..000000000 --- a/vendor/github.com/cockroachdb/redact/internal/print.go.diff +++ /dev/null @@ -1,58 +0,0 @@ ---- print.go.orig 2020-08-26 14:49:30.396184000 +0200 -+++ print.go 2020-08-26 14:50:29.330829000 +0200 -@@ -1,3 +1,6 @@ -+// Code generated from print.go.orig. DO NOT EDIT -+// GENERATED FILE DO NOT EDIT -+// - // 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. -@@ -5,12 +8,16 @@ - package fmt - - import ( -- "internal/fmtsort" -+ // CUSTOM: needed to avoid a type mismatch on Formatter. -+ origFmt "fmt" - "io" - "os" - "reflect" - "sync" - "unicode/utf8" -+ -+ // CUSTOM: our own import since we can't use internal from go stdlib. -+ "github.com/cockroachdb/redact/internal/fmtsort" - ) - - // Strings for use with buffer.WriteString. -@@ -51,7 +58,8 @@ - // The implementation of Format may call Sprint(f) or Fprint(f) etc. - // to generate its output. - type Formatter interface { -- Format(f State, c rune) -+ // CUSTOM: refer to the original type, not the one defined here. -+ Format(f origFmt.State, c rune) - } - - // Stringer is implemented by any value that has a String method, -@@ -105,6 +113,10 @@ - type pp struct { - buf buffer - -+ // CUSTOM: hook fn for the redact package. -+ printArgSubstituteFn func(p *pp, a interface{}, verb rune) (newState int) -+ substituteState int -+ - // arg holds the current item, as an interface{}. - arg interface{} - -@@ -635,7 +647,8 @@ - return false - } - --func (p *pp) printArg(arg interface{}, verb rune) { -+// CUSTOM: printArg() renamed to printArgOrig(). -+func (p *pp) printArgOrig(arg interface{}, verb rune) { - p.arg = arg - p.value = reflect.Value{} - diff --git a/vendor/github.com/cockroachdb/redact/internal/redact/doc.go b/vendor/github.com/cockroachdb/redact/internal/redact/doc.go new file mode 100644 index 000000000..1e42c2318 --- /dev/null +++ b/vendor/github.com/cockroachdb/redact/internal/redact/doc.go @@ -0,0 +1,19 @@ +// Copyright 2021 The Cockroach 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 redact is a helper internal package that provides the +// Unsafe and Safe value wrappers. Its name is 'redact' even though a +// better name would be 'wrappers' so as to ensure that the type name +// of generated values contains the 'redact.' prefix. +package redact diff --git a/vendor/github.com/cockroachdb/redact/wrappers.go b/vendor/github.com/cockroachdb/redact/internal/redact/wrappers.go similarity index 56% rename from vendor/github.com/cockroachdb/redact/wrappers.go rename to vendor/github.com/cockroachdb/redact/internal/redact/wrappers.go index 5cbd94d17..77d7a368b 100644 --- a/vendor/github.com/cockroachdb/redact/wrappers.go +++ b/vendor/github.com/cockroachdb/redact/internal/redact/wrappers.go @@ -14,7 +14,12 @@ package redact -import "fmt" +import ( + origFmt "fmt" + + i "github.com/cockroachdb/redact/interfaces" + "github.com/cockroachdb/redact/internal/fmtforward" +) // Unsafe turns any value that would otherwise be considered safe, // into an unsafe value. @@ -22,12 +27,20 @@ func Unsafe(a interface{}) interface{} { return unsafeWrap{a} } +// UnsafeWrap is the type of wrapper produced by Unsafe. +// This is exported only for use by the rfmt package. +// Client packages should not make assumptions about +// the concrete return type of Unsafe(). +type UnsafeWrap = unsafeWrap + type unsafeWrap struct { a interface{} } -func (w unsafeWrap) Format(s fmt.State, verb rune) { - reproducePrintf(s, s, verb, w.a) +func (w unsafeWrap) GetValue() interface{} { return w.a } + +func (w unsafeWrap) Format(s origFmt.State, verb rune) { + fmtforward.ReproducePrintf(s, s, verb, w.a) } // Safe turns any value into an object that is considered as safe by @@ -37,27 +50,35 @@ func (w unsafeWrap) Format(s fmt.State, verb rune) { // interfaces and conventions fail. Increased usage of this mechanism // should be taken as a signal that a new abstraction is missing. // The implementation is also slow. -func Safe(a interface{}) SafeValue { +func Safe(a interface{}) i.SafeValue { return safeWrapper{a} } +// SafeWrapper is the type of wrapper produced by Safe. +// This is exported only for use by the rfmt package. +// Client packages should not make assumptions about +// the concrete return type of Safe(). +type SafeWrapper = safeWrapper + type safeWrapper struct { a interface{} } -var _ SafeValue = safeWrapper{} -var _ fmt.Formatter = safeWrapper{} -var _ SafeMessager = safeWrapper{} +var _ i.SafeValue = safeWrapper{} +var _ origFmt.Formatter = safeWrapper{} +var _ i.SafeMessager = safeWrapper{} + +func (w safeWrapper) GetValue() interface{} { return w.a } // SafeValue implements the SafeValue interface. func (w safeWrapper) SafeValue() {} // Format implements the fmt.Formatter interface. -func (w safeWrapper) Format(s fmt.State, verb rune) { - reproducePrintf(s, s, verb, w.a) +func (w safeWrapper) Format(s origFmt.State, verb rune) { + fmtforward.ReproducePrintf(s, s, verb, w.a) } // SafeMessage implements SafeMessager. func (w safeWrapper) SafeMessage() string { - return fmt.Sprintf("%v", w.a) + return origFmt.Sprintf("%v", w.a) } diff --git a/vendor/github.com/cockroachdb/redact/internal/README.md b/vendor/github.com/cockroachdb/redact/internal/rfmt/README.md similarity index 77% rename from vendor/github.com/cockroachdb/redact/internal/README.md rename to vendor/github.com/cockroachdb/redact/internal/rfmt/README.md index 768a89545..ab2677444 100644 --- a/vendor/github.com/cockroachdb/redact/internal/README.md +++ b/vendor/github.com/cockroachdb/redact/internal/rfmt/README.md @@ -24,15 +24,6 @@ Overall, the original Go code is structured as follows: characters from the format string, as well as certain *constant* error strings (e.g. `%(BADPREC)`). -At this point **we make the following assumption**: there is no data -from the printed *arguments* that is emitted to `pp.buf` directly by a -`doPrint()` method. This is true of the implementation as of Go 1.14. - -From this point, this package contains a *custom patch* onto the -default implementation: the calls to `p.printArg` performed by the -`doPrint()` methods are redirected to a function callback that is -injected by the `redact` package. - Refreshing the sources ====================== diff --git a/vendor/github.com/cockroachdb/redact/internal/fmtsort/sort.go b/vendor/github.com/cockroachdb/redact/internal/rfmt/fmtsort/sort.go similarity index 99% rename from vendor/github.com/cockroachdb/redact/internal/fmtsort/sort.go rename to vendor/github.com/cockroachdb/redact/internal/rfmt/fmtsort/sort.go index 9d2d580aa..a64d5cdeb 100644 --- a/vendor/github.com/cockroachdb/redact/internal/fmtsort/sort.go +++ b/vendor/github.com/cockroachdb/redact/internal/rfmt/fmtsort/sort.go @@ -132,7 +132,7 @@ func compare(aVal, bVal reflect.Value) int { default: return -1 } - case reflect.Ptr: + case reflect.Ptr, reflect.UnsafePointer: a, b := aVal.Pointer(), bVal.Pointer() switch { case a < b: diff --git a/vendor/github.com/cockroachdb/redact/internal/format.go b/vendor/github.com/cockroachdb/redact/internal/rfmt/format.go similarity index 96% rename from vendor/github.com/cockroachdb/redact/internal/format.go rename to vendor/github.com/cockroachdb/redact/internal/rfmt/format.go index f93c2f135..56c81d34f 100644 --- a/vendor/github.com/cockroachdb/redact/internal/format.go +++ b/vendor/github.com/cockroachdb/redact/internal/rfmt/format.go @@ -1,10 +1,11 @@ // Code generated from the Go standard library. DO NOT EDIT // GENERATED FILE DO NOT EDIT +// // 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 fmt +package rfmt import ( "strconv" @@ -67,25 +68,17 @@ func (f *fmt) writePadding(n int) { if n <= 0 { // No padding bytes needed. return } - buf := *f.buf - oldLen := len(buf) - newLen := oldLen + n // Make enough room for padding. - if newLen > cap(buf) { - buf = make(buffer, cap(buf)*2+n) - copy(buf, *f.buf) - } + f.buf.Grow(n) // Decide which byte the padding should be filled with. padByte := byte(' ') if f.zero { padByte = byte('0') } // Fill padding with padByte. - padding := buf[oldLen:newLen] - for i := range padding { - padding[i] = padByte + for i := 0; i < n; i++ { + f.buf.writeByte(padByte) } - *f.buf = buf[:newLen] } // pad appends b to f.buf, padded on left (!f.minus) or right (f.minus). @@ -322,7 +315,7 @@ func (f *fmt) fmtInteger(u uint64, base int, isSigned bool, verb rune, digits st f.zero = oldZero } -// truncate truncates the string s to the specified precision, if present. +// truncateString truncates the string s to the specified precision, if present. func (f *fmt) truncateString(s string) string { if f.precPresent { n := f.prec @@ -403,19 +396,20 @@ func (f *fmt) fmtSbx(s string, b []byte, digits string) { f.writePadding(f.wid - width) } // Write the encoding directly into the output buffer. - buf := *f.buf if f.sharp { // Add leading 0x or 0X. - buf = append(buf, '0', digits[16]) + f.buf.WriteByte('0') + f.buf.WriteByte(digits[16]) } var c byte for i := 0; i < length; i++ { if f.space && i > 0 { // Separate elements with a space. - buf = append(buf, ' ') + f.buf.WriteByte(' ') if f.sharp { // Add leading 0x or 0X for each element. - buf = append(buf, '0', digits[16]) + f.buf.WriteByte('0') + f.buf.WriteByte(digits[16]) } } if b != nil { @@ -424,9 +418,9 @@ func (f *fmt) fmtSbx(s string, b []byte, digits string) { c = s[i] // Take a byte from the input string. } // Encode each byte as two hexadecimal digits. - buf = append(buf, digits[c>>4], digits[c&0xF]) + f.buf.WriteByte(digits[c>>4]) + f.buf.WriteByte(digits[c&0xF]) } - *f.buf = buf // Handle padding to the right. if f.widPresent && f.wid > width && f.minus { f.writePadding(f.wid - width) diff --git a/vendor/github.com/cockroachdb/redact/internal/rfmt/format.go.diff b/vendor/github.com/cockroachdb/redact/internal/rfmt/format.go.diff new file mode 100644 index 000000000..e2479b71e --- /dev/null +++ b/vendor/github.com/cockroachdb/redact/internal/rfmt/format.go.diff @@ -0,0 +1,81 @@ +--- format.go.orig 2022-01-07 15:25:57.762807000 +0100 ++++ format.go 2022-01-07 15:26:16.154491000 +0100 +@@ -1,8 +1,11 @@ ++// Code generated from the Go standard library. DO NOT EDIT ++// GENERATED FILE DO NOT EDIT ++// + // 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 fmt ++package rfmt + + import ( + "strconv" +@@ -65,25 +68,17 @@ + if n <= 0 { // No padding bytes needed. + return + } +- buf := *f.buf +- oldLen := len(buf) +- newLen := oldLen + n + // Make enough room for padding. +- if newLen > cap(buf) { +- buf = make(buffer, cap(buf)*2+n) +- copy(buf, *f.buf) +- } ++ f.buf.Grow(n) + // Decide which byte the padding should be filled with. + padByte := byte(' ') + if f.zero { + padByte = byte('0') + } + // Fill padding with padByte. +- padding := buf[oldLen:newLen] +- for i := range padding { +- padding[i] = padByte ++ for i := 0; i < n; i++ { ++ f.buf.writeByte(padByte) + } +- *f.buf = buf[:newLen] + } + + // pad appends b to f.buf, padded on left (!f.minus) or right (f.minus). +@@ -401,19 +396,20 @@ + f.writePadding(f.wid - width) + } + // Write the encoding directly into the output buffer. +- buf := *f.buf + if f.sharp { + // Add leading 0x or 0X. +- buf = append(buf, '0', digits[16]) ++ f.buf.WriteByte('0') ++ f.buf.WriteByte(digits[16]) + } + var c byte + for i := 0; i < length; i++ { + if f.space && i > 0 { + // Separate elements with a space. +- buf = append(buf, ' ') ++ f.buf.WriteByte(' ') + if f.sharp { + // Add leading 0x or 0X for each element. +- buf = append(buf, '0', digits[16]) ++ f.buf.WriteByte('0') ++ f.buf.WriteByte(digits[16]) + } + } + if b != nil { +@@ -422,9 +418,9 @@ + c = s[i] // Take a byte from the input string. + } + // Encode each byte as two hexadecimal digits. +- buf = append(buf, digits[c>>4], digits[c&0xF]) ++ f.buf.WriteByte(digits[c>>4]) ++ f.buf.WriteByte(digits[c&0xF]) + } +- *f.buf = buf + // Handle padding to the right. + if f.widPresent && f.wid > width && f.minus { + f.writePadding(f.wid - width) diff --git a/vendor/github.com/cockroachdb/redact/internal/rfmt/helpers.go b/vendor/github.com/cockroachdb/redact/internal/rfmt/helpers.go new file mode 100644 index 000000000..7868d1b34 --- /dev/null +++ b/vendor/github.com/cockroachdb/redact/internal/rfmt/helpers.go @@ -0,0 +1,160 @@ +// Copyright 2021 The Cockroach 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 rfmt + +import ( + "reflect" + + i "github.com/cockroachdb/redact/interfaces" + b "github.com/cockroachdb/redact/internal/buffer" + "github.com/cockroachdb/redact/internal/escape" + m "github.com/cockroachdb/redact/internal/markers" + rwrap "github.com/cockroachdb/redact/internal/redact" +) + +type overrideMode int + +const ( + noOverride overrideMode = iota + // Consider unsafe values as safe. + overrideSafe + // Consider safe and pre-redactable values as unsafe. + overrideUnsafe +) + +func (p *pp) startUnsafe() restorer { + prevMode := p.buf.GetMode() + if p.override != overrideSafe { + p.buf.SetMode(b.UnsafeEscaped) + } + return restorer{p, prevMode, p.override} +} + +func (p *pp) startPreRedactable() restorer { + prevMode := p.buf.GetMode() + if p.override != overrideUnsafe { + p.buf.SetMode(b.PreRedactable) + } + return restorer{p, prevMode, p.override} +} + +func (p *pp) startSafeOverride() restorer { + prevMode := p.buf.GetMode() + prevOverride := p.override + if p.override == noOverride { + p.buf.SetMode(b.SafeEscaped) + p.override = overrideSafe + } + return restorer{p, prevMode, prevOverride} +} + +func (p *pp) startUnsafeOverride() restorer { + prevMode := p.buf.GetMode() + prevOverride := p.override + if p.override == noOverride { + p.buf.SetMode(b.UnsafeEscaped) + p.override = overrideUnsafe + } + return restorer{p, prevMode, prevOverride} +} + +type restorer struct { + p *pp + prevMode b.OutputMode + prevOverride overrideMode +} + +func (r restorer) restore() { + r.p.buf.SetMode(r.prevMode) + r.p.override = r.prevOverride +} + +func (p *pp) handleSpecialValues( + value reflect.Value, t reflect.Type, verb rune, depth int, +) (handled bool) { + switch t { + case safeWrapperType: + handled = true + defer p.startSafeOverride().restore() + p.printValue(value.Field(0), verb, depth+1) + + case unsafeWrapperType: + handled = true + defer p.startUnsafeOverride().restore() + p.printValue(value.Field(0), verb, depth+1) + + case redactableStringType: + handled = true + defer p.startPreRedactable().restore() + p.buf.WriteString(value.String()) + + case redactableBytesType: + handled = true + defer p.startPreRedactable().restore() + p.buf.Write(value.Bytes()) + } + + return handled +} + +// Sprintfn produces a RedactableString using the provided +// SafeFormat-alike function. +func Sprintfn(printer func(w i.SafePrinter)) m.RedactableString { + p := newPrinter() + printer(p) + s := p.buf.TakeRedactableString() + p.free() + return s +} + +// HelperForErrorf is a helper to implement a redaction-aware +// fmt.Errorf-compatible function in a different package. It formats +// the string according to the given format and arguments in the same +// way as Sprintf, but in addition to this if the format contains %w +// and an error object in the proper argument position it also returns +// that error object. +// +// Note: This function only works if an error redaction function +// has been injected with RegisterRedactErrorFn(). +func HelperForErrorf(format string, args ...interface{}) (m.RedactableString, error) { + p := newPrinter() + p.wrapErrs = true + p.doPrintf(format, args) + e := p.wrappedErr + s := p.buf.TakeRedactableString() + p.free() + return s, e +} + +// EscapeBytes escapes markers inside the given byte slice and encloses +// the entire byte slice between redaction markers. +// EscapeBytes escapes markers inside the given byte slice and encloses +// the entire byte slice between redaction markers. +func EscapeBytes(s []byte) m.RedactableBytes { + buf := make([]byte, 0, len(s)+len(m.StartS)+len(m.EndS)) + buf = append(buf, m.StartS...) + start := len(buf) + buf = append(buf, s...) + buf = escape.InternalEscapeBytes(buf, start, true /* breakNewLine */, false /* strip */) + buf = append(buf, m.EndS...) + return m.RedactableBytes(buf) +} + +var ( + unsafeWrapperType = reflect.TypeOf(rwrap.UnsafeWrap{}) + safeWrapperType = reflect.TypeOf(rwrap.SafeWrapper{}) + redactableStringType = reflect.TypeOf(m.RedactableString("")) + redactableBytesType = reflect.TypeOf(m.RedactableBytes{}) +) diff --git a/vendor/github.com/cockroachdb/redact/internal/print.go b/vendor/github.com/cockroachdb/redact/internal/rfmt/print.go similarity index 86% rename from vendor/github.com/cockroachdb/redact/internal/print.go rename to vendor/github.com/cockroachdb/redact/internal/rfmt/print.go index b7cdd3fa6..16ba3ce73 100644 --- a/vendor/github.com/cockroachdb/redact/internal/print.go +++ b/vendor/github.com/cockroachdb/redact/internal/rfmt/print.go @@ -5,7 +5,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package fmt +package rfmt import ( // CUSTOM: needed to avoid a type mismatch on Formatter. @@ -16,8 +16,12 @@ import ( "sync" "unicode/utf8" - // CUSTOM: our own import since we can't use internal from go stdlib. - "github.com/cockroachdb/redact/internal/fmtsort" + // CUSTOM: our own imports. + i "github.com/cockroachdb/redact/interfaces" + b "github.com/cockroachdb/redact/internal/buffer" + m "github.com/cockroachdb/redact/internal/markers" + w "github.com/cockroachdb/redact/internal/redact" + "github.com/cockroachdb/redact/internal/rfmt/fmtsort" ) // Strings for use with buffer.WriteString. @@ -54,12 +58,12 @@ type State interface { Flag(c int) bool } -// Formatter is the interface implemented by values with a custom formatter. -// The implementation of Format may call Sprint(f) or Fprint(f) etc. -// to generate its output. +// Formatter is implemented by any value that has a Format method. +// The implementation controls how State and rune are interpreted, +// and may call Sprint(f) or Fprint(f) etc. to generate its output. type Formatter interface { // CUSTOM: refer to the original type, not the one defined here. - Format(f origFmt.State, c rune) + Format(f origFmt.State, verb rune) } // Stringer is implemented by any value that has a String method, @@ -79,43 +83,33 @@ type GoStringer interface { GoString() string } -// Use simple []byte instead of bytes.Buffer to avoid large dependency. -type buffer []byte +// CUSTOM: smarter buffer. +type buffer struct { + b.Buffer +} func (b *buffer) write(p []byte) { - *b = append(*b, p...) + b.Write(p) } func (b *buffer) writeString(s string) { - *b = append(*b, s...) + b.WriteString(s) } func (b *buffer) writeByte(c byte) { - *b = append(*b, c) + b.WriteByte(c) } func (bp *buffer) writeRune(r rune) { - if r < utf8.RuneSelf { - *bp = append(*bp, byte(r)) - return - } - - b := *bp - n := len(b) - for n+utf8.UTFMax > cap(b) { - b = append(b, 0) - } - w := utf8.EncodeRune(b[n:n+utf8.UTFMax], r) - *bp = b[:n+w] + bp.WriteRune(r) } // pp is used to store a printer's state and is reused with sync.Pool to avoid allocations. type pp struct { buf buffer - // CUSTOM: hook fn for the redact package. - printArgSubstituteFn func(p *pp, a interface{}, verb rune) (newState int) - substituteState int + // CUSTOM: override safety in recursive calls. + override overrideMode // arg holds the current item, as an interface{}. arg interface{} @@ -162,11 +156,11 @@ func (p *pp) free() { // to place back in the pool. // // See https://golang.org/issue/23199 - if cap(p.buf) > 64<<10 { + if p.buf.Cap() > 64<<10 { return } - p.buf = p.buf[:0] + p.buf.Reset() p.arg = nil p.value = reflect.Value{} p.wrappedErr = nil @@ -195,14 +189,16 @@ func (p *pp) Flag(b int) bool { // Implement Write so we can call Fprintf on a pp (through State), for // recursive use in custom verbs. -func (p *pp) Write(b []byte) (ret int, err error) { - p.buf.write(b) - return len(b), nil +func (p *pp) Write(bs []byte) (ret int, err error) { + defer p.startUnsafe().restore() + p.buf.write(bs) + return len(bs), nil } // Implement WriteString so that we can call io.WriteString // on a pp (through state), for efficiency. func (p *pp) WriteString(s string) (ret int, err error) { + defer p.startUnsafe().restore() p.buf.writeString(s) return len(s), nil } @@ -214,7 +210,7 @@ func (p *pp) WriteString(s string) (ret int, err error) { func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { p := newPrinter() p.doPrintf(format, a) - n, err = w.Write(p.buf) + n, err = w.Write([]byte(p.buf.TakeRedactableBytes())) p.free() return } @@ -226,10 +222,10 @@ func Printf(format string, a ...interface{}) (n int, err error) { } // Sprintf formats according to a format specifier and returns the resulting string. -func Sprintf(format string, a ...interface{}) string { +func Sprintf(format string, a ...interface{}) m.RedactableString { p := newPrinter() p.doPrintf(format, a) - s := string(p.buf) + s := p.buf.TakeRedactableString() p.free() return s } @@ -242,7 +238,7 @@ func Sprintf(format string, a ...interface{}) string { func Fprint(w io.Writer, a ...interface{}) (n int, err error) { p := newPrinter() p.doPrint(a) - n, err = w.Write(p.buf) + n, err = w.Write([]byte(p.buf.TakeRedactableBytes())) p.free() return } @@ -256,10 +252,10 @@ func Print(a ...interface{}) (n int, err error) { // Sprint formats using the default formats for its operands and returns the resulting string. // Spaces are added between operands when neither is a string. -func Sprint(a ...interface{}) string { +func Sprint(a ...interface{}) m.RedactableString { p := newPrinter() p.doPrint(a) - s := string(p.buf) + s := p.buf.TakeRedactableString() p.free() return s } @@ -274,7 +270,7 @@ func Sprint(a ...interface{}) string { func Fprintln(w io.Writer, a ...interface{}) (n int, err error) { p := newPrinter() p.doPrintln(a) - n, err = w.Write(p.buf) + n, err = w.Write([]byte(p.buf.TakeRedactableBytes())) p.free() return } @@ -288,10 +284,10 @@ func Println(a ...interface{}) (n int, err error) { // Sprintln formats using the default formats for its operands and returns the resulting string. // Spaces are always added between operands and a newline is appended. -func Sprintln(a ...interface{}) string { +func Sprintln(a ...interface{}) m.RedactableString { p := newPrinter() p.doPrintln(a) - s := string(p.buf) + s := p.buf.TakeRedactableString() p.free() return s } @@ -363,6 +359,7 @@ func (p *pp) badVerb(verb rune) { func (p *pp) fmtBool(v bool, verb rune) { switch verb { case 't', 'v': + defer p.startUnsafe().restore() p.fmt.fmtBoolean(v) default: p.badVerb(verb) @@ -374,6 +371,7 @@ func (p *pp) fmtBool(v bool, verb rune) { func (p *pp) fmt0x64(v uint64, leading0x bool) { sharp := p.fmt.sharp p.fmt.sharp = leading0x + defer p.startUnsafe().restore() p.fmt.fmtInteger(v, 16, unsigned, 'v', ldigits) p.fmt.sharp = sharp } @@ -385,27 +383,32 @@ func (p *pp) fmtInteger(v uint64, isSigned bool, verb rune) { if p.fmt.sharpV && !isSigned { p.fmt0x64(v, true) } else { + defer p.startUnsafe().restore() p.fmt.fmtInteger(v, 10, isSigned, verb, ldigits) } case 'd': + defer p.startUnsafe().restore() p.fmt.fmtInteger(v, 10, isSigned, verb, ldigits) case 'b': + defer p.startUnsafe().restore() p.fmt.fmtInteger(v, 2, isSigned, verb, ldigits) case 'o', 'O': + defer p.startUnsafe().restore() p.fmt.fmtInteger(v, 8, isSigned, verb, ldigits) case 'x': + defer p.startUnsafe().restore() p.fmt.fmtInteger(v, 16, isSigned, verb, ldigits) case 'X': + defer p.startUnsafe().restore() p.fmt.fmtInteger(v, 16, isSigned, verb, udigits) case 'c': + defer p.startUnsafe().restore() p.fmt.fmtC(v) case 'q': - if v <= utf8.MaxRune { - p.fmt.fmtQc(v) - } else { - p.badVerb(verb) - } + defer p.startUnsafe().restore() + p.fmt.fmtQc(v) case 'U': + defer p.startUnsafe().restore() p.fmt.fmtUnicode(v) default: p.badVerb(verb) @@ -417,12 +420,16 @@ func (p *pp) fmtInteger(v uint64, isSigned bool, verb rune) { func (p *pp) fmtFloat(v float64, size int, verb rune) { switch verb { case 'v': + defer p.startUnsafe().restore() p.fmt.fmtFloat(v, size, 'g', -1) case 'b', 'g', 'G', 'x', 'X': + defer p.startUnsafe().restore() p.fmt.fmtFloat(v, size, verb, -1) case 'f', 'e', 'E': + defer p.startUnsafe().restore() p.fmt.fmtFloat(v, size, verb, 6) case 'F': + defer p.startUnsafe().restore() p.fmt.fmtFloat(v, size, 'f', 6) default: p.badVerb(verb) @@ -453,18 +460,23 @@ func (p *pp) fmtComplex(v complex128, size int, verb rune) { func (p *pp) fmtString(v string, verb rune) { switch verb { case 'v': + defer p.startUnsafe().restore() if p.fmt.sharpV { p.fmt.fmtQ(v) } else { p.fmt.fmtS(v) } case 's': + defer p.startUnsafe().restore() p.fmt.fmtS(v) case 'x': + defer p.startUnsafe().restore() p.fmt.fmtSx(v, ldigits) case 'X': + defer p.startUnsafe().restore() p.fmt.fmtSx(v, udigits) case 'q': + defer p.startUnsafe().restore() p.fmt.fmtQ(v) default: p.badVerb(verb) @@ -494,17 +506,24 @@ func (p *pp) fmtBytes(v []byte, verb rune, typeString string) { if i > 0 { p.buf.writeByte(' ') } - p.fmt.fmtInteger(uint64(c), 10, unsigned, verb, ldigits) + func(p *pp, c byte, verb rune) { + defer p.startUnsafe().restore() + p.fmt.fmtInteger(uint64(c), 10, unsigned, verb, ldigits) + }(p, c, verb) } p.buf.writeByte(']') } case 's': + defer p.startUnsafe().restore() p.fmt.fmtBs(v) case 'x': + defer p.startUnsafe().restore() p.fmt.fmtBx(v, ldigits) case 'X': + defer p.startUnsafe().restore() p.fmt.fmtBx(v, udigits) case 'q': + defer p.startUnsafe().restore() p.fmt.fmtQ(string(v)) default: p.printValue(reflect.ValueOf(v), verb, 0) @@ -535,6 +554,7 @@ func (p *pp) fmtPointer(value reflect.Value, verb rune) { p.buf.writeByte(')') } else { if u == 0 { + defer p.startUnsafe().restore() p.fmt.padString(nilAngleString) } else { p.fmt0x64(uint64(u), !p.fmt.sharp) @@ -602,10 +622,37 @@ func (p *pp) handleMethods(verb rune) (handled bool) { verb = 'v' } + if p.override != overrideUnsafe { + switch v := p.arg.(type) { + case i.SafeFormatter: + handled = true + defer p.catchPanic(p.arg, verb, "SafeFormat") + v.SafeFormat(p, verb) + return + + case i.SafeMessager: + handled = true + defer p.catchPanic(p.arg, verb, "SafeMessager") + defer p.startSafeOverride().restore() + p.fmtString(v.SafeMessage(), verb) + return + + case error: + if redactErrorFn != nil { + handled = true + defer p.catchPanic(p.arg, verb, "SafeFormatter") + redactErrorFn(v, p, verb) + return + } + } + } + // Is it a Formatter? if formatter, ok := p.arg.(Formatter); ok { handled = true defer p.catchPanic(p.arg, verb, "Format") + // The mode is implicit: the Format() call will + // use p.Write() which already sets the mode. formatter.Format(p, verb) return } @@ -616,6 +663,7 @@ func (p *pp) handleMethods(verb rune) (handled bool) { handled = true defer p.catchPanic(p.arg, verb, "GoString") // Print the result of GoString unadorned. + defer p.startUnsafe().restore() p.fmt.fmtS(stringer.GoString()) return } @@ -647,8 +695,22 @@ func (p *pp) handleMethods(verb rune) (handled bool) { return false } -// CUSTOM: printArg() renamed to printArgOrig(). -func (p *pp) printArgOrig(arg interface{}, verb rune) { +func (p *pp) printArg(arg interface{}, verb rune) { + t := reflect.TypeOf(arg) + if safeTypeRegistry[t] { + defer p.startSafeOverride().restore() + } else if t == safeWrapperType { + defer p.startSafeOverride().restore() + arg = arg.(w.SafeWrapper).GetValue() + } else if t == unsafeWrapperType { + defer p.startUnsafeOverride().restore() + arg = arg.(w.UnsafeWrap).GetValue() + } + + if _, ok := arg.(i.SafeValue); ok { + defer p.startSafeOverride().restore() + } + p.arg = arg p.value = reflect.Value{} @@ -714,13 +776,35 @@ func (p *pp) printArgOrig(arg interface{}, verb rune) { case reflect.Value: // Handle extractable values with special methods // since printValue does not handle them at depth 0. - if f.IsValid() && f.CanInterface() { - p.arg = f.Interface() - if p.handleMethods(verb) { + if f.IsValid() { + t := f.Type() + if p.handleSpecialValues(f, t, verb, 0) { return } + + if safeTypeRegistry[t] { + defer p.startSafeOverride().restore() + } + + if f.CanInterface() { + p.arg = f.Interface() + if _, ok := p.arg.(i.SafeValue); ok { + defer p.startSafeOverride().restore() + } + if p.handleMethods(verb) { + return + } + } } p.printValue(f, verb, 0) + case m.RedactableString: + defer p.startPreRedactable().restore() + p.buf.WriteString(string(f)) + return + case m.RedactableBytes: + defer p.startPreRedactable().restore() + p.buf.Write([]byte(f)) + return default: // If the type is not simple, it might have methods. if !p.handleMethods(verb) { @@ -735,11 +819,25 @@ func (p *pp) printArgOrig(arg interface{}, verb rune) { // It does not handle 'p' and 'T' verbs because these should have been already handled by printArg. func (p *pp) printValue(value reflect.Value, verb rune, depth int) { // Handle values with special methods if not already handled by printArg (depth == 0). - if depth > 0 && value.IsValid() && value.CanInterface() { - p.arg = value.Interface() - if p.handleMethods(verb) { + if depth > 0 && value.IsValid() { + t := value.Type() + if p.handleSpecialValues(value, t, verb, depth) { return } + + if safeTypeRegistry[t] { + defer p.startSafeOverride().restore() + } + + if value.CanInterface() { + p.arg = value.Interface() + if _, ok := p.arg.(i.SafeValue); ok { + defer p.startSafeOverride().restore() + } + if p.handleMethods(verb) { + return + } + } } p.arg = nil p.value = value @@ -963,7 +1061,9 @@ func parseArgNumber(format string) (index int, wid int, ok bool) { // argNumber returns the next argument to evaluate, which is either the value of the passed-in // argNum or the value of the bracketed integer that begins format[i:]. It also returns // the new value of i, that is, the index of the next byte of the format to process. -func (p *pp) argNumber(argNum int, format string, i int, numArgs int) (newArgNum, newi int, found bool) { +func (p *pp) argNumber( + argNum int, format string, i int, numArgs int, +) (newArgNum, newi int, found bool) { if len(format) <= i || format[i] != '[' { return argNum, i, false } @@ -989,6 +1089,7 @@ func (p *pp) missingArg(verb rune) { } func (p *pp) doPrintf(format string, a []interface{}) { + p.buf.SetMode(b.SafeEscaped) end := len(format) argNum := 0 // we process one argument per non-trivial format afterIndex := false // previous item in format was an index like [3]. @@ -1164,6 +1265,7 @@ formatLoop: } func (p *pp) doPrint(a []interface{}) { + p.buf.SetMode(b.SafeEscaped) prevString := false for argNum, arg := range a { isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String @@ -1179,6 +1281,7 @@ func (p *pp) doPrint(a []interface{}) { // doPrintln is like doPrint but always adds a space between arguments // and a newline after the last argument. func (p *pp) doPrintln(a []interface{}) { + p.buf.SetMode(b.SafeEscaped) for argNum, arg := range a { if argNum > 0 { p.buf.writeByte(' ') diff --git a/vendor/github.com/cockroachdb/redact/internal/rfmt/print.go.diff b/vendor/github.com/cockroachdb/redact/internal/rfmt/print.go.diff new file mode 100644 index 000000000..997e1384f --- /dev/null +++ b/vendor/github.com/cockroachdb/redact/internal/rfmt/print.go.diff @@ -0,0 +1,489 @@ +--- print.go.orig 2021-06-18 16:45:56.623967000 +0200 ++++ print.go 2021-06-19 16:26:32.751061000 +0200 +@@ -1,16 +1,27 @@ ++// Code generated from print.go.orig. DO NOT EDIT ++// GENERATED FILE DO NOT EDIT ++// + // 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 fmt ++package rfmt + + import ( +- "internal/fmtsort" ++ // CUSTOM: needed to avoid a type mismatch on Formatter. ++ origFmt "fmt" + "io" + "os" + "reflect" + "sync" + "unicode/utf8" ++ ++ // CUSTOM: our own imports. ++ i "github.com/cockroachdb/redact/interfaces" ++ b "github.com/cockroachdb/redact/internal/buffer" ++ m "github.com/cockroachdb/redact/internal/markers" ++ w "github.com/cockroachdb/redact/internal/redact" ++ "github.com/cockroachdb/redact/internal/rfmt/fmtsort" + ) + + // Strings for use with buffer.WriteString. +@@ -51,7 +62,8 @@ + // The implementation controls how State and rune are interpreted, + // and may call Sprint(f) or Fprint(f) etc. to generate its output. + type Formatter interface { +- Format(f State, verb rune) ++ // CUSTOM: refer to the original type, not the one defined here. ++ Format(f origFmt.State, verb rune) + } + + // Stringer is implemented by any value that has a String method, +@@ -71,40 +83,34 @@ + GoString() string + } + +-// Use simple []byte instead of bytes.Buffer to avoid large dependency. +-type buffer []byte ++// CUSTOM: smarter buffer. ++type buffer struct { ++ b.Buffer ++} + + func (b *buffer) write(p []byte) { +- *b = append(*b, p...) ++ b.Write(p) + } + + func (b *buffer) writeString(s string) { +- *b = append(*b, s...) ++ b.WriteString(s) + } + + func (b *buffer) writeByte(c byte) { +- *b = append(*b, c) ++ b.WriteByte(c) + } + + func (bp *buffer) writeRune(r rune) { +- if r < utf8.RuneSelf { +- *bp = append(*bp, byte(r)) +- return +- } +- +- b := *bp +- n := len(b) +- for n+utf8.UTFMax > cap(b) { +- b = append(b, 0) +- } +- w := utf8.EncodeRune(b[n:n+utf8.UTFMax], r) +- *bp = b[:n+w] ++ bp.WriteRune(r) + } + + // pp is used to store a printer's state and is reused with sync.Pool to avoid allocations. + type pp struct { + buf buffer + ++ // CUSTOM: override safety in recursive calls. ++ override overrideMode ++ + // arg holds the current item, as an interface{}. + arg interface{} + +@@ -150,11 +156,11 @@ + // to place back in the pool. + // + // See https://golang.org/issue/23199 +- if cap(p.buf) > 64<<10 { ++ if p.buf.Cap() > 64<<10 { + return + } + +- p.buf = p.buf[:0] ++ p.buf.Reset() + p.arg = nil + p.value = reflect.Value{} + p.wrappedErr = nil +@@ -183,14 +189,16 @@ + + // Implement Write so we can call Fprintf on a pp (through State), for + // recursive use in custom verbs. +-func (p *pp) Write(b []byte) (ret int, err error) { +- p.buf.write(b) +- return len(b), nil ++func (p *pp) Write(bs []byte) (ret int, err error) { ++ defer p.startUnsafe().restore() ++ p.buf.write(bs) ++ return len(bs), nil + } + + // Implement WriteString so that we can call io.WriteString + // on a pp (through state), for efficiency. + func (p *pp) WriteString(s string) (ret int, err error) { ++ defer p.startUnsafe().restore() + p.buf.writeString(s) + return len(s), nil + } +@@ -202,7 +210,7 @@ + func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { + p := newPrinter() + p.doPrintf(format, a) +- n, err = w.Write(p.buf) ++ n, err = w.Write([]byte(p.buf.TakeRedactableBytes())) + p.free() + return + } +@@ -214,10 +222,10 @@ + } + + // Sprintf formats according to a format specifier and returns the resulting string. +-func Sprintf(format string, a ...interface{}) string { ++func Sprintf(format string, a ...interface{}) m.RedactableString { + p := newPrinter() + p.doPrintf(format, a) +- s := string(p.buf) ++ s := p.buf.TakeRedactableString() + p.free() + return s + } +@@ -230,7 +238,7 @@ + func Fprint(w io.Writer, a ...interface{}) (n int, err error) { + p := newPrinter() + p.doPrint(a) +- n, err = w.Write(p.buf) ++ n, err = w.Write([]byte(p.buf.TakeRedactableBytes())) + p.free() + return + } +@@ -244,10 +252,10 @@ + + // Sprint formats using the default formats for its operands and returns the resulting string. + // Spaces are added between operands when neither is a string. +-func Sprint(a ...interface{}) string { ++func Sprint(a ...interface{}) m.RedactableString { + p := newPrinter() + p.doPrint(a) +- s := string(p.buf) ++ s := p.buf.TakeRedactableString() + p.free() + return s + } +@@ -262,7 +270,7 @@ + func Fprintln(w io.Writer, a ...interface{}) (n int, err error) { + p := newPrinter() + p.doPrintln(a) +- n, err = w.Write(p.buf) ++ n, err = w.Write([]byte(p.buf.TakeRedactableBytes())) + p.free() + return + } +@@ -276,10 +284,10 @@ + + // Sprintln formats using the default formats for its operands and returns the resulting string. + // Spaces are always added between operands and a newline is appended. +-func Sprintln(a ...interface{}) string { ++func Sprintln(a ...interface{}) m.RedactableString { + p := newPrinter() + p.doPrintln(a) +- s := string(p.buf) ++ s := p.buf.TakeRedactableString() + p.free() + return s + } +@@ -351,6 +359,7 @@ + func (p *pp) fmtBool(v bool, verb rune) { + switch verb { + case 't', 'v': ++ defer p.startUnsafe().restore() + p.fmt.fmtBoolean(v) + default: + p.badVerb(verb) +@@ -362,6 +371,7 @@ + func (p *pp) fmt0x64(v uint64, leading0x bool) { + sharp := p.fmt.sharp + p.fmt.sharp = leading0x ++ defer p.startUnsafe().restore() + p.fmt.fmtInteger(v, 16, unsigned, 'v', ldigits) + p.fmt.sharp = sharp + } +@@ -373,23 +383,32 @@ + if p.fmt.sharpV && !isSigned { + p.fmt0x64(v, true) + } else { ++ defer p.startUnsafe().restore() + p.fmt.fmtInteger(v, 10, isSigned, verb, ldigits) + } + case 'd': ++ defer p.startUnsafe().restore() + p.fmt.fmtInteger(v, 10, isSigned, verb, ldigits) + case 'b': ++ defer p.startUnsafe().restore() + p.fmt.fmtInteger(v, 2, isSigned, verb, ldigits) + case 'o', 'O': ++ defer p.startUnsafe().restore() + p.fmt.fmtInteger(v, 8, isSigned, verb, ldigits) + case 'x': ++ defer p.startUnsafe().restore() + p.fmt.fmtInteger(v, 16, isSigned, verb, ldigits) + case 'X': ++ defer p.startUnsafe().restore() + p.fmt.fmtInteger(v, 16, isSigned, verb, udigits) + case 'c': ++ defer p.startUnsafe().restore() + p.fmt.fmtC(v) + case 'q': ++ defer p.startUnsafe().restore() + p.fmt.fmtQc(v) + case 'U': ++ defer p.startUnsafe().restore() + p.fmt.fmtUnicode(v) + default: + p.badVerb(verb) +@@ -401,12 +420,16 @@ + func (p *pp) fmtFloat(v float64, size int, verb rune) { + switch verb { + case 'v': ++ defer p.startUnsafe().restore() + p.fmt.fmtFloat(v, size, 'g', -1) + case 'b', 'g', 'G', 'x', 'X': ++ defer p.startUnsafe().restore() + p.fmt.fmtFloat(v, size, verb, -1) + case 'f', 'e', 'E': ++ defer p.startUnsafe().restore() + p.fmt.fmtFloat(v, size, verb, 6) + case 'F': ++ defer p.startUnsafe().restore() + p.fmt.fmtFloat(v, size, 'f', 6) + default: + p.badVerb(verb) +@@ -437,18 +460,23 @@ + func (p *pp) fmtString(v string, verb rune) { + switch verb { + case 'v': ++ defer p.startUnsafe().restore() + if p.fmt.sharpV { + p.fmt.fmtQ(v) + } else { + p.fmt.fmtS(v) + } + case 's': ++ defer p.startUnsafe().restore() + p.fmt.fmtS(v) + case 'x': ++ defer p.startUnsafe().restore() + p.fmt.fmtSx(v, ldigits) + case 'X': ++ defer p.startUnsafe().restore() + p.fmt.fmtSx(v, udigits) + case 'q': ++ defer p.startUnsafe().restore() + p.fmt.fmtQ(v) + default: + p.badVerb(verb) +@@ -478,17 +506,24 @@ + if i > 0 { + p.buf.writeByte(' ') + } +- p.fmt.fmtInteger(uint64(c), 10, unsigned, verb, ldigits) ++ func(p *pp, c byte, verb rune) { ++ defer p.startUnsafe().restore() ++ p.fmt.fmtInteger(uint64(c), 10, unsigned, verb, ldigits) ++ }(p, c, verb) + } + p.buf.writeByte(']') + } + case 's': ++ defer p.startUnsafe().restore() + p.fmt.fmtBs(v) + case 'x': ++ defer p.startUnsafe().restore() + p.fmt.fmtBx(v, ldigits) + case 'X': ++ defer p.startUnsafe().restore() + p.fmt.fmtBx(v, udigits) + case 'q': ++ defer p.startUnsafe().restore() + p.fmt.fmtQ(string(v)) + default: + p.printValue(reflect.ValueOf(v), verb, 0) +@@ -519,6 +554,7 @@ + p.buf.writeByte(')') + } else { + if u == 0 { ++ defer p.startUnsafe().restore() + p.fmt.padString(nilAngleString) + } else { + p.fmt0x64(uint64(u), !p.fmt.sharp) +@@ -586,10 +622,37 @@ + verb = 'v' + } + ++ if p.override != overrideUnsafe { ++ switch v := p.arg.(type) { ++ case i.SafeFormatter: ++ handled = true ++ defer p.catchPanic(p.arg, verb, "SafeFormat") ++ v.SafeFormat(p, verb) ++ return ++ ++ case i.SafeMessager: ++ handled = true ++ defer p.catchPanic(p.arg, verb, "SafeMessager") ++ defer p.startSafeOverride().restore() ++ p.fmtString(v.SafeMessage(), verb) ++ return ++ ++ case error: ++ if redactErrorFn != nil { ++ handled = true ++ defer p.catchPanic(p.arg, verb, "SafeFormatter") ++ redactErrorFn(v, p, verb) ++ return ++ } ++ } ++ } ++ + // Is it a Formatter? + if formatter, ok := p.arg.(Formatter); ok { + handled = true + defer p.catchPanic(p.arg, verb, "Format") ++ // The mode is implicit: the Format() call will ++ // use p.Write() which already sets the mode. + formatter.Format(p, verb) + return + } +@@ -600,6 +663,7 @@ + handled = true + defer p.catchPanic(p.arg, verb, "GoString") + // Print the result of GoString unadorned. ++ defer p.startUnsafe().restore() + p.fmt.fmtS(stringer.GoString()) + return + } +@@ -632,6 +696,21 @@ + } + + func (p *pp) printArg(arg interface{}, verb rune) { ++ t := reflect.TypeOf(arg) ++ if safeTypeRegistry[t] { ++ defer p.startSafeOverride().restore() ++ } else if t == safeWrapperType { ++ defer p.startSafeOverride().restore() ++ arg = arg.(w.SafeWrapper).GetValue() ++ } else if t == unsafeWrapperType { ++ defer p.startUnsafeOverride().restore() ++ arg = arg.(w.UnsafeWrap).GetValue() ++ } ++ ++ if _, ok := arg.(i.SafeValue); ok { ++ defer p.startSafeOverride().restore() ++ } ++ + p.arg = arg + p.value = reflect.Value{} + +@@ -697,13 +776,35 @@ + case reflect.Value: + // Handle extractable values with special methods + // since printValue does not handle them at depth 0. +- if f.IsValid() && f.CanInterface() { +- p.arg = f.Interface() +- if p.handleMethods(verb) { ++ if f.IsValid() { ++ t := f.Type() ++ if p.handleSpecialValues(f, t, verb, 0) { + return + } ++ ++ if safeTypeRegistry[t] { ++ defer p.startSafeOverride().restore() ++ } ++ ++ if f.CanInterface() { ++ p.arg = f.Interface() ++ if _, ok := p.arg.(i.SafeValue); ok { ++ defer p.startSafeOverride().restore() ++ } ++ if p.handleMethods(verb) { ++ return ++ } ++ } + } + p.printValue(f, verb, 0) ++ case m.RedactableString: ++ defer p.startPreRedactable().restore() ++ p.buf.WriteString(string(f)) ++ return ++ case m.RedactableBytes: ++ defer p.startPreRedactable().restore() ++ p.buf.Write([]byte(f)) ++ return + default: + // If the type is not simple, it might have methods. + if !p.handleMethods(verb) { +@@ -718,11 +819,25 @@ + // It does not handle 'p' and 'T' verbs because these should have been already handled by printArg. + func (p *pp) printValue(value reflect.Value, verb rune, depth int) { + // Handle values with special methods if not already handled by printArg (depth == 0). +- if depth > 0 && value.IsValid() && value.CanInterface() { +- p.arg = value.Interface() +- if p.handleMethods(verb) { ++ if depth > 0 && value.IsValid() { ++ t := value.Type() ++ if p.handleSpecialValues(value, t, verb, depth) { + return + } ++ ++ if safeTypeRegistry[t] { ++ defer p.startSafeOverride().restore() ++ } ++ ++ if value.CanInterface() { ++ p.arg = value.Interface() ++ if _, ok := p.arg.(i.SafeValue); ok { ++ defer p.startSafeOverride().restore() ++ } ++ if p.handleMethods(verb) { ++ return ++ } ++ } + } + p.arg = nil + p.value = value +@@ -946,7 +1061,9 @@ + // argNumber returns the next argument to evaluate, which is either the value of the passed-in + // argNum or the value of the bracketed integer that begins format[i:]. It also returns + // the new value of i, that is, the index of the next byte of the format to process. +-func (p *pp) argNumber(argNum int, format string, i int, numArgs int) (newArgNum, newi int, found bool) { ++func (p *pp) argNumber( ++ argNum int, format string, i int, numArgs int, ++) (newArgNum, newi int, found bool) { + if len(format) <= i || format[i] != '[' { + return argNum, i, false + } +@@ -972,6 +1089,7 @@ + } + + func (p *pp) doPrintf(format string, a []interface{}) { ++ p.buf.SetMode(b.SafeEscaped) + end := len(format) + argNum := 0 // we process one argument per non-trivial format + afterIndex := false // previous item in format was an index like [3]. +@@ -1147,6 +1265,7 @@ + } + + func (p *pp) doPrint(a []interface{}) { ++ p.buf.SetMode(b.SafeEscaped) + prevString := false + for argNum, arg := range a { + isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String +@@ -1162,6 +1281,7 @@ + // doPrintln is like doPrint but always adds a space between arguments + // and a newline after the last argument. + func (p *pp) doPrintln(a []interface{}) { ++ p.buf.SetMode(b.SafeEscaped) + for argNum, arg := range a { + if argNum > 0 { + p.buf.writeByte(' ') diff --git a/vendor/github.com/cockroachdb/redact/internal/rfmt/printer_adapter.go b/vendor/github.com/cockroachdb/redact/internal/rfmt/printer_adapter.go new file mode 100644 index 000000000..923d9724a --- /dev/null +++ b/vendor/github.com/cockroachdb/redact/internal/rfmt/printer_adapter.go @@ -0,0 +1,85 @@ +// Copyright 2021 The Cockroach 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 rfmt + +import i "github.com/cockroachdb/redact/interfaces" + +// SafeString implements SafePrinter. +func (p *pp) SafeString(s i.SafeString) { + defer p.startSafeOverride().restore() + p.buf.WriteString(string(s)) +} + +// SafeInt implements SafePrinter. +func (p *pp) SafeInt(s i.SafeInt) { + defer p.startSafeOverride().restore() + p.fmtInteger(uint64(s), signed, 'd') +} + +// SafeUint implements SafePrinter. +func (p *pp) SafeUint(s i.SafeUint) { + defer p.startSafeOverride().restore() + p.fmtInteger(uint64(s), unsigned, 'd') +} + +// SafeFloat implements SafePrinter. +func (p *pp) SafeFloat(s i.SafeFloat) { + defer p.startSafeOverride().restore() + p.fmtFloat(float64(s), 64, 'v') +} + +// SafeRune implements SafePrinter. +func (p *pp) SafeRune(r i.SafeRune) { + defer p.startSafeOverride().restore() + p.buf.WriteRune(rune(r)) +} + +func (p *pp) Print(args ...interface{}) { + defer p.buf.SetMode(p.buf.GetMode()) + np := newPrinter() + np.buf = p.buf + np.doPrint(args) + p.buf = np.buf + np.buf = buffer{} + np.free() +} + +func (p *pp) Printf(format string, arg ...interface{}) { + defer p.buf.SetMode(p.buf.GetMode()) + np := newPrinter() + np.buf = p.buf + np.doPrintf(format, arg) + p.buf = np.buf + np.buf = buffer{} + np.free() +} + +func (p *pp) UnsafeString(s string) { + defer p.startUnsafe().restore() + _, _ = p.buf.WriteString(s) +} + +func (p *pp) UnsafeByte(bb byte) { + defer p.startUnsafe().restore() + _ = p.buf.WriteByte(bb) +} +func (p *pp) UnsafeBytes(bs []byte) { + defer p.startUnsafe().restore() + _, _ = p.buf.Write(bs) +} +func (p *pp) UnsafeRune(r rune) { + defer p.startUnsafe().restore() + _ = p.buf.WriteRune(r) +} diff --git a/vendor/github.com/cockroachdb/redact/internal/refresh.sh b/vendor/github.com/cockroachdb/redact/internal/rfmt/refresh.sh similarity index 74% rename from vendor/github.com/cockroachdb/redact/internal/refresh.sh rename to vendor/github.com/cockroachdb/redact/internal/rfmt/refresh.sh index 1be06b5cb..99862dd46 100644 --- a/vendor/github.com/cockroachdb/redact/internal/refresh.sh +++ b/vendor/github.com/cockroachdb/redact/internal/rfmt/refresh.sh @@ -5,11 +5,8 @@ # set -euxo pipefail -( - echo "// Code generated from the Go standard library. DO NOT EDIT" - echo "// GENERATED FILE DO NOT EDIT" - cat $GOROOT/src/fmt/format.go -) >format.go +cp $GOROOT/src/fmt/format.go format.go +patch -p0 = 0; i-- { - if b[i] == '\n' || b[i] == ' ' { - end = i - } else { - break - } - } - b = b[:end] - } - - // Here we could choose to omit the output - // entirely if there was nothing but empty space: - // if len(b) == 0 { return 0, nil } - - // Note: we use len(...RedactableS) and not len(...RedactableBytes) - // because the ...S variant is a compile-time constant so this - // accelerates the loops below. - start, ls := startRedactableBytes, len(startRedactableS) - end, le := endRedactableBytes, len(endRedactableS) - escape := escapeBytes - - if p.enclose { - st = p.doWrite(start, st, false) - } - - // Now write the string. - - // k is the index in b up to (and excluding) the byte which we've - // already copied into the output. - k := 0 - - for i := 0; i < len(b); i++ { - if b[i] == '\n' && p.enclose { - // Avoid enclosing newline characters inside redaction markers. - // This is important when redact is used to render errors, where - // sub-strings split at newline characters are rendered - // separately. - st = p.doWrite(b[k:i], st, true) - st = p.doWrite(end, st, false) - // Advance to the last newline character. We want to forward - // them all in a single call to doWrite, for performance. - lastNewLine := i - for b[lastNewLine] == '\n' && lastNewLine < len(b) { - lastNewLine++ - } - st = p.doWrite(b[i:lastNewLine], st, true) - st = p.doWrite(start, st, false) - // Advance the counters by the number of newline characters. - k = lastNewLine - i = lastNewLine - 1 /* -1 because we have i++ at the end of every iteration */ - } else { - // Ensure that occurrences of the delimiter inside the string get - // escaped. - // Reminder: ls and le are likely greater than 1, as we are scanning - // utf-8 encoded delimiters (the utf-8 encoding is multibyte). - if i+ls <= len(b) && bytes.Equal(b[i:i+ls], start) { - st = p.doWrite(b[k:i], st, true) - st = p.doWrite(escape, st, false) - // Advance the counters by the length (in bytes) of the delimiter. - st.l += ls - k = i + ls - i += ls - 1 /* -1 because we have i++ at the end of every iteration */ - } else if i+le <= len(b) && bytes.Equal(b[i:i+le], end) { - st = p.doWrite(b[k:i], st, true) - st = p.doWrite(escape, st, false) - // Advance the counters by the length (in bytes) of the delimiter. - st.l += le - k = i + le - i += le - 1 /* -1 because we have i++ at the end of every iteration */ - } - } - } - st = p.doWrite(b[k:], st, true) - if p.enclose { - st = p.doWrite(end, st, false) - } - return st.l, st.err -} - -type escapeResult struct { - l int - err error -} - -func (p *escapeWriter) doWrite(b []byte, st escapeResult, count bool) escapeResult { - if st.err != nil { - // An error was encountered previously. - // No-op. - return st - } - sz, err := p.w.Write(b) - if count { - st.l += sz - } - st.err = err - return st -} - -// internalEscapeBytes escapes redaction markers in the provided buf -// starting at the location startLoc. -// The bytes before startLoc are considered safe (already escaped). -func internalEscapeBytes(b []byte, startLoc int) (res []byte) { - // Note: we use len(...RedactableS) and not len(...RedactableBytes) - // because the ...S variant is a compile-time constant so this - // accelerates the loops below. - start, ls := startRedactableBytes, len(startRedactableS) - end, le := endRedactableBytes, len(endRedactableS) - escape := escapeBytes - - // res is the output slice. In the common case where there is - // nothing to escape, the input slice is returned directly - // and no allocation takes place. - res = b - // copied is true if and only if `res` is a copy of `b`. It only - // turns to true if the loop below finds something to escape. - copied := false - // k is the index in b up to (and excluding) the byte which we've - // already copied into res (if copied=true). - k := 0 - - for i := startLoc; i < len(b); i++ { - // Ensure that occurrences of the delimiter inside the string get - // escaped. - // Reminder: ls and le are likely greater than 1, as we are scanning - // utf-8 encoded delimiters (the utf-8 encoding is multibyte). - if i+ls <= len(b) && bytes.Equal(b[i:i+ls], start) { - if !copied { - // We only allocate an output slice when we know we definitely - // need it. - res = make([]byte, 0, len(b)+len(escape)) - copied = true - } - res = append(res, b[k:i]...) - res = append(res, escape...) - // Advance the counters by the length (in bytes) of the delimiter. - k = i + ls - i += ls - 1 /* -1 because we have i++ at the end of every iteration */ - } else if i+le <= len(b) && bytes.Equal(b[i:i+le], end) { - if !copied { - // See the comment above about res allocation. - res = make([]byte, 0, len(b)+len(escape)) - copied = true - } - res = append(res, b[k:i]...) - res = append(res, escape...) - // Advance the counters by the length (in bytes) of the delimiter. - k = i + le - i += le - 1 /* -1 because we have i++ at the end of every iteration */ - } - } - if copied { - res = append(res, b[k:]...) - } - return -} diff --git a/vendor/github.com/cockroachdb/redact/markers_internal_print.go b/vendor/github.com/cockroachdb/redact/markers_internal_print.go deleted file mode 100644 index aea6a247f..000000000 --- a/vendor/github.com/cockroachdb/redact/markers_internal_print.go +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright 2020 The Cockroach 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 redact - -import ( - "fmt" - - internalFmt "github.com/cockroachdb/redact/internal" -) - -// printArgFn is the hook injected into the standard fmt logic -// by the printer functions in markers_print.go. -func printArgFn(p *internalFmt.InternalPrinter, arg interface{}, verb rune) (newState int) { - redactLastWrites(p) - - switch verb { - case 'T': - // If the value was wrapped, reveal its original type. Anything else is not very useful. - switch v := arg.(type) { - case safeWrapper: - arg = v.a - case unsafeWrap: - arg = v.a - } - - // Shortcut: %T is always safe to print as-is. - internalFmt.PrintArg(p, arg, verb) - return len(internalFmt.Buf(p)) - case 'p': - // Printing a pointer via %p is handled as special case in printf, - // so we need a special case here too. The other cases of - // printing a pointer via %v / %d %x etc is handled by the common path. - - switch v := arg.(type) { - case safeWrapper: - // If the value was meant to be safe, then print it as-is. - internalFmt.PrintArg(p, v.a, verb) - return len(internalFmt.Buf(p)) - - case unsafeWrap: - // If it's been wrapped, unwrap it. This helps preserve the - // original pointer value in the output. - arg = v.a - } - // Now perform an unsafe print: we are assuming that the pointer - // representation by the fmt.printf code does not contain - // redaction markers, and go a short route. If that assumption did - // not hold (or is invalidated by changes upstream after this - // comment is written), this code should be changed to use the - // escapeWriter instead. - internalFmt.Append(p, startRedactableBytes) - internalFmt.PrintArg(p, arg, verb) - internalFmt.Append(p, endRedactableBytes) - return len(internalFmt.Buf(p)) - } - - // nil arguments are printed as-is. Note: a nil argument under - // interface{} is not the same as a nil pointer passed via a pointer - // of a concrete type. The latter kind of nil goes through - // redaction as usual, because it may have its own custom Format() method. - if arg == nil { - internalFmt.PrintArg(p, arg, verb) - return len(internalFmt.Buf(p)) - } - - // RedactableBytes/RedactableString are already formatted as - // redactable. Include them as-is. - // - // NB: keep this logic synchronized with - // (RedactableString/Bytes).SafeFormat(). - switch v := arg.(type) { - case RedactableString: - internalFmt.Append(p, []byte(v)) - return len(internalFmt.Buf(p)) - case RedactableBytes: - internalFmt.Append(p, []byte(v)) - return len(internalFmt.Buf(p)) - } - - arg = annotateArg(arg, internalFmt.CollectingError(p)) - internalFmt.PrintArg(p, arg, verb) - return len(internalFmt.Buf(p)) -} - -// redactLastWrites escapes any markers that were added by the -// internals of the printf functions, for example -// if markers were present in the format string. -func redactLastWrites(p *internalFmt.InternalPrinter) { - state := internalFmt.GetState(p) - newBuf := internalEscapeBytes(internalFmt.Buf(p), state) - internalFmt.SetState(p, newBuf) -} - -// annotateArg wraps the arguments to one of the print functions with -// an indirect formatter which ensures that redaction markers inside -// the representation of the object are escaped, and optionally -// encloses the result of the display between redaction markers. -// -// collectingError is true iff we are in the context of -// HelperForErrorf, where we want the %w verb to work properly. This -// adds a little overhead to the processing, but this is OK because -// typically the error path is not perf-critical. -func annotateArg(arg interface{}, collectingError bool) interface{} { - var newArg fmt.Formatter - err, isError := arg.(error) - - switch v := arg.(type) { - case SafeFormatter: - // calls to Format() by fmt.Print will be redirected to - // v.SafeFormat(). This delegates the task of adding markers to - // the object itself. - newArg = &redactFormatRedirect{ - func(p SafePrinter, verb rune) { v.SafeFormat(p, verb) }, - } - - case SafeValue: - // calls to Format() by fmt.Print will be redirected to a - // display of v without redaction markers. - // - // Note that we can't let the value be displayed as-is because - // we must prevent any marker inside the value from leaking into - // the result. (We want to avoid mismatched markers.) - newArg = &escapeArg{arg: arg, enclose: false} - - case SafeMessager: - // Obsolete interface. - // TODO(knz): Remove this. - newArg = &escapeArg{arg: v.SafeMessage(), enclose: false} - - default: - if isError && redactErrorFn != nil { - // We place this case after the other cases above, in case - // the error object knows how to print itself safely already. - newArg = &redactFormatRedirect{ - func(p SafePrinter, verb rune) { redactErrorFn(err, p, verb) }, - } - } else { - // calls to Format() by fmt.Print will be redirected to a - // display of v within redaction markers if the type is - // considered unsafe, without markers otherwise. In any case, - // occurrences of delimiters within are escaped. - newArg = &escapeArg{arg: v, enclose: !isSafeValue(v)} - } - } - - if isError && collectingError { - // Ensure the arg still implements the `error` interface for - // detection by the handling of %w, while also implementing - // fmt.Formatter to forward the implementation to the objects - // constructed above. - newArg = &makeError{err: err, arg: newArg} - } - - return newArg -} - -type makeError struct { - err error - arg fmt.Formatter -} - -// Error implements error. -func (m *makeError) Error() string { return m.err.Error() } - -// Format implements fmt.Formatter. -func (m *makeError) Format(f fmt.State, verb rune) { m.arg.Format(f, verb) } - -// redactFormatRedirect wraps a safe print callback and uses it to -// implement fmt.Formatter. -type redactFormatRedirect struct { - printFn func(p SafePrinter, verb rune) -} - -// Format implements fmt.Formatter. -func (r *redactFormatRedirect) Format(s fmt.State, verb rune) { - defer func() { - if p := recover(); p != nil { - e := escapeWriter{w: s} - fmt.Fprintf(&e, "%%!%c(PANIC=SafeFormatter method: %v)", verb, p) - } - }() - p := &printer{} - p.escapeState = makeEscapeState(s, &p.buf) - r.printFn(p, verb) - _, _ = s.Write(p.buf.Bytes()) -} - -// passthrough passes a pre-formatted string through. -type passthrough struct{ arg []byte } - -// Format implements fmt.Formatter. -func (p *passthrough) Format(s fmt.State, _ rune) { - _, _ = s.Write(p.arg) -} - -// escapeArg wraps an arbitrary value and ensures that any occurrence -// of the redaction markers in its representation are escaped. -// -// The result of printing out the value is enclosed within markers or -// not depending on the value of the enclose bool. -type escapeArg struct { - arg interface{} - enclose bool -} - -func (r *escapeArg) Format(s fmt.State, verb rune) { - switch t := r.arg.(type) { - case fmt.Formatter: - // This is a special case from the default case below, which - // allows a shortcut through the layers of the fmt package. - p := &escapeState{ - State: s, - w: escapeWriter{ - w: s, - enclose: r.enclose, - strip: r.enclose, - }} - defer func() { - if recovered := recover(); recovered != nil { - fmt.Fprintf(p, "%%!%c(PANIC=Format method: %v)", verb, recovered) - } - }() - t.Format(p, verb) - - default: - // TODO(knz): It would be possible to implement struct formatting - // with conditional redaction based on field tag annotations here. - p := &escapeWriter{w: s, enclose: r.enclose, strip: r.enclose} - reproducePrintf(p, s, verb, r.arg) - } -} - -// printerfn is a helper struct for use by Sprintfn. -type printerfn struct { - fn func(SafePrinter) -} - -// SafeFormat implements the SafeFormatter interface. -func (p printerfn) SafeFormat(w SafePrinter, _ rune) { - p.fn(w) -} - -// redactErrorFn can be injected from an error library -// to render error objects safely. -var redactErrorFn func(err error, p SafePrinter, verb rune) - -// RegisterRedactErrorFn registers an error redaction function for use -// during automatic redaction by this package. -// Provided e.g. by cockroachdb/errors. -func RegisterRedactErrorFn(fn func(err error, p SafePrinter, verb rune)) { - redactErrorFn = fn -} diff --git a/vendor/github.com/cockroachdb/redact/markers_internal_printer.go b/vendor/github.com/cockroachdb/redact/markers_internal_printer.go deleted file mode 100644 index 7b0fd75a4..000000000 --- a/vendor/github.com/cockroachdb/redact/markers_internal_printer.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2020 The Cockroach 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 redact - -import ( - "bytes" - "fmt" - "unicode/utf8" -) - -// printer implements SafePrinter. -// This is the machinery for the Print() functions offered -// by this package. -type printer struct { - escapeState - buf bytes.Buffer -} - -var _ fmt.State = (*printer)(nil) -var _ SafeWriter = (*printer)(nil) - -// Print is part of the SafeWriter interface. -func (b *printer) Print(args ...interface{}) { - _, _ = Fprint(&b.buf, args...) -} - -// Printf is part of the SafeWriter interface. -func (b *printer) Printf(format string, args ...interface{}) { - _, _ = Fprintf(&b.buf, format, args...) -} - -// SafeString is part of the SafeWriter interface. -func (b *printer) SafeString(s SafeString) { - w := escapeWriter{w: &b.buf, enclose: false} - _, _ = w.Write([]byte(s)) -} - -// SafeRune is part of the SafeWriter interface. -func (b *printer) SafeRune(s SafeRune) { - if s == startRedactable || s == endRedactable { - s = escapeMark - } - _, _ = b.buf.WriteRune(rune(s)) -} - -// UnsafeString is part of the SafeWriter interface. -func (b *printer) UnsafeString(s string) { - w := escapeWriter{w: &b.buf, enclose: true, strip: true} - _, _ = w.Write([]byte(s)) -} - -// UnsafeRune is part of the SafeWriter interface. -func (b *printer) UnsafeRune(s rune) { - _, _ = b.buf.WriteRune(startRedactable) - b.SafeRune(SafeRune(s)) - _, _ = b.buf.WriteRune(endRedactable) -} - -// UnsafeByte is part of the SafeWriter interface. -func (b *printer) UnsafeByte(s byte) { - _, _ = b.buf.WriteRune(startRedactable) - if s >= utf8.RuneSelf || - s == startRedactableBytes[0] || s == endRedactableBytes[0] { - // Unsafe byte. Escape it. - _, _ = b.buf.Write(escapeBytes) - } else { - _ = b.buf.WriteByte(s) - } - _, _ = b.buf.WriteRune(endRedactable) -} - -// UnsafeBytes is part of the SafeWriter interface. -func (b *printer) UnsafeBytes(s []byte) { - w := escapeWriter{w: &b.buf, enclose: true, strip: true} - _, _ = w.Write(s) -} diff --git a/vendor/github.com/cockroachdb/redact/markers_print.go b/vendor/github.com/cockroachdb/redact/markers_print.go index 50eea32b4..b4e16f7ac 100644 --- a/vendor/github.com/cockroachdb/redact/markers_print.go +++ b/vendor/github.com/cockroachdb/redact/markers_print.go @@ -17,7 +17,7 @@ package redact import ( "io" - internalFmt "github.com/cockroachdb/redact/internal" + "github.com/cockroachdb/redact/internal/rfmt" ) // Sprint prints out the arguments and encloses unsafe bits @@ -27,13 +27,7 @@ import ( // If a RedactableString or RedactableBytes argument is passed, // it is reproduced as-is without escaping. func Sprint(args ...interface{}) RedactableString { - p := internalFmt.NewInternalPrinter() - internalFmt.SetHook(p, printArgFn) - internalFmt.DoPrint(p, args) - redactLastWrites(p) - s := RedactableString(internalFmt.Buf(p)) - internalFmt.Free(p) - return s + return rfmt.Sprint(args...) } // Sprintf formats the arguments and encloses unsafe bits @@ -44,13 +38,7 @@ func Sprint(args ...interface{}) RedactableString { // is responsible to ensure that the markers are not present // in the format string. func Sprintf(format string, args ...interface{}) RedactableString { - p := internalFmt.NewInternalPrinter() - internalFmt.SetHook(p, printArgFn) - internalFmt.DoPrintf(p, format, args) - redactLastWrites(p) - s := RedactableString(internalFmt.Buf(p)) - internalFmt.Free(p) - return s + return rfmt.Sprintf(format, args...) } // HelperForErrorf is a helper to implement a redaction-aware @@ -63,24 +51,13 @@ func Sprintf(format string, args ...interface{}) RedactableString { // Note: This function only works if an error redaction function // has been injected with RegisterRedactErrorFn(). func HelperForErrorf(format string, args ...interface{}) (RedactableString, error) { - p := internalFmt.NewInternalPrinter() - internalFmt.SetCollectError(p) - internalFmt.SetHook(p, printArgFn) - internalFmt.DoPrintf(p, format, args) - redactLastWrites(p) - s := RedactableString(internalFmt.Buf(p)) - e := internalFmt.WrappedError(p) - internalFmt.Free(p) - if m, ok := e.(*makeError); ok { - e = m.err - } - return s, e + return rfmt.HelperForErrorf(format, args...) } // Sprintfn produces a RedactableString using the provided // SafeFormat-alike function. func Sprintfn(printer func(w SafePrinter)) RedactableString { - return Sprint(printerfn{printer}) + return rfmt.Sprintfn(printer) } // StringWithoutMarkers formats the provided SafeFormatter and strips @@ -100,23 +77,11 @@ func StringWithoutMarkers(f SafeFormatter) string { // Fprint is like Sprint but outputs the redactable // string to the provided Writer. func Fprint(w io.Writer, args ...interface{}) (n int, err error) { - p := internalFmt.NewInternalPrinter() - internalFmt.SetHook(p, printArgFn) - internalFmt.DoPrint(p, args) - redactLastWrites(p) - n, err = w.Write(internalFmt.Buf(p)) - internalFmt.Free(p) - return + return rfmt.Fprint(w, args...) } // Fprintf is like Sprintf but outputs the redactable string to the // provided Writer. func Fprintf(w io.Writer, format string, args ...interface{}) (n int, err error) { - p := internalFmt.NewInternalPrinter() - internalFmt.SetHook(p, printArgFn) - internalFmt.DoPrintf(p, format, args) - redactLastWrites(p) - n, err = w.Write(internalFmt.Buf(p)) - internalFmt.Free(p) - return + return rfmt.Fprintf(w, format, args...) } diff --git a/vendor/github.com/cockroachdb/redact/util.go b/vendor/github.com/cockroachdb/redact/util.go new file mode 100644 index 000000000..ab3c6d4b6 --- /dev/null +++ b/vendor/github.com/cockroachdb/redact/util.go @@ -0,0 +1,62 @@ +// Copyright 2020 The Cockroach 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 redact + +import ( + "reflect" + "sort" + + "github.com/cockroachdb/redact/builder" +) + +// JoinTo writes the given slice of values delimited by the provided +// delimiter to the given SafeWriter. +func JoinTo(w SafeWriter, delim RedactableString, values interface{}) { + // Ideally, we'd make the interface clearer: JoinTo is a generic function, + // with a "values" argument of type []T where T is a type variable. + v := reflect.ValueOf(values) + if v.Kind() != reflect.Slice { + // Note a slice: just print the value as-is. + w.Print(values) + } + for i, l := 0, v.Len(); i < l; i++ { + if i > 0 { + w.Print(delim) + } + w.Print(v.Index(i).Interface()) + } +} + +// Join creates a redactable string from the +// given slice of redactable strings, adjoined +// with the provided delimiter. +func Join(delim RedactableString, s []RedactableString) RedactableString { + var b builder.StringBuilder + JoinTo(&b, delim, s) + return b.RedactableString() +} + +// SortStrings sorts the provided slice of redactable strings. +func SortStrings(s []RedactableString) { + sort.Sort(sortableSlice(s)) +} + +// sortableSlice attaches the methods of sort.Interface to +// []RedactableString, sorting in increasing order. +type sortableSlice []RedactableString + +func (p sortableSlice) Len() int { return len(p) } +func (p sortableSlice) Less(i, j int) bool { return p[i] < p[j] } +func (p sortableSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } diff --git a/vendor/github.com/cockroachdb/sentry-go/.craft.yml b/vendor/github.com/cockroachdb/sentry-go/.craft.yml deleted file mode 100644 index 8880dfec2..000000000 --- a/vendor/github.com/cockroachdb/sentry-go/.craft.yml +++ /dev/null @@ -1,19 +0,0 @@ -minVersion: '0.9.2' -github: - owner: getsentry - repo: sentry-go -preReleaseCommand: bash scripts/craft-pre-release.sh -changelogPolicy: simple -statusProvider: - name: github - config: - contexts: - - Travis CI - Branch -targets: - - name: github - includeNames: /none/ - tagPrefix: v - - name: registry - type: sdk - config: - canonical: "github:getsentry/sentry-go" diff --git a/vendor/github.com/cockroachdb/sentry-go/.gitignore b/vendor/github.com/cockroachdb/sentry-go/.gitignore deleted file mode 100644 index 29bfd6f1b..000000000 --- a/vendor/github.com/cockroachdb/sentry-go/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -coverage.txt - -# Just my personal way of tracking stuff — Kamil -FIXME.md -TODO.md -!NOTES.md \ No newline at end of file diff --git a/vendor/github.com/cockroachdb/sentry-go/.travis.yml b/vendor/github.com/cockroachdb/sentry-go/.travis.yml deleted file mode 100644 index 96f5acafa..000000000 --- a/vendor/github.com/cockroachdb/sentry-go/.travis.yml +++ /dev/null @@ -1,49 +0,0 @@ -language: go - -go: - - 1.12.x - - 1.13.x - - 1.14.x - - master - -env: - - GO111MODULE=on GOFLAGS=-mod=readonly - - GO111MODULE=off - -jobs: - include: - - name: "Module support outside of GOPATH" - go: stable - before_script: >- - mv $GOPATH/src/github.com/getsentry/sentry-go ~/sentry-go && - cd ~/sentry-go && - export GOPATH= && - go env GOPATH - script: >- - go test ./... && - go test ./... -race - allow_failures: - - go: master - fast_finish: true - -before_install: - - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/v1.19.1/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.19.1 - # Fetch origin/master. This is required for `git merge-base` when testing a - # branch, since Travis clones only the target branch. - - git fetch origin master:remotes/origin/master - -script: - - golangci-lint run --new-from-rev=$(git merge-base origin/master HEAD) - - go build ./... - - go test ./... - - go test ./... -race - -notifications: - webhooks: - urls: - - https://zeus.ci/hooks/befe9810-9285-11e9-b01a-0a580a281808/public/provider/travis/webhook - on_success: always - on_failure: always - on_start: always - on_cancel: always - on_error: always diff --git a/vendor/github.com/cockroachdb/sentry-go/CHANGELOG.md b/vendor/github.com/cockroachdb/sentry-go/CHANGELOG.md deleted file mode 100644 index bd6649c2e..000000000 --- a/vendor/github.com/cockroachdb/sentry-go/CHANGELOG.md +++ /dev/null @@ -1,226 +0,0 @@ -# Changelog - -## Unreleased - -- "I am running away from my responsibilities. And it feels good." – Michael Scott, Season 4, "Money" - -## v0.6.1 - -- fix: Use NewEvent to init Event struct (#220) - -_NOTE:_ -A change introduced in v0.6.0 with the intent of avoiding allocations made a -pattern used in official examples break in certain circumstances (attempting -to write to a nil map). -This release reverts the change such that maps in the Event struct are always -allocated. - -## v0.6.0 - -- feat: Read module dependencies from runtime/debug (#199) -- feat: Support chained errors using Unwrap (#206) -- feat: Report chain of errors when available (#185) -- **[breaking]** fix: Accept http.RoundTripper to customize transport (#205) - Before the SDK accepted a concrete value of type `*http.Transport` in - `ClientOptions`, now it accepts any value implementing the `http.RoundTripper` - interface. Note that `*http.Transport` implements `http.RoundTripper`, so most - code bases will continue to work unchanged. - Users of custom transport gain the ability to pass in other implementations of - `http.RoundTripper` and may be able to simplify their code bases. -- fix: Do not panic when scope event processor drops event (#192) -- **[breaking]** fix: Use time.Time for timestamps (#191) - Users of sentry-go typically do not need to manipulate timestamps manually. - For those who do, the field type changed from `int64` to `time.Time`, which - should be more convenient to use. The recommended way to get the current time - is `time.Now().UTC()`. -- fix: Report usage error including stack trace (#189) -- feat: Add Exception.ThreadID field (#183) -- ci: Test against Go 1.14, drop 1.11 (#170) -- feat: Limit reading bytes from request bodies (#168) -- **[breaking]** fix: Rename fasthttp integration package sentryhttp => sentryfasthttp - The current recommendation is to use a named import, in which case existing - code should not require any change: - ```go - package main - - import ( - "fmt" - - "github.com/getsentry/sentry-go" - sentryfasthttp "github.com/getsentry/sentry-go/fasthttp" - "github.com/valyala/fasthttp" - ) - ``` - -_NOTE:_ -This version includes some new features and a few breaking changes, none of -which should pose troubles with upgrading. Most code bases should be able to -upgrade without any changes. - -## v0.5.1 - -- fix: Ignore err.Cause() when it is nil (#160) - -## v0.5.0 - -- fix: Synchronize access to HTTPTransport.disabledUntil (#158) -- docs: Update Flush documentation (#153) -- fix: HTTPTransport.Flush panic and data race (#140) - -_NOTE:_ -This version changes the implementation of the default transport, modifying the -behavior of `sentry.Flush`. The previous behavior was to wait until there were -no buffered events; new concurrent events kept `Flush` from returning. The new -behavior is to wait until the last event prior to the call to `Flush` has been -sent or the timeout; new concurrent events have no effect. The new behavior is -inline with the [Unified API -Guidelines](https://docs.sentry.io/development/sdk-dev/unified-api/). - -We have updated the documentation and examples to clarify that `Flush` is meant -to be called typically only once before program termination, to wait for -in-flight events to be sent to Sentry. Calling `Flush` after every event is not -recommended, as it introduces unnecessary latency to the surrounding function. -Please verify the usage of `sentry.Flush` in your code base. - -## v0.4.0 - -- fix(stacktrace): Correctly report package names (#127) -- fix(stacktrace): Do not rely on AbsPath of files (#123) -- build: Require github.com/ugorji/go@v1.1.7 (#110) -- fix: Correctly store last event id (#99) -- fix: Include request body in event payload (#94) -- build: Reset go.mod version to 1.11 (#109) -- fix: Eliminate data race in modules integration (#105) -- feat: Add support for path prefixes in the DSN (#102) -- feat: Add HTTPClient option (#86) -- feat: Extract correct type and value from top-most error (#85) -- feat: Check for broken pipe errors in Gin integration (#82) -- fix: Client.CaptureMessage accept nil EventModifier (#72) - -## v0.3.1 - -- feat: Send extra information exposed by the Go runtime (#76) -- fix: Handle new lines in module integration (#65) -- fix: Make sure that cache is locked when updating for contextifyFramesIntegration -- ref: Update Iris integration and example to version 12 -- misc: Remove indirect dependencies in order to move them to separate go.mod files - -## v0.3.0 - -- feat: Retry event marshalling without contextual data if the first pass fails -- fix: Include `url.Parse` error in `DsnParseError` -- fix: Make more `Scope` methods safe for concurrency -- fix: Synchronize concurrent access to `Hub.client` -- ref: Remove mutex from `Scope` exported API -- ref: Remove mutex from `Hub` exported API -- ref: Compile regexps for `filterFrames` only once -- ref: Change `SampleRate` type to `float64` -- doc: `Scope.Clear` not safe for concurrent use -- ci: Test sentry-go with `go1.13`, drop `go1.10` - -_NOTE:_ -This version removes some of the internal APIs that landed publicly (namely `Hub/Scope` mutex structs) and may require (but shouldn't) some changes to your code. -It's not done through major version update, as we are still in `0.x` stage. - -## v0.2.1 - -- fix: Run `Contextify` integration on `Threads` as well - -## v0.2.0 - -- feat: Add `SetTransaction()` method on the `Scope` -- feat: `fasthttp` framework support with `sentryfasthttp` package -- fix: Add `RWMutex` locks to internal `Hub` and `Scope` changes - -## v0.1.3 - -- feat: Move frames context reading into `contextifyFramesIntegration` (#28) - -_NOTE:_ -In case of any performance issues due to source contexts IO, you can let us know and turn off the integration in the meantime with: - -```go -sentry.Init(sentry.ClientOptions{ - Integrations: func(integrations []sentry.Integration) []sentry.Integration { - var filteredIntegrations []sentry.Integration - for _, integration := range integrations { - if integration.Name() == "ContextifyFrames" { - continue - } - filteredIntegrations = append(filteredIntegrations, integration) - } - return filteredIntegrations - }, -}) -``` - -## v0.1.2 - -- feat: Better source code location resolution and more useful inapp frames (#26) -- feat: Use `noopTransport` when no `Dsn` provided (#27) -- ref: Allow empty `Dsn` instead of returning an error (#22) -- fix: Use `NewScope` instead of literal struct inside a `scope.Clear` call (#24) -- fix: Add to `WaitGroup` before the request is put inside a buffer (#25) - -## v0.1.1 - -- fix: Check for initialized `Client` in `AddBreadcrumbs` (#20) -- build: Bump version when releasing with Craft (#19) - -## v0.1.0 - -- First stable release! \o/ - -## v0.0.1-beta.5 - -- feat: **[breaking]** Add `NewHTTPTransport` and `NewHTTPSyncTransport` which accepts all transport options -- feat: New `HTTPSyncTransport` that blocks after each call -- feat: New `Echo` integration -- ref: **[breaking]** Remove `BufferSize` option from `ClientOptions` and move it to `HTTPTransport` instead -- ref: Export default `HTTPTransport` -- ref: Export `net/http` integration handler -- ref: Set `Request` instantly in the package handlers, not in `recoverWithSentry` so it can be accessed later on -- ci: Add craft config - -## v0.0.1-beta.4 - -- feat: `IgnoreErrors` client option and corresponding integration -- ref: Reworked `net/http` integration, wrote better example and complete readme -- ref: Reworked `Gin` integration, wrote better example and complete readme -- ref: Reworked `Iris` integration, wrote better example and complete readme -- ref: Reworked `Negroni` integration, wrote better example and complete readme -- ref: Reworked `Martini` integration, wrote better example and complete readme -- ref: Remove `Handle()` from frameworks handlers and return it directly from New - -## v0.0.1-beta.3 - -- feat: `Iris` framework support with `sentryiris` package -- feat: `Gin` framework support with `sentrygin` package -- feat: `Martini` framework support with `sentrymartini` package -- feat: `Negroni` framework support with `sentrynegroni` package -- feat: Add `Hub.Clone()` for easier frameworks integration -- feat: Return `EventID` from `Recovery` methods -- feat: Add `NewScope` and `NewEvent` functions and use them in the whole codebase -- feat: Add `AddEventProcessor` to the `Client` -- fix: Operate on requests body copy instead of the original -- ref: Try to read source files from the root directory, based on the filename as well, to make it work on AWS Lambda -- ref: Remove `gocertifi` dependence and document how to provide your own certificates -- ref: **[breaking]** Remove `Decorate` and `DecorateFunc` methods in favor of `sentryhttp` package -- ref: **[breaking]** Allow for integrations to live on the client, by passing client instance in `SetupOnce` method -- ref: **[breaking]** Remove `GetIntegration` from the `Hub` -- ref: **[breaking]** Remove `GlobalEventProcessors` getter from the public API - -## v0.0.1-beta.2 - -- feat: Add `AttachStacktrace` client option to include stacktrace for messages -- feat: Add `BufferSize` client option to configure transport buffer size -- feat: Add `SetRequest` method on a `Scope` to control `Request` context data -- feat: Add `FromHTTPRequest` for `Request` type for easier extraction -- ref: Extract `Request` information more accurately -- fix: Attach `ServerName`, `Release`, `Dist`, `Environment` options to the event -- fix: Don't log events dropped due to full transport buffer as sent -- fix: Don't panic and create an appropriate event when called `CaptureException` or `Recover` with `nil` value - -## v0.0.1-beta - -- Initial release diff --git a/vendor/github.com/cockroachdb/sentry-go/CONTRIBUTING.md b/vendor/github.com/cockroachdb/sentry-go/CONTRIBUTING.md deleted file mode 100644 index 04bfafa09..000000000 --- a/vendor/github.com/cockroachdb/sentry-go/CONTRIBUTING.md +++ /dev/null @@ -1,53 +0,0 @@ -## Community - -The public-facing channels for support and development of Sentry SDKs can be found on [Discord](https://discord.gg/Ww9hbqr). - -## Testing - -```console -$ go test -``` - -### Watch mode - -Use: https://github.com/cespare/reflex - -```console -$ reflex -g '*.go' -d "none" -- sh -c 'printf "\n"; go test' -``` - -### With data race detection - -```console -$ go test -race -``` - -### Coverage -```console -$ go test -race -coverprofile=coverage.txt -covermode=atomic && go tool cover -html coverage.txt -``` - -## Linting - -```console -$ golangci-lint run -``` - -## Release - -1. Update `CHANGELOG.md` with new version in `vX.X.X` format title and list of changes. - - The command below can be used to get a list of changes since the last tag, with the format used in `CHANGELOG.md`: - - ```console - $ git log --no-merges --format=%s $(git describe --abbrev=0).. | sed 's/^/- /' - ``` - -2. Commit with `misc: vX.X.X changelog` commit message and push to `master`. - -3. Let [`craft`](https://github.com/getsentry/craft) do the rest: - - ```console - $ craft prepare X.X.X - $ craft publish X.X.X - ``` diff --git a/vendor/github.com/cockroachdb/sentry-go/MIGRATION.md b/vendor/github.com/cockroachdb/sentry-go/MIGRATION.md deleted file mode 100644 index 0be4949eb..000000000 --- a/vendor/github.com/cockroachdb/sentry-go/MIGRATION.md +++ /dev/null @@ -1,392 +0,0 @@ -# `raven-go` to `sentry-go` Migration Guide - -## Installation - -raven-go - -```go -go get github.com/getsentry/raven-go -``` - -sentry-go - -```go -go get github.com/getsentry/sentry-go@v0.0.1 -``` - -## Configuration - -raven-go - -```go -import "github.com/getsentry/raven-go" - -func main() { - raven.SetDSN("___PUBLIC_DSN___") -} -``` - -sentry-go - -```go -import ( - "fmt" - "github.com/getsentry/sentry-go" -) - -func main() { - err := sentry.Init(sentry.ClientOptions{ - Dsn: "___PUBLIC_DSN___", - }) - - if err != nil { - fmt.Printf("Sentry initialization failed: %v\n", err) - } -} -``` - -raven-go - -```go -SetDSN() -SetDefaultLoggerName() -SetDebug() -SetEnvironment() -SetRelease() -SetSampleRate() -SetIgnoreErrors() -SetIncludePaths() -``` - -sentry-go - -```go -sentry.Init(sentry.ClientOptions{ - Dsn: "___PUBLIC_DSN___", - DebugWriter: os.Stderr, - Debug: true, - Environment: "environment", - Release: "release", - SampleRate: 0.5, - // IgnoreErrors: TBD, - // IncludePaths: TBD -}) -``` - -Available options: see [Configuration](https://docs.sentry.io/platforms/go/config/) section. - -### Providing SSL Certificates - -By default, TLS uses the host's root CA set. If you don't have `ca-certificates` (which should be your go-to way of fixing the issue of missing certificates) and want to use `gocertifi` instead, you can provide pre-loaded cert files as one of the options to the `sentry.Init` call: - -```go -package main - -import ( - "log" - - "github.com/certifi/gocertifi" - "github.com/getsentry/sentry-go" -) - -sentryClientOptions := sentry.ClientOptions{ - Dsn: "___PUBLIC_DSN___", -} - -rootCAs, err := gocertifi.CACerts() -if err != nil { - log.Println("Couldn't load CA Certificates: %v\n", err) -} else { - sentryClientOptions.CaCerts = rootCAs -} - -sentry.Init(sentryClientOptions) -``` - -## Usage - -### Capturing Errors - -raven-go - -```go -f, err := os.Open("filename.ext") -if err != nil { - raven.CaptureError(err, nil) -} -``` - -sentry-go - -```go -f, err := os.Open("filename.ext") -if err != nil { - sentry.CaptureException(err) -} -``` - -### Capturing Panics - -raven-go - -```go -raven.CapturePanic(func() { - // do all of the scary things here -}, nil) -``` - -sentry-go - -```go -func() { - defer sentry.Recover() - // do all of the scary things here -}() -``` - -### Capturing Messages - -raven-go - -```go -raven.CaptureMessage("Something bad happened and I would like to know about that") -``` - -sentry-go - -```go -sentry.CaptureMessage("Something bad happened and I would like to know about that") -``` - -### Capturing Events - -raven-go - -```go -packet := &raven.Packet{ - Message: "Hand-crafted event", - Extra: &raven.Extra{ - "runtime.Version": runtime.Version(), - "runtime.NumCPU": runtime.NumCPU(), - }, -} -raven.Capture(packet) -``` - -sentry-go - -```go -event := &sentry.NewEvent() -event.Message = "Hand-crafted event" -event.Extra["runtime.Version"] = runtime.Version() -event.Extra["runtime.NumCPU"] = runtime.NumCPU() - -sentry.CaptureEvent(event) -``` - -### Additional Data - -See Context section. - -### Event Sampling - -raven-go - -```go -raven.SetSampleRate(0.25) -``` - -sentry-go - -```go -sentry.Init(sentry.ClientOptions{ - SampleRate: 0.25, -}) -``` - -### Awaiting the response (not recommended) - -```go -raven.CaptureMessageAndWait("Something bad happened and I would like to know about that") -``` - -sentry-go - -```go -sentry.CaptureMessage("Something bad happened and I would like to know about that") - -if sentry.Flush(time.Second * 2) { - // event delivered -} else { - // timeout reached -} -``` - -## Context - -### Per-event - -raven-go - -```go -raven.CaptureError(err, map[string]string{"browser": "Firefox"}, &raven.Http{ - Method: "GET", - URL: "https://example.com/raven-go" -}) -``` - -sentry-go - -```go -sentry.WithScope(func(scope *sentry.Scope) { - scope.SetTag("browser", "Firefox") - scope.SetContext("Request", map[string]string{ - "Method": "GET", - "URL": "https://example.com/raven-go", - }) - sentry.CaptureException(err) -}) -``` - -### Globally - -#### SetHttpContext - -raven-go - -```go -raven.SetHttpContext(&raven.Http{ - Method: "GET", - URL: "https://example.com/raven-go", -}) -``` - -sentry-go - -```go -sentry.ConfigureScope(func(scope *sentry.Scope) { - scope.SetContext("Request", map[string]string{ - "Method": "GET", - "URL": "https://example.com/raven-go", - }) -}) -``` - -#### SetTagsContext - -raven-go - -```go -t := map[string]string{"day": "Friday", "sport": "Weightlifting"} -raven.SetTagsContext(map[string]string{"day": "Friday", "sport": "Weightlifting"}) -``` - -sentry-go - -```go -sentry.ConfigureScope(func(scope *sentry.Scope) { - scope.SetTags(map[string]string{"day": "Friday", "sport": "Weightlifting"}) -}) -``` - -#### SetUserContext - -raven-go - -```go -raven.SetUserContext(&raven.User{ - ID: "1337", - Username: "kamilogorek", - Email: "kamil@sentry.io", - IP: "127.0.0.1", -}) -``` - -sentry-go - -```go -sentry.ConfigureScope(func(scope *sentry.Scope) { - scope.SetUser(sentry.User{ - ID: "1337", - Username: "kamilogorek", - Email: "kamil@sentry.io", - IPAddress: "127.0.0.1", - }) -}) -``` - -#### ClearContext - -raven-go - -```go -raven.ClearContext() -``` - -sentry-go - -```go -sentry.ConfigureScope(func(scope *sentry.Scope) { - scope.Clear() -}) -``` - -#### WrapWithExtra - -raven-go - -```go -path := "filename.ext" -f, err := os.Open(path) -if err != nil { - err = raven.WrapWithExtra(err, map[string]string{"path": path, "cwd": os.Getwd()} - raven.CaptureError(err, nil) -} -``` - -sentry-go - -```go -// use `sentry.WithScope`, see "Context / Per-event Section" -path := "filename.ext" -f, err := os.Open(path) -if err != nil { - sentry.WithScope(func(scope *sentry.Scope) { - sentry.SetExtras(map[string]interface{}{"path": path, "cwd": os.Getwd()) - sentry.CaptureException(err) - }) -} -``` - -## Integrations - -### net/http - -raven-go - -```go -mux := http.NewServeMux -http.Handle("/", raven.Recoverer(mux)) - -// or - -func root(w http.ResponseWriter, r *http.Request) {} -http.HandleFunc("/", raven.RecoveryHandler(root)) -``` - -sentry-go - -```go -sentryHandler := sentryhttp.New(sentryhttp.Options{ - Repanic: false, - WaitForDelivery: true, -}) - -mux := http.NewServeMux -http.Handle("/", sentryHandler.Handle(mux)) - -// or - -func root(w http.ResponseWriter, r *http.Request) {} -http.HandleFunc("/", sentryHandler.HandleFunc(root)) -``` diff --git a/vendor/github.com/cockroachdb/sentry-go/README.md b/vendor/github.com/cockroachdb/sentry-go/README.md deleted file mode 100644 index 9cf449e39..000000000 --- a/vendor/github.com/cockroachdb/sentry-go/README.md +++ /dev/null @@ -1,190 +0,0 @@ -

- - - -
-

- -# Official Sentry SDK for Go - -[![Build Status](https://travis-ci.com/getsentry/sentry-go.svg?branch=master)](https://travis-ci.com/getsentry/sentry-go) -[![Go Report Card](https://goreportcard.com/badge/github.com/getsentry/sentry-go)](https://goreportcard.com/report/github.com/getsentry/sentry-go) -[![Discord](https://img.shields.io/discord/621778831602221064)](https://discord.gg/Ww9hbqr) -[![GoDoc](https://godoc.org/github.com/getsentry/sentry-go?status.svg)](https://godoc.org/github.com/getsentry/sentry-go) -[![go.dev](https://img.shields.io/badge/go.dev-pkg-007d9c.svg?style=flat)](https://pkg.go.dev/github.com/getsentry/sentry-go) - -`sentry-go` provides a Sentry client implementation for the Go programming -language. This is the next line of the Go SDK for [Sentry](https://sentry.io/), -intended to replace the `raven-go` package. - -> Looking for the old `raven-go` SDK documentation? See the Legacy client section [here](https://docs.sentry.io/clients/go/). -> If you want to start using sentry-go instead, check out the [migration guide](https://docs.sentry.io/platforms/go/migration/). - -## Requirements - -The only requirement is a Go compiler. - -We verify this package against the 3 most recent releases of Go. Those are the -supported versions. The exact versions are defined in -[`.travis.yml`](.travis.yml). - -In addition, we run tests against the current master branch of the Go toolchain, -though support for this configuration is best-effort. - -## Installation - -`sentry-go` can be installed like any other Go library through `go get`: - -```console -$ go get github.com/getsentry/sentry-go -``` - -Or, if you are already using -[Go Modules](https://github.com/golang/go/wiki/Modules), you may specify a -version number as well: - -```console -$ go get github.com/getsentry/sentry-go@latest -``` - -Check out the [list of released versions](https://pkg.go.dev/github.com/getsentry/sentry-go?tab=versions). - -## Configuration - -To use `sentry-go`, you’ll need to import the `sentry-go` package and initialize -it with your DSN and other [options](https://godoc.org/github.com/getsentry/sentry-go#ClientOptions). - -If not specified in the SDK initialization, the -[DSN](https://docs.sentry.io/error-reporting/configuration/?platform=go#dsn), -[Release](https://docs.sentry.io/workflow/releases/?platform=go) and -[Environment](https://docs.sentry.io/enriching-error-data/environments/?platform=go) -are read from the environment variables `SENTRY_DSN`, `SENTRY_RELEASE` and -`SENTRY_ENVIRONMENT`, respectively. - -More on this in the [Configuration](https://docs.sentry.io/platforms/go/config/) -section of the official Sentry documentation. - -## Usage - -The SDK must be initialized with a call to `sentry.Init`. The default transport -is asynchronous and thus most programs should call `sentry.Flush` to wait until -buffered events are sent to Sentry right before the program terminates. - -Typically, `sentry.Init` is called in the beginning of `func main` and -`sentry.Flush` is [deferred](https://golang.org/ref/spec#Defer_statements) right -after. - -> Note that if the program terminates with a call to -> [`os.Exit`](https://golang.org/pkg/os/#Exit), either directly or indirectly -> via another function like `log.Fatal`, deferred functions are not run. -> -> In that case, and if it is important for you to report outstanding events -> before terminating the program, arrange for `sentry.Flush` to be called before -> the program terminates. - -Example: - -```go -// This is an example program that makes an HTTP request and prints response -// headers. Whenever a request fails, the error is reported to Sentry. -// -// Try it by running: -// -// go run main.go -// go run main.go https://sentry.io -// go run main.go bad-url -// -// To actually report events to Sentry, set the DSN either by editing the -// appropriate line below or setting the environment variable SENTRY_DSN to -// match the DSN of your Sentry project. -package main - -import ( - "fmt" - "log" - "net/http" - "os" - "time" - - "github.com/getsentry/sentry-go" -) - -func main() { - if len(os.Args) < 2 { - log.Fatalf("usage: %s URL", os.Args[0]) - } - - err := sentry.Init(sentry.ClientOptions{ - // Either set your DSN here or set the SENTRY_DSN environment variable. - Dsn: "", - // Enable printing of SDK debug messages. - // Useful when getting started or trying to figure something out. - Debug: true, - }) - if err != nil { - log.Fatalf("sentry.Init: %s", err) - } - // Flush buffered events before the program terminates. - // Set the timeout to the maximum duration the program can afford to wait. - defer sentry.Flush(2 * time.Second) - - resp, err := http.Get(os.Args[1]) - if err != nil { - sentry.CaptureException(err) - log.Printf("reported to Sentry: %s", err) - return - } - defer resp.Body.Close() - - for header, values := range resp.Header { - for _, value := range values { - fmt.Printf("%s=%s\n", header, value) - } - } -} -``` - -For your convenience, this example is available at -[`example/basic/main.go`](example/basic/main.go). -There are also more examples in the -[example](example) directory. - -For more detailed information about how to get the most out of `sentry-go`, -checkout the official documentation: - -- [Configuration](https://docs.sentry.io/platforms/go/config) -- [Error Reporting](https://docs.sentry.io/error-reporting/quickstart?platform=go) -- [Enriching Error Data](https://docs.sentry.io/enriching-error-data/context?platform=go) -- [Transports](https://docs.sentry.io/platforms/go/transports) -- [Integrations](https://docs.sentry.io/platforms/go/integrations) - - [net/http](https://docs.sentry.io/platforms/go/http) - - [echo](https://docs.sentry.io/platforms/go/echo) - - [fasthttp](https://docs.sentry.io/platforms/go/fasthttp) - - [gin](https://docs.sentry.io/platforms/go/gin) - - [iris](https://docs.sentry.io/platforms/go/iris) - - [martini](https://docs.sentry.io/platforms/go/martini) - - [negroni](https://docs.sentry.io/platforms/go/negroni) - -## Resources - -- [Bug Tracker](https://github.com/getsentry/sentry-go/issues) -- [GitHub Project](https://github.com/getsentry/sentry-go) -- [![GoDoc](https://godoc.org/github.com/getsentry/sentry-go?status.svg)](https://godoc.org/github.com/getsentry/sentry-go) -- [![go.dev](https://img.shields.io/badge/go.dev-pkg-007d9c.svg?style=flat)](https://pkg.go.dev/github.com/getsentry/sentry-go) -- [![Documentation](https://img.shields.io/badge/documentation-sentry.io-green.svg)](https://docs.sentry.io/platforms/go/) -- [![Forum](https://img.shields.io/badge/forum-sentry-green.svg)](https://forum.sentry.io/c/sdks) -- [![Discord](https://img.shields.io/discord/621778831602221064)](https://discord.gg/Ww9hbqr) -- [![Stack Overflow](https://img.shields.io/badge/stack%20overflow-sentry-green.svg)](http://stackoverflow.com/questions/tagged/sentry) -- [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry) - - -## License - -Licensed under -[The 2-Clause BSD License](https://opensource.org/licenses/BSD-2-Clause), see -[`LICENSE`](LICENSE). - -## Community - -Join Sentry's [`#go` channel on Discord](https://discord.gg/Ww9hbqr) to get -involved and help us improve the SDK! diff --git a/vendor/github.com/cockroachdb/sentry-go/client.go b/vendor/github.com/cockroachdb/sentry-go/client.go deleted file mode 100644 index aaf9590d9..000000000 --- a/vendor/github.com/cockroachdb/sentry-go/client.go +++ /dev/null @@ -1,487 +0,0 @@ -package sentry - -import ( - "context" - "crypto/x509" - "fmt" - "io" - "io/ioutil" - "log" - "math/rand" - "net/http" - "os" - "reflect" - "sort" - "time" -) - -// maxErrorDepth is the maximum number of errors reported in a chain of errors. -// This protects the SDK from an arbitrarily long chain of wrapped errors. -// -// An additional consideration is that arguably reporting a long chain of errors -// is of little use when debugging production errors with Sentry. The Sentry UI -// is not optimized for long chains either. The top-level error together with a -// stack trace is often the most useful information. -const maxErrorDepth = 10 - -// usageError is used to report to Sentry an SDK usage error. -// -// It is not exported because it is never returned by any function or method in -// the exported API. -type usageError struct { - error -} - -// Logger is an instance of log.Logger that is use to provide debug information about running Sentry Client -// can be enabled by either using `Logger.SetOutput` directly or with `Debug` client option -var Logger = log.New(ioutil.Discard, "[Sentry] ", log.LstdFlags) //nolint: gochecknoglobals - -type EventProcessor func(event *Event, hint *EventHint) *Event - -type EventModifier interface { - ApplyToEvent(event *Event, hint *EventHint) *Event -} - -var globalEventProcessors []EventProcessor //nolint: gochecknoglobals - -func AddGlobalEventProcessor(processor EventProcessor) { - globalEventProcessors = append(globalEventProcessors, processor) -} - -// Integration allows for registering a functions that modify or discard captured events. -type Integration interface { - Name() string - SetupOnce(client *Client) -} - -// ClientOptions that configures a SDK Client -type ClientOptions struct { - // The DSN to use. If the DSN is not set, the client is effectively disabled. - Dsn string - // In debug mode, the debug information is printed to stdout to help you understand what - // sentry is doing. - Debug bool - // Configures whether SDK should generate and attach stacktraces to pure capture message calls. - AttachStacktrace bool - // The sample rate for event submission (0.0 - 1.0, defaults to 1.0). - SampleRate float64 - // List of regexp strings that will be used to match against event's message - // and if applicable, caught errors type and value. - // If the match is found, then a whole event will be dropped. - IgnoreErrors []string - // Before send callback. - BeforeSend func(event *Event, hint *EventHint) *Event - // Before breadcrumb add callback. - BeforeBreadcrumb func(breadcrumb *Breadcrumb, hint *BreadcrumbHint) *Breadcrumb - // Integrations to be installed on the current Client, receives default integrations - Integrations func([]Integration) []Integration - // io.Writer implementation that should be used with the `Debug` mode - DebugWriter io.Writer - // The transport to use. - // This is an instance of a struct implementing `Transport` interface. - // Defaults to `httpTransport` from `transport.go` - Transport Transport - // The server name to be reported. - ServerName string - // The release to be sent with events. - Release string - // The dist to be sent with events. - Dist string - // The environment to be sent with events. - Environment string - // Maximum number of breadcrumbs. - MaxBreadcrumbs int - // An optional pointer to `http.Client` that will be used with a default HTTPTransport. - // Using your own client will make HTTPTransport, HTTPProxy, HTTPSProxy and CaCerts options ignored. - HTTPClient *http.Client - // An optional pointer to `http.Transport` that will be used with a default HTTPTransport. - // Using your own transport will make HTTPProxy, HTTPSProxy and CaCerts options ignored. - HTTPTransport http.RoundTripper - // An optional HTTP proxy to use. - // This will default to the `http_proxy` environment variable. - // or `https_proxy` if that one exists. - HTTPProxy string - // An optional HTTPS proxy to use. - // This will default to the `HTTPS_PROXY` environment variable - // or `http_proxy` if that one exists. - HTTPSProxy string - // An optional CaCerts to use. - // Defaults to `gocertifi.CACerts()`. - CaCerts *x509.CertPool -} - -// Client is the underlying processor that's used by the main API and `Hub` instances. -type Client struct { - options ClientOptions - dsn *Dsn - eventProcessors []EventProcessor - integrations []Integration - Transport Transport -} - -// NewClient creates and returns an instance of `Client` configured using `ClientOptions`. -func NewClient(options ClientOptions) (*Client, error) { - if options.Debug { - debugWriter := options.DebugWriter - if debugWriter == nil { - debugWriter = os.Stdout - } - Logger.SetOutput(debugWriter) - } - - if options.Dsn == "" { - options.Dsn = os.Getenv("SENTRY_DSN") - } - - if options.Release == "" { - options.Release = os.Getenv("SENTRY_RELEASE") - } - - if options.Environment == "" { - options.Environment = os.Getenv("SENTRY_ENVIRONMENT") - } - - var dsn *Dsn - if options.Dsn != "" { - var err error - dsn, err = NewDsn(options.Dsn) - if err != nil { - return nil, err - } - } - - client := Client{ - options: options, - dsn: dsn, - } - - client.setupTransport() - client.setupIntegrations() - - return &client, nil -} - -func (client *Client) setupTransport() { - transport := client.options.Transport - - if transport == nil { - if client.options.Dsn == "" { - transport = new(noopTransport) - } else { - transport = NewHTTPTransport() - } - } - - transport.Configure(client.options) - client.Transport = transport -} - -func (client *Client) setupIntegrations() { - integrations := []Integration{ - new(contextifyFramesIntegration), - new(environmentIntegration), - new(modulesIntegration), - new(ignoreErrorsIntegration), - } - - if client.options.Integrations != nil { - integrations = client.options.Integrations(integrations) - } - - for _, integration := range integrations { - if client.integrationAlreadyInstalled(integration.Name()) { - Logger.Printf("Integration %s is already installed\n", integration.Name()) - continue - } - client.integrations = append(client.integrations, integration) - integration.SetupOnce(client) - Logger.Printf("Integration installed: %s\n", integration.Name()) - } -} - -// AddEventProcessor adds an event processor to the client. -func (client *Client) AddEventProcessor(processor EventProcessor) { - client.eventProcessors = append(client.eventProcessors, processor) -} - -// Options return `ClientOptions` for the current `Client`. -func (client Client) Options() ClientOptions { - return client.options -} - -// CaptureMessage captures an arbitrary message. -func (client *Client) CaptureMessage(message string, hint *EventHint, scope EventModifier) *EventID { - event := client.eventFromMessage(message, LevelInfo) - return client.CaptureEvent(event, hint, scope) -} - -// CaptureException captures an error. -func (client *Client) CaptureException(exception error, hint *EventHint, scope EventModifier) *EventID { - event := client.eventFromException(exception, LevelError) - return client.CaptureEvent(event, hint, scope) -} - -// CaptureEvent captures an event on the currently active client if any. -// -// The event must already be assembled. Typically code would instead use -// the utility methods like `CaptureException`. The return value is the -// event ID. In case Sentry is disabled or event was dropped, the return value will be nil. -func (client *Client) CaptureEvent(event *Event, hint *EventHint, scope EventModifier) *EventID { - return client.processEvent(event, hint, scope) -} - -// Recover captures a panic. -// Returns `EventID` if successfully, or `nil` if there's no error to recover from. -func (client *Client) Recover(err interface{}, hint *EventHint, scope EventModifier) *EventID { - if err == nil { - err = recover() - } - - if err != nil { - if err, ok := err.(error); ok { - event := client.eventFromException(err, LevelFatal) - return client.CaptureEvent(event, hint, scope) - } - - if err, ok := err.(string); ok { - event := client.eventFromMessage(err, LevelFatal) - return client.CaptureEvent(event, hint, scope) - } - } - - return nil -} - -// Recover captures a panic and passes relevant context object. -// Returns `EventID` if successfully, or `nil` if there's no error to recover from. -func (client *Client) RecoverWithContext( - ctx context.Context, - err interface{}, - hint *EventHint, - scope EventModifier, -) *EventID { - if err == nil { - err = recover() - } - - if err != nil { - if hint.Context == nil && ctx != nil { - hint.Context = ctx - } - - if err, ok := err.(error); ok { - event := client.eventFromException(err, LevelFatal) - return client.CaptureEvent(event, hint, scope) - } - - if err, ok := err.(string); ok { - event := client.eventFromMessage(err, LevelFatal) - return client.CaptureEvent(event, hint, scope) - } - } - - return nil -} - -// Flush waits until the underlying Transport sends any buffered events to the -// Sentry server, blocking for at most the given timeout. It returns false if -// the timeout was reached. In that case, some events may not have been sent. -// -// Flush should be called before terminating the program to avoid -// unintentionally dropping events. -// -// Do not call Flush indiscriminately after every call to CaptureEvent, -// CaptureException or CaptureMessage. Instead, to have the SDK send events over -// the network synchronously, configure it to use the HTTPSyncTransport in the -// call to Init. -func (client *Client) Flush(timeout time.Duration) bool { - return client.Transport.Flush(timeout) -} - -func (client *Client) eventFromMessage(message string, level Level) *Event { - event := NewEvent() - event.Level = level - event.Message = message - - if client.Options().AttachStacktrace { - event.Threads = []Thread{{ - Stacktrace: NewStacktrace(), - Crashed: false, - Current: true, - }} - } - - return event -} - -func (client *Client) eventFromException(exception error, level Level) *Event { - err := exception - if err == nil { - err = usageError{fmt.Errorf("%s called with nil error", callerFunctionName())} - } - - event := NewEvent() - event.Level = level - - for i := 0; i < maxErrorDepth && err != nil; i++ { - event.Exception = append(event.Exception, Exception{ - Value: err.Error(), - Type: reflect.TypeOf(err).String(), - Stacktrace: ExtractStacktrace(err), - }) - switch previous := err.(type) { - case interface{ Unwrap() error }: - err = previous.Unwrap() - case interface{ Cause() error }: - err = previous.Cause() - default: - err = nil - } - } - - // Add a trace of the current stack to the most recent error in a chain if - // it doesn't have a stack trace yet. - // We only add to the most recent error to avoid duplication and because the - // current stack is most likely unrelated to errors deeper in the chain. - if event.Exception[0].Stacktrace == nil { - event.Exception[0].Stacktrace = NewStacktrace() - } - - // event.Exception should be sorted such that the most recent error is last. - reverse(event.Exception) - - return event -} - -// reverse reverses the slice a in place. -func reverse(a []Exception) { - for i := len(a)/2 - 1; i >= 0; i-- { - opp := len(a) - 1 - i - a[i], a[opp] = a[opp], a[i] - } -} - -func (client *Client) processEvent(event *Event, hint *EventHint, scope EventModifier) *EventID { - options := client.Options() - - // TODO: Reconsider if its worth going away from default implementation - // of other SDKs. In Go zero value (default) for float32 is 0.0, - // which means that if someone uses ClientOptions{} struct directly - // and we would not check for 0 here, we'd skip all events by default - if options.SampleRate != 0.0 { - randomFloat := rand.New(rand.NewSource(time.Now().UnixNano())).Float64() - if randomFloat > options.SampleRate { - Logger.Println("Event dropped due to SampleRate hit.") - return nil - } - } - - if event = client.prepareEvent(event, hint, scope); event == nil { - return nil - } - - if options.BeforeSend != nil { - h := &EventHint{} - if hint != nil { - h = hint - } - if event = options.BeforeSend(event, h); event == nil { - Logger.Println("Event dropped due to BeforeSend callback.") - return nil - } - } - - client.Transport.SendEvent(event) - - return &event.EventID -} - -func (client *Client) prepareEvent(event *Event, hint *EventHint, scope EventModifier) *Event { - if event.EventID == "" { - event.EventID = EventID(uuid()) - } - - if event.Timestamp.IsZero() { - event.Timestamp = time.Now().UTC() - } - - if event.Level == "" { - event.Level = LevelInfo - } - - if event.ServerName == "" { - if client.Options().ServerName != "" { - event.ServerName = client.Options().ServerName - } else if hostname, err := os.Hostname(); err == nil { - event.ServerName = hostname - } - } - - if event.Release == "" && client.Options().Release != "" { - event.Release = client.Options().Release - } - - if event.Dist == "" && client.Options().Dist != "" { - event.Dist = client.Options().Dist - } - - if event.Environment == "" && client.Options().Environment != "" { - event.Environment = client.Options().Environment - } - - event.Platform = "go" - event.Sdk = SdkInfo{ - Name: "sentry.go", - Version: Version, - Integrations: client.listIntegrations(), - Packages: []SdkPackage{{ - Name: "sentry-go", - Version: Version, - }}, - } - - if scope != nil { - event = scope.ApplyToEvent(event, hint) - if event == nil { - return nil - } - } - - for _, processor := range client.eventProcessors { - id := event.EventID - event = processor(event, hint) - if event == nil { - Logger.Printf("Event dropped by one of the Client EventProcessors: %s\n", id) - return nil - } - } - - for _, processor := range globalEventProcessors { - id := event.EventID - event = processor(event, hint) - if event == nil { - Logger.Printf("Event dropped by one of the Global EventProcessors: %s\n", id) - return nil - } - } - - return event -} - -func (client Client) listIntegrations() []string { - integrations := make([]string, 0, len(client.integrations)) - for _, integration := range client.integrations { - integrations = append(integrations, integration.Name()) - } - sort.Strings(integrations) - return integrations -} - -func (client Client) integrationAlreadyInstalled(name string) bool { - for _, integration := range client.integrations { - if integration.Name() == name { - return true - } - } - return false -} diff --git a/vendor/github.com/cockroachdb/sentry-go/interfaces.go b/vendor/github.com/cockroachdb/sentry-go/interfaces.go deleted file mode 100644 index 0f7e7b177..000000000 --- a/vendor/github.com/cockroachdb/sentry-go/interfaces.go +++ /dev/null @@ -1,221 +0,0 @@ -package sentry - -import ( - "context" - "encoding/json" - "fmt" - "net" - "net/http" - "strings" - "time" -) - -// Protocol Docs (kinda) -// https://github.com/getsentry/rust-sentry-types/blob/master/src/protocol/v7.rs - -// Level marks the severity of the event -type Level string - -const ( - LevelDebug Level = "debug" - LevelInfo Level = "info" - LevelWarning Level = "warning" - LevelError Level = "error" - LevelFatal Level = "fatal" -) - -// https://docs.sentry.io/development/sdk-dev/event-payloads/sdk/ -type SdkInfo struct { - Name string `json:"name,omitempty"` - Version string `json:"version,omitempty"` - Integrations []string `json:"integrations,omitempty"` - Packages []SdkPackage `json:"packages,omitempty"` -} - -type SdkPackage struct { - Name string `json:"name,omitempty"` - Version string `json:"version,omitempty"` -} - -// TODO: This type could be more useful, as map of interface{} is too generic -// and requires a lot of type assertions in beforeBreadcrumb calls -// plus it could just be `map[string]interface{}` then -type BreadcrumbHint map[string]interface{} - -// https://docs.sentry.io/development/sdk-dev/event-payloads/breadcrumbs/ -type Breadcrumb struct { - Category string `json:"category,omitempty"` - Data map[string]interface{} `json:"data,omitempty"` - Level Level `json:"level,omitempty"` - Message string `json:"message,omitempty"` - Timestamp time.Time `json:"timestamp"` - Type string `json:"type,omitempty"` -} - -func (b *Breadcrumb) MarshalJSON() ([]byte, error) { - type alias Breadcrumb - // encoding/json doesn't support the "omitempty" option for struct types. - // See https://golang.org/issues/11939. - // This implementation of MarshalJSON shadows the original Timestamp field - // forcing it to be omitted when the Timestamp is the zero value of - // time.Time. - if b.Timestamp.IsZero() { - return json.Marshal(&struct { - *alias - Timestamp json.RawMessage `json:"timestamp,omitempty"` - }{ - alias: (*alias)(b), - }) - } - return json.Marshal(&struct { - *alias - }{ - alias: (*alias)(b), - }) -} - -// https://docs.sentry.io/development/sdk-dev/event-payloads/user/ -type User struct { - Email string `json:"email,omitempty"` - ID string `json:"id,omitempty"` - IPAddress string `json:"ip_address,omitempty"` - Username string `json:"username,omitempty"` -} - -// https://docs.sentry.io/development/sdk-dev/event-payloads/request/ -type Request struct { - URL string `json:"url,omitempty"` - Method string `json:"method,omitempty"` - Data string `json:"data,omitempty"` - QueryString string `json:"query_string,omitempty"` - Cookies string `json:"cookies,omitempty"` - Headers map[string]string `json:"headers,omitempty"` - Env map[string]string `json:"env,omitempty"` -} - -// NewRequest returns a new Sentry Request from the given http.Request. -// -// NewRequest avoids operations that depend on network access. In particular, it -// does not read r.Body. -func NewRequest(r *http.Request) *Request { - protocol := schemeHTTP - if r.TLS != nil || r.Header.Get("X-Forwarded-Proto") == "https" { - protocol = schemeHTTPS - } - url := fmt.Sprintf("%s://%s%s", protocol, r.Host, r.URL.Path) - - // We read only the first Cookie header because of the specification: - // https://tools.ietf.org/html/rfc6265#section-5.4 - // When the user agent generates an HTTP request, the user agent MUST NOT - // attach more than one Cookie header field. - cookies := r.Header.Get("Cookie") - - headers := make(map[string]string, len(r.Header)) - for k, v := range r.Header { - headers[k] = strings.Join(v, ",") - } - headers["Host"] = r.Host - - var env map[string]string - if addr, port, err := net.SplitHostPort(r.RemoteAddr); err == nil { - env = map[string]string{"REMOTE_ADDR": addr, "REMOTE_PORT": port} - } - - return &Request{ - URL: url, - Method: r.Method, - QueryString: r.URL.RawQuery, - Cookies: cookies, - Headers: headers, - Env: env, - } -} - -// https://docs.sentry.io/development/sdk-dev/event-payloads/exception/ -type Exception struct { - Type string `json:"type,omitempty"` - Value string `json:"value,omitempty"` - Module string `json:"module,omitempty"` - ThreadID string `json:"thread_id,omitempty"` - Stacktrace *Stacktrace `json:"stacktrace,omitempty"` - RawStacktrace *Stacktrace `json:"raw_stacktrace,omitempty"` -} - -type EventID string - -// https://docs.sentry.io/development/sdk-dev/event-payloads/ -type Event struct { - Breadcrumbs []*Breadcrumb `json:"breadcrumbs,omitempty"` - Contexts map[string]interface{} `json:"contexts,omitempty"` - Dist string `json:"dist,omitempty"` - Environment string `json:"environment,omitempty"` - EventID EventID `json:"event_id,omitempty"` - Extra map[string]interface{} `json:"extra,omitempty"` - Fingerprint []string `json:"fingerprint,omitempty"` - Level Level `json:"level,omitempty"` - Message string `json:"message,omitempty"` - Platform string `json:"platform,omitempty"` - Release string `json:"release,omitempty"` - Sdk SdkInfo `json:"sdk,omitempty"` - ServerName string `json:"server_name,omitempty"` - Threads []Thread `json:"threads,omitempty"` - Tags map[string]string `json:"tags,omitempty"` - Timestamp time.Time `json:"timestamp"` - Transaction string `json:"transaction,omitempty"` - User User `json:"user,omitempty"` - Logger string `json:"logger,omitempty"` - Modules map[string]string `json:"modules,omitempty"` - Request *Request `json:"request,omitempty"` - Exception []Exception `json:"exception,omitempty"` -} - -func (e *Event) MarshalJSON() ([]byte, error) { - type alias Event - // encoding/json doesn't support the "omitempty" option for struct types. - // See https://golang.org/issues/11939. - // This implementation of MarshalJSON shadows the original Timestamp field - // forcing it to be omitted when the Timestamp is the zero value of - // time.Time. - if e.Timestamp.IsZero() { - return json.Marshal(&struct { - *alias - Timestamp json.RawMessage `json:"timestamp,omitempty"` - }{ - alias: (*alias)(e), - }) - } - return json.Marshal(&struct { - *alias - }{ - alias: (*alias)(e), - }) -} - -func NewEvent() *Event { - event := Event{ - Contexts: make(map[string]interface{}), - Extra: make(map[string]interface{}), - Tags: make(map[string]string), - Modules: make(map[string]string), - } - return &event -} - -type Thread struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Stacktrace *Stacktrace `json:"stacktrace,omitempty"` - RawStacktrace *Stacktrace `json:"raw_stacktrace,omitempty"` - Crashed bool `json:"crashed,omitempty"` - Current bool `json:"current,omitempty"` -} - -type EventHint struct { - Data interface{} - EventID string - OriginalException error - RecoveredException interface{} - Context context.Context - Request *http.Request - Response *http.Response -} diff --git a/vendor/github.com/cockroachdb/sentry-go/util.go b/vendor/github.com/cockroachdb/sentry-go/util.go deleted file mode 100644 index e9a42e3ea..000000000 --- a/vendor/github.com/cockroachdb/sentry-go/util.go +++ /dev/null @@ -1,34 +0,0 @@ -package sentry - -import ( - "crypto/rand" - "encoding/hex" - "encoding/json" - "fmt" - "io" - "os" -) - -func uuid() string { - id := make([]byte, 16) - _, _ = io.ReadFull(rand.Reader, id) - id[6] &= 0x0F // clear version - id[6] |= 0x40 // set version to 4 (random uuid) - id[8] &= 0x3F // clear variant - id[8] |= 0x80 // set to IETF variant - return hex.EncodeToString(id) -} - -func fileExists(fileName string) bool { - if _, err := os.Stat(fileName); err != nil { - return false - } - - return true -} - -//nolint: deadcode, unused -func prettyPrint(data interface{}) { - dbg, _ := json.MarshalIndent(data, "", " ") - fmt.Println(string(dbg)) -} diff --git a/vendor/github.com/cockroachdb/tokenbucket/token_bucket.go b/vendor/github.com/cockroachdb/tokenbucket/token_bucket.go index 79f2a3728..6a8159fdd 100644 --- a/vendor/github.com/cockroachdb/tokenbucket/token_bucket.go +++ b/vendor/github.com/cockroachdb/tokenbucket/token_bucket.go @@ -15,6 +15,7 @@ package tokenbucket import ( + "context" "time" ) @@ -50,7 +51,8 @@ func (tb *TokenBucket) Init(rate TokensPerSecond, burst Tokens) { }) } -// Init the token bucket with a custom "Now" fuction. +// Init the token bucket with a custom "Now" function. +// Note that Wait/WaitCtx cannot be used with a custom time function. func (tb *TokenBucket) InitWithNowFn(rate TokensPerSecond, burst Tokens, nowFn func() time.Time) { *tb = TokenBucket{ rate: rate, @@ -137,6 +139,33 @@ func (tb *TokenBucket) TryToFulfill(amount Tokens) (fulfilled bool, tryAgainAfte return true, 0 } +// Wait removes the given amount, waiting as long as necessary. +func (tb *TokenBucket) Wait(amount Tokens) { + _ = tb.WaitCtx(context.Background(), amount) +} + +// WaitCtx removes the given amount, waiting as long as necessary or until the +// context is canceled. +func (tb *TokenBucket) WaitCtx(ctx context.Context, amount Tokens) error { + // We want to check for context cancelation even if we don't need to wait. + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + for { + fulfilled, tryAgainAfter := tb.TryToFulfill(amount) + if fulfilled { + return nil + } + select { + case <-time.After(tryAgainAfter): + case <-ctx.Done(): + return ctx.Err() + } + } +} + // Exhausted returns the cumulative duration over which this token bucket was // exhausted. Exported only for metrics. func (tb *TokenBucket) Exhausted() time.Duration { diff --git a/vendor/github.com/getsentry/sentry-go/.codecov.yml b/vendor/github.com/getsentry/sentry-go/.codecov.yml new file mode 100644 index 000000000..df0b26811 --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/.codecov.yml @@ -0,0 +1,13 @@ +codecov: + # across + notify: + # Do not notify until at least this number of reports have been uploaded + # from the CI pipeline. We normally have more than that number, but 6 + # should be enough to get a first notification. + after_n_builds: 6 +coverage: + status: + project: + default: + # Do not fail the commit status if the coverage was reduced up to this value + threshold: 0.5% diff --git a/vendor/github.com/getsentry/sentry-go/.craft.yml b/vendor/github.com/getsentry/sentry-go/.craft.yml new file mode 100644 index 000000000..238288e45 --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/.craft.yml @@ -0,0 +1,13 @@ +minVersion: 0.35.0 +changelogPolicy: simple +artifactProvider: + name: none +targets: + - name: github + tagPrefix: v + - name: github + tagPrefix: otel/v + tagOnly: true + - name: registry + sdks: + github:getsentry/sentry-go: diff --git a/vendor/github.com/getsentry/sentry-go/.gitattributes b/vendor/github.com/getsentry/sentry-go/.gitattributes new file mode 100644 index 000000000..bccfeeab0 --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/.gitattributes @@ -0,0 +1,5 @@ +# Tell Git to use LF for line endings on all platforms. +# Required to have correct test data on Windows. +# https://github.com/mvdan/github-actions-golang#caveats +# https://github.com/actions/checkout/issues/135#issuecomment-613361104 +* text eol=lf diff --git a/vendor/github.com/getsentry/sentry-go/.gitignore b/vendor/github.com/getsentry/sentry-go/.gitignore new file mode 100644 index 000000000..b1249ba55 --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/.gitignore @@ -0,0 +1,14 @@ +# Code coverage artifacts +coverage.txt +coverage.out +coverage.html +.coverage/ + +# Just my personal way of tracking stuff — Kamil +FIXME.md +TODO.md +!NOTES.md + +# IDE system files +.idea +.vscode diff --git a/vendor/github.com/cockroachdb/sentry-go/.golangci.yml b/vendor/github.com/getsentry/sentry-go/.golangci.yml similarity index 70% rename from vendor/github.com/cockroachdb/sentry-go/.golangci.yml rename to vendor/github.com/getsentry/sentry-go/.golangci.yml index b1416bc01..0f3532381 100644 --- a/vendor/github.com/cockroachdb/sentry-go/.golangci.yml +++ b/vendor/github.com/getsentry/sentry-go/.golangci.yml @@ -7,25 +7,22 @@ linters: - dogsled - dupl - errcheck - - gochecknoglobals + - exportloopref - gochecknoinits - goconst - gocritic - gocyclo + - godot - gofmt - goimports - - golint - gosec - gosimple - govet - ineffassign - - interfacer - - lll - - maligned - misspell - nakedret - prealloc - - scopelint + - revive - staticcheck - structcheck - typecheck @@ -33,18 +30,21 @@ linters: - unparam - unused - varcheck -run: - skip-dirs: - - echo - - example/echo + - whitespace issues: - exclude: - - "not declared by package utf8" - - "unicode/utf8/utf8.go" exclude-rules: - path: _test\.go linters: + - goconst - prealloc + - path: _test\.go + text: "G306:" + linters: + - gosec - path: errors_test\.go linters: - unused + - path: http/example_test\.go + linters: + - errcheck + - bodyclose diff --git a/vendor/github.com/getsentry/sentry-go/CHANGELOG.md b/vendor/github.com/getsentry/sentry-go/CHANGELOG.md new file mode 100644 index 000000000..4bf5e9c48 --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/CHANGELOG.md @@ -0,0 +1,488 @@ +# Changelog + +## 0.18.0 + +The Sentry SDK team is happy to announce the immediate availability of Sentry Go SDK v0.18.0. +This release contains initial support for [OpenTelemetry](https://opentelemetry.io/) and various other bug fixes and improvements. + +**Note**: This is the last release supporting Go 1.17. + +### Features + +- Initial support for [OpenTelemetry](https://opentelemetry.io/). + You can now send all your OpenTelemetry spans to Sentry. + + Install the `otel` module + + ```bash + go get github.com/getsentry/sentry-go \ + github.com/getsentry/sentry-go/otel + ``` + + Configure the Sentry and OpenTelemetry SDKs + + ```go + import ( + "go.opentelemetry.io/otel" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + "github.com/getsentry/sentry-go" + "github.com/getsentry/sentry-go/otel" + // ... + ) + + // Initlaize the Sentry SDK + sentry.Init(sentry.ClientOptions{ + Dsn: "__DSN__", + EnableTracing: true, + TracesSampleRate: 1.0, + }) + + // Set up the Sentry span processor + tp := sdktrace.NewTracerProvider( + sdktrace.WithSpanProcessor(sentryotel.NewSentrySpanProcessor()), + // ... + ) + otel.SetTracerProvider(tp) + + // Set up the Sentry propagator + otel.SetTextMapPropagator(sentryotel.NewSentryPropagator()) + ``` + + You can read more about using OpenTelemetry with Sentry in our [docs](https://docs.sentry.io/platforms/go/performance/instrumentation/opentelemetry/). + +### Bug Fixes + +- Do not freeze the Dynamic Sampling Context when no Sentry values are present in the baggage header ([#532](https://github.com/getsentry/sentry-go/pull/532)) +- Create a frozen Dynamic Sampling Context when calling `span.ToBaggage()` ([#566](https://github.com/getsentry/sentry-go/pull/566)) +- Fix baggage parsing and encoding in vendored otel package ([#568](https://github.com/getsentry/sentry-go/pull/568)) + +### Misc + +- Add `Span.SetDynamicSamplingContext()` ([#539](https://github.com/getsentry/sentry-go/pull/539/)) +- Add various getters for `Dsn` ([#540](https://github.com/getsentry/sentry-go/pull/540)) +- Add `SpanOption::SpanSampled` ([#546](https://github.com/getsentry/sentry-go/pull/546)) +- Add `Span.SetData()` ([#542](https://github.com/getsentry/sentry-go/pull/542)) +- Add `Span.IsTransaction()` ([#543](https://github.com/getsentry/sentry-go/pull/543)) +- Add `Span.GetTransaction()` method ([#558](https://github.com/getsentry/sentry-go/pull/558)) + +## 0.17.0 + +The Sentry SDK team is happy to announce the immediate availability of Sentry Go SDK v0.17.0. +This release contains a new `BeforeSendTransaction` hook option and corrects two regressions introduced in `0.16.0`. + +### Features + +- Add `BeforeSendTransaction` hook to `ClientOptions` ([#517](https://github.com/getsentry/sentry-go/pull/517)) + - Here's [an example](https://github.com/getsentry/sentry-go/blob/master/_examples/http/main.go#L56-L66) of how BeforeSendTransaction can be used to modify or drop transaction events. + +### Bug Fixes + +- Do not crash in Span.Finish() when the Client is empty [#520](https://github.com/getsentry/sentry-go/pull/520) + - Fixes [#518](https://github.com/getsentry/sentry-go/issues/518) +- Attach non-PII/non-sensitive request headers to events when `ClientOptions.SendDefaultPii` is set to `false` ([#524](https://github.com/getsentry/sentry-go/pull/524)) + - Fixes [#523](https://github.com/getsentry/sentry-go/issues/523) + +### Misc + +- Clarify how to handle logrus.Fatalf events ([#501](https://github.com/getsentry/sentry-go/pull/501/)) +- Rename the `examples` directory to `_examples` ([#521](https://github.com/getsentry/sentry-go/pull/521)) + - This removes an indirect dependency to `github.com/golang-jwt/jwt` + +## 0.16.0 + +The Sentry SDK team is happy to announce the immediate availability of Sentry Go SDK v0.16.0. +Due to ongoing work towards a stable API for `v1.0.0`, we sadly had to include **two breaking changes** in this release. + +### Breaking Changes + +- Add `EnableTracing`, a boolean option flag to enable performance monitoring (`false` by default). + - If you're using `TracesSampleRate` or `TracesSampler`, this option is **required** to enable performance monitoring. + + ```go + sentry.Init(sentry.ClientOptions{ + EnableTracing: true, + TracesSampleRate: 1.0, + }) + ``` +- Unify TracesSampler [#498](https://github.com/getsentry/sentry-go/pull/498) + - `TracesSampler` was changed to a callback that must return a `float64` between `0.0` and `1.0`. + + For example, you can apply a sample rate of `1.0` (100%) to all `/api` transactions, and a sample rate of `0.5` (50%) to all other transactions. + You can read more about this in our [SDK docs](https://docs.sentry.io/platforms/go/configuration/filtering/#using-sampling-to-filter-transaction-events). + + ```go + sentry.Init(sentry.ClientOptions{ + TracesSampler: sentry.TracesSampler(func(ctx sentry.SamplingContext) float64 { + hub := sentry.GetHubFromContext(ctx.Span.Context()) + name := hub.Scope().Transaction() + + if strings.HasPrefix(name, "GET /api") { + return 1.0 + } + + return 0.5 + }), + } + ``` + +### Features + +- Send errors logged with [Logrus](https://github.com/sirupsen/logrus) to Sentry. + - Have a look at our [logrus examples](https://github.com/getsentry/sentry-go/blob/master/_examples/logrus/main.go) on how to use the integration. +- Add support for Dynamic Sampling [#491](https://github.com/getsentry/sentry-go/pull/491) + - You can read more about Dynamic Sampling in our [product docs](https://docs.sentry.io/product/data-management-settings/dynamic-sampling/). +- Add detailed logging about the reason transactions are being dropped. + - You can enable SDK logging via `sentry.ClientOptions.Debug: true`. + +### Bug Fixes + +- Do not clone the hub when calling `StartTransaction` [#505](https://github.com/getsentry/sentry-go/pull/505) + - Fixes [#502](https://github.com/getsentry/sentry-go/issues/502) + +## 0.15.0 + +- fix: Scope values should not override Event values (#446) +- feat: Make maximum amount of spans configurable (#460) +- feat: Add a method to start a transaction (#482) +- feat: Extend User interface by adding Data, Name and Segment (#483) +- feat: Add ClientOptions.SendDefaultPII (#485) + +## 0.14.0 + +- feat: Add function to continue from trace string (#434) +- feat: Add `max-depth` options (#428) +- *[breaking]* ref: Use a `Context` type mapping to a `map[string]interface{}` for all event contexts (#444) +- *[breaking]* ref: Replace deprecated `ioutil` pkg with `os` & `io` (#454) +- ref: Optimize `stacktrace.go` from size and speed (#467) +- ci: Test against `go1.19` and `go1.18`, drop `go1.16` and `go1.15` support (#432, #477) +- deps: Dependency update to fix CVEs (#462, #464, #477) + +_NOTE:_ This version drops support for Go 1.16 and Go 1.15. The currently supported Go versions are the last 3 stable releases: 1.19, 1.18 and 1.17. + +## v0.13.0 + +- ref: Change DSN ProjectID to be a string (#420) +- fix: When extracting PCs from stack frames, try the `PC` field (#393) +- build: Bump gin-gonic/gin from v1.4.0 to v1.7.7 (#412) +- build: Bump Go version in go.mod (#410) +- ci: Bump golangci-lint version in GH workflow (#419) +- ci: Update GraphQL config with appropriate permissions (#417) +- ci: ci: Add craft release automation (#422) + +## v0.12.0 + +- feat: Automatic Release detection (#363, #369, #386, #400) +- fix: Do not change Hub.lastEventID for transactions (#379) +- fix: Do not clear LastEventID when events are dropped (#382) +- Updates to documentation (#366, #385) + +_NOTE:_ +This version drops support for Go 1.14, however no changes have been made that would make the SDK not work with Go 1.14. The currently supported Go versions are the last 3 stable releases: 1.15, 1.16 and 1.17. +There are two behavior changes related to `LastEventID`, both of which were intended to align the behavior of the Sentry Go SDK with other Sentry SDKs. +The new [automatic release detection feature](https://github.com/getsentry/sentry-go/issues/335) makes it easier to use Sentry and separate events per release without requiring extra work from users. We intend to improve this functionality in a future release by utilizing information that will be available in runtime starting with Go 1.18. The tracking issue is [#401](https://github.com/getsentry/sentry-go/issues/401). + +## v0.11.0 + +- feat(transports): Category-based Rate Limiting ([#354](https://github.com/getsentry/sentry-go/pull/354)) +- feat(transports): Report User-Agent identifying SDK ([#357](https://github.com/getsentry/sentry-go/pull/357)) +- fix(scope): Include event processors in clone ([#349](https://github.com/getsentry/sentry-go/pull/349)) +- Improvements to `go doc` documentation ([#344](https://github.com/getsentry/sentry-go/pull/344), [#350](https://github.com/getsentry/sentry-go/pull/350), [#351](https://github.com/getsentry/sentry-go/pull/351)) +- Miscellaneous changes to our testing infrastructure with GitHub Actions + ([57123a40](https://github.com/getsentry/sentry-go/commit/57123a409be55f61b1d5a6da93c176c55a399ad0), [#128](https://github.com/getsentry/sentry-go/pull/128), [#338](https://github.com/getsentry/sentry-go/pull/338), [#345](https://github.com/getsentry/sentry-go/pull/345), [#346](https://github.com/getsentry/sentry-go/pull/346), [#352](https://github.com/getsentry/sentry-go/pull/352), [#353](https://github.com/getsentry/sentry-go/pull/353), [#355](https://github.com/getsentry/sentry-go/pull/355)) + +_NOTE:_ +This version drops support for Go 1.13. The currently supported Go versions are the last 3 stable releases: 1.14, 1.15 and 1.16. +Users of the tracing functionality (`StartSpan`, etc) should upgrade to this version to benefit from separate rate limits for errors and transactions. +There are no breaking changes and upgrading should be a smooth experience for all users. + +## v0.10.0 + +- feat: Debug connection reuse (#323) +- fix: Send root span data as `Event.Extra` (#329) +- fix: Do not double sample transactions (#328) +- fix: Do not override trace context of transactions (#327) +- fix: Drain and close API response bodies (#322) +- ci: Run tests against Go tip (#319) +- ci: Move away from Travis in favor of GitHub Actions (#314) (#321) + +## v0.9.0 + +- feat: Initial tracing and performance monitoring support (#285) +- doc: Revamp sentryhttp documentation (#304) +- fix: Hub.PopScope never empties the scope stack (#300) +- ref: Report Event.Timestamp in local time (#299) +- ref: Report Breadcrumb.Timestamp in local time (#299) + +_NOTE:_ +This version introduces support for [Sentry's Performance Monitoring](https://docs.sentry.io/platforms/go/performance/). +The new tracing capabilities are beta, and we plan to expand them on future versions. Feedback is welcome, please open new issues on GitHub. +The `sentryhttp` package got better API docs, an [updated usage example](https://github.com/getsentry/sentry-go/tree/master/_examples/http) and support for creating automatic transactions as part of Performance Monitoring. + +## v0.8.0 + +- build: Bump required version of Iris (#296) +- fix: avoid unnecessary allocation in Client.processEvent (#293) +- doc: Remove deprecation of sentryhttp.HandleFunc (#284) +- ref: Update sentryhttp example (#283) +- doc: Improve documentation of sentryhttp package (#282) +- doc: Clarify SampleRate documentation (#279) +- fix: Remove RawStacktrace (#278) +- docs: Add example of custom HTTP transport +- ci: Test against go1.15, drop go1.12 support (#271) + +_NOTE:_ +This version comes with a few updates. Some examples and documentation have been +improved. We've bumped the supported version of the Iris framework to avoid +LGPL-licensed modules in the module dependency graph. +The `Exception.RawStacktrace` and `Thread.RawStacktrace` fields have been +removed to conform to Sentry's ingestion protocol, only `Exception.Stacktrace` +and `Thread.Stacktrace` should appear in user code. + +## v0.7.0 + +- feat: Include original error when event cannot be encoded as JSON (#258) +- feat: Use Hub from request context when available (#217, #259) +- feat: Extract stack frames from golang.org/x/xerrors (#262) +- feat: Make Environment Integration preserve existing context data (#261) +- feat: Recover and RecoverWithContext with arbitrary types (#268) +- feat: Report bad usage of CaptureMessage and CaptureEvent (#269) +- feat: Send debug logging to stderr by default (#266) +- feat: Several improvements to documentation (#223, #245, #250, #265) +- feat: Example of Recover followed by panic (#241, #247) +- feat: Add Transactions and Spans (to support OpenTelemetry Sentry Exporter) (#235, #243, #254) +- fix: Set either Frame.Filename or Frame.AbsPath (#233) +- fix: Clone requestBody to new Scope (#244) +- fix: Synchronize access and mutation of Hub.lastEventID (#264) +- fix: Avoid repeated syscalls in prepareEvent (#256) +- fix: Do not allocate new RNG for every event (#256) +- fix: Remove stale replace directive in go.mod (#255) +- fix(http): Deprecate HandleFunc, remove duplication (#260) + +_NOTE:_ +This version comes packed with several fixes and improvements and no breaking +changes. +Notably, there is a change in how the SDK reports file names in stack traces +that should resolve any ambiguity when looking at stack traces and using the +Suspect Commits feature. +We recommend all users to upgrade. + +## v0.6.1 + +- fix: Use NewEvent to init Event struct (#220) + +_NOTE:_ +A change introduced in v0.6.0 with the intent of avoiding allocations made a +pattern used in official examples break in certain circumstances (attempting +to write to a nil map). +This release reverts the change such that maps in the Event struct are always +allocated. + +## v0.6.0 + +- feat: Read module dependencies from runtime/debug (#199) +- feat: Support chained errors using Unwrap (#206) +- feat: Report chain of errors when available (#185) +- **[breaking]** fix: Accept http.RoundTripper to customize transport (#205) + Before the SDK accepted a concrete value of type `*http.Transport` in + `ClientOptions`, now it accepts any value implementing the `http.RoundTripper` + interface. Note that `*http.Transport` implements `http.RoundTripper`, so most + code bases will continue to work unchanged. + Users of custom transport gain the ability to pass in other implementations of + `http.RoundTripper` and may be able to simplify their code bases. +- fix: Do not panic when scope event processor drops event (#192) +- **[breaking]** fix: Use time.Time for timestamps (#191) + Users of sentry-go typically do not need to manipulate timestamps manually. + For those who do, the field type changed from `int64` to `time.Time`, which + should be more convenient to use. The recommended way to get the current time + is `time.Now().UTC()`. +- fix: Report usage error including stack trace (#189) +- feat: Add Exception.ThreadID field (#183) +- ci: Test against Go 1.14, drop 1.11 (#170) +- feat: Limit reading bytes from request bodies (#168) +- **[breaking]** fix: Rename fasthttp integration package sentryhttp => sentryfasthttp + The current recommendation is to use a named import, in which case existing + code should not require any change: + ```go + package main + + import ( + "fmt" + + "github.com/getsentry/sentry-go" + sentryfasthttp "github.com/getsentry/sentry-go/fasthttp" + "github.com/valyala/fasthttp" + ) + ``` + +_NOTE:_ +This version includes some new features and a few breaking changes, none of +which should pose troubles with upgrading. Most code bases should be able to +upgrade without any changes. + +## v0.5.1 + +- fix: Ignore err.Cause() when it is nil (#160) + +## v0.5.0 + +- fix: Synchronize access to HTTPTransport.disabledUntil (#158) +- docs: Update Flush documentation (#153) +- fix: HTTPTransport.Flush panic and data race (#140) + +_NOTE:_ +This version changes the implementation of the default transport, modifying the +behavior of `sentry.Flush`. The previous behavior was to wait until there were +no buffered events; new concurrent events kept `Flush` from returning. The new +behavior is to wait until the last event prior to the call to `Flush` has been +sent or the timeout; new concurrent events have no effect. The new behavior is +inline with the [Unified API +Guidelines](https://docs.sentry.io/development/sdk-dev/unified-api/). + +We have updated the documentation and examples to clarify that `Flush` is meant +to be called typically only once before program termination, to wait for +in-flight events to be sent to Sentry. Calling `Flush` after every event is not +recommended, as it introduces unnecessary latency to the surrounding function. +Please verify the usage of `sentry.Flush` in your code base. + +## v0.4.0 + +- fix(stacktrace): Correctly report package names (#127) +- fix(stacktrace): Do not rely on AbsPath of files (#123) +- build: Require github.com/ugorji/go@v1.1.7 (#110) +- fix: Correctly store last event id (#99) +- fix: Include request body in event payload (#94) +- build: Reset go.mod version to 1.11 (#109) +- fix: Eliminate data race in modules integration (#105) +- feat: Add support for path prefixes in the DSN (#102) +- feat: Add HTTPClient option (#86) +- feat: Extract correct type and value from top-most error (#85) +- feat: Check for broken pipe errors in Gin integration (#82) +- fix: Client.CaptureMessage accept nil EventModifier (#72) + +## v0.3.1 + +- feat: Send extra information exposed by the Go runtime (#76) +- fix: Handle new lines in module integration (#65) +- fix: Make sure that cache is locked when updating for contextifyFramesIntegration +- ref: Update Iris integration and example to version 12 +- misc: Remove indirect dependencies in order to move them to separate go.mod files + +## v0.3.0 + +- feat: Retry event marshaling without contextual data if the first pass fails +- fix: Include `url.Parse` error in `DsnParseError` +- fix: Make more `Scope` methods safe for concurrency +- fix: Synchronize concurrent access to `Hub.client` +- ref: Remove mutex from `Scope` exported API +- ref: Remove mutex from `Hub` exported API +- ref: Compile regexps for `filterFrames` only once +- ref: Change `SampleRate` type to `float64` +- doc: `Scope.Clear` not safe for concurrent use +- ci: Test sentry-go with `go1.13`, drop `go1.10` + +_NOTE:_ +This version removes some of the internal APIs that landed publicly (namely `Hub/Scope` mutex structs) and may require (but shouldn't) some changes to your code. +It's not done through major version update, as we are still in `0.x` stage. + +## v0.2.1 + +- fix: Run `Contextify` integration on `Threads` as well + +## v0.2.0 + +- feat: Add `SetTransaction()` method on the `Scope` +- feat: `fasthttp` framework support with `sentryfasthttp` package +- fix: Add `RWMutex` locks to internal `Hub` and `Scope` changes + +## v0.1.3 + +- feat: Move frames context reading into `contextifyFramesIntegration` (#28) + +_NOTE:_ +In case of any performance issues due to source contexts IO, you can let us know and turn off the integration in the meantime with: + +```go +sentry.Init(sentry.ClientOptions{ + Integrations: func(integrations []sentry.Integration) []sentry.Integration { + var filteredIntegrations []sentry.Integration + for _, integration := range integrations { + if integration.Name() == "ContextifyFrames" { + continue + } + filteredIntegrations = append(filteredIntegrations, integration) + } + return filteredIntegrations + }, +}) +``` + +## v0.1.2 + +- feat: Better source code location resolution and more useful inapp frames (#26) +- feat: Use `noopTransport` when no `Dsn` provided (#27) +- ref: Allow empty `Dsn` instead of returning an error (#22) +- fix: Use `NewScope` instead of literal struct inside a `scope.Clear` call (#24) +- fix: Add to `WaitGroup` before the request is put inside a buffer (#25) + +## v0.1.1 + +- fix: Check for initialized `Client` in `AddBreadcrumbs` (#20) +- build: Bump version when releasing with Craft (#19) + +## v0.1.0 + +- First stable release! \o/ + +## v0.0.1-beta.5 + +- feat: **[breaking]** Add `NewHTTPTransport` and `NewHTTPSyncTransport` which accepts all transport options +- feat: New `HTTPSyncTransport` that blocks after each call +- feat: New `Echo` integration +- ref: **[breaking]** Remove `BufferSize` option from `ClientOptions` and move it to `HTTPTransport` instead +- ref: Export default `HTTPTransport` +- ref: Export `net/http` integration handler +- ref: Set `Request` instantly in the package handlers, not in `recoverWithSentry` so it can be accessed later on +- ci: Add craft config + +## v0.0.1-beta.4 + +- feat: `IgnoreErrors` client option and corresponding integration +- ref: Reworked `net/http` integration, wrote better example and complete readme +- ref: Reworked `Gin` integration, wrote better example and complete readme +- ref: Reworked `Iris` integration, wrote better example and complete readme +- ref: Reworked `Negroni` integration, wrote better example and complete readme +- ref: Reworked `Martini` integration, wrote better example and complete readme +- ref: Remove `Handle()` from frameworks handlers and return it directly from New + +## v0.0.1-beta.3 + +- feat: `Iris` framework support with `sentryiris` package +- feat: `Gin` framework support with `sentrygin` package +- feat: `Martini` framework support with `sentrymartini` package +- feat: `Negroni` framework support with `sentrynegroni` package +- feat: Add `Hub.Clone()` for easier frameworks integration +- feat: Return `EventID` from `Recovery` methods +- feat: Add `NewScope` and `NewEvent` functions and use them in the whole codebase +- feat: Add `AddEventProcessor` to the `Client` +- fix: Operate on requests body copy instead of the original +- ref: Try to read source files from the root directory, based on the filename as well, to make it work on AWS Lambda +- ref: Remove `gocertifi` dependence and document how to provide your own certificates +- ref: **[breaking]** Remove `Decorate` and `DecorateFunc` methods in favor of `sentryhttp` package +- ref: **[breaking]** Allow for integrations to live on the client, by passing client instance in `SetupOnce` method +- ref: **[breaking]** Remove `GetIntegration` from the `Hub` +- ref: **[breaking]** Remove `GlobalEventProcessors` getter from the public API + +## v0.0.1-beta.2 + +- feat: Add `AttachStacktrace` client option to include stacktrace for messages +- feat: Add `BufferSize` client option to configure transport buffer size +- feat: Add `SetRequest` method on a `Scope` to control `Request` context data +- feat: Add `FromHTTPRequest` for `Request` type for easier extraction +- ref: Extract `Request` information more accurately +- fix: Attach `ServerName`, `Release`, `Dist`, `Environment` options to the event +- fix: Don't log events dropped due to full transport buffer as sent +- fix: Don't panic and create an appropriate event when called `CaptureException` or `Recover` with `nil` value + +## v0.0.1-beta + +- Initial release diff --git a/vendor/github.com/getsentry/sentry-go/CONTRIBUTING.md b/vendor/github.com/getsentry/sentry-go/CONTRIBUTING.md new file mode 100644 index 000000000..9808f1862 --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/CONTRIBUTING.md @@ -0,0 +1,98 @@ +# Contributing to sentry-go + +Hey, thank you if you're reading this, we welcome your contribution! + +## Sending a Pull Request + +Please help us save time when reviewing your PR by following this simple +process: + +1. Is your PR a simple typo fix? Read no further, **click that green "Create + pull request" button**! + +2. For more complex PRs that involve behavior changes or new APIs, please + consider [opening an **issue**][new-issue] describing the problem you're + trying to solve if there's not one already. + + A PR is often one specific solution to a problem and sometimes talking about + the problem unfolds new possible solutions. Remember we will be responsible + for maintaining the changes later. + +3. Fixing a bug and changing a behavior? Please add automated tests to prevent + future regression. + +4. Practice writing good commit messages. We have [commit + guidelines][commit-guide]. + +5. We have [guidelines for PR submitters][pr-guide]. A short summary: + + - Good PR descriptions are very helpful and most of the time they include + **why** something is done and why done in this particular way. Also list + other possible solutions that were considered and discarded. + - Be your own first reviewer. Make sure your code compiles and passes the + existing tests. + +[new-issue]: https://github.com/getsentry/sentry-go/issues/new/choose +[commit-guide]: https://develop.sentry.dev/code-review/#commit-guidelines +[pr-guide]: https://develop.sentry.dev/code-review/#guidelines-for-submitters + +Please also read through our [SDK Development docs](https://develop.sentry.dev/sdk/). +It contains information about SDK features, expected payloads and best practices for +contributing to Sentry SDKs. + +## Community + +The public-facing channels for support and development of Sentry SDKs can be found on [Discord](https://discord.gg/Ww9hbqr). + +## Testing + +```console +$ go test +``` + +### Watch mode + +Use: https://github.com/cespare/reflex + +```console +$ reflex -g '*.go' -d "none" -- sh -c 'printf "\n"; go test' +``` + +### With data race detection + +```console +$ go test -race +``` + +### Coverage + +```console +$ go test -race -coverprofile=coverage.txt -covermode=atomic && go tool cover -html coverage.txt +``` + +## Linting + +Lint with [`golangci-lint`](https://github.com/golangci/golangci-lint): + +```console +$ golangci-lint run +``` + +## Release + +1. Update `CHANGELOG.md` with new version in `vX.X.X` format title and list of changes. + + The command below can be used to get a list of changes since the last tag, with the format used in `CHANGELOG.md`: + + ```console + $ git log --no-merges --format=%s $(git describe --abbrev=0).. | sed 's/^/- /' + ``` + +2. Commit with `misc: vX.X.X changelog` commit message and push to `master`. + +3. Let [`craft`](https://github.com/getsentry/craft) do the rest: + + ```console + $ craft prepare X.X.X + $ craft publish X.X.X + ``` diff --git a/vendor/github.com/cockroachdb/sentry-go/LICENSE b/vendor/github.com/getsentry/sentry-go/LICENSE similarity index 100% rename from vendor/github.com/cockroachdb/sentry-go/LICENSE rename to vendor/github.com/getsentry/sentry-go/LICENSE diff --git a/vendor/github.com/getsentry/sentry-go/MIGRATION.md b/vendor/github.com/getsentry/sentry-go/MIGRATION.md new file mode 100644 index 000000000..2c30d6288 --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/MIGRATION.md @@ -0,0 +1,3 @@ +# `raven-go` to `sentry-go` Migration Guide + +A [`raven-go` to `sentry-go` migration guide](https://docs.sentry.io/platforms/go/migration/) is available at the official Sentry documentation site. diff --git a/vendor/github.com/getsentry/sentry-go/Makefile b/vendor/github.com/getsentry/sentry-go/Makefile new file mode 100644 index 000000000..087ab24f9 --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/Makefile @@ -0,0 +1,63 @@ +.DEFAULT_GOAL := help + +MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) +MKFILE_DIR := $(dir $(MKFILE_PATH)) +ALL_GO_MOD_DIRS := $(shell find . -type f -name 'go.mod' -exec dirname {} \; | sort) +GO = go +TIMEOUT = 300 + +# Parse Makefile and display the help +help: ## Show help + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' +.PHONY: help + +build: ## Build everything + go build ./... +.PHONY: build + +### Tests (inspired by https://github.com/open-telemetry/opentelemetry-go/blob/main/Makefile) +TEST_TARGETS := test-short test-verbose test-race +test-race: ARGS=-race +test-short: ARGS=-short +test-verbose: ARGS=-v -race +$(TEST_TARGETS): test +test: $(ALL_GO_MOD_DIRS:%=test/%) ## Run tests +test/%: DIR=$* +test/%: + @echo ">>> Running tests for module: $(DIR)" + @# We use '-count=1' to disable test caching. + (cd $(DIR) && $(GO) test -count=1 -timeout $(TIMEOUT)s $(ARGS) ./...) +.PHONY: $(TEST_TARGETS) test + +# Coverage +COVERAGE_MODE = atomic +COVERAGE_PROFILE = coverage.out +COVERAGE_REPORT_DIR = .coverage +COVERAGE_REPORT_DIR_ABS = "$(MKFILE_DIR)/$(COVERAGE_REPORT_DIR)" +$(COVERAGE_REPORT_DIR): + mkdir -p $(COVERAGE_REPORT_DIR) +clean-report-dir: $(COVERAGE_REPORT_DIR) + test $(COVERAGE_REPORT_DIR) && rm -f $(COVERAGE_REPORT_DIR)/* +test-coverage: $(COVERAGE_REPORT_DIR) clean-report-dir ## Test with coverage enabled + for dir in $(ALL_GO_MOD_DIRS); do \ + echo ">>> Running tests with coverage for module: $${dir}"; \ + DIR_ABS=$$(python -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' $${dir}) ; \ + REPORT_NAME=$$(basename $${DIR_ABS}); \ + (cd "$${dir}" && \ + $(GO) test -count=1 -coverpkg=./... -covermode=$(COVERAGE_MODE) -coverprofile="$(COVERAGE_PROFILE)" ./... && \ + cp $(COVERAGE_PROFILE) "$(COVERAGE_REPORT_DIR_ABS)/$${REPORT_NAME}_$(COVERAGE_PROFILE)" && \ + $(GO) tool cover -html=$(COVERAGE_PROFILE) -o coverage.html); \ + done; +.PHONY: test-coverage clean-report-dir + +vet: ## Run "go vet" + go vet ./... +.PHONY: vet + +lint: ## Lint (using "golangci-lint") + golangci-lint run +.PHONY: lint + +fmt: ## Format all Go files + gofmt -l -w -s . +.PHONY: fmt diff --git a/vendor/github.com/getsentry/sentry-go/README.md b/vendor/github.com/getsentry/sentry-go/README.md new file mode 100644 index 000000000..451959f39 --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/README.md @@ -0,0 +1,105 @@ +

+ + + + + Sentry + + +

+ +# Official Sentry SDK for Go + +[![Build Status](https://github.com/getsentry/sentry-go/workflows/go-workflow/badge.svg)](https://github.com/getsentry/sentry-go/actions?query=workflow%3Ago-workflow) +[![Go Report Card](https://goreportcard.com/badge/github.com/getsentry/sentry-go)](https://goreportcard.com/report/github.com/getsentry/sentry-go) +[![Discord](https://img.shields.io/discord/621778831602221064)](https://discord.gg/Ww9hbqr) +[![GoDoc](https://godoc.org/github.com/getsentry/sentry-go?status.svg)](https://godoc.org/github.com/getsentry/sentry-go) +[![go.dev](https://img.shields.io/badge/go.dev-pkg-007d9c.svg?style=flat)](https://pkg.go.dev/github.com/getsentry/sentry-go) + +`sentry-go` provides a Sentry client implementation for the Go programming +language. This is the next generation of the Go SDK for [Sentry](https://sentry.io/), +intended to replace the `raven-go` package. + +> Looking for the old `raven-go` SDK documentation? See the Legacy client section [here](https://docs.sentry.io/clients/go/). +> If you want to start using `sentry-go` instead, check out the [migration guide](https://docs.sentry.io/platforms/go/migration/). + +## Requirements + +The only requirement is a Go compiler. + +We verify this package against the 3 most recent releases of Go. Those are the +supported versions. The exact versions are defined in +[`GitHub workflow`](.github/workflows/test.yml). + +In addition, we run tests against the current master branch of the Go toolchain, +though support for this configuration is best-effort. + +## Installation + +`sentry-go` can be installed like any other Go library through `go get`: + +```console +$ go get github.com/getsentry/sentry-go@latest +``` + +Check out the [list of released versions](https://github.com/getsentry/sentry-go/releases). + +## Configuration + +To use `sentry-go`, you’ll need to import the `sentry-go` package and initialize +it with your DSN and other [options](https://pkg.go.dev/github.com/getsentry/sentry-go#ClientOptions). + +If not specified in the SDK initialization, the +[DSN](https://docs.sentry.io/product/sentry-basics/dsn-explainer/), +[Release](https://docs.sentry.io/product/releases/) and +[Environment](https://docs.sentry.io/product/sentry-basics/environments/) +are read from the environment variables `SENTRY_DSN`, `SENTRY_RELEASE` and +`SENTRY_ENVIRONMENT`, respectively. + +More on this in the [Configuration section of the official Sentry Go SDK documentation](https://docs.sentry.io/platforms/go/configuration/). + +## Usage + +The SDK supports reporting errors and tracking application performance. + +To get started, have a look at one of our [examples](_examples/): +- [Basic error instrumentation](_examples/basic/main.go) +- [Error and tracing for HTTP servers](_examples/http/main.go) + +We also provide a [complete API reference](https://pkg.go.dev/github.com/getsentry/sentry-go). + +For more detailed information about how to get the most out of `sentry-go`, +checkout the official documentation: + +- [Sentry Go SDK documentation](https://docs.sentry.io/platforms/go/) +- Guides: + - [net/http](https://docs.sentry.io/platforms/go/guides/http/) + - [echo](https://docs.sentry.io/platforms/go/guides/echo/) + - [fasthttp](https://docs.sentry.io/platforms/go/guides/fasthttp/) + - [gin](https://docs.sentry.io/platforms/go/guides/gin/) + - [iris](https://docs.sentry.io/platforms/go/guides/iris/) + - [martini](https://docs.sentry.io/platforms/go/guides/martini/) + - [negroni](https://docs.sentry.io/platforms/go/guides/negroni/) + +## Resources + +- [Bug Tracker](https://github.com/getsentry/sentry-go/issues) +- [GitHub Project](https://github.com/getsentry/sentry-go) +- [![GoDoc](https://godoc.org/github.com/getsentry/sentry-go?status.svg)](https://godoc.org/github.com/getsentry/sentry-go) +- [![go.dev](https://img.shields.io/badge/go.dev-pkg-007d9c.svg?style=flat)](https://pkg.go.dev/github.com/getsentry/sentry-go) +- [![Documentation](https://img.shields.io/badge/documentation-sentry.io-green.svg)](https://docs.sentry.io/platforms/go/) +- [![Discussions](https://img.shields.io/github/discussions/getsentry/sentry-go.svg)](https://github.com/getsentry/sentry-go/discussions) +- [![Discord](https://img.shields.io/discord/621778831602221064)](https://discord.gg/Ww9hbqr) +- [![Stack Overflow](https://img.shields.io/badge/stack%20overflow-sentry-green.svg)](http://stackoverflow.com/questions/tagged/sentry) +- [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry) + +## License + +Licensed under +[The 2-Clause BSD License](https://opensource.org/licenses/BSD-2-Clause), see +[`LICENSE`](LICENSE). + +## Community + +Join Sentry's [`#go` channel on Discord](https://discord.gg/Ww9hbqr) to get +involved and help us improve the SDK! diff --git a/vendor/github.com/getsentry/sentry-go/client.go b/vendor/github.com/getsentry/sentry-go/client.go new file mode 100644 index 000000000..49e2cd5ff --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/client.go @@ -0,0 +1,691 @@ +package sentry + +import ( + "context" + "crypto/x509" + "fmt" + "io" + "log" + "math/rand" + "net/http" + "os" + "reflect" + "sort" + "strings" + "sync" + "time" + + "github.com/getsentry/sentry-go/internal/debug" +) + +// maxErrorDepth is the maximum number of errors reported in a chain of errors. +// This protects the SDK from an arbitrarily long chain of wrapped errors. +// +// An additional consideration is that arguably reporting a long chain of errors +// is of little use when debugging production errors with Sentry. The Sentry UI +// is not optimized for long chains either. The top-level error together with a +// stack trace is often the most useful information. +const maxErrorDepth = 10 + +// defaultMaxSpans limits the default number of recorded spans per transaction. The limit is +// meant to bound memory usage and prevent too large transaction events that +// would be rejected by Sentry. +const defaultMaxSpans = 1000 + +// hostname is the host name reported by the kernel. It is precomputed once to +// avoid syscalls when capturing events. +// +// The error is ignored because retrieving the host name is best-effort. If the +// error is non-nil, there is nothing to do other than retrying. We choose not +// to retry for now. +var hostname, _ = os.Hostname() + +// lockedRand is a random number generator safe for concurrent use. Its API is +// intentionally limited and it is not meant as a full replacement for a +// rand.Rand. +type lockedRand struct { + mu sync.Mutex + r *rand.Rand +} + +// Float64 returns a pseudo-random number in [0.0,1.0). +func (r *lockedRand) Float64() float64 { + r.mu.Lock() + defer r.mu.Unlock() + return r.r.Float64() +} + +// rng is the internal random number generator. +// +// We do not use the global functions from math/rand because, while they are +// safe for concurrent use, any package in a build could change the seed and +// affect the generated numbers, for instance making them deterministic. On the +// other hand, the source returned from rand.NewSource is not safe for +// concurrent use, so we need to couple its use with a sync.Mutex. +var rng = &lockedRand{ + // #nosec G404 -- We are fine using transparent, non-secure value here. + r: rand.New(rand.NewSource(time.Now().UnixNano())), +} + +// usageError is used to report to Sentry an SDK usage error. +// +// It is not exported because it is never returned by any function or method in +// the exported API. +type usageError struct { + error +} + +// Logger is an instance of log.Logger that is use to provide debug information about running Sentry Client +// can be enabled by either using Logger.SetOutput directly or with Debug client option. +var Logger = log.New(io.Discard, "[Sentry] ", log.LstdFlags) + +// EventProcessor is a function that processes an event. +// Event processors are used to change an event before it is sent to Sentry. +type EventProcessor func(event *Event, hint *EventHint) *Event + +// EventModifier is the interface that wraps the ApplyToEvent method. +// +// ApplyToEvent changes an event based on external data and/or +// an event hint. +type EventModifier interface { + ApplyToEvent(event *Event, hint *EventHint) *Event +} + +var globalEventProcessors []EventProcessor + +// AddGlobalEventProcessor adds processor to the global list of event +// processors. Global event processors apply to all events. +// +// AddGlobalEventProcessor is deprecated. Most users will prefer to initialize +// the SDK with Init and provide a ClientOptions.BeforeSend function or use +// Scope.AddEventProcessor instead. +func AddGlobalEventProcessor(processor EventProcessor) { + globalEventProcessors = append(globalEventProcessors, processor) +} + +// Integration allows for registering a functions that modify or discard captured events. +type Integration interface { + Name() string + SetupOnce(client *Client) +} + +// ClientOptions that configures a SDK Client. +type ClientOptions struct { + // The DSN to use. If the DSN is not set, the client is effectively + // disabled. + Dsn string + // In debug mode, the debug information is printed to stdout to help you + // understand what sentry is doing. + Debug bool + // Configures whether SDK should generate and attach stacktraces to pure + // capture message calls. + AttachStacktrace bool + // The sample rate for event submission in the range [0.0, 1.0]. By default, + // all events are sent. Thus, as a historical special case, the sample rate + // 0.0 is treated as if it was 1.0. To drop all events, set the DSN to the + // empty string. + SampleRate float64 + // Enable performance tracing. + EnableTracing bool + // The sample rate for sampling traces in the range [0.0, 1.0]. + TracesSampleRate float64 + // Used to customize the sampling of traces, overrides TracesSampleRate. + TracesSampler TracesSampler + // List of regexp strings that will be used to match against event's message + // and if applicable, caught errors type and value. + // If the match is found, then a whole event will be dropped. + IgnoreErrors []string + // If this flag is enabled, certain personally identifiable information (PII) is added by active integrations. + // By default, no such data is sent. + SendDefaultPII bool + // BeforeSend is called before error events are sent to Sentry. + // Use it to mutate the event or return nil to discard the event. + BeforeSend func(event *Event, hint *EventHint) *Event + // BeforeSendTransaction is called before transaction events are sent to Sentry. + // Use it to mutate the transaction or return nil to discard the transaction. + BeforeSendTransaction func(event *Event, hint *EventHint) *Event + // Before breadcrumb add callback. + BeforeBreadcrumb func(breadcrumb *Breadcrumb, hint *BreadcrumbHint) *Breadcrumb + // Integrations to be installed on the current Client, receives default + // integrations. + Integrations func([]Integration) []Integration + // io.Writer implementation that should be used with the Debug mode. + DebugWriter io.Writer + // The transport to use. Defaults to HTTPTransport. + Transport Transport + // The server name to be reported. + ServerName string + // The release to be sent with events. + // + // Some Sentry features are built around releases, and, thus, reporting + // events with a non-empty release improves the product experience. See + // https://docs.sentry.io/product/releases/. + // + // If Release is not set, the SDK will try to derive a default value + // from environment variables or the Git repository in the working + // directory. + // + // If you distribute a compiled binary, it is recommended to set the + // Release value explicitly at build time. As an example, you can use: + // + // go build -ldflags='-X main.release=VALUE' + // + // That will set the value of a predeclared variable 'release' in the + // 'main' package to 'VALUE'. Then, use that variable when initializing + // the SDK: + // + // sentry.Init(ClientOptions{Release: release}) + // + // See https://golang.org/cmd/go/ and https://golang.org/cmd/link/ for + // the official documentation of -ldflags and -X, respectively. + Release string + // The dist to be sent with events. + Dist string + // The environment to be sent with events. + Environment string + // Maximum number of breadcrumbs + // when MaxBreadcrumbs is negative then ignore breadcrumbs. + MaxBreadcrumbs int + // Maximum number of spans. + // + // See https://develop.sentry.dev/sdk/envelopes/#size-limits for size limits + // applied during event ingestion. Events that exceed these limits might get dropped. + MaxSpans int + // An optional pointer to http.Client that will be used with a default + // HTTPTransport. Using your own client will make HTTPTransport, HTTPProxy, + // HTTPSProxy and CaCerts options ignored. + HTTPClient *http.Client + // An optional pointer to http.Transport that will be used with a default + // HTTPTransport. Using your own transport will make HTTPProxy, HTTPSProxy + // and CaCerts options ignored. + HTTPTransport http.RoundTripper + // An optional HTTP proxy to use. + // This will default to the HTTP_PROXY environment variable. + HTTPProxy string + // An optional HTTPS proxy to use. + // This will default to the HTTPS_PROXY environment variable. + // HTTPS_PROXY takes precedence over HTTP_PROXY for https requests. + HTTPSProxy string + // An optional set of SSL certificates to use. + CaCerts *x509.CertPool + // MaxErrorDepth is the maximum number of errors reported in a chain of errors. + // This protects the SDK from an arbitrarily long chain of wrapped errors. + // + // An additional consideration is that arguably reporting a long chain of errors + // is of little use when debugging production errors with Sentry. The Sentry UI + // is not optimized for long chains either. The top-level error together with a + // stack trace is often the most useful information. + MaxErrorDepth int +} + +// Client is the underlying processor that is used by the main API and Hub +// instances. It must be created with NewClient. +type Client struct { + options ClientOptions + dsn *Dsn + eventProcessors []EventProcessor + integrations []Integration + // Transport is read-only. Replacing the transport of an existing client is + // not supported, create a new client instead. + Transport Transport +} + +// NewClient creates and returns an instance of Client configured using +// ClientOptions. +// +// Most users will not create clients directly. Instead, initialize the SDK with +// Init and use the package-level functions (for simple programs that run on a +// single goroutine) or hub methods (for concurrent programs, for example web +// servers). +func NewClient(options ClientOptions) (*Client, error) { + if options.Debug { + debugWriter := options.DebugWriter + if debugWriter == nil { + debugWriter = os.Stderr + } + Logger.SetOutput(debugWriter) + } + + if options.Dsn == "" { + options.Dsn = os.Getenv("SENTRY_DSN") + } + + if options.Release == "" { + options.Release = defaultRelease() + } + + if options.Environment == "" { + options.Environment = os.Getenv("SENTRY_ENVIRONMENT") + } + + if options.MaxErrorDepth == 0 { + options.MaxErrorDepth = maxErrorDepth + } + + if options.MaxSpans == 0 { + options.MaxSpans = defaultMaxSpans + } + + // SENTRYGODEBUG is a comma-separated list of key=value pairs (similar + // to GODEBUG). It is not a supported feature: recognized debug options + // may change any time. + // + // The intended public is SDK developers. It is orthogonal to + // options.Debug, which is also available for SDK users. + dbg := strings.Split(os.Getenv("SENTRYGODEBUG"), ",") + sort.Strings(dbg) + // dbgOpt returns true when the given debug option is enabled, for + // example SENTRYGODEBUG=someopt=1. + dbgOpt := func(opt string) bool { + s := opt + "=1" + return dbg[sort.SearchStrings(dbg, s)%len(dbg)] == s + } + if dbgOpt("httpdump") || dbgOpt("httptrace") { + options.HTTPTransport = &debug.Transport{ + RoundTripper: http.DefaultTransport, + Output: os.Stderr, + Dump: dbgOpt("httpdump"), + Trace: dbgOpt("httptrace"), + } + } + + var dsn *Dsn + if options.Dsn != "" { + var err error + dsn, err = NewDsn(options.Dsn) + if err != nil { + return nil, err + } + } + + client := Client{ + options: options, + dsn: dsn, + } + + client.setupTransport() + client.setupIntegrations() + + return &client, nil +} + +func (client *Client) setupTransport() { + opts := client.options + transport := opts.Transport + + if transport == nil { + if opts.Dsn == "" { + transport = new(noopTransport) + } else { + httpTransport := NewHTTPTransport() + // When tracing is enabled, use larger buffer to + // accommodate more concurrent events. + // TODO(tracing): consider using separate buffers per + // event type. + if opts.EnableTracing { + httpTransport.BufferSize = 1000 + } + transport = httpTransport + } + } + + transport.Configure(opts) + client.Transport = transport +} + +func (client *Client) setupIntegrations() { + integrations := []Integration{ + new(contextifyFramesIntegration), + new(environmentIntegration), + new(modulesIntegration), + new(ignoreErrorsIntegration), + } + + if client.options.Integrations != nil { + integrations = client.options.Integrations(integrations) + } + + for _, integration := range integrations { + if client.integrationAlreadyInstalled(integration.Name()) { + Logger.Printf("Integration %s is already installed\n", integration.Name()) + continue + } + client.integrations = append(client.integrations, integration) + integration.SetupOnce(client) + Logger.Printf("Integration installed: %s\n", integration.Name()) + } + + sort.Slice(client.integrations, func(i, j int) bool { + return client.integrations[i].Name() < client.integrations[j].Name() + }) +} + +// AddEventProcessor adds an event processor to the client. It must not be +// called from concurrent goroutines. Most users will prefer to use +// ClientOptions.BeforeSend or Scope.AddEventProcessor instead. +// +// Note that typical programs have only a single client created by Init and the +// client is shared among multiple hubs, one per goroutine, such that adding an +// event processor to the client affects all hubs that share the client. +func (client *Client) AddEventProcessor(processor EventProcessor) { + client.eventProcessors = append(client.eventProcessors, processor) +} + +// Options return ClientOptions for the current Client. +func (client Client) Options() ClientOptions { + return client.options +} + +// CaptureMessage captures an arbitrary message. +func (client *Client) CaptureMessage(message string, hint *EventHint, scope EventModifier) *EventID { + event := client.eventFromMessage(message, LevelInfo) + return client.CaptureEvent(event, hint, scope) +} + +// CaptureException captures an error. +func (client *Client) CaptureException(exception error, hint *EventHint, scope EventModifier) *EventID { + event := client.eventFromException(exception, LevelError) + return client.CaptureEvent(event, hint, scope) +} + +// CaptureEvent captures an event on the currently active client if any. +// +// The event must already be assembled. Typically code would instead use +// the utility methods like CaptureException. The return value is the +// event ID. In case Sentry is disabled or event was dropped, the return value will be nil. +func (client *Client) CaptureEvent(event *Event, hint *EventHint, scope EventModifier) *EventID { + return client.processEvent(event, hint, scope) +} + +// Recover captures a panic. +// Returns EventID if successfully, or nil if there's no error to recover from. +func (client *Client) Recover(err interface{}, hint *EventHint, scope EventModifier) *EventID { + if err == nil { + err = recover() + } + + // Normally we would not pass a nil Context, but RecoverWithContext doesn't + // use the Context for communicating deadline nor cancelation. All it does + // is store the Context in the EventHint and there nil means the Context is + // not available. + // nolint: staticcheck + return client.RecoverWithContext(nil, err, hint, scope) +} + +// RecoverWithContext captures a panic and passes relevant context object. +// Returns EventID if successfully, or nil if there's no error to recover from. +func (client *Client) RecoverWithContext( + ctx context.Context, + err interface{}, + hint *EventHint, + scope EventModifier, +) *EventID { + if err == nil { + err = recover() + } + if err == nil { + return nil + } + + if ctx != nil { + if hint == nil { + hint = &EventHint{} + } + if hint.Context == nil { + hint.Context = ctx + } + } + + var event *Event + switch err := err.(type) { + case error: + event = client.eventFromException(err, LevelFatal) + case string: + event = client.eventFromMessage(err, LevelFatal) + default: + event = client.eventFromMessage(fmt.Sprintf("%#v", err), LevelFatal) + } + return client.CaptureEvent(event, hint, scope) +} + +// Flush waits until the underlying Transport sends any buffered events to the +// Sentry server, blocking for at most the given timeout. It returns false if +// the timeout was reached. In that case, some events may not have been sent. +// +// Flush should be called before terminating the program to avoid +// unintentionally dropping events. +// +// Do not call Flush indiscriminately after every call to CaptureEvent, +// CaptureException or CaptureMessage. Instead, to have the SDK send events over +// the network synchronously, configure it to use the HTTPSyncTransport in the +// call to Init. +func (client *Client) Flush(timeout time.Duration) bool { + return client.Transport.Flush(timeout) +} + +func (client *Client) eventFromMessage(message string, level Level) *Event { + if message == "" { + err := usageError{fmt.Errorf("%s called with empty message", callerFunctionName())} + return client.eventFromException(err, level) + } + event := NewEvent() + event.Level = level + event.Message = message + + if client.Options().AttachStacktrace { + event.Threads = []Thread{{ + Stacktrace: NewStacktrace(), + Crashed: false, + Current: true, + }} + } + + return event +} + +func (client *Client) eventFromException(exception error, level Level) *Event { + err := exception + if err == nil { + err = usageError{fmt.Errorf("%s called with nil error", callerFunctionName())} + } + + event := NewEvent() + event.Level = level + + for i := 0; i < client.options.MaxErrorDepth && err != nil; i++ { + event.Exception = append(event.Exception, Exception{ + Value: err.Error(), + Type: reflect.TypeOf(err).String(), + Stacktrace: ExtractStacktrace(err), + }) + switch previous := err.(type) { + case interface{ Unwrap() error }: + err = previous.Unwrap() + case interface{ Cause() error }: + err = previous.Cause() + default: + err = nil + } + } + + // Add a trace of the current stack to the most recent error in a chain if + // it doesn't have a stack trace yet. + // We only add to the most recent error to avoid duplication and because the + // current stack is most likely unrelated to errors deeper in the chain. + if event.Exception[0].Stacktrace == nil { + event.Exception[0].Stacktrace = NewStacktrace() + } + + // event.Exception should be sorted such that the most recent error is last. + reverse(event.Exception) + + return event +} + +// reverse reverses the slice a in place. +func reverse(a []Exception) { + for i := len(a)/2 - 1; i >= 0; i-- { + opp := len(a) - 1 - i + a[i], a[opp] = a[opp], a[i] + } +} + +func (client *Client) processEvent(event *Event, hint *EventHint, scope EventModifier) *EventID { + if event == nil { + err := usageError{fmt.Errorf("%s called with nil event", callerFunctionName())} + return client.CaptureException(err, hint, scope) + } + + options := client.Options() + + // The default error event sample rate for all SDKs is 1.0 (send all). + // + // In Go, the zero value (default) for float64 is 0.0, which means that + // constructing a client with NewClient(ClientOptions{}), or, equivalently, + // initializing the SDK with Init(ClientOptions{}) without an explicit + // SampleRate would drop all events. + // + // To retain the desired default behavior, we exceptionally flip SampleRate + // from 0.0 to 1.0 here. Setting the sample rate to 0.0 is not very useful + // anyway, and the same end result can be achieved in many other ways like + // not initializing the SDK, setting the DSN to the empty string or using an + // event processor that always returns nil. + // + // An alternative API could be such that default options don't need to be + // the same as Go's zero values, for example using the Functional Options + // pattern. That would either require a breaking change if we want to reuse + // the obvious NewClient name, or a new function as an alternative + // constructor. + if options.SampleRate == 0.0 { + options.SampleRate = 1.0 + } + + // Transactions are sampled by options.TracesSampleRate or + // options.TracesSampler when they are started. All other events + // (errors, messages) are sampled here. + if event.Type != transactionType && !sample(options.SampleRate) { + Logger.Println("Event dropped due to SampleRate hit.") + return nil + } + + if event = client.prepareEvent(event, hint, scope); event == nil { + return nil + } + + // Apply beforeSend* processors + if hint == nil { + hint = &EventHint{} + } + if event.Type == transactionType && options.BeforeSendTransaction != nil { + // Transaction events + if event = options.BeforeSendTransaction(event, hint); event == nil { + Logger.Println("Transaction dropped due to BeforeSendTransaction callback.") + return nil + } + } else if event.Type != transactionType && options.BeforeSend != nil { + // All other events + if event = options.BeforeSend(event, hint); event == nil { + Logger.Println("Event dropped due to BeforeSend callback.") + return nil + } + } + + client.Transport.SendEvent(event) + + return &event.EventID +} + +func (client *Client) prepareEvent(event *Event, hint *EventHint, scope EventModifier) *Event { + if event.EventID == "" { + event.EventID = EventID(uuid()) + } + + if event.Timestamp.IsZero() { + event.Timestamp = time.Now() + } + + if event.Level == "" { + event.Level = LevelInfo + } + + if event.ServerName == "" { + event.ServerName = client.Options().ServerName + + if event.ServerName == "" { + event.ServerName = hostname + } + } + + if event.Release == "" { + event.Release = client.Options().Release + } + + if event.Dist == "" { + event.Dist = client.Options().Dist + } + + if event.Environment == "" { + event.Environment = client.Options().Environment + } + + event.Platform = "go" + event.Sdk = SdkInfo{ + Name: SDKIdentifier, + Version: SDKVersion, + Integrations: client.listIntegrations(), + Packages: []SdkPackage{{ + Name: "sentry-go", + Version: SDKVersion, + }}, + } + + if scope != nil { + event = scope.ApplyToEvent(event, hint) + if event == nil { + return nil + } + } + + for _, processor := range client.eventProcessors { + id := event.EventID + event = processor(event, hint) + if event == nil { + Logger.Printf("Event dropped by one of the Client EventProcessors: %s\n", id) + return nil + } + } + + for _, processor := range globalEventProcessors { + id := event.EventID + event = processor(event, hint) + if event == nil { + Logger.Printf("Event dropped by one of the Global EventProcessors: %s\n", id) + return nil + } + } + + return event +} + +func (client Client) listIntegrations() []string { + integrations := make([]string, len(client.integrations)) + for i, integration := range client.integrations { + integrations[i] = integration.Name() + } + return integrations +} + +func (client Client) integrationAlreadyInstalled(name string) bool { + for _, integration := range client.integrations { + if integration.Name() == name { + return true + } + } + return false +} + +// sample returns true with the given probability, which must be in the range +// [0.0, 1.0]. +func sample(probability float64) bool { + return rng.Float64() < probability +} diff --git a/vendor/github.com/getsentry/sentry-go/doc.go b/vendor/github.com/getsentry/sentry-go/doc.go new file mode 100644 index 000000000..5e6830880 --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/doc.go @@ -0,0 +1,64 @@ +/* +Package sentry is the official Sentry SDK for Go. + +Use it to report errors and track application performance through distributed +tracing. + +For more information about Sentry and SDK features please have a look at the +documentation site https://docs.sentry.io/platforms/go/. + +# Basic Usage + +The first step is to initialize the SDK, providing at a minimum the DSN of your +Sentry project. This step is accomplished through a call to sentry.Init. + + func main() { + err := sentry.Init(...) + ... + } + +A more detailed yet simple example is available at +https://github.com/getsentry/sentry-go/blob/master/_examples/basic/main.go. + +# Error Reporting + +The Capture* functions report messages and errors to Sentry. + + sentry.CaptureMessage(...) + sentry.CaptureException(...) + sentry.CaptureEvent(...) + +Use similarly named functions in the Hub for concurrent programs like web +servers. + +# Performance Monitoring + +You can use Sentry to monitor your application's performance. More information +on the product page https://docs.sentry.io/product/performance/. + +The StartSpan function creates new spans. + + span := sentry.StartSpan(ctx, "operation") + ... + span.Finish() + +# Integrations + +The SDK has support for several Go frameworks, available as subpackages. + +# Getting Support + +For paid Sentry.io accounts, head out to https://sentry.io/support. + +For all users, support channels include: + + Forum: https://forum.sentry.io + Discord: https://discord.gg/Ww9hbqr (#go channel) + +If you found an issue with the SDK, please report through +https://github.com/getsentry/sentry-go/issues/new/choose. + +For responsibly disclosing a security issue, please follow the steps in +https://sentry.io/security/#vulnerability-disclosure. +*/ +package sentry diff --git a/vendor/github.com/cockroachdb/sentry-go/dsn.go b/vendor/github.com/getsentry/sentry-go/dsn.go similarity index 67% rename from vendor/github.com/cockroachdb/sentry-go/dsn.go rename to vendor/github.com/getsentry/sentry-go/dsn.go index 59946845d..141f46468 100644 --- a/vendor/github.com/cockroachdb/sentry-go/dsn.go +++ b/vendor/github.com/getsentry/sentry-go/dsn.go @@ -27,6 +27,8 @@ func (scheme scheme) defaultPort() int { } } +// DsnParseError represents an error that occurs if a Sentry +// DSN cannot be parsed. type DsnParseError struct { Message string } @@ -43,11 +45,12 @@ type Dsn struct { host string port int path string - projectID int + projectID string } -// NewDsn creates an instance of `Dsn` by parsing provided url in a `string` format. -// If Dsn is not set the client is effectively disabled. +// NewDsn creates a Dsn by parsing rawURL. Most users will never call this +// function directly. It is provided for use in custom Transport +// implementations. func NewDsn(rawURL string) (*Dsn, error) { // Parse parsedURL, err := url.Parse(rawURL) @@ -97,13 +100,14 @@ func NewDsn(rawURL string) (*Dsn, error) { } // ProjectID - if len(parsedURL.Path) == 0 || parsedURL.Path == "/" { + if parsedURL.Path == "" || parsedURL.Path == "/" { return nil, &DsnParseError{"empty project id"} } pathSegments := strings.Split(parsedURL.Path[1:], "/") - projectID, err := strconv.Atoi(pathSegments[len(pathSegments)-1]) - if err != nil { - return nil, &DsnParseError{"invalid project id"} + projectID := pathSegments[len(pathSegments)-1] + + if projectID == "" { + return nil, &DsnParseError{"empty project id"} } // Path @@ -123,7 +127,7 @@ func NewDsn(rawURL string) (*Dsn, error) { }, nil } -// String formats Dsn struct into a valid string url +// String formats Dsn struct into a valid string url. func (dsn Dsn) String() string { var url string url += fmt.Sprintf("%s://%s", dsn.scheme, dsn.publicKey) @@ -137,13 +141,58 @@ func (dsn Dsn) String() string { if dsn.path != "" { url += dsn.path } - url += fmt.Sprintf("/%d", dsn.projectID) + url += fmt.Sprintf("/%s", dsn.projectID) return url } -// StoreAPIURL returns assembled url to be used in the transport. -// It points to configures Sentry instance. +// Get the scheme of the DSN. +func (dsn Dsn) GetScheme() string { + return string(dsn.scheme) +} + +// Get the public key of the DSN. +func (dsn Dsn) GetPublicKey() string { + return dsn.publicKey +} + +// Get the secret key of the DSN. +func (dsn Dsn) GetSecretKey() string { + return dsn.secretKey +} + +// Get the host of the DSN. +func (dsn Dsn) GetHost() string { + return dsn.host +} + +// Get the port of the DSN. +func (dsn Dsn) GetPort() int { + return dsn.port +} + +// Get the path of the DSN. +func (dsn Dsn) GetPath() string { + return dsn.path +} + +// Get the project ID of the DSN. +func (dsn Dsn) GetProjectID() string { + return dsn.projectID +} + +// StoreAPIURL returns the URL of the store endpoint of the project associated +// with the DSN. func (dsn Dsn) StoreAPIURL() *url.URL { + return dsn.getAPIURL("store") +} + +// EnvelopeAPIURL returns the URL of the envelope endpoint of the project +// associated with the DSN. +func (dsn Dsn) EnvelopeAPIURL() *url.URL { + return dsn.getAPIURL("envelope") +} + +func (dsn Dsn) getAPIURL(s string) *url.URL { var rawURL string rawURL += fmt.Sprintf("%s://%s", dsn.scheme, dsn.host) if dsn.port != dsn.scheme.defaultPort() { @@ -152,7 +201,7 @@ func (dsn Dsn) StoreAPIURL() *url.URL { if dsn.path != "" { rawURL += dsn.path } - rawURL += fmt.Sprintf("/api/%d/store/", dsn.projectID) + rawURL += fmt.Sprintf("/api/%s/%s/", dsn.projectID, s) parsedURL, _ := url.Parse(rawURL) return parsedURL } @@ -172,10 +221,12 @@ func (dsn Dsn) RequestHeaders() map[string]string { } } +// MarshalJSON converts the Dsn struct to JSON. func (dsn Dsn) MarshalJSON() ([]byte, error) { return json.Marshal(dsn.String()) } +// UnmarshalJSON converts JSON data to the Dsn struct. func (dsn *Dsn) UnmarshalJSON(data []byte) error { var str string _ = json.Unmarshal(data, &str) diff --git a/vendor/github.com/getsentry/sentry-go/dynamic_sampling_context.go b/vendor/github.com/getsentry/sentry-go/dynamic_sampling_context.go new file mode 100644 index 000000000..53c95e179 --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/dynamic_sampling_context.go @@ -0,0 +1,119 @@ +package sentry + +import ( + "strconv" + "strings" + + "github.com/getsentry/sentry-go/internal/otel/baggage" +) + +const ( + sentryPrefix = "sentry-" +) + +// DynamicSamplingContext holds information about the current event that can be used to make dynamic sampling decisions. +type DynamicSamplingContext struct { + Entries map[string]string + Frozen bool +} + +func DynamicSamplingContextFromHeader(header []byte) (DynamicSamplingContext, error) { + bag, err := baggage.Parse(string(header)) + if err != nil { + return DynamicSamplingContext{}, err + } + + entries := map[string]string{} + for _, member := range bag.Members() { + // We only store baggage members if their key starts with "sentry-". + if k, v := member.Key(), member.Value(); strings.HasPrefix(k, sentryPrefix) { + entries[strings.TrimPrefix(k, sentryPrefix)] = v + } + } + + return DynamicSamplingContext{ + Entries: entries, + // If there's at least one Sentry value, we consider the DSC frozen + Frozen: len(entries) > 0, + }, nil +} + +func DynamicSamplingContextFromTransaction(span *Span) DynamicSamplingContext { + entries := map[string]string{} + + hub := hubFromContext(span.Context()) + scope := hub.Scope() + client := hub.Client() + + if client == nil || scope == nil { + return DynamicSamplingContext{ + Entries: map[string]string{}, + Frozen: false, + } + } + + options := client.Options() + + if traceID := span.TraceID.String(); traceID != "" { + entries["trace_id"] = traceID + } + if sampleRate := span.sampleRate; sampleRate != 0 { + entries["sample_rate"] = strconv.FormatFloat(sampleRate, 'f', -1, 64) + } + + if dsn := client.dsn; dsn != nil { + if publicKey := dsn.publicKey; publicKey != "" { + entries["public_key"] = publicKey + } + } + if release := options.Release; release != "" { + entries["release"] = release + } + if environment := options.Environment; environment != "" { + entries["environment"] = environment + } + + // Only include the transaction name if it's of good quality (not empty and not SourceURL) + if span.Source != "" && span.Source != SourceURL { + if transactionName := scope.Transaction(); transactionName != "" { + entries["transaction"] = transactionName + } + } + + if userSegment := scope.user.Segment; userSegment != "" { + entries["user_segment"] = userSegment + } + + return DynamicSamplingContext{ + Entries: entries, + Frozen: true, + } +} + +func (d DynamicSamplingContext) HasEntries() bool { + return len(d.Entries) > 0 +} + +func (d DynamicSamplingContext) IsFrozen() bool { + return d.Frozen +} + +func (d DynamicSamplingContext) String() string { + members := []baggage.Member{} + for k, entry := range d.Entries { + member, err := baggage.NewMember(sentryPrefix+k, entry) + if err != nil { + continue + } + members = append(members, member) + } + if len(members) > 0 { + baggage, err := baggage.New(members...) + if err != nil { + return "" + } + return baggage.String() + } + + return "" +} diff --git a/vendor/github.com/cockroachdb/sentry-go/hub.go b/vendor/github.com/getsentry/sentry-go/hub.go similarity index 56% rename from vendor/github.com/cockroachdb/sentry-go/hub.go rename to vendor/github.com/getsentry/sentry-go/hub.go index 9394fc47d..71608df34 100644 --- a/vendor/github.com/cockroachdb/sentry-go/hub.go +++ b/vendor/github.com/getsentry/sentry-go/hub.go @@ -8,21 +8,25 @@ import ( type contextKey int -// HubContextKey is a context key used to store Hub on any context.Context type -const HubContextKey = contextKey(1) - -// RequestContextKey is a context key used to store http.Request on the context passed to RecoverWithContext -const RequestContextKey = contextKey(2) +// Keys used to store values in a Context. Use with Context.Value to access +// values stored by the SDK. +const ( + // HubContextKey is the key used to store the current Hub. + HubContextKey = contextKey(1) + // RequestContextKey is the key used to store the current http.Request. + RequestContextKey = contextKey(2) +) -// Default maximum number of breadcrumbs added to an event. Can be overwritten `maxBreadcrumbs` option. +// defaultMaxBreadcrumbs is the default maximum number of breadcrumbs added to +// an event. Can be overwritten with the maxBreadcrumbs option. const defaultMaxBreadcrumbs = 30 -// Absolute maximum number of breadcrumbs added to an event. -// The `maxBreadcrumbs` option cannot be higher than this value. +// maxBreadcrumbs is the absolute maximum number of breadcrumbs added to an +// event. The maxBreadcrumbs option cannot be set higher than this value. const maxBreadcrumbs = 100 -// Initial instance of the Hub that has no `Client` bound and an empty `Scope` -var currentHub = NewHub(nil, NewScope()) //nolint: gochecknoglobals +// currentHub is the initial Hub with no Client bound and an empty Scope. +var currentHub = NewHub(nil, NewScope()) // Hub is the central object that manages scopes and clients. // @@ -31,7 +35,7 @@ var currentHub = NewHub(nil, NewScope()) //nolint: gochecknoglobals // // In most situations developers do not need to interface the hub. Instead // toplevel convenience functions are exposed that will automatically dispatch -// to global (`CurrentHub`) hub. In some situations this might not be +// to global (CurrentHub) hub. In some situations this might not be // possible in which case it might become necessary to manually work with the // hub. This is for instance the case when working with async code. type Hub struct { @@ -64,7 +68,7 @@ func (l *layer) SetClient(c *Client) { type stack []*layer -// NewHub returns an instance of a `Hub` with provided `Client` and `Scope` bound. +// NewHub returns an instance of a Hub with provided Client and Scope bound. func NewHub(client *Client, scope *Scope) *Hub { hub := Hub{ stack: &stack{{ @@ -75,40 +79,45 @@ func NewHub(client *Client, scope *Scope) *Hub { return &hub } -// CurrentHub returns an instance of previously initialized `Hub` stored in the global namespace. +// CurrentHub returns an instance of previously initialized Hub stored in the global namespace. func CurrentHub() *Hub { return currentHub } -// LastEventID returns an ID of last captured event for the current `Hub`. +// LastEventID returns the ID of the last event (error or message) captured +// through the hub and sent to the underlying transport. +// +// Transactions and events dropped by sampling or event processors do not change +// the last event ID. +// +// LastEventID is a convenience method to cover use cases in which errors are +// captured indirectly and the ID is needed. For example, it can be used as part +// of an HTTP middleware to log the ID of the last error, if any. +// +// For more flexibility, consider instead using the ClientOptions.BeforeSend +// function or event processors. func (hub *Hub) LastEventID() EventID { + hub.mu.RLock() + defer hub.mu.RUnlock() + return hub.lastEventID } +// stackTop returns the top layer of the hub stack. Valid hubs always have at +// least one layer, therefore stackTop always return a non-nil pointer. func (hub *Hub) stackTop() *layer { hub.mu.RLock() defer hub.mu.RUnlock() stack := hub.stack - if stack == nil { - return nil - } - stackLen := len(*stack) - if stackLen == 0 { - return nil - } top := (*stack)[stackLen-1] - return top } // Clone returns a copy of the current Hub with top-most scope and client copied over. func (hub *Hub) Clone() *Hub { top := hub.stackTop() - if top == nil { - return nil - } scope := top.scope if scope != nil { scope = scope.Clone() @@ -116,35 +125,24 @@ func (hub *Hub) Clone() *Hub { return NewHub(top.Client(), scope) } -// Scope returns top-level `Scope` of the current `Hub` or `nil` if no `Scope` is bound. +// Scope returns top-level Scope of the current Hub or nil if no Scope is bound. func (hub *Hub) Scope() *Scope { top := hub.stackTop() - if top == nil { - return nil - } return top.scope } -// Scope returns top-level `Client` of the current `Hub` or `nil` if no `Client` is bound. +// Client returns top-level Client of the current Hub or nil if no Client is bound. func (hub *Hub) Client() *Client { top := hub.stackTop() - if top == nil { - return nil - } return top.Client() } -// PushScope pushes a new scope for the current `Hub` and reuses previously bound `Client`. +// PushScope pushes a new scope for the current Hub and reuses previously bound Client. func (hub *Hub) PushScope() *Scope { top := hub.stackTop() - var client *Client - if top != nil { - client = top.Client() - } - var scope *Scope - if top != nil && top.scope != nil { + if top.scope != nil { scope = top.scope.Clone() } else { scope = NewScope() @@ -154,101 +152,117 @@ func (hub *Hub) PushScope() *Scope { defer hub.mu.Unlock() *hub.stack = append(*hub.stack, &layer{ - client: client, + client: top.Client(), scope: scope, }) return scope } -// PushScope pops the most recent scope for the current `Hub`. +// PopScope drops the most recent scope. +// +// Calls to PopScope must be coordinated with PushScope. For most cases, using +// WithScope should be more convenient. +// +// Calls to PopScope that do not match previous calls to PushScope are silently +// ignored. func (hub *Hub) PopScope() { hub.mu.Lock() defer hub.mu.Unlock() stack := *hub.stack stackLen := len(stack) - if stackLen > 0 { + if stackLen > 1 { + // Never pop the last item off the stack, the stack should always have + // at least one item. *hub.stack = stack[0 : stackLen-1] } } -// BindClient binds a new `Client` for the current `Hub`. +// BindClient binds a new Client for the current Hub. func (hub *Hub) BindClient(client *Client) { top := hub.stackTop() - if top != nil { - top.SetClient(client) - } + top.SetClient(client) } -// WithScope temporarily pushes a scope for a single call. +// WithScope runs f in an isolated temporary scope. +// +// It is useful when extra data should be sent with a single capture call, for +// instance a different level or tags. // -// A shorthand for: -// PushScope() -// f(scope) -// PopScope() +// The scope passed to f starts as a clone of the current scope and can be +// freely modified without affecting the current scope. +// +// It is a shorthand for PushScope followed by PopScope. func (hub *Hub) WithScope(f func(scope *Scope)) { scope := hub.PushScope() defer hub.PopScope() f(scope) } -// ConfigureScope invokes a function that can modify the current scope. +// ConfigureScope runs f in the current scope. +// +// It is useful to set data that applies to all events that share the current +// scope. +// +// Modifying the scope affects all references to the current scope. // -// The function is passed a mutable reference to the `Scope` so that modifications -// can be performed. +// See also WithScope for making isolated temporary changes. func (hub *Hub) ConfigureScope(f func(scope *Scope)) { scope := hub.Scope() f(scope) } -// CaptureEvent calls the method of a same name on currently bound `Client` instance -// passing it a top-level `Scope`. -// Returns `EventID` if successfully, or `nil` if there's no `Scope` or `Client` available. +// CaptureEvent calls the method of a same name on currently bound Client instance +// passing it a top-level Scope. +// Returns EventID if successfully, or nil if there's no Scope or Client available. func (hub *Hub) CaptureEvent(event *Event) *EventID { client, scope := hub.Client(), hub.Scope() if client == nil || scope == nil { return nil } eventID := client.CaptureEvent(event, nil, scope) - if eventID != nil { + + if event.Type != transactionType && eventID != nil { + hub.mu.Lock() hub.lastEventID = *eventID - } else { - hub.lastEventID = "" + hub.mu.Unlock() } return eventID } -// CaptureMessage calls the method of a same name on currently bound `Client` instance -// passing it a top-level `Scope`. -// Returns `EventID` if successfully, or `nil` if there's no `Scope` or `Client` available. +// CaptureMessage calls the method of a same name on currently bound Client instance +// passing it a top-level Scope. +// Returns EventID if successfully, or nil if there's no Scope or Client available. func (hub *Hub) CaptureMessage(message string) *EventID { client, scope := hub.Client(), hub.Scope() if client == nil || scope == nil { return nil } eventID := client.CaptureMessage(message, nil, scope) + if eventID != nil { + hub.mu.Lock() hub.lastEventID = *eventID - } else { - hub.lastEventID = "" + hub.mu.Unlock() } return eventID } -// CaptureException calls the method of a same name on currently bound `Client` instance -// passing it a top-level `Scope`. -// Returns `EventID` if successfully, or `nil` if there's no `Scope` or `Client` available. +// CaptureException calls the method of a same name on currently bound Client instance +// passing it a top-level Scope. +// Returns EventID if successfully, or nil if there's no Scope or Client available. func (hub *Hub) CaptureException(exception error) *EventID { client, scope := hub.Client(), hub.Scope() if client == nil || scope == nil { return nil } eventID := client.CaptureException(exception, &EventHint{OriginalException: exception}, scope) + if eventID != nil { + hub.mu.Lock() hub.lastEventID = *eventID - } else { - hub.lastEventID = "" + hub.mu.Unlock() } return eventID } @@ -267,36 +281,33 @@ func (hub *Hub) AddBreadcrumb(breadcrumb *Breadcrumb, hint *BreadcrumbHint) { } options := client.Options() - max := defaultMaxBreadcrumbs - - if options.MaxBreadcrumbs != 0 { - max = options.MaxBreadcrumbs - } - + max := options.MaxBreadcrumbs if max < 0 { return } if options.BeforeBreadcrumb != nil { - h := &BreadcrumbHint{} - if hint != nil { - h = hint + if hint == nil { + hint = &BreadcrumbHint{} } - if breadcrumb = options.BeforeBreadcrumb(breadcrumb, h); breadcrumb == nil { + if breadcrumb = options.BeforeBreadcrumb(breadcrumb, hint); breadcrumb == nil { Logger.Println("breadcrumb dropped due to BeforeBreadcrumb callback.") return } } - if max > maxBreadcrumbs { + if max == 0 { + max = defaultMaxBreadcrumbs + } else if max > maxBreadcrumbs { max = maxBreadcrumbs } + hub.Scope().AddBreadcrumb(breadcrumb, max) } -// Recover calls the method of a same name on currently bound `Client` instance -// passing it a top-level `Scope`. -// Returns `EventID` if successfully, or `nil` if there's no `Scope` or `Client` available. +// Recover calls the method of a same name on currently bound Client instance +// passing it a top-level Scope. +// Returns EventID if successfully, or nil if there's no Scope or Client available. func (hub *Hub) Recover(err interface{}) *EventID { if err == nil { err = recover() @@ -308,9 +319,9 @@ func (hub *Hub) Recover(err interface{}) *EventID { return client.Recover(err, &EventHint{RecoveredException: err}, scope) } -// RecoverWithContext calls the method of a same name on currently bound `Client` instance -// passing it a top-level `Scope`. -// Returns `EventID` if successfully, or `nil` if there's no `Scope` or `Client` available. +// RecoverWithContext calls the method of a same name on currently bound Client instance +// passing it a top-level Scope. +// Returns EventID if successfully, or nil if there's no Scope or Client available. func (hub *Hub) RecoverWithContext(ctx context.Context, err interface{}) *EventID { if err == nil { err = recover() @@ -343,14 +354,14 @@ func (hub *Hub) Flush(timeout time.Duration) bool { return client.Flush(timeout) } -// HasHubOnContext checks whether `Hub` instance is bound to a given `Context` struct. +// HasHubOnContext checks whether Hub instance is bound to a given Context struct. func HasHubOnContext(ctx context.Context) bool { _, ok := ctx.Value(HubContextKey).(*Hub) return ok } -// GetHubFromContext tries to retrieve `Hub` instance from the given `Context` struct -// or return `nil` if one is not found. +// GetHubFromContext tries to retrieve Hub instance from the given Context struct +// or return nil if one is not found. func GetHubFromContext(ctx context.Context) *Hub { if hub, ok := ctx.Value(HubContextKey).(*Hub); ok { return hub @@ -358,7 +369,16 @@ func GetHubFromContext(ctx context.Context) *Hub { return nil } -// SetHubOnContext stores given `Hub` instance on the `Context` struct and returns a new `Context`. +// hubFromContext returns either a hub stored in the context or the current hub. +// The return value is guaranteed to be non-nil, unlike GetHubFromContext. +func hubFromContext(ctx context.Context) *Hub { + if hub, ok := ctx.Value(HubContextKey).(*Hub); ok { + return hub + } + return currentHub +} + +// SetHubOnContext stores given Hub instance on the Context struct and returns a new Context. func SetHubOnContext(ctx context.Context, hub *Hub) context.Context { return context.WithValue(ctx, HubContextKey, hub) } diff --git a/vendor/github.com/cockroachdb/sentry-go/integrations.go b/vendor/github.com/getsentry/sentry-go/integrations.go similarity index 80% rename from vendor/github.com/cockroachdb/sentry-go/integrations.go rename to vendor/github.com/getsentry/sentry-go/integrations.go index eb11aa977..6a9e55a2b 100644 --- a/vendor/github.com/cockroachdb/sentry-go/integrations.go +++ b/vendor/github.com/getsentry/sentry-go/integrations.go @@ -70,27 +70,50 @@ func (ei *environmentIntegration) SetupOnce(client *Client) { } func (ei *environmentIntegration) processor(event *Event, hint *EventHint) *Event { + // Initialize maps as necessary. + contextNames := []string{"device", "os", "runtime"} if event.Contexts == nil { - event.Contexts = make(map[string]interface{}) + event.Contexts = make(map[string]Context, len(contextNames)) } - - event.Contexts["device"] = map[string]interface{}{ - "arch": runtime.GOARCH, - "num_cpu": runtime.NumCPU(), + for _, name := range contextNames { + if event.Contexts[name] == nil { + event.Contexts[name] = make(Context) + } } - event.Contexts["os"] = map[string]interface{}{ - "name": runtime.GOOS, + // Set contextual information preserving existing data. For each context, if + // the existing value is not of type map[string]interface{}, then no + // additional information is added. + if deviceContext, ok := event.Contexts["device"]; ok { + if _, ok := deviceContext["arch"]; !ok { + deviceContext["arch"] = runtime.GOARCH + } + if _, ok := deviceContext["num_cpu"]; !ok { + deviceContext["num_cpu"] = runtime.NumCPU() + } } - - event.Contexts["runtime"] = map[string]interface{}{ - "name": "go", - "version": runtime.Version(), - "go_numroutines": runtime.NumGoroutine(), - "go_maxprocs": runtime.GOMAXPROCS(0), - "go_numcgocalls": runtime.NumCgoCall(), + if osContext, ok := event.Contexts["os"]; ok { + if _, ok := osContext["name"]; !ok { + osContext["name"] = runtime.GOOS + } + } + if runtimeContext, ok := event.Contexts["runtime"]; ok { + if _, ok := runtimeContext["name"]; !ok { + runtimeContext["name"] = "go" + } + if _, ok := runtimeContext["version"]; !ok { + runtimeContext["version"] = runtime.Version() + } + if _, ok := runtimeContext["go_numroutines"]; !ok { + runtimeContext["go_numroutines"] = runtime.NumGoroutine() + } + if _, ok := runtimeContext["go_maxprocs"]; !ok { + runtimeContext["go_maxprocs"] = runtime.GOMAXPROCS(0) + } + if _, ok := runtimeContext["go_numcgocalls"]; !ok { + runtimeContext["go_numcgocalls"] = runtime.NumCgoCall() + } } - return event } @@ -148,8 +171,7 @@ func getIgnoreErrorsSuspects(event *Event) []string { } for _, ex := range event.Exception { - suspects = append(suspects, ex.Type) - suspects = append(suspects, ex.Value) + suspects = append(suspects, ex.Type, ex.Value) } return suspects diff --git a/vendor/github.com/getsentry/sentry-go/interfaces.go b/vendor/github.com/getsentry/sentry-go/interfaces.go new file mode 100644 index 000000000..8b0d06621 --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/interfaces.go @@ -0,0 +1,390 @@ +package sentry + +import ( + "context" + "encoding/json" + "fmt" + "net" + "net/http" + "strings" + "time" +) + +// Protocol Docs (kinda) +// https://github.com/getsentry/rust-sentry-types/blob/master/src/protocol/v7.rs + +// transactionType is the type of a transaction event. +const transactionType = "transaction" + +// Level marks the severity of the event. +type Level string + +// Describes the severity of the event. +const ( + LevelDebug Level = "debug" + LevelInfo Level = "info" + LevelWarning Level = "warning" + LevelError Level = "error" + LevelFatal Level = "fatal" +) + +func getSensitiveHeaders() map[string]bool { + return map[string]bool{ + "Authorization": true, + "Cookie": true, + "X-Forwarded-For": true, + "X-Real-Ip": true, + } +} + +// SdkInfo contains all metadata about about the SDK being used. +type SdkInfo struct { + Name string `json:"name,omitempty"` + Version string `json:"version,omitempty"` + Integrations []string `json:"integrations,omitempty"` + Packages []SdkPackage `json:"packages,omitempty"` +} + +// SdkPackage describes a package that was installed. +type SdkPackage struct { + Name string `json:"name,omitempty"` + Version string `json:"version,omitempty"` +} + +// TODO: This type could be more useful, as map of interface{} is too generic +// and requires a lot of type assertions in beforeBreadcrumb calls +// plus it could just be map[string]interface{} then. + +// BreadcrumbHint contains information that can be associated with a Breadcrumb. +type BreadcrumbHint map[string]interface{} + +// Breadcrumb specifies an application event that occurred before a Sentry event. +// An event may contain one or more breadcrumbs. +type Breadcrumb struct { + Type string `json:"type,omitempty"` + Category string `json:"category,omitempty"` + Message string `json:"message,omitempty"` + Data map[string]interface{} `json:"data,omitempty"` + Level Level `json:"level,omitempty"` + Timestamp time.Time `json:"timestamp"` +} + +// TODO: provide constants for known breadcrumb types. +// See https://develop.sentry.dev/sdk/event-payloads/breadcrumbs/#breadcrumb-types. + +// MarshalJSON converts the Breadcrumb struct to JSON. +func (b *Breadcrumb) MarshalJSON() ([]byte, error) { + // We want to omit time.Time zero values, otherwise the server will try to + // interpret dates too far in the past. However, encoding/json doesn't + // support the "omitempty" option for struct types. See + // https://golang.org/issues/11939. + // + // We overcome the limitation and achieve what we want by shadowing fields + // and a few type tricks. + + // breadcrumb aliases Breadcrumb to allow calling json.Marshal without an + // infinite loop. It preserves all fields while none of the attached + // methods. + type breadcrumb Breadcrumb + + if b.Timestamp.IsZero() { + return json.Marshal(struct { + // Embed all of the fields of Breadcrumb. + *breadcrumb + // Timestamp shadows the original Timestamp field and is meant to + // remain nil, triggering the omitempty behavior. + Timestamp json.RawMessage `json:"timestamp,omitempty"` + }{breadcrumb: (*breadcrumb)(b)}) + } + return json.Marshal((*breadcrumb)(b)) +} + +// User describes the user associated with an Event. If this is used, at least +// an ID or an IP address should be provided. +type User struct { + ID string `json:"id,omitempty"` + Email string `json:"email,omitempty"` + IPAddress string `json:"ip_address,omitempty"` + Username string `json:"username,omitempty"` + Name string `json:"name,omitempty"` + Segment string `json:"segment,omitempty"` + Data map[string]string `json:"data,omitempty"` +} + +func (u User) IsEmpty() bool { + if len(u.ID) > 0 { + return false + } + + if len(u.Email) > 0 { + return false + } + + if len(u.IPAddress) > 0 { + return false + } + + if len(u.Username) > 0 { + return false + } + + if len(u.Name) > 0 { + return false + } + + if len(u.Segment) > 0 { + return false + } + + if len(u.Data) > 0 { + return false + } + + return true +} + +// Request contains information on a HTTP request related to the event. +type Request struct { + URL string `json:"url,omitempty"` + Method string `json:"method,omitempty"` + Data string `json:"data,omitempty"` + QueryString string `json:"query_string,omitempty"` + Cookies string `json:"cookies,omitempty"` + Headers map[string]string `json:"headers,omitempty"` + Env map[string]string `json:"env,omitempty"` +} + +// NewRequest returns a new Sentry Request from the given http.Request. +// +// NewRequest avoids operations that depend on network access. In particular, it +// does not read r.Body. +func NewRequest(r *http.Request) *Request { + protocol := schemeHTTP + if r.TLS != nil || r.Header.Get("X-Forwarded-Proto") == "https" { + protocol = schemeHTTPS + } + url := fmt.Sprintf("%s://%s%s", protocol, r.Host, r.URL.Path) + + var cookies string + var env map[string]string + headers := map[string]string{} + + if client := CurrentHub().Client(); client != nil && client.Options().SendDefaultPII { + // We read only the first Cookie header because of the specification: + // https://tools.ietf.org/html/rfc6265#section-5.4 + // When the user agent generates an HTTP request, the user agent MUST NOT + // attach more than one Cookie header field. + cookies = r.Header.Get("Cookie") + + for k, v := range r.Header { + headers[k] = strings.Join(v, ",") + } + + if addr, port, err := net.SplitHostPort(r.RemoteAddr); err == nil { + env = map[string]string{"REMOTE_ADDR": addr, "REMOTE_PORT": port} + } + } else { + sensitiveHeaders := getSensitiveHeaders() + for k, v := range r.Header { + if _, ok := sensitiveHeaders[k]; !ok { + headers[k] = strings.Join(v, ",") + } + } + } + + headers["Host"] = r.Host + + return &Request{ + URL: url, + Method: r.Method, + QueryString: r.URL.RawQuery, + Cookies: cookies, + Headers: headers, + Env: env, + } +} + +// Exception specifies an error that occurred. +type Exception struct { + Type string `json:"type,omitempty"` // used as the main issue title + Value string `json:"value,omitempty"` // used as the main issue subtitle + Module string `json:"module,omitempty"` + ThreadID string `json:"thread_id,omitempty"` + Stacktrace *Stacktrace `json:"stacktrace,omitempty"` +} + +// SDKMetaData is a struct to stash data which is needed at some point in the SDK's event processing pipeline +// but which shouldn't get send to Sentry. +type SDKMetaData struct { + dsc DynamicSamplingContext +} + +// Contains information about how the name of the transaction was determined. +type TransactionInfo struct { + Source TransactionSource `json:"source,omitempty"` +} + +// EventID is a hexadecimal string representing a unique uuid4 for an Event. +// An EventID must be 32 characters long, lowercase and not have any dashes. +type EventID string + +type Context = map[string]interface{} + +// Event is the fundamental data structure that is sent to Sentry. +type Event struct { + Breadcrumbs []*Breadcrumb `json:"breadcrumbs,omitempty"` + Contexts map[string]Context `json:"contexts,omitempty"` + Dist string `json:"dist,omitempty"` + Environment string `json:"environment,omitempty"` + EventID EventID `json:"event_id,omitempty"` + Extra map[string]interface{} `json:"extra,omitempty"` + Fingerprint []string `json:"fingerprint,omitempty"` + Level Level `json:"level,omitempty"` + Message string `json:"message,omitempty"` + Platform string `json:"platform,omitempty"` + Release string `json:"release,omitempty"` + Sdk SdkInfo `json:"sdk,omitempty"` + ServerName string `json:"server_name,omitempty"` + Threads []Thread `json:"threads,omitempty"` + Tags map[string]string `json:"tags,omitempty"` + Timestamp time.Time `json:"timestamp"` + Transaction string `json:"transaction,omitempty"` + User User `json:"user,omitempty"` + Logger string `json:"logger,omitempty"` + Modules map[string]string `json:"modules,omitempty"` + Request *Request `json:"request,omitempty"` + Exception []Exception `json:"exception,omitempty"` + + // The fields below are only relevant for transactions. + + Type string `json:"type,omitempty"` + StartTime time.Time `json:"start_timestamp"` + Spans []*Span `json:"spans,omitempty"` + TransactionInfo *TransactionInfo `json:"transaction_info,omitempty"` + + // The fields below are not part of the final JSON payload. + + sdkMetaData SDKMetaData +} + +// TODO: Event.Contexts map[string]interface{} => map[string]EventContext, +// to prevent accidentally storing T when we mean *T. +// For example, the TraceContext must be stored as *TraceContext to pick up the +// MarshalJSON method (and avoid copying). +// type EventContext interface{ EventContext() } + +// MarshalJSON converts the Event struct to JSON. +func (e *Event) MarshalJSON() ([]byte, error) { + // We want to omit time.Time zero values, otherwise the server will try to + // interpret dates too far in the past. However, encoding/json doesn't + // support the "omitempty" option for struct types. See + // https://golang.org/issues/11939. + // + // We overcome the limitation and achieve what we want by shadowing fields + // and a few type tricks. + if e.Type == transactionType { + return e.transactionMarshalJSON() + } + return e.defaultMarshalJSON() +} + +func (e *Event) defaultMarshalJSON() ([]byte, error) { + // event aliases Event to allow calling json.Marshal without an infinite + // loop. It preserves all fields while none of the attached methods. + type event Event + + // errorEvent is like Event with shadowed fields for customizing JSON + // marshaling. + type errorEvent struct { + *event + + // Timestamp shadows the original Timestamp field. It allows us to + // include the timestamp when non-zero and omit it otherwise. + Timestamp json.RawMessage `json:"timestamp,omitempty"` + + // The fields below are not part of error events and only make sense to + // be sent for transactions. They shadow the respective fields in Event + // and are meant to remain nil, triggering the omitempty behavior. + + Type json.RawMessage `json:"type,omitempty"` + StartTime json.RawMessage `json:"start_timestamp,omitempty"` + Spans json.RawMessage `json:"spans,omitempty"` + TransactionInfo json.RawMessage `json:"transaction_info,omitempty"` + } + + x := errorEvent{event: (*event)(e)} + if !e.Timestamp.IsZero() { + b, err := e.Timestamp.MarshalJSON() + if err != nil { + return nil, err + } + x.Timestamp = b + } + return json.Marshal(x) +} + +func (e *Event) transactionMarshalJSON() ([]byte, error) { + // event aliases Event to allow calling json.Marshal without an infinite + // loop. It preserves all fields while none of the attached methods. + type event Event + + // transactionEvent is like Event with shadowed fields for customizing JSON + // marshaling. + type transactionEvent struct { + *event + + // The fields below shadow the respective fields in Event. They allow us + // to include timestamps when non-zero and omit them otherwise. + + StartTime json.RawMessage `json:"start_timestamp,omitempty"` + Timestamp json.RawMessage `json:"timestamp,omitempty"` + } + + x := transactionEvent{event: (*event)(e)} + if !e.Timestamp.IsZero() { + b, err := e.Timestamp.MarshalJSON() + if err != nil { + return nil, err + } + x.Timestamp = b + } + if !e.StartTime.IsZero() { + b, err := e.StartTime.MarshalJSON() + if err != nil { + return nil, err + } + x.StartTime = b + } + return json.Marshal(x) +} + +// NewEvent creates a new Event. +func NewEvent() *Event { + event := Event{ + Contexts: make(map[string]Context), + Extra: make(map[string]interface{}), + Tags: make(map[string]string), + Modules: make(map[string]string), + } + return &event +} + +// Thread specifies threads that were running at the time of an event. +type Thread struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Stacktrace *Stacktrace `json:"stacktrace,omitempty"` + Crashed bool `json:"crashed,omitempty"` + Current bool `json:"current,omitempty"` +} + +// EventHint contains information that can be associated with an Event. +type EventHint struct { + Data interface{} + EventID string + OriginalException error + RecoveredException interface{} + Context context.Context + Request *http.Request + Response *http.Response +} diff --git a/vendor/github.com/getsentry/sentry-go/internal/debug/transport.go b/vendor/github.com/getsentry/sentry-go/internal/debug/transport.go new file mode 100644 index 000000000..199c3a303 --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/internal/debug/transport.go @@ -0,0 +1,79 @@ +package debug + +import ( + "bytes" + "fmt" + "io" + "net/http" + "net/http/httptrace" + "net/http/httputil" +) + +// Transport implements http.RoundTripper and can be used to wrap other HTTP +// transports for debugging, normally http.DefaultTransport. +type Transport struct { + http.RoundTripper + Output io.Writer + // Dump controls whether to dump HTTP request and responses. + Dump bool + // Trace enables usage of net/http/httptrace. + Trace bool +} + +func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { + var buf bytes.Buffer + if t.Dump { + b, err := httputil.DumpRequestOut(req, true) + if err != nil { + panic(err) + } + _, err = buf.Write(ensureTrailingNewline(b)) + if err != nil { + panic(err) + } + } + if t.Trace { + trace := &httptrace.ClientTrace{ + DNSDone: func(di httptrace.DNSDoneInfo) { + fmt.Fprintf(&buf, "* DNS %v → %v\n", req.Host, di.Addrs) + }, + GotConn: func(ci httptrace.GotConnInfo) { + fmt.Fprintf(&buf, "* Connection local=%v remote=%v", ci.Conn.LocalAddr(), ci.Conn.RemoteAddr()) + if ci.Reused { + fmt.Fprint(&buf, " (reused)") + } + if ci.WasIdle { + fmt.Fprintf(&buf, " (idle %v)", ci.IdleTime) + } + fmt.Fprintln(&buf) + }, + } + req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace)) + } + resp, err := t.RoundTripper.RoundTrip(req) + if err != nil { + return nil, err + } + if t.Dump { + b, err := httputil.DumpResponse(resp, true) + if err != nil { + panic(err) + } + _, err = buf.Write(ensureTrailingNewline(b)) + if err != nil { + panic(err) + } + } + _, err = io.Copy(t.Output, &buf) + if err != nil { + panic(err) + } + return resp, nil +} + +func ensureTrailingNewline(b []byte) []byte { + if len(b) > 0 && b[len(b)-1] != '\n' { + b = append(b, '\n') + } + return b +} diff --git a/vendor/github.com/getsentry/sentry-go/internal/otel/baggage/README.md b/vendor/github.com/getsentry/sentry-go/internal/otel/baggage/README.md new file mode 100644 index 000000000..2718f314b --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/internal/otel/baggage/README.md @@ -0,0 +1,12 @@ +## Why do we have this "otel/baggage" folder? + +The root sentry-go SDK (namely, the Dynamic Sampling functionality) needs an implementation of the [baggage spec](https://www.w3.org/TR/baggage/). +For that reason, we've taken the existing baggage implementation from the [opentelemetry-go](https://github.com/open-telemetry/opentelemetry-go/) repository, and fixed a few things that in our opinion were violating the specification. + +These issues are: +1. Baggage string value `one%20two` should be properly parsed as "one two" +1. Baggage string value `one+two` should be parsed as "one+two" +1. Go string value "one two" should be encoded as `one%20two` (percent encoding), and NOT as `one+two` (URL query encoding). +1. Go string value "1=1" might be encoded as `1=1`, because the spec says: "Note, value MAY contain any number of the equal sign (=) characters. Parsers MUST NOT assume that the equal sign is only used to separate key and value.". `1%3D1` is also valid, but to simplify the implementation we're not doing it. + +Changes were made in this PR: https://github.com/getsentry/sentry-go/pull/568 diff --git a/vendor/github.com/getsentry/sentry-go/internal/otel/baggage/baggage.go b/vendor/github.com/getsentry/sentry-go/internal/otel/baggage/baggage.go new file mode 100644 index 000000000..bd4c27abd --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/internal/otel/baggage/baggage.go @@ -0,0 +1,602 @@ +// # Copyright The OpenTelemetry 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 baggage + +import ( + "errors" + "fmt" + "net/url" + "regexp" + "strings" + "unicode/utf8" + + "github.com/getsentry/sentry-go/internal/otel/baggage/internal/baggage" +) + +const ( + maxMembers = 180 + maxBytesPerMembers = 4096 + maxBytesPerBaggageString = 8192 + + listDelimiter = "," + keyValueDelimiter = "=" + propertyDelimiter = ";" + + keyDef = `([\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5a\x5e-\x7a\x7c\x7e]+)` + valueDef = `([\x21\x23-\x2b\x2d-\x3a\x3c-\x5B\x5D-\x7e]*)` + keyValueDef = `\s*` + keyDef + `\s*` + keyValueDelimiter + `\s*` + valueDef + `\s*` +) + +var ( + keyRe = regexp.MustCompile(`^` + keyDef + `$`) + valueRe = regexp.MustCompile(`^` + valueDef + `$`) + propertyRe = regexp.MustCompile(`^(?:\s*` + keyDef + `\s*|` + keyValueDef + `)$`) +) + +var ( + errInvalidKey = errors.New("invalid key") + errInvalidValue = errors.New("invalid value") + errInvalidProperty = errors.New("invalid baggage list-member property") + errInvalidMember = errors.New("invalid baggage list-member") + errMemberNumber = errors.New("too many list-members in baggage-string") + errMemberBytes = errors.New("list-member too large") + errBaggageBytes = errors.New("baggage-string too large") +) + +// Property is an additional metadata entry for a baggage list-member. +type Property struct { + key, value string + + // hasValue indicates if a zero-value value means the property does not + // have a value or if it was the zero-value. + hasValue bool + + // hasData indicates whether the created property contains data or not. + // Properties that do not contain data are invalid with no other check + // required. + hasData bool +} + +// NewKeyProperty returns a new Property for key. +// +// If key is invalid, an error will be returned. +func NewKeyProperty(key string) (Property, error) { + if !keyRe.MatchString(key) { + return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidKey, key) + } + + p := Property{key: key, hasData: true} + return p, nil +} + +// NewKeyValueProperty returns a new Property for key with value. +// +// If key or value are invalid, an error will be returned. +func NewKeyValueProperty(key, value string) (Property, error) { + if !keyRe.MatchString(key) { + return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidKey, key) + } + if !valueRe.MatchString(value) { + return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidValue, value) + } + + p := Property{ + key: key, + value: value, + hasValue: true, + hasData: true, + } + return p, nil +} + +func newInvalidProperty() Property { + return Property{} +} + +// parseProperty attempts to decode a Property from the passed string. It +// returns an error if the input is invalid according to the W3C Baggage +// specification. +func parseProperty(property string) (Property, error) { + if property == "" { + return newInvalidProperty(), nil + } + + match := propertyRe.FindStringSubmatch(property) + if len(match) != 4 { + return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidProperty, property) + } + + p := Property{hasData: true} + if match[1] != "" { + p.key = match[1] + } else { + p.key = match[2] + p.value = match[3] + p.hasValue = true + } + + return p, nil +} + +// validate ensures p conforms to the W3C Baggage specification, returning an +// error otherwise. +func (p Property) validate() error { + errFunc := func(err error) error { + return fmt.Errorf("invalid property: %w", err) + } + + if !p.hasData { + return errFunc(fmt.Errorf("%w: %q", errInvalidProperty, p)) + } + + if !keyRe.MatchString(p.key) { + return errFunc(fmt.Errorf("%w: %q", errInvalidKey, p.key)) + } + if p.hasValue && !valueRe.MatchString(p.value) { + return errFunc(fmt.Errorf("%w: %q", errInvalidValue, p.value)) + } + if !p.hasValue && p.value != "" { + return errFunc(errors.New("inconsistent value")) + } + return nil +} + +// Key returns the Property key. +func (p Property) Key() string { + return p.key +} + +// Value returns the Property value. Additionally, a boolean value is returned +// indicating if the returned value is the empty if the Property has a value +// that is empty or if the value is not set. +func (p Property) Value() (string, bool) { + return p.value, p.hasValue +} + +// String encodes Property into a string compliant with the W3C Baggage +// specification. +func (p Property) String() string { + if p.hasValue { + return fmt.Sprintf("%s%s%v", p.key, keyValueDelimiter, p.value) + } + return p.key +} + +type properties []Property + +func fromInternalProperties(iProps []baggage.Property) properties { + if len(iProps) == 0 { + return nil + } + + props := make(properties, len(iProps)) + for i, p := range iProps { + props[i] = Property{ + key: p.Key, + value: p.Value, + hasValue: p.HasValue, + } + } + return props +} + +func (p properties) asInternal() []baggage.Property { + if len(p) == 0 { + return nil + } + + iProps := make([]baggage.Property, len(p)) + for i, prop := range p { + iProps[i] = baggage.Property{ + Key: prop.key, + Value: prop.value, + HasValue: prop.hasValue, + } + } + return iProps +} + +func (p properties) Copy() properties { + if len(p) == 0 { + return nil + } + + props := make(properties, len(p)) + copy(props, p) + return props +} + +// validate ensures each Property in p conforms to the W3C Baggage +// specification, returning an error otherwise. +func (p properties) validate() error { + for _, prop := range p { + if err := prop.validate(); err != nil { + return err + } + } + return nil +} + +// String encodes properties into a string compliant with the W3C Baggage +// specification. +func (p properties) String() string { + props := make([]string, len(p)) + for i, prop := range p { + props[i] = prop.String() + } + return strings.Join(props, propertyDelimiter) +} + +// Member is a list-member of a baggage-string as defined by the W3C Baggage +// specification. +type Member struct { + key, value string + properties properties + + // hasData indicates whether the created property contains data or not. + // Properties that do not contain data are invalid with no other check + // required. + hasData bool +} + +// NewMember returns a new Member from the passed arguments. The key will be +// used directly while the value will be url decoded after validation. An error +// is returned if the created Member would be invalid according to the W3C +// Baggage specification. +func NewMember(key, value string, props ...Property) (Member, error) { + m := Member{ + key: key, + value: value, + properties: properties(props).Copy(), + hasData: true, + } + if err := m.validate(); err != nil { + return newInvalidMember(), err + } + //// NOTE(anton): I don't think we need to unescape here + // decodedValue, err := url.PathUnescape(value) + // if err != nil { + // return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidValue, value) + // } + // m.value = decodedValue + return m, nil +} + +func newInvalidMember() Member { + return Member{} +} + +// parseMember attempts to decode a Member from the passed string. It returns +// an error if the input is invalid according to the W3C Baggage +// specification. +func parseMember(member string) (Member, error) { + if n := len(member); n > maxBytesPerMembers { + return newInvalidMember(), fmt.Errorf("%w: %d", errMemberBytes, n) + } + + var ( + key, value string + props properties + ) + + parts := strings.SplitN(member, propertyDelimiter, 2) + switch len(parts) { + case 2: + // Parse the member properties. + for _, pStr := range strings.Split(parts[1], propertyDelimiter) { + p, err := parseProperty(pStr) + if err != nil { + return newInvalidMember(), err + } + props = append(props, p) + } + fallthrough + case 1: + // Parse the member key/value pair. + + // Take into account a value can contain equal signs (=). + kv := strings.SplitN(parts[0], keyValueDelimiter, 2) + if len(kv) != 2 { + return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidMember, member) + } + // "Leading and trailing whitespaces are allowed but MUST be trimmed + // when converting the header into a data structure." + key = strings.TrimSpace(kv[0]) + value = strings.TrimSpace(kv[1]) + var err error + if !keyRe.MatchString(key) { + return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidKey, key) + } + if !valueRe.MatchString(value) { + return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidValue, value) + } + decodedValue, err := url.PathUnescape(value) + if err != nil { + return newInvalidMember(), fmt.Errorf("%w: %q", err, value) + } + value = decodedValue + default: + // This should never happen unless a developer has changed the string + // splitting somehow. Panic instead of failing silently and allowing + // the bug to slip past the CI checks. + panic("failed to parse baggage member") + } + + return Member{key: key, value: value, properties: props, hasData: true}, nil +} + +// validate ensures m conforms to the W3C Baggage specification. +// A key is just an ASCII string, but a value must be URL encoded UTF-8, +// returning an error otherwise. +func (m Member) validate() error { + if !m.hasData { + return fmt.Errorf("%w: %q", errInvalidMember, m) + } + + if !keyRe.MatchString(m.key) { + return fmt.Errorf("%w: %q", errInvalidKey, m.key) + } + //// NOTE(anton): IMO it's too early to validate the value here. + // if !valueRe.MatchString(m.value) { + // return fmt.Errorf("%w: %q", errInvalidValue, m.value) + // } + return m.properties.validate() +} + +// Key returns the Member key. +func (m Member) Key() string { return m.key } + +// Value returns the Member value. +func (m Member) Value() string { return m.value } + +// Properties returns a copy of the Member properties. +func (m Member) Properties() []Property { return m.properties.Copy() } + +// String encodes Member into a string compliant with the W3C Baggage +// specification. +func (m Member) String() string { + // A key is just an ASCII string, but a value is URL encoded UTF-8. + s := fmt.Sprintf("%s%s%s", m.key, keyValueDelimiter, percentEncodeValue(m.value)) + if len(m.properties) > 0 { + s = fmt.Sprintf("%s%s%s", s, propertyDelimiter, m.properties.String()) + } + return s +} + +// percentEncodeValue encodes the baggage value, using percent-encoding for +// disallowed octets. +func percentEncodeValue(s string) string { + const upperhex = "0123456789ABCDEF" + var sb strings.Builder + + for byteIndex, width := 0, 0; byteIndex < len(s); byteIndex += width { + runeValue, w := utf8.DecodeRuneInString(s[byteIndex:]) + width = w + char := string(runeValue) + if valueRe.MatchString(char) && char != "%" { + // The character is returned as is, no need to percent-encode + sb.WriteString(char) + } else { + // We need to percent-encode each byte of the multi-octet character + for j := 0; j < width; j++ { + b := s[byteIndex+j] + sb.WriteByte('%') + // Bitwise operations are inspired by "net/url" + sb.WriteByte(upperhex[b>>4]) + sb.WriteByte(upperhex[b&15]) + } + } + } + return sb.String() +} + +// Baggage is a list of baggage members representing the baggage-string as +// defined by the W3C Baggage specification. +type Baggage struct { //nolint:golint + list baggage.List +} + +// New returns a new valid Baggage. It returns an error if it results in a +// Baggage exceeding limits set in that specification. +// +// It expects all the provided members to have already been validated. +func New(members ...Member) (Baggage, error) { + if len(members) == 0 { + return Baggage{}, nil + } + + b := make(baggage.List) + for _, m := range members { + if !m.hasData { + return Baggage{}, errInvalidMember + } + + // OpenTelemetry resolves duplicates by last-one-wins. + b[m.key] = baggage.Item{ + Value: m.value, + Properties: m.properties.asInternal(), + } + } + + // Check member numbers after deduplication. + if len(b) > maxMembers { + return Baggage{}, errMemberNumber + } + + bag := Baggage{b} + if n := len(bag.String()); n > maxBytesPerBaggageString { + return Baggage{}, fmt.Errorf("%w: %d", errBaggageBytes, n) + } + + return bag, nil +} + +// Parse attempts to decode a baggage-string from the passed string. It +// returns an error if the input is invalid according to the W3C Baggage +// specification. +// +// If there are duplicate list-members contained in baggage, the last one +// defined (reading left-to-right) will be the only one kept. This diverges +// from the W3C Baggage specification which allows duplicate list-members, but +// conforms to the OpenTelemetry Baggage specification. +func Parse(bStr string) (Baggage, error) { + if bStr == "" { + return Baggage{}, nil + } + + if n := len(bStr); n > maxBytesPerBaggageString { + return Baggage{}, fmt.Errorf("%w: %d", errBaggageBytes, n) + } + + b := make(baggage.List) + for _, memberStr := range strings.Split(bStr, listDelimiter) { + m, err := parseMember(memberStr) + if err != nil { + return Baggage{}, err + } + // OpenTelemetry resolves duplicates by last-one-wins. + b[m.key] = baggage.Item{ + Value: m.value, + Properties: m.properties.asInternal(), + } + } + + // OpenTelemetry does not allow for duplicate list-members, but the W3C + // specification does. Now that we have deduplicated, ensure the baggage + // does not exceed list-member limits. + if len(b) > maxMembers { + return Baggage{}, errMemberNumber + } + + return Baggage{b}, nil +} + +// Member returns the baggage list-member identified by key. +// +// If there is no list-member matching the passed key the returned Member will +// be a zero-value Member. +// The returned member is not validated, as we assume the validation happened +// when it was added to the Baggage. +func (b Baggage) Member(key string) Member { + v, ok := b.list[key] + if !ok { + // We do not need to worry about distinguishing between the situation + // where a zero-valued Member is included in the Baggage because a + // zero-valued Member is invalid according to the W3C Baggage + // specification (it has an empty key). + return newInvalidMember() + } + + return Member{ + key: key, + value: v.Value, + properties: fromInternalProperties(v.Properties), + hasData: true, + } +} + +// Members returns all the baggage list-members. +// The order of the returned list-members does not have significance. +// +// The returned members are not validated, as we assume the validation happened +// when they were added to the Baggage. +func (b Baggage) Members() []Member { + if len(b.list) == 0 { + return nil + } + + members := make([]Member, 0, len(b.list)) + for k, v := range b.list { + members = append(members, Member{ + key: k, + value: v.Value, + properties: fromInternalProperties(v.Properties), + hasData: true, + }) + } + return members +} + +// SetMember returns a copy the Baggage with the member included. If the +// baggage contains a Member with the same key the existing Member is +// replaced. +// +// If member is invalid according to the W3C Baggage specification, an error +// is returned with the original Baggage. +func (b Baggage) SetMember(member Member) (Baggage, error) { + if !member.hasData { + return b, errInvalidMember + } + + n := len(b.list) + if _, ok := b.list[member.key]; !ok { + n++ + } + list := make(baggage.List, n) + + for k, v := range b.list { + // Do not copy if we are just going to overwrite. + if k == member.key { + continue + } + list[k] = v + } + + list[member.key] = baggage.Item{ + Value: member.value, + Properties: member.properties.asInternal(), + } + + return Baggage{list: list}, nil +} + +// DeleteMember returns a copy of the Baggage with the list-member identified +// by key removed. +func (b Baggage) DeleteMember(key string) Baggage { + n := len(b.list) + if _, ok := b.list[key]; ok { + n-- + } + list := make(baggage.List, n) + + for k, v := range b.list { + if k == key { + continue + } + list[k] = v + } + + return Baggage{list: list} +} + +// Len returns the number of list-members in the Baggage. +func (b Baggage) Len() int { + return len(b.list) +} + +// String encodes Baggage into a string compliant with the W3C Baggage +// specification. The returned string will be invalid if the Baggage contains +// any invalid list-members. +func (b Baggage) String() string { + members := make([]string, 0, len(b.list)) + for k, v := range b.list { + members = append(members, Member{ + key: k, + value: v.Value, + properties: fromInternalProperties(v.Properties), + }.String()) + } + return strings.Join(members, listDelimiter) +} diff --git a/vendor/github.com/getsentry/sentry-go/internal/otel/baggage/internal/baggage/baggage.go b/vendor/github.com/getsentry/sentry-go/internal/otel/baggage/internal/baggage/baggage.go new file mode 100644 index 000000000..04e414024 --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/internal/otel/baggage/internal/baggage/baggage.go @@ -0,0 +1,46 @@ +// This file was vendored in unmodified from +// https://github.com/open-telemetry/opentelemetry-go/blob/c21b6b6bb31a2f74edd06e262f1690f3f6ea3d5c/internal/baggage/baggage.go +// +// Copyright The OpenTelemetry 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 baggage provides base types and functionality to store and retrieve +baggage in Go context. This package exists because the OpenTracing bridge to +OpenTelemetry needs to synchronize state whenever baggage for a context is +modified and that context contains an OpenTracing span. If it were not for +this need this package would not need to exist and the +`go.opentelemetry.io/otel/baggage` package would be the singular place where +W3C baggage is handled. +*/ +package baggage + +// List is the collection of baggage members. The W3C allows for duplicates, +// but OpenTelemetry does not, therefore, this is represented as a map. +type List map[string]Item + +// Item is the value and metadata properties part of a list-member. +type Item struct { + Value string + Properties []Property +} + +// Property is a metadata entry for a list-member. +type Property struct { + Key, Value string + + // HasValue indicates if a zero-value value means the property does not + // have a value or if it was the zero-value. + HasValue bool +} diff --git a/vendor/github.com/getsentry/sentry-go/internal/ratelimit/category.go b/vendor/github.com/getsentry/sentry-go/internal/ratelimit/category.go new file mode 100644 index 000000000..cf5dff50b --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/internal/ratelimit/category.go @@ -0,0 +1,46 @@ +package ratelimit + +import ( + "strings" + + "golang.org/x/text/cases" + "golang.org/x/text/language" +) + +// Reference: +// https://github.com/getsentry/relay/blob/0424a2e017d193a93918053c90cdae9472d164bf/relay-common/src/constants.rs#L116-L127 + +// Category classifies supported payload types that can be ingested by Sentry +// and, therefore, rate limited. +type Category string + +// Known rate limit categories. As a special case, the CategoryAll applies to +// all known payload types. +const ( + CategoryAll Category = "" + CategoryError Category = "error" + CategoryTransaction Category = "transaction" +) + +// knownCategories is the set of currently known categories. Other categories +// are ignored for the purpose of rate-limiting. +var knownCategories = map[Category]struct{}{ + CategoryAll: {}, + CategoryError: {}, + CategoryTransaction: {}, +} + +// String returns the category formatted for debugging. +func (c Category) String() string { + switch c { + case "": + return "CategoryAll" + default: + caser := cases.Title(language.English) + rv := "Category" + for _, w := range strings.Fields(string(c)) { + rv += caser.String(w) + } + return rv + } +} diff --git a/vendor/github.com/getsentry/sentry-go/internal/ratelimit/deadline.go b/vendor/github.com/getsentry/sentry-go/internal/ratelimit/deadline.go new file mode 100644 index 000000000..c00258335 --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/internal/ratelimit/deadline.go @@ -0,0 +1,22 @@ +package ratelimit + +import "time" + +// A Deadline is a time instant when a rate limit expires. +type Deadline time.Time + +// After reports whether the deadline d is after other. +func (d Deadline) After(other Deadline) bool { + return time.Time(d).After(time.Time(other)) +} + +// Equal reports whether d and e represent the same deadline. +func (d Deadline) Equal(e Deadline) bool { + return time.Time(d).Equal(time.Time(e)) +} + +// String returns the deadline formatted for debugging. +func (d Deadline) String() string { + // Like time.Time.String, but without the monotonic clock reading. + return time.Time(d).Round(0).String() +} diff --git a/vendor/github.com/getsentry/sentry-go/internal/ratelimit/doc.go b/vendor/github.com/getsentry/sentry-go/internal/ratelimit/doc.go new file mode 100644 index 000000000..80b9fdda2 --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/internal/ratelimit/doc.go @@ -0,0 +1,3 @@ +// Package ratelimit provides tools to work with rate limits imposed by Sentry's +// data ingestion pipeline. +package ratelimit diff --git a/vendor/github.com/getsentry/sentry-go/internal/ratelimit/map.go b/vendor/github.com/getsentry/sentry-go/internal/ratelimit/map.go new file mode 100644 index 000000000..e590430ec --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/internal/ratelimit/map.go @@ -0,0 +1,64 @@ +package ratelimit + +import ( + "net/http" + "time" +) + +// Map maps categories to rate limit deadlines. +// +// A rate limit is in effect for a given category if either the category's +// deadline or the deadline for the special CategoryAll has not yet expired. +// +// Use IsRateLimited to check whether a category is rate-limited. +type Map map[Category]Deadline + +// IsRateLimited returns true if the category is currently rate limited. +func (m Map) IsRateLimited(c Category) bool { + return m.isRateLimited(c, time.Now()) +} + +func (m Map) isRateLimited(c Category, now time.Time) bool { + return m.Deadline(c).After(Deadline(now)) +} + +// Deadline returns the deadline when the rate limit for the given category or +// the special CategoryAll expire, whichever is furthest into the future. +func (m Map) Deadline(c Category) Deadline { + categoryDeadline := m[c] + allDeadline := m[CategoryAll] + if categoryDeadline.After(allDeadline) { + return categoryDeadline + } + return allDeadline +} + +// Merge merges the other map into m. +// +// If a category appears in both maps, the deadline that is furthest into the +// future is preserved. +func (m Map) Merge(other Map) { + for c, d := range other { + if d.After(m[c]) { + m[c] = d + } + } +} + +// FromResponse returns a rate limit map from an HTTP response. +func FromResponse(r *http.Response) Map { + return fromResponse(r, time.Now()) +} + +func fromResponse(r *http.Response, now time.Time) Map { + s := r.Header.Get("X-Sentry-Rate-Limits") + if s != "" { + return parseXSentryRateLimits(s, now) + } + if r.StatusCode == http.StatusTooManyRequests { + s := r.Header.Get("Retry-After") + deadline, _ := parseRetryAfter(s, now) + return Map{CategoryAll: deadline} + } + return Map{} +} diff --git a/vendor/github.com/getsentry/sentry-go/internal/ratelimit/rate_limits.go b/vendor/github.com/getsentry/sentry-go/internal/ratelimit/rate_limits.go new file mode 100644 index 000000000..579297e42 --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/internal/ratelimit/rate_limits.go @@ -0,0 +1,76 @@ +package ratelimit + +import ( + "errors" + "math" + "strconv" + "strings" + "time" +) + +var errInvalidXSRLRetryAfter = errors.New("invalid retry-after value") + +// parseXSentryRateLimits returns a RateLimits map by parsing an input string in +// the format of the X-Sentry-Rate-Limits header. +// +// Example +// +// X-Sentry-Rate-Limits: 60:transaction, 2700:default;error;security +// +// This will rate limit transactions for the next 60 seconds and errors for the +// next 2700 seconds. +// +// Limits for unknown categories are ignored. +func parseXSentryRateLimits(s string, now time.Time) Map { + // https://github.com/getsentry/relay/blob/0424a2e017d193a93918053c90cdae9472d164bf/relay-server/src/utils/rate_limits.rs#L44-L82 + m := make(Map, len(knownCategories)) + for _, limit := range strings.Split(s, ",") { + limit = strings.TrimSpace(limit) + if limit == "" { + continue + } + components := strings.Split(limit, ":") + if len(components) == 0 { + continue + } + retryAfter, err := parseXSRLRetryAfter(strings.TrimSpace(components[0]), now) + if err != nil { + continue + } + categories := "" + if len(components) > 1 { + categories = components[1] + } + for _, category := range strings.Split(categories, ";") { + c := Category(strings.ToLower(strings.TrimSpace(category))) + if _, ok := knownCategories[c]; !ok { + // skip unknown categories, keep m small + continue + } + // always keep the deadline furthest into the future + if retryAfter.After(m[c]) { + m[c] = retryAfter + } + } + } + return m +} + +// parseXSRLRetryAfter parses a string into a retry-after rate limit deadline. +// +// Valid input is a number, possibly signed and possibly floating-point, +// indicating the number of seconds to wait before sending another request. +// Negative values are treated as zero. Fractional values are rounded to the +// next integer. +func parseXSRLRetryAfter(s string, now time.Time) (Deadline, error) { + // https://github.com/getsentry/relay/blob/0424a2e017d193a93918053c90cdae9472d164bf/relay-quotas/src/rate_limit.rs#L88-L96 + f, err := strconv.ParseFloat(s, 64) + if err != nil { + return Deadline{}, errInvalidXSRLRetryAfter + } + d := time.Duration(math.Ceil(math.Max(f, 0.0))) * time.Second + if d < 0 { + d = 0 + } + return Deadline(now.Add(d)), nil +} diff --git a/vendor/github.com/getsentry/sentry-go/internal/ratelimit/retry_after.go b/vendor/github.com/getsentry/sentry-go/internal/ratelimit/retry_after.go new file mode 100644 index 000000000..576e29dcd --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/internal/ratelimit/retry_after.go @@ -0,0 +1,40 @@ +package ratelimit + +import ( + "errors" + "strconv" + "time" +) + +const defaultRetryAfter = 1 * time.Minute + +var errInvalidRetryAfter = errors.New("invalid input") + +// parseRetryAfter parses a string s as in the standard Retry-After HTTP header +// and returns a deadline until when requests are rate limited and therefore new +// requests should not be sent. The input may be either a date or a non-negative +// integer number of seconds. +// +// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After +// +// parseRetryAfter always returns a usable deadline, even in case of an error. +// +// This is the original rate limiting mechanism used by Sentry, superseeded by +// the X-Sentry-Rate-Limits response header. +func parseRetryAfter(s string, now time.Time) (Deadline, error) { + if s == "" { + goto invalid + } + if n, err := strconv.Atoi(s); err == nil { + if n < 0 { + goto invalid + } + d := time.Duration(n) * time.Second + return Deadline(now.Add(d)), nil + } + if date, err := time.Parse(time.RFC1123, s); err == nil { + return Deadline(date), nil + } +invalid: + return Deadline(now.Add(defaultRetryAfter)), errInvalidRetryAfter +} diff --git a/vendor/github.com/cockroachdb/sentry-go/scope.go b/vendor/github.com/getsentry/sentry-go/scope.go similarity index 80% rename from vendor/github.com/cockroachdb/sentry-go/scope.go rename to vendor/github.com/getsentry/sentry-go/scope.go index 600cd81b2..063047b91 100644 --- a/vendor/github.com/cockroachdb/sentry-go/scope.go +++ b/vendor/github.com/getsentry/sentry-go/scope.go @@ -4,32 +4,30 @@ import ( "bytes" "io" "net/http" - "reflect" "sync" "time" ) // Scope holds contextual data for the current scope. // -// The scope is an object that can cloned efficiently and stores data that -// is locally relevant to an event. For instance the scope will hold recorded +// The scope is an object that can cloned efficiently and stores data that is +// locally relevant to an event. For instance the scope will hold recorded // breadcrumbs and similar information. // -// The scope can be interacted with in two ways: +// The scope can be interacted with in two ways. First, the scope is routinely +// updated with information by functions such as AddBreadcrumb which will modify +// the current scope. Second, the current scope can be configured through the +// ConfigureScope function or Hub method of the same name. // -// 1. the scope is routinely updated with information by functions such as -// `AddBreadcrumb` which will modify the currently top-most scope. -// 2. the topmost scope can also be configured through the `ConfigureScope` -// method. -// -// Note that the scope can only be modified but not inspected. -// Only the client can use the scope to extract information currently. +// The scope is meant to be modified but not inspected directly. When preparing +// an event for reporting, the current client adds information from the current +// scope into the event. type Scope struct { mu sync.RWMutex breadcrumbs []*Breadcrumb user User tags map[string]string - contexts map[string]interface{} + contexts map[string]Context extra map[string]interface{} fingerprint []string level Level @@ -47,11 +45,12 @@ type Scope struct { eventProcessors []EventProcessor } +// NewScope creates a new Scope. func NewScope() *Scope { scope := Scope{ breadcrumbs: make([]*Breadcrumb, 0), tags: make(map[string]string), - contexts: make(map[string]interface{}), + contexts: make(map[string]Context), extra: make(map[string]interface{}), fingerprint: make([]string, 0), } @@ -63,17 +62,15 @@ func NewScope() *Scope { // and optionally throws the old one if limit is reached. func (scope *Scope) AddBreadcrumb(breadcrumb *Breadcrumb, limit int) { if breadcrumb.Timestamp.IsZero() { - breadcrumb.Timestamp = time.Now().UTC() + breadcrumb.Timestamp = time.Now() } scope.mu.Lock() defer scope.mu.Unlock() - breadcrumbs := append(scope.breadcrumbs, breadcrumb) - if len(breadcrumbs) > limit { - scope.breadcrumbs = breadcrumbs[1 : limit+1] - } else { - scope.breadcrumbs = breadcrumbs + scope.breadcrumbs = append(scope.breadcrumbs, breadcrumb) + if len(scope.breadcrumbs) > limit { + scope.breadcrumbs = scope.breadcrumbs[1 : limit+1] } } @@ -148,7 +145,7 @@ const maxRequestBodyBytes = 10 * 1024 // A limitedBuffer is like a bytes.Buffer, but limited to store at most Capacity // bytes. Any writes past the capacity are silently discarded, similar to -// ioutil.Discard. +// io.Discard. type limitedBuffer struct { Capacity int @@ -211,7 +208,7 @@ func (scope *Scope) RemoveTag(key string) { } // SetContext adds a context to the current scope. -func (scope *Scope) SetContext(key string, value interface{}) { +func (scope *Scope) SetContext(key string, value Context) { scope.mu.Lock() defer scope.mu.Unlock() @@ -219,7 +216,7 @@ func (scope *Scope) SetContext(key string, value interface{}) { } // SetContexts assigns multiple contexts to the current scope. -func (scope *Scope) SetContexts(contexts map[string]interface{}) { +func (scope *Scope) SetContexts(contexts map[string]Context) { scope.mu.Lock() defer scope.mu.Unlock() @@ -278,12 +275,20 @@ func (scope *Scope) SetLevel(level Level) { scope.level = level } -// SetTransaction sets new transaction name for the current transaction. -func (scope *Scope) SetTransaction(transactionName string) { +// SetTransaction sets the transaction name for the current transaction. +func (scope *Scope) SetTransaction(name string) { scope.mu.Lock() defer scope.mu.Unlock() - scope.transaction = transactionName + scope.transaction = name +} + +// Transaction returns the transaction name for the current transaction. +func (scope *Scope) Transaction() (name string) { + scope.mu.RLock() + defer scope.mu.RUnlock() + + return scope.transaction } // Clone returns a copy of the current scope with all data copied over. @@ -309,7 +314,8 @@ func (scope *Scope) Clone() *Scope { clone.level = scope.level clone.transaction = scope.transaction clone.request = scope.request - + clone.requestBody = scope.requestBody + clone.eventProcessors = scope.eventProcessors return clone } @@ -332,16 +338,12 @@ func (scope *Scope) ApplyToEvent(event *Event, hint *EventHint) *Event { defer scope.mu.RUnlock() if len(scope.breadcrumbs) > 0 { - if event.Breadcrumbs == nil { - event.Breadcrumbs = []*Breadcrumb{} - } - event.Breadcrumbs = append(event.Breadcrumbs, scope.breadcrumbs...) } if len(scope.tags) > 0 { if event.Tags == nil { - event.Tags = make(map[string]string) + event.Tags = make(map[string]string, len(scope.tags)) } for key, value := range scope.tags { @@ -351,17 +353,29 @@ func (scope *Scope) ApplyToEvent(event *Event, hint *EventHint) *Event { if len(scope.contexts) > 0 { if event.Contexts == nil { - event.Contexts = make(map[string]interface{}) + event.Contexts = make(map[string]Context) } for key, value := range scope.contexts { - event.Contexts[key] = value + if key == "trace" && event.Type == transactionType { + // Do not override trace context of + // transactions, otherwise it breaks the + // transaction event representation. + // For error events, the trace context is used + // to link errors and traces/spans in Sentry. + continue + } + + // Ensure we are not overwriting event fields + if _, ok := event.Contexts[key]; !ok { + event.Contexts[key] = value + } } } if len(scope.extra) > 0 { if event.Extra == nil { - event.Extra = make(map[string]interface{}) + event.Extra = make(map[string]interface{}, len(scope.extra)) } for key, value := range scope.extra { @@ -369,14 +383,12 @@ func (scope *Scope) ApplyToEvent(event *Event, hint *EventHint) *Event { } } - if (reflect.DeepEqual(event.User, User{})) { + if event.User.IsEmpty() { event.User = scope.user } - if (event.Fingerprint == nil || len(event.Fingerprint) == 0) && - len(scope.fingerprint) > 0 { - event.Fingerprint = make([]string, len(scope.fingerprint)) - copy(event.Fingerprint, scope.fingerprint) + if len(event.Fingerprint) == 0 { + event.Fingerprint = append(event.Fingerprint, scope.fingerprint...) } if scope.level != "" { diff --git a/vendor/github.com/cockroachdb/sentry-go/sentry.go b/vendor/github.com/getsentry/sentry-go/sentry.go similarity index 77% rename from vendor/github.com/cockroachdb/sentry-go/sentry.go rename to vendor/github.com/getsentry/sentry-go/sentry.go index 8d736ab0e..7b3fdec9c 100644 --- a/vendor/github.com/cockroachdb/sentry-go/sentry.go +++ b/vendor/github.com/getsentry/sentry-go/sentry.go @@ -5,14 +5,24 @@ import ( "time" ) -// Version is the version of the sentry-go SDK. -const Version = "0.6.1" +// Deprecated: Use SDKVersion instead. +const Version = SDKVersion + +// Version is the version of the SDK. +const SDKVersion = "0.18.0" + +// The identifier of the SDK. +const SDKIdentifier = "sentry.go" // apiVersion is the minimum version of the Sentry API compatible with the // sentry-go SDK. const apiVersion = "7" -// Init initializes whole SDK by creating new `Client` and binding it to the current `Hub` +// userAgent is the User-Agent of outgoing HTTP requests. +const userAgent = "sentry-go/" + SDKVersion + +// Init initializes the SDK with options. The returned error is non-nil if +// options is invalid, for instance if a malformed DSN is provided. func Init(options ClientOptions) error { hub := CurrentHub() client, err := NewClient(options) @@ -47,7 +57,7 @@ func CaptureException(exception error) *EventID { // CaptureEvent captures an event on the currently active client if any. // // The event must already be assembled. Typically code would instead use -// the utility methods like `CaptureException`. The return value is the +// the utility methods like CaptureException. The return value is the // event ID. In case Sentry is disabled or event was dropped, the return value will be nil. func CaptureEvent(event *Event) *EventID { hub := CurrentHub() @@ -63,7 +73,7 @@ func Recover() *EventID { return nil } -// Recover captures a panic and passes relevant context object. +// RecoverWithContext captures a panic and passes relevant context object. func RecoverWithContext(ctx context.Context) *EventID { if err := recover(); err != nil { var hub *Hub @@ -79,34 +89,25 @@ func RecoverWithContext(ctx context.Context) *EventID { return nil } -// WithScope temporarily pushes a scope for a single call. -// -// This function takes one argument, a callback that executes -// in the context of that scope. -// -// This is useful when extra data should be send with a single capture call -// for instance a different level or tags +// WithScope is a shorthand for CurrentHub().WithScope. func WithScope(f func(scope *Scope)) { hub := CurrentHub() hub.WithScope(f) } -// ConfigureScope invokes a function that can modify the current scope. -// -// The function is passed a mutable reference to the `Scope` so that modifications -// can be performed. +// ConfigureScope is a shorthand for CurrentHub().ConfigureScope. func ConfigureScope(f func(scope *Scope)) { hub := CurrentHub() hub.ConfigureScope(f) } -// PushScope pushes a new scope. +// PushScope is a shorthand for CurrentHub().PushScope. func PushScope() { hub := CurrentHub() hub.PushScope() } -// PopScope pushes a new scope. +// PopScope is a shorthand for CurrentHub().PopScope. func PopScope() { hub := CurrentHub() hub.PopScope() diff --git a/vendor/github.com/cockroachdb/sentry-go/sourcereader.go b/vendor/github.com/getsentry/sentry-go/sourcereader.go similarity index 88% rename from vendor/github.com/cockroachdb/sentry-go/sourcereader.go rename to vendor/github.com/getsentry/sentry-go/sourcereader.go index 2d357689b..74a083848 100644 --- a/vendor/github.com/cockroachdb/sentry-go/sourcereader.go +++ b/vendor/github.com/getsentry/sentry-go/sourcereader.go @@ -2,7 +2,7 @@ package sentry import ( "bytes" - "io/ioutil" + "os" "sync" ) @@ -24,7 +24,7 @@ func (sr *sourceReader) readContextLines(filename string, line, context int) ([] lines, ok := sr.cache[filename] if !ok { - data, err := ioutil.ReadFile(filename) + data, err := os.ReadFile(filename) if err != nil { sr.cache[filename] = nil return nil, 0 @@ -36,11 +36,12 @@ func (sr *sourceReader) readContextLines(filename string, line, context int) ([] return sr.calculateContextLines(lines, line, context) } -// `contextLine` points to a line that caused an issue itself, in relation to returned slice func (sr *sourceReader) calculateContextLines(lines [][]byte, line, context int) ([][]byte, int) { // Stacktrace lines are 1-indexed, slices are 0-indexed line-- + // contextLine points to a line that caused an issue itself, in relation to + // returned slice. contextLine := context if lines == nil || line >= len(lines) || line < 0 { diff --git a/vendor/github.com/getsentry/sentry-go/span_recorder.go b/vendor/github.com/getsentry/sentry-go/span_recorder.go new file mode 100644 index 000000000..137aa233e --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/span_recorder.go @@ -0,0 +1,56 @@ +package sentry + +import ( + "sync" +) + +// A spanRecorder stores a span tree that makes up a transaction. Safe for +// concurrent use. It is okay to add child spans from multiple goroutines. +type spanRecorder struct { + mu sync.Mutex + spans []*Span + overflowOnce sync.Once +} + +// record stores a span. The first stored span is assumed to be the root of a +// span tree. +func (r *spanRecorder) record(s *Span) { + maxSpans := defaultMaxSpans + if client := CurrentHub().Client(); client != nil { + maxSpans = client.Options().MaxSpans + } + r.mu.Lock() + defer r.mu.Unlock() + if len(r.spans) >= maxSpans { + r.overflowOnce.Do(func() { + root := r.spans[0] + Logger.Printf("Too many spans: dropping spans from transaction with TraceID=%s SpanID=%s limit=%d", + root.TraceID, root.SpanID, maxSpans) + }) + // TODO(tracing): mark the transaction event in some way to + // communicate that spans were dropped. + return + } + r.spans = append(r.spans, s) +} + +// root returns the first recorded span. Returns nil if none have been recorded. +func (r *spanRecorder) root() *Span { + r.mu.Lock() + defer r.mu.Unlock() + if len(r.spans) == 0 { + return nil + } + return r.spans[0] +} + +// children returns a list of all recorded spans, except the root. Returns nil +// if there are no children. +func (r *spanRecorder) children() []*Span { + r.mu.Lock() + defer r.mu.Unlock() + if len(r.spans) < 2 { + return nil + } + return r.spans[1:] +} diff --git a/vendor/github.com/cockroachdb/sentry-go/stacktrace.go b/vendor/github.com/getsentry/sentry-go/stacktrace.go similarity index 57% rename from vendor/github.com/cockroachdb/sentry-go/stacktrace.go rename to vendor/github.com/getsentry/sentry-go/stacktrace.go index d1f7ede89..8c256ec98 100644 --- a/vendor/github.com/cockroachdb/sentry-go/stacktrace.go +++ b/vendor/github.com/getsentry/sentry-go/stacktrace.go @@ -23,7 +23,7 @@ type Stacktrace struct { FramesOmitted []uint `json:"frames_omitted,omitempty"` } -// NewStacktrace creates a stacktrace using `runtime.Callers`. +// NewStacktrace creates a stacktrace using runtime.Callers. func NewStacktrace() *Stacktrace { pcs := make([]uintptr, 100) n := runtime.Callers(1, pcs) @@ -42,17 +42,21 @@ func NewStacktrace() *Stacktrace { return &stacktrace } -// ExtractStacktrace creates a new `Stacktrace` based on the given `error` object. // TODO: Make it configurable so that anyone can provide their own implementation? -// Use of reflection allows us to not have a hard dependency on any given package, so we don't have to import it +// Use of reflection allows us to not have a hard dependency on any given +// package, so we don't have to import it. + +// ExtractStacktrace creates a new Stacktrace based on the given error. func ExtractStacktrace(err error) *Stacktrace { method := extractReflectedStacktraceMethod(err) - if !method.IsValid() { - return nil - } + var pcs []uintptr - pcs := extractPcs(method) + if method.IsValid() { + pcs = extractPcs(method) + } else { + pcs = extractXErrorsPC(err) + } if len(pcs) == 0 { return nil @@ -69,39 +73,38 @@ func ExtractStacktrace(err error) *Stacktrace { } func extractReflectedStacktraceMethod(err error) reflect.Value { - var method reflect.Value + errValue := reflect.ValueOf(err) - // https://github.com/pingcap/errors - methodGetStackTracer := reflect.ValueOf(err).MethodByName("GetStackTracer") - // https://github.com/pkg/errors - methodStackTrace := reflect.ValueOf(err).MethodByName("StackTrace") // https://github.com/go-errors/errors - methodStackFrames := reflect.ValueOf(err).MethodByName("StackFrames") + methodStackFrames := errValue.MethodByName("StackFrames") + if methodStackFrames.IsValid() { + return methodStackFrames + } + // https://github.com/pkg/errors + methodStackTrace := errValue.MethodByName("StackTrace") + if methodStackTrace.IsValid() { + return methodStackTrace + } + + // https://github.com/pingcap/errors + methodGetStackTracer := errValue.MethodByName("GetStackTracer") if methodGetStackTracer.IsValid() { - stacktracer := methodGetStackTracer.Call(make([]reflect.Value, 0))[0] + stacktracer := methodGetStackTracer.Call(nil)[0] stacktracerStackTrace := reflect.ValueOf(stacktracer).MethodByName("StackTrace") if stacktracerStackTrace.IsValid() { - method = stacktracerStackTrace + return stacktracerStackTrace } } - if methodStackTrace.IsValid() { - method = methodStackTrace - } - - if methodStackFrames.IsValid() { - method = methodStackFrames - } - - return method + return reflect.Value{} } func extractPcs(method reflect.Value) []uintptr { var pcs []uintptr - stacktrace := method.Call(make([]reflect.Value, 0))[0] + stacktrace := method.Call(nil)[0] if stacktrace.Kind() != reflect.Slice { return nil @@ -110,16 +113,19 @@ func extractPcs(method reflect.Value) []uintptr { for i := 0; i < stacktrace.Len(); i++ { pc := stacktrace.Index(i) - if pc.Kind() == reflect.Uintptr { + switch pc.Kind() { + case reflect.Uintptr: pcs = append(pcs, uintptr(pc.Uint())) - continue - } - - if pc.Kind() == reflect.Struct { - field := pc.FieldByName("ProgramCounter") - if field.IsValid() && field.Kind() == reflect.Uintptr { - pcs = append(pcs, uintptr(field.Uint())) - continue + case reflect.Struct: + for _, fieldName := range []string{"ProgramCounter", "PC"} { + field := pc.FieldByName(fieldName) + if !field.IsValid() { + continue + } + if field.Kind() == reflect.Uintptr { + pcs = append(pcs, uintptr(field.Uint())) + break + } } } } @@ -127,11 +133,45 @@ func extractPcs(method reflect.Value) []uintptr { return pcs } -// https://docs.sentry.io/development/sdk-dev/event-payloads/stacktrace/ +// extractXErrorsPC extracts program counters from error values compatible with +// the error types from golang.org/x/xerrors. +// +// It returns nil if err is not compatible with errors from that package or if +// no program counters are stored in err. +func extractXErrorsPC(err error) []uintptr { + // This implementation uses the reflect package to avoid a hard dependency + // on third-party packages. + + // We don't know if err matches the expected type. For simplicity, instead + // of trying to account for all possible ways things can go wrong, some + // assumptions are made and if they are violated the code will panic. We + // recover from any panic and ignore it, returning nil. + //nolint: errcheck + defer func() { recover() }() + + field := reflect.ValueOf(err).Elem().FieldByName("frame") // type Frame struct{ frames [3]uintptr } + field = field.FieldByName("frames") + field = field.Slice(1, field.Len()) // drop first pc pointing to xerrors.New + pc := make([]uintptr, field.Len()) + for i := 0; i < field.Len(); i++ { + pc[i] = uintptr(field.Index(i).Uint()) + } + return pc +} + +// Frame represents a function call and it's metadata. Frames are associated +// with a Stacktrace. type Frame struct { - Function string `json:"function,omitempty"` - Symbol string `json:"symbol,omitempty"` - Module string `json:"module,omitempty"` + Function string `json:"function,omitempty"` + Symbol string `json:"symbol,omitempty"` + // Module is, despite the name, the Sentry protocol equivalent of a Go + // package's import path. + Module string `json:"module,omitempty"` + // Package is not used for Go stack trace frames. In other platforms it + // refers to a container where the Module can be found. For example, a + // Java JAR, a .NET Assembly, or a native dynamic library. + // It exists for completeness, allowing the construction and reporting + // of custom event payloads. Package string `json:"package,omitempty"` Filename string `json:"filename,omitempty"` AbsPath string `json:"abs_path,omitempty"` @@ -144,22 +184,38 @@ type Frame struct { Vars map[string]interface{} `json:"vars,omitempty"` } -// NewFrame assembles a stacktrace frame out of `runtime.Frame`. +// NewFrame assembles a stacktrace frame out of runtime.Frame. func NewFrame(f runtime.Frame) Frame { - abspath := f.File - filename := f.File - function := f.Function - var pkg string - - if filename != "" { - filename = filepath.Base(filename) - } else { - filename = unknown + var abspath, relpath string + // NOTE: f.File paths historically use forward slash as path separator even + // on Windows, though this is not yet documented, see + // https://golang.org/issues/3335. In any case, filepath.IsAbs can work with + // paths with either slash or backslash on Windows. + switch { + case f.File == "": + relpath = unknown + // Leave abspath as the empty string to be omitted when serializing + // event as JSON. + abspath = "" + case filepath.IsAbs(f.File): + abspath = f.File + // TODO: in the general case, it is not trivial to come up with a + // "project relative" path with the data we have in run time. + // We shall not use filepath.Base because it creates ambiguous paths and + // affects the "Suspect Commits" feature. + // For now, leave relpath empty to be omitted when serializing the event + // as JSON. Improve this later. + relpath = "" + default: + // f.File is a relative path. This may happen when the binary is built + // with the -trimpath flag. + relpath = f.File + // Omit abspath when serializing the event as JSON. + abspath = "" } - if abspath == "" { - abspath = unknown - } + function := f.Function + var pkg string if function != "" { pkg, function = splitQualifiedFunctionName(function) @@ -167,7 +223,7 @@ func NewFrame(f runtime.Frame) Frame { frame := Frame{ AbsPath: abspath, - Filename: filename, + Filename: relpath, Lineno: f.Line, Module: pkg, Function: function, @@ -188,21 +244,24 @@ func splitQualifiedFunctionName(name string) (pkg string, fun string) { } func extractFrames(pcs []uintptr) []Frame { - var frames []Frame + var frames = make([]Frame, 0, len(pcs)) callersFrames := runtime.CallersFrames(pcs) for { callerFrame, more := callersFrames.Next() - frames = append([]Frame{ - NewFrame(callerFrame), - }, frames...) + frames = append(frames, NewFrame(callerFrame)) if !more { break } } + // reverse + for i, j := 0, len(frames)-1; i < j; i, j = i+1, j-1 { + frames[i], frames[j] = frames[j], frames[i] + } + return frames } @@ -213,7 +272,8 @@ func filterFrames(frames []Frame) []Frame { return nil } - filteredFrames := make([]Frame, 0, len(frames)) + // reuse + filteredFrames := frames[:0] for _, frame := range frames { // Skip Go internal frames. @@ -222,7 +282,7 @@ func filterFrames(frames []Frame) []Frame { } // Skip Sentry internal frames, except for frames in _test packages (for // testing). - if strings.HasPrefix(frame.Module, "github.com/cockroachdb/sentry-go") && + if strings.HasPrefix(frame.Module, "github.com/getsentry/sentry-go") && !strings.HasSuffix(frame.Module, "_test") { continue } diff --git a/vendor/github.com/getsentry/sentry-go/traces_sampler.go b/vendor/github.com/getsentry/sentry-go/traces_sampler.go new file mode 100644 index 000000000..69e7cb7fa --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/traces_sampler.go @@ -0,0 +1,19 @@ +package sentry + +// A SamplingContext is passed to a TracesSampler to determine a sampling +// decision. +// +// TODO(tracing): possibly expand SamplingContext to include custom / +// user-provided data. +type SamplingContext struct { + Span *Span // The current span, always non-nil. + Parent *Span // The parent span, may be nil. +} + +// The TracesSample type is an adapter to allow the use of ordinary +// functions as a TracesSampler. +type TracesSampler func(ctx SamplingContext) float64 + +func (f TracesSampler) Sample(ctx SamplingContext) float64 { + return f(ctx) +} diff --git a/vendor/github.com/getsentry/sentry-go/tracing.go b/vendor/github.com/getsentry/sentry-go/tracing.go new file mode 100644 index 000000000..e18325dd2 --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/tracing.go @@ -0,0 +1,881 @@ +package sentry + +import ( + "context" + "crypto/rand" + "encoding/hex" + "encoding/json" + "fmt" + "net/http" + "regexp" + "strings" + "time" +) + +const ( + SentryTraceHeader = "sentry-trace" + SentryBaggageHeader = "baggage" +) + +// A Span is the building block of a Sentry transaction. Spans build up a tree +// structure of timed operations. The span tree makes up a transaction event +// that is sent to Sentry when the root span is finished. +// +// Spans must be started with either StartSpan or Span.StartChild. +type Span struct { //nolint: maligned // prefer readability over optimal memory layout (see note below *) + TraceID TraceID `json:"trace_id"` + SpanID SpanID `json:"span_id"` + ParentSpanID SpanID `json:"parent_span_id"` + Op string `json:"op,omitempty"` + Description string `json:"description,omitempty"` + Status SpanStatus `json:"status,omitempty"` + Tags map[string]string `json:"tags,omitempty"` + StartTime time.Time `json:"start_timestamp"` + EndTime time.Time `json:"timestamp"` + Data map[string]interface{} `json:"data,omitempty"` + Sampled Sampled `json:"-"` + Source TransactionSource `json:"-"` + + // sample rate the span was sampled with. + sampleRate float64 + // ctx is the context where the span was started. Always non-nil. + ctx context.Context + // Dynamic Sampling context + dynamicSamplingContext DynamicSamplingContext + // parent refers to the immediate local parent span. A remote parent span is + // only referenced by setting ParentSpanID. + parent *Span + // isTransaction is true only for the root span of a local span tree. The + // root span is the first span started in a context. Note that a local root + // span may have a remote parent belonging to the same trace, therefore + // isTransaction depends on ctx and not on parent. + isTransaction bool + // recorder stores all spans in a transaction. Guaranteed to be non-nil. + recorder *spanRecorder +} + +// TraceParentContext describes the context of a (remote) parent span. +// +// The context is normally extracted from a received "sentry-trace" header and +// used to initialize a new transaction. +// +// Note: the name might be not the best one. It was taken mostly to stay aligned +// with other SDKs, and it alludes to W3C "traceparent" header (https://www.w3.org/TR/trace-context/), +// which serves a similar purpose to "sentry-trace". We should eventually consider +// making this type internal-only and give it a better name. +type TraceParentContext struct { + TraceID TraceID + ParentSpanID SpanID + Sampled Sampled +} + +// (*) Note on maligned: +// +// We prefer readability over optimal memory layout. If we ever decide to +// reorder fields, we can use a tool: +// +// go run honnef.co/go/tools/cmd/structlayout -json . Span | go run honnef.co/go/tools/cmd/structlayout-optimize +// +// Other structs would deserve reordering as well, for example Event. + +// TODO: make Span.Tags and Span.Data opaque types (struct{unexported []slice}). +// An opaque type allows us to add methods and make it more convenient to use +// than maps, because maps require careful nil checks to use properly or rely on +// explicit initialization for every span, even when there might be no +// tags/data. For Span.Data, must gracefully handle values that cannot be +// marshaled into JSON (see transport.go:getRequestBodyFromEvent). + +// StartSpan starts a new span to describe an operation. The new span will be a +// child of the last span stored in ctx, if any. +// +// One or more options can be used to modify the span properties. Typically one +// option as a function literal is enough. Combining multiple options can be +// useful to define and reuse specific properties with named functions. +// +// Caller should call the Finish method on the span to mark its end. Finishing a +// root span sends the span and all of its children, recursively, as a +// transaction to Sentry. +func StartSpan(ctx context.Context, operation string, options ...SpanOption) *Span { + parent, hasParent := ctx.Value(spanContextKey{}).(*Span) + var span Span + span = Span{ + // defaults + Op: operation, + StartTime: time.Now(), + Sampled: SampledUndefined, + + ctx: context.WithValue(ctx, spanContextKey{}, &span), + parent: parent, + isTransaction: !hasParent, + } + if hasParent { + span.TraceID = parent.TraceID + } else { + // Only set the Source if this is a transaction + span.Source = SourceCustom + + // Implementation note: + // + // While math/rand is ~2x faster than crypto/rand (exact + // difference depends on hardware / OS), crypto/rand is probably + // fast enough and a safer choice. + // + // For reference, OpenTelemetry [1] uses crypto/rand to seed + // math/rand. AFAICT this approach does not preserve the + // properties from crypto/rand that make it suitable for + // cryptography. While it might be debatable whether those + // properties are important for us here, again, we're taking the + // safer path. + // + // See [2a] & [2b] for a discussion of some of the properties we + // obtain by using crypto/rand and [3a] & [3b] for why we avoid + // math/rand. + // + // Because the math/rand seed has only 64 bits (int64), if the + // first thing we do after seeding an RNG is to read in a random + // TraceID, there are only 2^64 possible values. Compared to + // UUID v4 that have 122 random bits, there is a much greater + // chance of collision [4a] & [4b]. + // + // [1]: https://github.com/open-telemetry/opentelemetry-go/blob/958041ddf619a128/sdk/trace/trace.go#L25-L31 + // [2a]: https://security.stackexchange.com/q/120352/246345 + // [2b]: https://security.stackexchange.com/a/120365/246345 + // [3a]: https://github.com/golang/go/issues/11871#issuecomment-126333686 + // [3b]: https://github.com/golang/go/issues/11871#issuecomment-126357889 + // [4a]: https://en.wikipedia.org/wiki/Universally_unique_identifier#Collisions + // [4b]: https://www.wolframalpha.com/input/?i=sqrt%282*2%5E64*ln%281%2F%281-0.5%29%29%29 + _, err := rand.Read(span.TraceID[:]) + if err != nil { + panic(err) + } + } + _, err := rand.Read(span.SpanID[:]) + if err != nil { + panic(err) + } + if hasParent { + span.ParentSpanID = parent.SpanID + } + + // Apply options to override defaults. + for _, option := range options { + option(&span) + } + + span.Sampled = span.sample() + + if hasParent { + span.recorder = parent.spanRecorder() + } else { + span.recorder = &spanRecorder{} + } + span.recorder.record(&span) + + // Update scope so that all events include a trace context, allowing + // Sentry to correlate errors to transactions/spans. + hubFromContext(ctx).Scope().SetContext("trace", span.traceContext().Map()) + + return &span +} + +// Finish sets the span's end time, unless already set. If the span is the root +// of a span tree, Finish sends the span tree to Sentry as a transaction. +func (s *Span) Finish() { + // TODO(tracing): maybe make Finish run at most once, such that + // (incorrectly) calling it twice never double sends to Sentry. + + if s.EndTime.IsZero() { + s.EndTime = monotonicTimeSince(s.StartTime) + } + if !s.Sampled.Bool() { + return + } + event := s.toEvent() + if event == nil { + return + } + + // TODO(tracing): add breadcrumbs + // (see https://github.com/getsentry/sentry-python/blob/f6f3525f8812f609/sentry_sdk/tracing.py#L372) + + hub := hubFromContext(s.ctx) + if hub.Scope().Transaction() == "" { + Logger.Printf("Missing transaction name for span with op = %q", s.Op) + } + hub.CaptureEvent(event) +} + +// Context returns the context containing the span. +func (s *Span) Context() context.Context { return s.ctx } + +// StartChild starts a new child span. +// +// The call span.StartChild(operation, options...) is a shortcut for +// StartSpan(span.Context(), operation, options...). +func (s *Span) StartChild(operation string, options ...SpanOption) *Span { + return StartSpan(s.Context(), operation, options...) +} + +// SetTag sets a tag on the span. It is recommended to use SetTag instead of +// accessing the tags map directly as SetTag takes care of initializing the map +// when necessary. +func (s *Span) SetTag(name, value string) { + if s.Tags == nil { + s.Tags = make(map[string]string) + } + s.Tags[name] = value +} + +// SetData sets a data on the span. It is recommended to use SetData instead of +// accessing the data map directly as SetData takes care of initializing the map +// when necessary. +func (s *Span) SetData(name, value string) { + if s.Data == nil { + s.Data = make(map[string]interface{}) + } + s.Data[name] = value +} + +// IsTransaction checks if the given span is a transaction. +func (s *Span) IsTransaction() bool { + return s.isTransaction +} + +// GetTransaction returns the transaction that contains this span. +// +// For transaction spans it returns itself. For spans that were created manually +// the method returns "nil". +func (s *Span) GetTransaction() *Span { + spanRecorder := s.spanRecorder() + if spanRecorder == nil { + // This probably means that the Span was created manually (not via + // StartTransaction/StartSpan or StartChild). + // Return "nil" to indicate that it's not a normal situation. + return nil + } + recorderRoot := spanRecorder.root() + if recorderRoot == nil { + // Same as above: manually created Span. + return nil + } + return recorderRoot +} + +// TODO(tracing): maybe add shortcuts to get/set transaction name. Right now the +// transaction name is in the Scope, as it has existed there historically, prior +// to tracing. +// +// See Scope.Transaction() and Scope.SetTransaction(). +// +// func (s *Span) TransactionName() string +// func (s *Span) SetTransactionName(name string) + +// ToSentryTrace returns the seralized TraceParentContext from a transaction/sapn. +// Use this function to propagate the TraceParentContext to a downstream SDK, +// either as the value of the "sentry-trace" HTTP header, or as an html "sentry-trace" meta tag. +func (s *Span) ToSentryTrace() string { + // TODO(tracing): add instrumentation for outgoing HTTP requests using + // ToSentryTrace. + var b strings.Builder + fmt.Fprintf(&b, "%s-%s", s.TraceID.Hex(), s.SpanID.Hex()) + switch s.Sampled { + case SampledTrue: + b.WriteString("-1") + case SampledFalse: + b.WriteString("-0") + } + return b.String() +} + +// ToBaggage returns the serialized DynamicSamplingContext from a transaction. +// Use this function to propagate the DynamicSamplingContext to a downstream SDK, +// either as the value of the "baggage" HTTP header, or as an html "baggage" meta tag. +func (s *Span) ToBaggage() string { + if containingTransaction := s.GetTransaction(); containingTransaction != nil { + // In case there is currently no frozen DynamicSamplingContext attached to the transaction, + // create one from the properties of the transaction. + if !s.dynamicSamplingContext.IsFrozen() { + // This will return a frozen DynamicSamplingContext. + s.dynamicSamplingContext = DynamicSamplingContextFromTransaction(containingTransaction) + } + + return containingTransaction.dynamicSamplingContext.String() + } + return "" +} + +// SetDynamicSamplingContext sets the given dynamic sampling context on the +// current transaction. +func (s *Span) SetDynamicSamplingContext(dsc DynamicSamplingContext) { + if s.isTransaction { + s.dynamicSamplingContext = dsc + } +} + +// sentryTracePattern matches either +// +// TRACE_ID - SPAN_ID +// [[:xdigit:]]{32}-[[:xdigit:]]{16} +// +// or +// +// TRACE_ID - SPAN_ID - SAMPLED +// [[:xdigit:]]{32}-[[:xdigit:]]{16}-[01] +var sentryTracePattern = regexp.MustCompile(`^([[:xdigit:]]{32})-([[:xdigit:]]{16})(?:-([01]))?$`) + +// updateFromSentryTrace parses a sentry-trace HTTP header (as returned by +// ToSentryTrace) and updates fields of the span. If the header cannot be +// recognized as valid, the span is left unchanged. The returned value indicates +// whether the span was updated. +func (s *Span) updateFromSentryTrace(header []byte) (updated bool) { + m := sentryTracePattern.FindSubmatch(header) + if m == nil { + // no match + return false + } + _, _ = hex.Decode(s.TraceID[:], m[1]) + _, _ = hex.Decode(s.ParentSpanID[:], m[2]) + if len(m[3]) != 0 { + switch m[3][0] { + case '0': + s.Sampled = SampledFalse + case '1': + s.Sampled = SampledTrue + } + } + return true +} + +func (s *Span) updateFromBaggage(header []byte) { + if s.isTransaction { + dsc, err := DynamicSamplingContextFromHeader(header) + if err != nil { + return + } + + s.dynamicSamplingContext = dsc + } +} + +func (s *Span) MarshalJSON() ([]byte, error) { + // span aliases Span to allow calling json.Marshal without an infinite loop. + // It preserves all fields while none of the attached methods. + type span Span + var parentSpanID string + if s.ParentSpanID != zeroSpanID { + parentSpanID = s.ParentSpanID.String() + } + return json.Marshal(struct { + *span + ParentSpanID string `json:"parent_span_id,omitempty"` + }{ + span: (*span)(s), + ParentSpanID: parentSpanID, + }) +} + +func (s *Span) sample() Sampled { + hub := hubFromContext(s.ctx) + var clientOptions ClientOptions + client := hub.Client() + if client != nil { + clientOptions = hub.Client().Options() + } + + // https://develop.sentry.dev/sdk/performance/#sampling + // #1 tracing is not enabled. + if !clientOptions.EnableTracing { + Logger.Printf("Dropping transaction: EnableTracing is set to %t", clientOptions.EnableTracing) + s.sampleRate = 0.0 + return SampledFalse + } + + // #2 explicit sampling decision via StartSpan/StartTransaction options. + if s.Sampled != SampledUndefined { + Logger.Printf("Using explicit sampling decision from StartSpan/StartTransaction: %v", s.Sampled) + switch s.Sampled { + case SampledTrue: + s.sampleRate = 1.0 + case SampledFalse: + s.sampleRate = 0.0 + } + return s.Sampled + } + + // Variant for non-transaction spans: they inherit the parent decision. + // Note: non-transaction should always have a parent, but we check both + // conditions anyway -- the first for semantic meaning, the second to + // avoid a nil pointer dereference. + if !s.isTransaction && s.parent != nil { + return s.parent.Sampled + } + + // #3 use TracesSampler from ClientOptions. + sampler := clientOptions.TracesSampler + samplingContext := SamplingContext{Span: s, Parent: s.parent} + if sampler != nil { + tracesSamplerSampleRate := sampler.Sample(samplingContext) + s.sampleRate = tracesSamplerSampleRate + if tracesSamplerSampleRate < 0.0 || tracesSamplerSampleRate > 1.0 { + Logger.Printf("Dropping transaction: Returned TracesSampler rate is out of range [0.0, 1.0]: %f", tracesSamplerSampleRate) + return SampledFalse + } + if tracesSamplerSampleRate == 0 { + Logger.Printf("Dropping transaction: Returned TracesSampler rate is: %f", tracesSamplerSampleRate) + return SampledFalse + } + + if rng.Float64() < tracesSamplerSampleRate { + return SampledTrue + } + Logger.Printf("Dropping transaction: TracesSampler returned rate: %f", tracesSamplerSampleRate) + return SampledFalse + } + // #4 inherit parent decision. + if s.parent != nil { + Logger.Printf("Using sampling decision from parent: %v", s.parent.Sampled) + switch s.parent.Sampled { + case SampledTrue: + s.sampleRate = 1.0 + case SampledFalse: + s.sampleRate = 0.0 + } + return s.parent.Sampled + } + + // #5 use TracesSampleRate from ClientOptions. + sampleRate := clientOptions.TracesSampleRate + s.sampleRate = sampleRate + if sampleRate < 0.0 || sampleRate > 1.0 { + Logger.Printf("Dropping transaction: TracesSamplerRate out of range [0.0, 1.0]: %f", sampleRate) + return SampledFalse + } + if sampleRate == 0.0 { + Logger.Printf("Dropping transaction: TracesSampleRate rate is: %f", sampleRate) + return SampledFalse + } + + if rng.Float64() < sampleRate { + return SampledTrue + } + + return SampledFalse +} + +func (s *Span) toEvent() *Event { + if !s.isTransaction { + return nil // only transactions can be transformed into events + } + hub := hubFromContext(s.ctx) + + children := s.recorder.children() + finished := make([]*Span, 0, len(children)) + for _, child := range children { + if child.EndTime.IsZero() { + Logger.Printf("Dropped unfinished span: Op=%q TraceID=%s SpanID=%s", child.Op, child.TraceID, child.SpanID) + continue + } + finished = append(finished, child) + } + + // Create and attach a DynamicSamplingContext to the transaction. + // If the DynamicSamplingContext is not frozen at this point, we can assume being head of trace. + if !s.dynamicSamplingContext.IsFrozen() { + s.dynamicSamplingContext = DynamicSamplingContextFromTransaction(s) + } + + return &Event{ + Type: transactionType, + Transaction: hub.Scope().Transaction(), + Contexts: map[string]Context{ + "trace": s.traceContext().Map(), + }, + Tags: s.Tags, + Extra: s.Data, + Timestamp: s.EndTime, + StartTime: s.StartTime, + Spans: finished, + TransactionInfo: &TransactionInfo{ + Source: s.Source, + }, + sdkMetaData: SDKMetaData{ + dsc: s.dynamicSamplingContext, + }, + } +} + +func (s *Span) traceContext() *TraceContext { + return &TraceContext{ + TraceID: s.TraceID, + SpanID: s.SpanID, + ParentSpanID: s.ParentSpanID, + Op: s.Op, + Description: s.Description, + Status: s.Status, + } +} + +// spanRecorder stores the span tree. Guaranteed to be non-nil. +func (s *Span) spanRecorder() *spanRecorder { return s.recorder } + +// ParseTraceParentContext parses a sentry-trace header and builds a TraceParentContext from the +// parsed values. If the header was parsed correctly, the second returned argument +// ("valid") will be set to true, otherwise (e.g., empty or malformed header) it will +// be false. +func ParseTraceParentContext(header []byte) (traceParentContext TraceParentContext, valid bool) { + s := Span{} + updated := s.updateFromSentryTrace(header) + if !updated { + return TraceParentContext{}, false + } + return TraceParentContext{ + TraceID: s.TraceID, + ParentSpanID: s.ParentSpanID, + Sampled: s.Sampled, + }, true +} + +// TraceID identifies a trace. +type TraceID [16]byte + +func (id TraceID) Hex() []byte { + b := make([]byte, hex.EncodedLen(len(id))) + hex.Encode(b, id[:]) + return b +} + +func (id TraceID) String() string { + return string(id.Hex()) +} + +func (id TraceID) MarshalText() ([]byte, error) { + return id.Hex(), nil +} + +// SpanID identifies a span. +type SpanID [8]byte + +func (id SpanID) Hex() []byte { + b := make([]byte, hex.EncodedLen(len(id))) + hex.Encode(b, id[:]) + return b +} + +func (id SpanID) String() string { + return string(id.Hex()) +} + +func (id SpanID) MarshalText() ([]byte, error) { + return id.Hex(), nil +} + +// Zero values of TraceID and SpanID used for comparisons. +var ( + zeroTraceID TraceID + zeroSpanID SpanID +) + +// Contains information about how the name of the transaction was determined. +type TransactionSource string + +const ( + SourceCustom TransactionSource = "custom" + SourceURL TransactionSource = "url" + SourceRoute TransactionSource = "route" + SourceView TransactionSource = "view" + SourceComponent TransactionSource = "component" + SourceTask TransactionSource = "task" +) + +// SpanStatus is the status of a span. +type SpanStatus uint8 + +// Implementation note: +// +// In Relay (ingestion), the SpanStatus type is an enum used as +// Annotated when embedded in structs, making it effectively +// Option. It means the status is either null or one of the known +// string values. +// +// In Snuba (search), the SpanStatus is stored as an uint8 and defaulted to 2 +// ("unknown") when not set. It means that Discover searches for +// `transaction.status:unknown` return both transactions/spans with status +// `null` or `"unknown"`. Searches for `transaction.status:""` return nothing. +// +// With that in mind, the Go SDK default is SpanStatusUndefined, which is +// null/omitted when serializing to JSON, but integrations may update the status +// automatically based on contextual information. + +const ( + SpanStatusUndefined SpanStatus = iota + SpanStatusOK + SpanStatusCanceled + SpanStatusUnknown + SpanStatusInvalidArgument + SpanStatusDeadlineExceeded + SpanStatusNotFound + SpanStatusAlreadyExists + SpanStatusPermissionDenied + SpanStatusResourceExhausted + SpanStatusFailedPrecondition + SpanStatusAborted + SpanStatusOutOfRange + SpanStatusUnimplemented + SpanStatusInternalError + SpanStatusUnavailable + SpanStatusDataLoss + SpanStatusUnauthenticated + maxSpanStatus +) + +func (ss SpanStatus) String() string { + if ss >= maxSpanStatus { + return "" + } + m := [maxSpanStatus]string{ + "", + "ok", + "cancelled", // [sic] + "unknown", + "invalid_argument", + "deadline_exceeded", + "not_found", + "already_exists", + "permission_denied", + "resource_exhausted", + "failed_precondition", + "aborted", + "out_of_range", + "unimplemented", + "internal_error", + "unavailable", + "data_loss", + "unauthenticated", + } + return m[ss] +} + +func (ss SpanStatus) MarshalJSON() ([]byte, error) { + s := ss.String() + if s == "" { + return []byte("null"), nil + } + return json.Marshal(s) +} + +// A TraceContext carries information about an ongoing trace and is meant to be +// stored in Event.Contexts (as *TraceContext). +type TraceContext struct { + TraceID TraceID `json:"trace_id"` + SpanID SpanID `json:"span_id"` + ParentSpanID SpanID `json:"parent_span_id"` + Op string `json:"op,omitempty"` + Description string `json:"description,omitempty"` + Status SpanStatus `json:"status,omitempty"` +} + +func (tc *TraceContext) MarshalJSON() ([]byte, error) { + // traceContext aliases TraceContext to allow calling json.Marshal without + // an infinite loop. It preserves all fields while none of the attached + // methods. + type traceContext TraceContext + var parentSpanID string + if tc.ParentSpanID != zeroSpanID { + parentSpanID = tc.ParentSpanID.String() + } + return json.Marshal(struct { + *traceContext + ParentSpanID string `json:"parent_span_id,omitempty"` + }{ + traceContext: (*traceContext)(tc), + ParentSpanID: parentSpanID, + }) +} + +func (tc TraceContext) Map() map[string]interface{} { + m := map[string]interface{}{ + "trace_id": tc.TraceID, + "span_id": tc.SpanID, + } + + if tc.ParentSpanID != [8]byte{} { + m["parent_span_id"] = tc.ParentSpanID + } + + if tc.Op != "" { + m["op"] = tc.Op + } + + if tc.Description != "" { + m["description"] = tc.Description + } + + if tc.Status > 0 && tc.Status < maxSpanStatus { + m["status"] = tc.Status + } + + return m +} + +// Sampled signifies a sampling decision. +type Sampled int8 + +// The possible trace sampling decisions are: SampledFalse, SampledUndefined +// (default) and SampledTrue. +const ( + SampledFalse Sampled = -1 + SampledUndefined Sampled = 0 + SampledTrue Sampled = 1 +) + +func (s Sampled) String() string { + switch s { + case SampledFalse: + return "SampledFalse" + case SampledUndefined: + return "SampledUndefined" + case SampledTrue: + return "SampledTrue" + default: + return fmt.Sprintf("SampledInvalid(%d)", s) + } +} + +// Bool returns true if the sample decision is SampledTrue, false otherwise. +func (s Sampled) Bool() bool { + return s == SampledTrue +} + +// A SpanOption is a function that can modify the properties of a span. +type SpanOption func(s *Span) + +// The TransactionName option sets the name of the current transaction. +// +// A span tree has a single transaction name, therefore using this option when +// starting a span affects the span tree as a whole, potentially overwriting a +// name set previously. +func TransactionName(name string) SpanOption { + return func(s *Span) { + hubFromContext(s.Context()).Scope().SetTransaction(name) + } +} + +// OpName sets the operation name for a given span. +func OpName(name string) SpanOption { + return func(s *Span) { + s.Op = name + } +} + +// TransctionSource sets the source of the transaction name. +// TODO(anton): Fix the typo. +func TransctionSource(source TransactionSource) SpanOption { + return func(s *Span) { + s.Source = source + } +} + +// SpanSampled updates the sampling flag for a given span. +func SpanSampled(sampled Sampled) SpanOption { + return func(s *Span) { + s.Sampled = sampled + } +} + +// ContinueFromRequest returns a span option that updates the span to continue +// an existing trace. If it cannot detect an existing trace in the request, the +// span will be left unchanged. +// +// ContinueFromRequest is an alias for: +// +// ContinueFromHeaders(r.Header.Get(SentryTraceHeader), r.Header.Get(SentryBaggageHeader)). +func ContinueFromRequest(r *http.Request) SpanOption { + return ContinueFromHeaders(r.Header.Get(SentryTraceHeader), r.Header.Get(SentryBaggageHeader)) +} + +// ContinueFromHeaders returns a span option that updates the span to continue +// an existing TraceID and propagates the Dynamic Sampling context. +func ContinueFromHeaders(trace, baggage string) SpanOption { + return func(s *Span) { + if trace != "" { + s.updateFromSentryTrace([]byte(trace)) + } + if baggage != "" { + s.updateFromBaggage([]byte(baggage)) + } + + // In case a sentry-trace header is present but there are no sentry-related + // values in the baggage, create an empty, frozen DynamicSamplingContext. + if trace != "" && !s.dynamicSamplingContext.HasEntries() { + s.dynamicSamplingContext = DynamicSamplingContext{ + Frozen: true, + } + } + } +} + +// ContinueFromTrace returns a span option that updates the span to continue +// an existing TraceID. +func ContinueFromTrace(trace string) SpanOption { + return func(s *Span) { + if trace == "" { + return + } + s.updateFromSentryTrace([]byte(trace)) + } +} + +// spanContextKey is used to store span values in contexts. +type spanContextKey struct{} + +// TransactionFromContext returns the root span of the current transaction. It +// returns nil if no transaction is tracked in the context. +func TransactionFromContext(ctx context.Context) *Span { + if span, ok := ctx.Value(spanContextKey{}).(*Span); ok { + return span.recorder.root() + } + return nil +} + +// spanFromContext returns the last span stored in the context or a dummy +// non-nil span. +// +// TODO(tracing): consider exporting this. Without this, users cannot retrieve a +// span from a context since spanContextKey is not exported. +// +// This can be added retroactively, and in the meantime think better whether it +// should return nil (like GetHubFromContext), always non-nil (like +// HubFromContext), or both: two exported functions. +// +// Note the equivalence: +// +// SpanFromContext(ctx).StartChild(...) === StartSpan(ctx, ...) +// +// So we don't aim spanFromContext at creating spans, but mutating existing +// spans that you'd have no access otherwise (because it was created in code you +// do not control, for example SDK auto-instrumentation). +// +// For now we provide TransactionFromContext, which solves the more common case +// of setting tags, etc, on the current transaction. +func spanFromContext(ctx context.Context) *Span { + if span, ok := ctx.Value(spanContextKey{}).(*Span); ok { + return span + } + return nil +} + +// StartTransaction will create a transaction (root span) if there's no existing +// transaction in the context otherwise, it will return the existing transaction. +func StartTransaction(ctx context.Context, name string, options ...SpanOption) *Span { + currentTransaction, exists := ctx.Value(spanContextKey{}).(*Span) + if exists { + return currentTransaction + } + + options = append(options, TransactionName(name)) + return StartSpan( + ctx, + "", + options..., + ) +} diff --git a/vendor/github.com/cockroachdb/sentry-go/transport.go b/vendor/github.com/getsentry/sentry-go/transport.go similarity index 55% rename from vendor/github.com/cockroachdb/sentry-go/transport.go rename to vendor/github.com/getsentry/sentry-go/transport.go index 34ae64594..3722217e6 100644 --- a/vendor/github.com/cockroachdb/sentry-go/transport.go +++ b/vendor/github.com/getsentry/sentry-go/transport.go @@ -4,18 +4,32 @@ import ( "bytes" "crypto/tls" "encoding/json" + "errors" + "fmt" + "io" "net/http" "net/url" - "strconv" "sync" "time" + + "github.com/getsentry/sentry-go/internal/ratelimit" ) const defaultBufferSize = 30 -const defaultRetryAfter = time.Second * 60 const defaultTimeout = time.Second * 30 -// Transport is used by the `Client` to deliver events to remote server. +// maxDrainResponseBytes is the maximum number of bytes that transport +// implementations will read from response bodies when draining them. +// +// Sentry's ingestion API responses are typically short and the SDK doesn't need +// the contents of the response body. However, the net/http HTTP client requires +// response bodies to be fully drained (and closed) for TCP keep-alive to work. +// +// maxDrainResponseBytes strikes a balance between reading too much data (if the +// server is misbehaving) and reusing TCP connections. +const maxDrainResponseBytes = 16 << 10 + +// Transport is used by the Client to deliver events to remote server. type Transport interface { Flush(timeout time.Duration) bool Configure(options ClientOptions) @@ -24,11 +38,13 @@ type Transport interface { func getProxyConfig(options ClientOptions) func(*http.Request) (*url.URL, error) { if options.HTTPSProxy != "" { - return func(_ *http.Request) (*url.URL, error) { + return func(*http.Request) (*url.URL, error) { return url.Parse(options.HTTPSProxy) } - } else if options.HTTPProxy != "" { - return func(_ *http.Request) (*url.URL, error) { + } + + if options.HTTPProxy != "" { + return func(*http.Request) (*url.URL, error) { return url.Parse(options.HTTPProxy) } } @@ -38,6 +54,8 @@ func getProxyConfig(options ClientOptions) func(*http.Request) (*url.URL, error) func getTLSConfig(options ClientOptions) *tls.Config { if options.CaCerts != nil { + // #nosec G402 -- We should be using `MinVersion: tls.VersionTLS12`, + // but we don't want to break peoples code without the major bump. return &tls.Config{ RootCAs: options.CaCerts, } @@ -46,64 +64,149 @@ func getTLSConfig(options ClientOptions) *tls.Config { return nil } -func retryAfter(now time.Time, r *http.Response) time.Duration { - retryAfterHeader := r.Header["Retry-After"] - - if retryAfterHeader == nil { - return defaultRetryAfter - } - - if date, err := time.Parse(time.RFC1123, retryAfterHeader[0]); err == nil { - return date.Sub(now) - } - - if seconds, err := strconv.Atoi(retryAfterHeader[0]); err == nil { - return time.Second * time.Duration(seconds) - } - - return defaultRetryAfter -} - func getRequestBodyFromEvent(event *Event) []byte { body, err := json.Marshal(event) if err == nil { return body } - partialMarshallMessage := "Original event couldn't be marshalled. Succeeded by stripping the data " + - "that uses interface{} type. Please verify that the data you attach to the scope is serializable." + msg := fmt.Sprintf("Could not encode original event as JSON. "+ + "Succeeded by removing Breadcrumbs, Contexts and Extra. "+ + "Please verify the data you attach to the scope. "+ + "Error: %s", err) // Try to serialize the event, with all the contextual data that allows for interface{} stripped. event.Breadcrumbs = nil event.Contexts = nil event.Extra = map[string]interface{}{ - "info": partialMarshallMessage, + "info": msg, } body, err = json.Marshal(event) if err == nil { - Logger.Println(partialMarshallMessage) + Logger.Println(msg) return body } // This should _only_ happen when Event.Exception[0].Stacktrace.Frames[0].Vars is unserializable // Which won't ever happen, as we don't use it now (although it's the part of public interface accepted by Sentry) // Juuust in case something, somehow goes utterly wrong. - Logger.Println("Event couldn't be marshalled, even with stripped contextual data. Skipping delivery. " + + Logger.Println("Event couldn't be marshaled, even with stripped contextual data. Skipping delivery. " + "Please notify the SDK owners with possibly broken payload.") return nil } +func transactionEnvelopeFromBody(event *Event, dsn *Dsn, sentAt time.Time, body json.RawMessage) (*bytes.Buffer, error) { + var b bytes.Buffer + enc := json.NewEncoder(&b) + + // Construct the trace envelope header + var trace = map[string]string{} + if dsc := event.sdkMetaData.dsc; dsc.HasEntries() { + for k, v := range dsc.Entries { + trace[k] = v + } + } + + // Envelope header + err := enc.Encode(struct { + EventID EventID `json:"event_id"` + SentAt time.Time `json:"sent_at"` + Dsn string `json:"dsn"` + Sdk map[string]string `json:"sdk"` + Trace map[string]string `json:"trace,omitempty"` + }{ + EventID: event.EventID, + SentAt: sentAt, + Trace: trace, + Dsn: dsn.String(), + Sdk: map[string]string{ + "name": event.Sdk.Name, + "version": event.Sdk.Version, + }, + }) + if err != nil { + return nil, err + } + + // Item header + err = enc.Encode(struct { + Type string `json:"type"` + Length int `json:"length"` + }{ + Type: transactionType, + Length: len(body), + }) + if err != nil { + return nil, err + } + // payload + err = enc.Encode(body) + if err != nil { + return nil, err + } + + return &b, nil +} + +func getRequestFromEvent(event *Event, dsn *Dsn) (r *http.Request, err error) { + defer func() { + if r != nil { + r.Header.Set("User-Agent", userAgent) + } + }() + body := getRequestBodyFromEvent(event) + if body == nil { + return nil, errors.New("event could not be marshaled") + } + if event.Type == transactionType { + b, err := transactionEnvelopeFromBody(event, dsn, time.Now(), body) + if err != nil { + return nil, err + } + return http.NewRequest( + http.MethodPost, + dsn.EnvelopeAPIURL().String(), + b, + ) + } + return http.NewRequest( + http.MethodPost, + dsn.StoreAPIURL().String(), + bytes.NewReader(body), + ) +} + +func categoryFor(eventType string) ratelimit.Category { + switch eventType { + case "": + return ratelimit.CategoryError + case transactionType: + return ratelimit.CategoryTransaction + default: + return ratelimit.Category(eventType) + } +} + // ================================ // HTTPTransport // ================================ // A batch groups items that are processed sequentially. type batch struct { - items chan *http.Request + items chan batchItem started chan struct{} // closed to signal items started to be worked on done chan struct{} // closed to signal completion of all items } -// HTTPTransport is a default implementation of `Transport` interface used by `Client`. +type batchItem struct { + request *http.Request + category ratelimit.Category +} + +// HTTPTransport is the default, non-blocking, implementation of Transport. +// +// Clients using this transport will enqueue requests in a buffer and return to +// the caller before any network communication has happened. Requests are sent +// to Sentry sequentially from a background goroutine. type HTTPTransport struct { dsn *Dsn client *http.Client @@ -120,20 +223,21 @@ type HTTPTransport struct { // HTTP Client request timeout. Defaults to 30 seconds. Timeout time.Duration - mu sync.RWMutex - disabledUntil time.Time + mu sync.RWMutex + limits ratelimit.Map } -// NewHTTPTransport returns a new pre-configured instance of HTTPTransport +// NewHTTPTransport returns a new pre-configured instance of HTTPTransport. func NewHTTPTransport() *HTTPTransport { transport := HTTPTransport{ BufferSize: defaultBufferSize, Timeout: defaultTimeout, + limits: make(ratelimit.Map), } return &transport } -// Configure is called by the `Client` itself, providing it it's own `ClientOptions`. +// Configure is called by the Client itself, providing it it's own ClientOptions. func (t *HTTPTransport) Configure(options ClientOptions) { dsn, err := NewDsn(options.Dsn) if err != nil { @@ -147,7 +251,7 @@ func (t *HTTPTransport) Configure(options ClientOptions) { // synchronized by reading from and writing to the channel. t.buffer = make(chan batch, 1) t.buffer <- batch{ - items: make(chan *http.Request, t.BufferSize), + items: make(chan batchItem, t.BufferSize), started: make(chan struct{}), done: make(chan struct{}), } @@ -175,29 +279,23 @@ func (t *HTTPTransport) Configure(options ClientOptions) { }) } -// SendEvent assembles a new packet out of `Event` and sends it to remote server. +// SendEvent assembles a new packet out of Event and sends it to remote server. func (t *HTTPTransport) SendEvent(event *Event) { if t.dsn == nil { return } - t.mu.RLock() - disabled := time.Now().Before(t.disabledUntil) - t.mu.RUnlock() - if disabled { + + category := categoryFor(event.Type) + + if t.disabled(category) { return } - body := getRequestBodyFromEvent(event) - if body == nil { + request, err := getRequestFromEvent(event, t.dsn) + if err != nil { return } - request, _ := http.NewRequest( - http.MethodPost, - t.dsn.StoreAPIURL().String(), - bytes.NewBuffer(body), - ) - for headerKey, headerValue := range t.dsn.RequestHeaders() { request.Header.Set(headerKey, headerValue) } @@ -216,10 +314,19 @@ func (t *HTTPTransport) SendEvent(event *Event) { b := <-t.buffer select { - case b.items <- request: + case b.items <- batchItem{ + request: request, + category: category, + }: + var eventType string + if event.Type == transactionType { + eventType = "transaction" + } else { + eventType = fmt.Sprintf("%s event", event.Level) + } Logger.Printf( - "Sending %s event [%s] to %s project: %d\n", - event.Level, + "Sending %s [%s] to %s project: %s", + eventType, event.EventID, t.dsn.host, t.dsn.projectID, @@ -271,7 +378,7 @@ started: close(b.items) // Start a new batch for subsequent events. t.buffer <- batch{ - items: make(chan *http.Request, t.BufferSize), + items: make(chan batchItem, t.BufferSize), started: make(chan struct{}), done: make(chan struct{}), } @@ -300,27 +407,23 @@ func (t *HTTPTransport) worker() { t.buffer <- b // Process all batch items. - for request := range b.items { - t.mu.RLock() - disabled := time.Now().Before(t.disabledUntil) - t.mu.RUnlock() - if disabled { + for item := range b.items { + if t.disabled(item.category) { continue } - response, err := t.client.Do(request) - + response, err := t.client.Do(item.request) if err != nil { Logger.Printf("There was an issue with sending an event: %v", err) + continue } - - if response != nil && response.StatusCode == http.StatusTooManyRequests { - deadline := time.Now().Add(retryAfter(time.Now(), response)) - t.mu.Lock() - t.disabledUntil = deadline - t.mu.Unlock() - Logger.Printf("Too many requests, backing off till: %s\n", deadline) - } + t.mu.Lock() + t.limits.Merge(ratelimit.FromResponse(response)) + t.mu.Unlock() + // Drain body up to a limit and close it, allowing the + // transport to reuse TCP connections. + _, _ = io.CopyN(io.Discard, response.Body, maxDrainResponseBytes) + response.Body.Close() } // Signal that processing of the batch is done. @@ -328,31 +431,54 @@ func (t *HTTPTransport) worker() { } } +func (t *HTTPTransport) disabled(c ratelimit.Category) bool { + t.mu.RLock() + defer t.mu.RUnlock() + disabled := t.limits.IsRateLimited(c) + if disabled { + Logger.Printf("Too many requests for %q, backing off till: %v", c, t.limits.Deadline(c)) + } + return disabled +} + // ================================ // HTTPSyncTransport // ================================ -// HTTPSyncTransport is an implementation of `Transport` interface which blocks after each captured event. +// HTTPSyncTransport is a blocking implementation of Transport. +// +// Clients using this transport will send requests to Sentry sequentially and +// block until a response is returned. +// +// The blocking behavior is useful in a limited set of use cases. For example, +// use it when deploying code to a Function as a Service ("Serverless") +// platform, where any work happening in a background goroutine is not +// guaranteed to execute. +// +// For most cases, prefer HTTPTransport. type HTTPSyncTransport struct { - dsn *Dsn - client *http.Client - transport http.RoundTripper - disabledUntil time.Time + dsn *Dsn + client *http.Client + transport http.RoundTripper + + mu sync.Mutex + limits ratelimit.Map // HTTP Client request timeout. Defaults to 30 seconds. Timeout time.Duration } -// NewHTTPSyncTransport returns a new pre-configured instance of HTTPSyncTransport +// NewHTTPSyncTransport returns a new pre-configured instance of HTTPSyncTransport. func NewHTTPSyncTransport() *HTTPSyncTransport { transport := HTTPSyncTransport{ Timeout: defaultTimeout, + limits: make(ratelimit.Map), } return &transport } -// Configure is called by the `Client` itself, providing it it's own `ClientOptions`. +// Configure is called by the Client itself, providing it it's own ClientOptions. func (t *HTTPSyncTransport) Configure(options ClientOptions) { dsn, err := NewDsn(options.Dsn) if err != nil { @@ -380,45 +506,52 @@ func (t *HTTPSyncTransport) Configure(options ClientOptions) { } } -// SendEvent assembles a new packet out of `Event` and sends it to remote server. +// SendEvent assembles a new packet out of Event and sends it to remote server. func (t *HTTPSyncTransport) SendEvent(event *Event) { - if t.dsn == nil || time.Now().Before(t.disabledUntil) { + if t.dsn == nil { return } - body := getRequestBodyFromEvent(event) - if body == nil { + if t.disabled(categoryFor(event.Type)) { return } - request, _ := http.NewRequest( - http.MethodPost, - t.dsn.StoreAPIURL().String(), - bytes.NewBuffer(body), - ) + request, err := getRequestFromEvent(event, t.dsn) + if err != nil { + return + } for headerKey, headerValue := range t.dsn.RequestHeaders() { request.Header.Set(headerKey, headerValue) } + var eventType string + if event.Type == transactionType { + eventType = "transaction" + } else { + eventType = fmt.Sprintf("%s event", event.Level) + } Logger.Printf( - "Sending %s event [%s] to %s project: %d\n", - event.Level, + "Sending %s [%s] to %s project: %s", + eventType, event.EventID, t.dsn.host, t.dsn.projectID, ) response, err := t.client.Do(request) - if err != nil { Logger.Printf("There was an issue with sending an event: %v", err) + return } - - if response != nil && response.StatusCode == http.StatusTooManyRequests { - t.disabledUntil = time.Now().Add(retryAfter(time.Now(), response)) - Logger.Printf("Too many requests, backing off till: %s\n", t.disabledUntil) - } + t.mu.Lock() + t.limits.Merge(ratelimit.FromResponse(response)) + t.mu.Unlock() + + // Drain body up to a limit and close it, allowing the + // transport to reuse TCP connections. + _, _ = io.CopyN(io.Discard, response.Body, maxDrainResponseBytes) + response.Body.Close() } // Flush is a no-op for HTTPSyncTransport. It always returns true immediately. @@ -426,22 +559,34 @@ func (t *HTTPSyncTransport) Flush(_ time.Duration) bool { return true } +func (t *HTTPSyncTransport) disabled(c ratelimit.Category) bool { + t.mu.Lock() + defer t.mu.Unlock() + disabled := t.limits.IsRateLimited(c) + if disabled { + Logger.Printf("Too many requests for %q, backing off till: %v", c, t.limits.Deadline(c)) + } + return disabled +} + // ================================ // noopTransport // ================================ -// noopTransport is an implementation of `Transport` interface which drops all the events. +// noopTransport is an implementation of Transport interface which drops all the events. // Only used internally when an empty DSN is provided, which effectively disables the SDK. type noopTransport struct{} -func (t *noopTransport) Configure(options ClientOptions) { +var _ Transport = noopTransport{} + +func (noopTransport) Configure(ClientOptions) { Logger.Println("Sentry client initialized with an empty DSN. Using noopTransport. No events will be delivered.") } -func (t *noopTransport) SendEvent(event *Event) { +func (noopTransport) SendEvent(*Event) { Logger.Println("Event dropped due to noopTransport usage.") } -func (t *noopTransport) Flush(_ time.Duration) bool { +func (noopTransport) Flush(time.Duration) bool { return true } diff --git a/vendor/github.com/getsentry/sentry-go/util.go b/vendor/github.com/getsentry/sentry-go/util.go new file mode 100644 index 000000000..e5717c631 --- /dev/null +++ b/vendor/github.com/getsentry/sentry-go/util.go @@ -0,0 +1,91 @@ +package sentry + +import ( + "crypto/rand" + "encoding/hex" + "encoding/json" + "fmt" + "os" + "strings" + "time" + + exec "golang.org/x/sys/execabs" +) + +func uuid() string { + id := make([]byte, 16) + // Prefer rand.Read over rand.Reader, see https://go-review.googlesource.com/c/go/+/272326/. + _, _ = rand.Read(id) + id[6] &= 0x0F // clear version + id[6] |= 0x40 // set version to 4 (random uuid) + id[8] &= 0x3F // clear variant + id[8] |= 0x80 // set to IETF variant + return hex.EncodeToString(id) +} + +func fileExists(fileName string) bool { + _, err := os.Stat(fileName) + return err == nil +} + +// monotonicTimeSince replaces uses of time.Now() to take into account the +// monotonic clock reading stored in start, such that duration = end - start is +// unaffected by changes in the system wall clock. +func monotonicTimeSince(start time.Time) (end time.Time) { + return start.Add(time.Since(start)) +} + +// nolint: deadcode, unused +func prettyPrint(data interface{}) { + dbg, _ := json.MarshalIndent(data, "", " ") + fmt.Println(string(dbg)) +} + +// defaultRelease attempts to guess a default release for the currently running +// program. +func defaultRelease() (release string) { + // Return first non-empty environment variable known to hold release info, if any. + envs := []string{ + "SENTRY_RELEASE", + "HEROKU_SLUG_COMMIT", + "SOURCE_VERSION", + "CODEBUILD_RESOLVED_SOURCE_VERSION", + "CIRCLE_SHA1", + "GAE_DEPLOYMENT_ID", + "GITHUB_SHA", // GitHub Actions - https://help.github.com/en/actions + "COMMIT_REF", // Netlify - https://docs.netlify.com/ + "VERCEL_GIT_COMMIT_SHA", // Vercel - https://vercel.com/ + "ZEIT_GITHUB_COMMIT_SHA", // Zeit (now known as Vercel) + "ZEIT_GITLAB_COMMIT_SHA", + "ZEIT_BITBUCKET_COMMIT_SHA", + } + for _, e := range envs { + if release = os.Getenv(e); release != "" { + Logger.Printf("Using release from environment variable %s: %s", e, release) + return release + } + } + + // Derive a version string from Git. Example outputs: + // v1.0.1-0-g9de4 + // v2.0-8-g77df-dirty + // 4f72d7 + cmd := exec.Command("git", "describe", "--long", "--always", "--dirty") + b, err := cmd.Output() + if err != nil { + // Either Git is not available or the current directory is not a + // Git repository. + var s strings.Builder + fmt.Fprintf(&s, "Release detection failed: %v", err) + if err, ok := err.(*exec.ExitError); ok && len(err.Stderr) > 0 { + fmt.Fprintf(&s, ": %s", err.Stderr) + } + Logger.Print(s.String()) + Logger.Print("Some Sentry features will not be available. See https://docs.sentry.io/product/releases/.") + Logger.Print("To stop seeing this message, pass a Release to sentry.Init or set the SENTRY_RELEASE environment variable.") + return "" + } + release = strings.TrimSpace(string(b)) + Logger.Printf("Using release from Git: %s", release) + return release +} diff --git a/vendor/github.com/gogo/googleapis/LICENSE b/vendor/github.com/gogo/googleapis/LICENSE new file mode 100644 index 000000000..d6f85b181 --- /dev/null +++ b/vendor/github.com/gogo/googleapis/LICENSE @@ -0,0 +1,203 @@ +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 2015, Google Inc + Copyright 2018, GoGo 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/github.com/gogo/googleapis/google/rpc/code.pb.go b/vendor/github.com/gogo/googleapis/google/rpc/code.pb.go index 78c52a9a8..12a135dbe 100644 --- a/vendor/github.com/gogo/googleapis/google/rpc/code.pb.go +++ b/vendor/github.com/gogo/googleapis/google/rpc/code.pb.go @@ -3,18 +3,25 @@ package rpc -import proto "github.com/gogo/protobuf/proto" -import fmt "fmt" -import math "math" - -import strconv "strconv" +import ( + fmt "fmt" + proto "github.com/gogo/protobuf/proto" + math "math" + strconv "strconv" +) // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf -// The canonical error codes for Google APIs. +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// The canonical error codes for gRPC APIs. // // // Sometimes multiple error codes may apply. Services should return @@ -149,7 +156,8 @@ const ( INTERNAL Code = 13 // The service is currently unavailable. This is most likely a // transient condition, which can be corrected by retrying with - // a backoff. + // a backoff. Note that it is not always safe to retry + // non-idempotent operations. // // See the guidelines above for deciding between `FAILED_PRECONDITION`, // `ABORTED`, and `UNAVAILABLE`. @@ -181,6 +189,7 @@ var Code_name = map[int32]string{ 14: "UNAVAILABLE", 15: "DATA_LOSS", } + var Code_value = map[string]int32{ "OK": 0, "CANCELLED": 1, @@ -201,11 +210,45 @@ var Code_value = map[string]int32{ "DATA_LOSS": 15, } -func (Code) EnumDescriptor() ([]byte, []int) { return fileDescriptorCode, []int{0} } +func (Code) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_fe593a732623ccf0, []int{0} +} func init() { proto.RegisterEnum("google.rpc.Code", Code_name, Code_value) } + +func init() { proto.RegisterFile("google/rpc/code.proto", fileDescriptor_fe593a732623ccf0) } + +var fileDescriptor_fe593a732623ccf0 = []byte{ + // 393 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x44, 0x91, 0x3d, 0x6e, 0x13, 0x41, + 0x14, 0xc7, 0x3d, 0x76, 0x70, 0xe2, 0xf1, 0xd7, 0xcb, 0x84, 0x40, 0x37, 0x07, 0xa0, 0x70, 0x0a, + 0x4e, 0xf0, 0xbc, 0xf3, 0x9c, 0x8c, 0x32, 0x7e, 0xb3, 0x9a, 0x9d, 0x09, 0x01, 0x21, 0xad, 0xc4, + 0xc6, 0x4a, 0x03, 0x5a, 0xcb, 0xe2, 0x00, 0x9c, 0x85, 0x8a, 0x1b, 0x70, 0x85, 0x94, 0x29, 0x29, + 0xf1, 0xa6, 0xa1, 0x74, 0x49, 0x89, 0x06, 0x0a, 0xda, 0x9f, 0xde, 0xc7, 0xff, 0x43, 0x9e, 0xdf, + 0xb7, 0xed, 0xfd, 0xc7, 0xcd, 0xc5, 0x6e, 0xdb, 0x5c, 0x34, 0xed, 0xdd, 0x66, 0xb1, 0xdd, 0xb5, + 0x9f, 0x5b, 0x25, 0xff, 0xe1, 0xc5, 0x6e, 0xdb, 0xbc, 0xfa, 0xde, 0x97, 0x47, 0x45, 0x7b, 0xb7, + 0x51, 0x43, 0xd9, 0xf7, 0xd7, 0xd0, 0x53, 0x53, 0x39, 0x2a, 0x90, 0x0b, 0x72, 0x8e, 0x0c, 0x08, + 0x35, 0x96, 0xc7, 0x89, 0xaf, 0xd9, 0xbf, 0x61, 0xe8, 0xab, 0xe7, 0x12, 0x2c, 0xdf, 0xa0, 0xb3, + 0xa6, 0xc6, 0x70, 0x99, 0xd6, 0xc4, 0x11, 0x06, 0xea, 0x5c, 0x9e, 0x1a, 0x42, 0xe3, 0x2c, 0x53, + 0x4d, 0xb7, 0x05, 0x91, 0x21, 0x03, 0x47, 0xf9, 0x10, 0xfb, 0x58, 0xaf, 0x7c, 0x62, 0x03, 0xcf, + 0x94, 0x92, 0x33, 0x74, 0x81, 0xd0, 0xbc, 0xad, 0xe9, 0xd6, 0x56, 0xb1, 0x82, 0x61, 0xde, 0x2c, + 0x29, 0xac, 0x6d, 0x55, 0x59, 0xcf, 0xb5, 0x21, 0xb6, 0x64, 0xe0, 0x58, 0x9d, 0xc9, 0x79, 0x62, + 0x4c, 0xf1, 0x8a, 0x38, 0xda, 0x02, 0x23, 0x19, 0x00, 0xf5, 0x42, 0xaa, 0x40, 0x95, 0x4f, 0xa1, + 0xc8, 0x5f, 0xae, 0x30, 0x55, 0x99, 0x9f, 0xa8, 0x97, 0xf2, 0x6c, 0x85, 0xd6, 0x91, 0xa9, 0xcb, + 0x40, 0x85, 0x67, 0x63, 0xa3, 0xf5, 0x0c, 0xa3, 0xac, 0x1c, 0x97, 0x3e, 0xe4, 0x29, 0xa9, 0x40, + 0x4e, 0x7c, 0x8a, 0xb5, 0x5f, 0xd5, 0x01, 0xf9, 0x92, 0x60, 0xac, 0x4e, 0xe5, 0x34, 0xb1, 0x5d, + 0x97, 0x8e, 0xb2, 0x0d, 0x32, 0x30, 0x51, 0x13, 0x79, 0x62, 0x39, 0x52, 0x60, 0x74, 0x30, 0x55, + 0x73, 0x39, 0x4e, 0x8c, 0x37, 0x68, 0x1d, 0x2e, 0x1d, 0xc1, 0x2c, 0x1b, 0x32, 0x18, 0xb1, 0x76, + 0xbe, 0xaa, 0x60, 0xbe, 0x7c, 0xff, 0xb8, 0xd7, 0xbd, 0x1f, 0x7b, 0xdd, 0x3b, 0xec, 0xb5, 0xf8, + 0xbd, 0xd7, 0xe2, 0x4b, 0xa7, 0xc5, 0xb7, 0x4e, 0x8b, 0x87, 0x4e, 0x8b, 0xc7, 0x4e, 0x8b, 0x9f, + 0x9d, 0x16, 0xbf, 0x3a, 0xdd, 0x3b, 0x64, 0xfe, 0xa4, 0xc5, 0xc3, 0x93, 0x16, 0x72, 0xd6, 0xb4, + 0x9f, 0x16, 0xff, 0xf3, 0x5f, 0x8e, 0x72, 0xf8, 0x65, 0xae, 0xa5, 0x14, 0xef, 0x06, 0xbb, 0x6d, + 0xf3, 0xb5, 0x3f, 0x08, 0x65, 0xf1, 0x61, 0xf8, 0xb7, 0xaa, 0xd7, 0x7f, 0x02, 0x00, 0x00, 0xff, + 0xff, 0x03, 0xd4, 0x27, 0xff, 0xc3, 0x01, 0x00, 0x00, +} + func (x Code) String() string { s, ok := Code_name[int32(x)] if ok { @@ -213,34 +256,3 @@ func (x Code) String() string { } return strconv.Itoa(int(x)) } - -func init() { proto.RegisterFile("google/rpc/code.proto", fileDescriptorCode) } - -var fileDescriptorCode = []byte{ - // 388 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x44, 0x91, 0x3d, 0x72, 0x13, 0x31, - 0x14, 0xc7, 0x2d, 0x3b, 0x38, 0xb1, 0xfc, 0xf5, 0xa2, 0x10, 0xe8, 0x74, 0x00, 0x0a, 0xa7, 0xe0, - 0x04, 0xcf, 0xab, 0xe7, 0x44, 0x13, 0xf9, 0x69, 0x47, 0x2b, 0x05, 0x43, 0xb3, 0x33, 0x6c, 0x3c, - 0x69, 0x60, 0xd6, 0xe3, 0xe1, 0x00, 0x9c, 0x85, 0x8a, 0x1b, 0x70, 0x05, 0xca, 0x94, 0x94, 0x78, - 0x69, 0x28, 0x5d, 0x52, 0x32, 0x82, 0x22, 0xed, 0x6f, 0xde, 0xc7, 0xff, 0x43, 0x5e, 0x3e, 0xb4, - 0xed, 0xc3, 0x87, 0xed, 0xd5, 0x7e, 0xd7, 0x5c, 0x35, 0xed, 0xfd, 0x76, 0xb1, 0xdb, 0xb7, 0x9f, - 0x5a, 0x25, 0xff, 0xe3, 0xc5, 0x7e, 0xd7, 0xbc, 0xfa, 0xd6, 0x97, 0x27, 0x45, 0x7b, 0xbf, 0x55, - 0x43, 0xd9, 0xf7, 0xb7, 0xd0, 0x53, 0x53, 0x39, 0x2a, 0x90, 0x0b, 0x72, 0x8e, 0x0c, 0x08, 0x35, - 0x96, 0xa7, 0x89, 0x6f, 0xd9, 0xbf, 0x61, 0xe8, 0xab, 0xe7, 0x12, 0x2c, 0xdf, 0xa1, 0xb3, 0xa6, - 0xc6, 0x70, 0x9d, 0xd6, 0xc4, 0x11, 0x06, 0xea, 0x52, 0x9e, 0x1b, 0x42, 0xe3, 0x2c, 0x53, 0x4d, - 0x9b, 0x82, 0xc8, 0x90, 0x81, 0x93, 0x7c, 0x88, 0x7d, 0xac, 0x57, 0x3e, 0xb1, 0x81, 0x67, 0x4a, - 0xc9, 0x19, 0xba, 0x40, 0x68, 0xde, 0xd6, 0xb4, 0xb1, 0x55, 0xac, 0x60, 0x98, 0x37, 0x4b, 0x0a, - 0x6b, 0x5b, 0x55, 0xd6, 0x73, 0x6d, 0x88, 0x2d, 0x19, 0x38, 0x55, 0x17, 0x72, 0x9e, 0x18, 0x53, - 0xbc, 0x21, 0x8e, 0xb6, 0xc0, 0x48, 0x06, 0x40, 0xbd, 0x90, 0x2a, 0x50, 0xe5, 0x53, 0x28, 0xf2, - 0x97, 0x1b, 0x4c, 0x55, 0xe6, 0x67, 0xea, 0xa5, 0xbc, 0x58, 0xa1, 0x75, 0x64, 0xea, 0x32, 0x50, - 0xe1, 0xd9, 0xd8, 0x68, 0x3d, 0xc3, 0x28, 0x2b, 0xc7, 0xa5, 0x0f, 0x79, 0x4a, 0x2a, 0x90, 0x13, - 0x9f, 0x62, 0xed, 0x57, 0x75, 0x40, 0xbe, 0x26, 0x18, 0xab, 0x73, 0x39, 0x4d, 0x6c, 0xd7, 0xa5, - 0xa3, 0x6c, 0x83, 0x0c, 0x4c, 0xd4, 0x44, 0x9e, 0x59, 0x8e, 0x14, 0x18, 0x1d, 0x4c, 0xd5, 0x5c, - 0x8e, 0x13, 0xe3, 0x1d, 0x5a, 0x87, 0x4b, 0x47, 0x30, 0xcb, 0x86, 0x0c, 0x46, 0xac, 0x9d, 0xaf, - 0x2a, 0x98, 0x2f, 0x37, 0x8f, 0x07, 0xdd, 0xfb, 0x71, 0xd0, 0xbd, 0xe3, 0x41, 0x8b, 0x3f, 0x07, - 0x2d, 0x3e, 0x77, 0x5a, 0x7c, 0xed, 0xb4, 0xf8, 0xde, 0x69, 0xf1, 0xd8, 0x69, 0xf1, 0xb3, 0xd3, - 0xe2, 0x77, 0xa7, 0x7b, 0xc7, 0xcc, 0x7f, 0x69, 0x21, 0x67, 0x4d, 0xfb, 0x71, 0xf1, 0x94, 0xfd, - 0x72, 0x94, 0x83, 0x2f, 0x73, 0x25, 0xa5, 0x78, 0x37, 0xd8, 0xef, 0x9a, 0x2f, 0xfd, 0x41, 0x28, - 0x8b, 0xf7, 0xc3, 0x7f, 0x35, 0xbd, 0xfe, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x57, 0x56, 0x47, 0xc3, - 0xbf, 0x01, 0x00, 0x00, -} diff --git a/vendor/github.com/gogo/googleapis/google/rpc/code.proto b/vendor/github.com/gogo/googleapis/google/rpc/code.proto index d832de11e..29954b14d 100644 --- a/vendor/github.com/gogo/googleapis/google/rpc/code.proto +++ b/vendor/github.com/gogo/googleapis/google/rpc/code.proto @@ -1,4 +1,4 @@ -// Copyright 2017 Google Inc. +// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -22,8 +22,7 @@ option java_outer_classname = "CodeProto"; option java_package = "com.google.rpc"; option objc_class_prefix = "RPC"; - -// The canonical error codes for Google APIs. +// The canonical error codes for gRPC APIs. // // // Sometimes multiple error codes may apply. Services should return @@ -171,7 +170,8 @@ enum Code { // The service is currently unavailable. This is most likely a // transient condition, which can be corrected by retrying with - // a backoff. + // a backoff. Note that it is not always safe to retry + // non-idempotent operations. // // See the guidelines above for deciding between `FAILED_PRECONDITION`, // `ABORTED`, and `UNAVAILABLE`. diff --git a/vendor/github.com/gogo/googleapis/google/rpc/error_details.pb.go b/vendor/github.com/gogo/googleapis/google/rpc/error_details.pb.go index 2d3afa8da..18accb727 100644 --- a/vendor/github.com/gogo/googleapis/google/rpc/error_details.pb.go +++ b/vendor/github.com/gogo/googleapis/google/rpc/error_details.pb.go @@ -3,21 +3,30 @@ package rpc -import proto "github.com/gogo/protobuf/proto" -import fmt "fmt" -import math "math" -import google_protobuf1 "github.com/gogo/protobuf/types" - -import strings "strings" -import reflect "reflect" - -import io "io" +import ( + bytes "bytes" + fmt "fmt" + proto "github.com/gogo/protobuf/proto" + github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys" + types "github.com/gogo/protobuf/types" + io "io" + math "math" + math_bits "math/bits" + reflect "reflect" + strings "strings" +) // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + // 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. @@ -29,35 +38,101 @@ var _ = math.Inf // 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 retires have been reached or a maximum retry delay cap has been +// number of retries have been reached or a maximum retry delay cap has been // reached. type RetryInfo struct { // Clients should wait at least this long between retrying the same request. - RetryDelay *google_protobuf1.Duration `protobuf:"bytes,1,opt,name=retry_delay,json=retryDelay" json:"retry_delay,omitempty"` + RetryDelay *types.Duration `protobuf:"bytes,1,opt,name=retry_delay,json=retryDelay,proto3" json:"retry_delay,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *RetryInfo) Reset() { *m = RetryInfo{} } +func (*RetryInfo) ProtoMessage() {} +func (*RetryInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_851816e4d6b6361a, []int{0} +} +func (m *RetryInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RetryInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RetryInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RetryInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_RetryInfo.Merge(m, src) +} +func (m *RetryInfo) XXX_Size() int { + return m.Size() +} +func (m *RetryInfo) XXX_DiscardUnknown() { + xxx_messageInfo_RetryInfo.DiscardUnknown(m) } -func (m *RetryInfo) Reset() { *m = RetryInfo{} } -func (*RetryInfo) ProtoMessage() {} -func (*RetryInfo) Descriptor() ([]byte, []int) { return fileDescriptorErrorDetails, []int{0} } +var xxx_messageInfo_RetryInfo proto.InternalMessageInfo -func (m *RetryInfo) GetRetryDelay() *google_protobuf1.Duration { +func (m *RetryInfo) GetRetryDelay() *types.Duration { if m != nil { return m.RetryDelay } return nil } +func (*RetryInfo) XXX_MessageName() string { + return "google.rpc.RetryInfo" +} + // Describes additional debugging info. type DebugInfo struct { // The stack trace entries indicating where the error occurred. - StackEntries []string `protobuf:"bytes,1,rep,name=stack_entries,json=stackEntries" json:"stack_entries,omitempty"` + 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"` + Detail string `protobuf:"bytes,2,opt,name=detail,proto3" json:"detail,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DebugInfo) Reset() { *m = DebugInfo{} } +func (*DebugInfo) ProtoMessage() {} +func (*DebugInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_851816e4d6b6361a, []int{1} +} +func (m *DebugInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *DebugInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_DebugInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *DebugInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_DebugInfo.Merge(m, src) +} +func (m *DebugInfo) XXX_Size() int { + return m.Size() +} +func (m *DebugInfo) XXX_DiscardUnknown() { + xxx_messageInfo_DebugInfo.DiscardUnknown(m) } -func (m *DebugInfo) Reset() { *m = DebugInfo{} } -func (*DebugInfo) ProtoMessage() {} -func (*DebugInfo) Descriptor() ([]byte, []int) { return fileDescriptorErrorDetails, []int{1} } +var xxx_messageInfo_DebugInfo proto.InternalMessageInfo func (m *DebugInfo) GetStackEntries() []string { if m != nil { @@ -73,6 +148,10 @@ func (m *DebugInfo) GetDetail() string { return "" } +func (*DebugInfo) XXX_MessageName() string { + return "google.rpc.DebugInfo" +} + // Describes how a quota check failed. // // For example if a daily limit was exceeded for the calling project, @@ -82,16 +161,47 @@ func (m *DebugInfo) GetDetail() string { // a service could respond with the project id and set `service_disabled` // to true. // -// Also see RetryDetail and Help types for other details about handling a +// Also see RetryInfo and Help types for other details about handling a // quota failure. type QuotaFailure struct { // Describes all quota violations. - Violations []*QuotaFailure_Violation `protobuf:"bytes,1,rep,name=violations" json:"violations,omitempty"` + Violations []*QuotaFailure_Violation `protobuf:"bytes,1,rep,name=violations,proto3" json:"violations,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *QuotaFailure) Reset() { *m = QuotaFailure{} } +func (*QuotaFailure) ProtoMessage() {} +func (*QuotaFailure) Descriptor() ([]byte, []int) { + return fileDescriptor_851816e4d6b6361a, []int{2} +} +func (m *QuotaFailure) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QuotaFailure) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QuotaFailure.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QuotaFailure) XXX_Merge(src proto.Message) { + xxx_messageInfo_QuotaFailure.Merge(m, src) +} +func (m *QuotaFailure) XXX_Size() int { + return m.Size() +} +func (m *QuotaFailure) XXX_DiscardUnknown() { + xxx_messageInfo_QuotaFailure.DiscardUnknown(m) } -func (m *QuotaFailure) Reset() { *m = QuotaFailure{} } -func (*QuotaFailure) ProtoMessage() {} -func (*QuotaFailure) Descriptor() ([]byte, []int) { return fileDescriptorErrorDetails, []int{2} } +var xxx_messageInfo_QuotaFailure proto.InternalMessageInfo func (m *QuotaFailure) GetViolations() []*QuotaFailure_Violation { if m != nil { @@ -100,6 +210,10 @@ func (m *QuotaFailure) GetViolations() []*QuotaFailure_Violation { return nil } +func (*QuotaFailure) XXX_MessageName() string { + return "google.rpc.QuotaFailure" +} + // 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 { @@ -114,15 +228,44 @@ type QuotaFailure_Violation struct { // // For example: "Service disabled" or "Daily Limit for read operations // exceeded". - Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *QuotaFailure_Violation) Reset() { *m = QuotaFailure_Violation{} } func (*QuotaFailure_Violation) ProtoMessage() {} func (*QuotaFailure_Violation) Descriptor() ([]byte, []int) { - return fileDescriptorErrorDetails, []int{2, 0} + return fileDescriptor_851816e4d6b6361a, []int{2, 0} +} +func (m *QuotaFailure_Violation) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QuotaFailure_Violation) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QuotaFailure_Violation.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QuotaFailure_Violation) XXX_Merge(src proto.Message) { + xxx_messageInfo_QuotaFailure_Violation.Merge(m, src) +} +func (m *QuotaFailure_Violation) XXX_Size() int { + return m.Size() +} +func (m *QuotaFailure_Violation) XXX_DiscardUnknown() { + xxx_messageInfo_QuotaFailure_Violation.DiscardUnknown(m) } +var xxx_messageInfo_QuotaFailure_Violation proto.InternalMessageInfo + func (m *QuotaFailure_Violation) GetSubject() string { if m != nil { return m.Subject @@ -137,6 +280,118 @@ func (m *QuotaFailure_Violation) GetDescription() string { return "" } +func (*QuotaFailure_Violation) XXX_MessageName() string { + return "google.rpc.QuotaFailure.Violation" +} + +// 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 { + // 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-Z0-9_]+/. + 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 should match /[a-zA-Z0-9-_]/ and 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"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ErrorInfo) Reset() { *m = ErrorInfo{} } +func (*ErrorInfo) ProtoMessage() {} +func (*ErrorInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_851816e4d6b6361a, []int{3} +} +func (m *ErrorInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ErrorInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ErrorInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ErrorInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ErrorInfo.Merge(m, src) +} +func (m *ErrorInfo) XXX_Size() int { + return m.Size() +} +func (m *ErrorInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ErrorInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_ErrorInfo proto.InternalMessageInfo + +func (m *ErrorInfo) GetReason() string { + if m != nil { + return m.Reason + } + return "" +} + +func (m *ErrorInfo) GetDomain() string { + if m != nil { + return m.Domain + } + return "" +} + +func (m *ErrorInfo) GetMetadata() map[string]string { + if m != nil { + return m.Metadata + } + return nil +} + +func (*ErrorInfo) XXX_MessageName() string { + return "google.rpc.ErrorInfo" +} + // Describes what preconditions have failed. // // For example, if an RPC failed because it required the Terms of Service to be @@ -144,12 +399,43 @@ func (m *QuotaFailure_Violation) GetDescription() string { // PreconditionFailure message. type PreconditionFailure struct { // Describes all precondition violations. - Violations []*PreconditionFailure_Violation `protobuf:"bytes,1,rep,name=violations" json:"violations,omitempty"` + Violations []*PreconditionFailure_Violation `protobuf:"bytes,1,rep,name=violations,proto3" json:"violations,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PreconditionFailure) Reset() { *m = PreconditionFailure{} } +func (*PreconditionFailure) ProtoMessage() {} +func (*PreconditionFailure) Descriptor() ([]byte, []int) { + return fileDescriptor_851816e4d6b6361a, []int{4} +} +func (m *PreconditionFailure) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PreconditionFailure) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PreconditionFailure.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PreconditionFailure) XXX_Merge(src proto.Message) { + xxx_messageInfo_PreconditionFailure.Merge(m, src) +} +func (m *PreconditionFailure) XXX_Size() int { + return m.Size() +} +func (m *PreconditionFailure) XXX_DiscardUnknown() { + xxx_messageInfo_PreconditionFailure.DiscardUnknown(m) } -func (m *PreconditionFailure) Reset() { *m = PreconditionFailure{} } -func (*PreconditionFailure) ProtoMessage() {} -func (*PreconditionFailure) Descriptor() ([]byte, []int) { return fileDescriptorErrorDetails, []int{3} } +var xxx_messageInfo_PreconditionFailure proto.InternalMessageInfo func (m *PreconditionFailure) GetViolations() []*PreconditionFailure_Violation { if m != nil { @@ -158,28 +444,61 @@ func (m *PreconditionFailure) GetViolations() []*PreconditionFailure_Violation { return nil } +func (*PreconditionFailure) XXX_MessageName() string { + return "google.rpc.PreconditionFailure" +} + // A message type used to describe a single precondition failure. type PreconditionFailure_Violation struct { // The type of PreconditionFailure. We recommend using a service-specific - // enum type to define the supported precondition violation types. For + // 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. + // 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"` + Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *PreconditionFailure_Violation) Reset() { *m = PreconditionFailure_Violation{} } func (*PreconditionFailure_Violation) ProtoMessage() {} func (*PreconditionFailure_Violation) Descriptor() ([]byte, []int) { - return fileDescriptorErrorDetails, []int{3, 0} + return fileDescriptor_851816e4d6b6361a, []int{4, 0} +} +func (m *PreconditionFailure_Violation) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) } +func (m *PreconditionFailure_Violation) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PreconditionFailure_Violation.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PreconditionFailure_Violation) XXX_Merge(src proto.Message) { + xxx_messageInfo_PreconditionFailure_Violation.Merge(m, src) +} +func (m *PreconditionFailure_Violation) XXX_Size() int { + return m.Size() +} +func (m *PreconditionFailure_Violation) XXX_DiscardUnknown() { + xxx_messageInfo_PreconditionFailure_Violation.DiscardUnknown(m) +} + +var xxx_messageInfo_PreconditionFailure_Violation proto.InternalMessageInfo func (m *PreconditionFailure_Violation) GetType() string { if m != nil { @@ -202,16 +521,51 @@ func (m *PreconditionFailure_Violation) GetDescription() string { return "" } +func (*PreconditionFailure_Violation) XXX_MessageName() string { + return "google.rpc.PreconditionFailure.Violation" +} + // Describes violations in a client request. This error type focuses on the // syntactic aspects of the request. type BadRequest struct { // Describes all violations in a client request. - FieldViolations []*BadRequest_FieldViolation `protobuf:"bytes,1,rep,name=field_violations,json=fieldViolations" json:"field_violations,omitempty"` + FieldViolations []*BadRequest_FieldViolation `protobuf:"bytes,1,rep,name=field_violations,json=fieldViolations,proto3" json:"field_violations,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *BadRequest) Reset() { *m = BadRequest{} } +func (*BadRequest) ProtoMessage() {} +func (*BadRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_851816e4d6b6361a, []int{5} +} +func (m *BadRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *BadRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_BadRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *BadRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_BadRequest.Merge(m, src) +} +func (m *BadRequest) XXX_Size() int { + return m.Size() +} +func (m *BadRequest) XXX_DiscardUnknown() { + xxx_messageInfo_BadRequest.DiscardUnknown(m) } -func (m *BadRequest) Reset() { *m = BadRequest{} } -func (*BadRequest) ProtoMessage() {} -func (*BadRequest) Descriptor() ([]byte, []int) { return fileDescriptorErrorDetails, []int{4} } +var xxx_messageInfo_BadRequest proto.InternalMessageInfo func (m *BadRequest) GetFieldViolations() []*BadRequest_FieldViolation { if m != nil { @@ -220,6 +574,10 @@ func (m *BadRequest) GetFieldViolations() []*BadRequest_FieldViolation { return nil } +func (*BadRequest) XXX_MessageName() string { + return "google.rpc.BadRequest" +} + // A message type used to describe a single bad request field. type BadRequest_FieldViolation struct { // A path leading to a field in the request body. The value will be a @@ -227,15 +585,44 @@ type BadRequest_FieldViolation struct { // field. E.g., "field_violations.field" would identify this field. 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"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *BadRequest_FieldViolation) Reset() { *m = BadRequest_FieldViolation{} } func (*BadRequest_FieldViolation) ProtoMessage() {} func (*BadRequest_FieldViolation) Descriptor() ([]byte, []int) { - return fileDescriptorErrorDetails, []int{4, 0} + return fileDescriptor_851816e4d6b6361a, []int{5, 0} +} +func (m *BadRequest_FieldViolation) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *BadRequest_FieldViolation) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_BadRequest_FieldViolation.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *BadRequest_FieldViolation) XXX_Merge(src proto.Message) { + xxx_messageInfo_BadRequest_FieldViolation.Merge(m, src) +} +func (m *BadRequest_FieldViolation) XXX_Size() int { + return m.Size() +} +func (m *BadRequest_FieldViolation) XXX_DiscardUnknown() { + xxx_messageInfo_BadRequest_FieldViolation.DiscardUnknown(m) } +var xxx_messageInfo_BadRequest_FieldViolation proto.InternalMessageInfo + func (m *BadRequest_FieldViolation) GetField() string { if m != nil { return m.Field @@ -250,6 +637,10 @@ func (m *BadRequest_FieldViolation) GetDescription() string { return "" } +func (*BadRequest_FieldViolation) XXX_MessageName() string { + return "google.rpc.BadRequest.FieldViolation" +} + // Contains metadata about the request that clients can attach when filing a bug // or providing other forms of feedback. type RequestInfo struct { @@ -258,12 +649,43 @@ type RequestInfo struct { 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"` + ServingData string `protobuf:"bytes,2,opt,name=serving_data,json=servingData,proto3" json:"serving_data,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *RequestInfo) Reset() { *m = RequestInfo{} } +func (*RequestInfo) ProtoMessage() {} +func (*RequestInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_851816e4d6b6361a, []int{6} +} +func (m *RequestInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestInfo.Merge(m, src) +} +func (m *RequestInfo) XXX_Size() int { + return m.Size() +} +func (m *RequestInfo) XXX_DiscardUnknown() { + xxx_messageInfo_RequestInfo.DiscardUnknown(m) } -func (m *RequestInfo) Reset() { *m = RequestInfo{} } -func (*RequestInfo) ProtoMessage() {} -func (*RequestInfo) Descriptor() ([]byte, []int) { return fileDescriptorErrorDetails, []int{5} } +var xxx_messageInfo_RequestInfo proto.InternalMessageInfo func (m *RequestInfo) GetRequestId() string { if m != nil { @@ -279,6 +701,10 @@ func (m *RequestInfo) GetServingData() string { return "" } +func (*RequestInfo) XXX_MessageName() string { + return "google.rpc.RequestInfo" +} + // Describes the resource that is being accessed. type ResourceInfo struct { // A name for the type of resource being accessed, e.g. "sql table", @@ -296,12 +722,43 @@ type ResourceInfo struct { // 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"` + Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ResourceInfo) Reset() { *m = ResourceInfo{} } +func (*ResourceInfo) ProtoMessage() {} +func (*ResourceInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_851816e4d6b6361a, []int{7} +} +func (m *ResourceInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResourceInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResourceInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResourceInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResourceInfo.Merge(m, src) +} +func (m *ResourceInfo) XXX_Size() int { + return m.Size() +} +func (m *ResourceInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ResourceInfo.DiscardUnknown(m) } -func (m *ResourceInfo) Reset() { *m = ResourceInfo{} } -func (*ResourceInfo) ProtoMessage() {} -func (*ResourceInfo) Descriptor() ([]byte, []int) { return fileDescriptorErrorDetails, []int{6} } +var xxx_messageInfo_ResourceInfo proto.InternalMessageInfo func (m *ResourceInfo) GetResourceType() string { if m != nil { @@ -331,6 +788,10 @@ func (m *ResourceInfo) GetDescription() string { return "" } +func (*ResourceInfo) XXX_MessageName() string { + return "google.rpc.ResourceInfo" +} + // 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 @@ -338,12 +799,43 @@ func (m *ResourceInfo) GetDescription() string { // directly to the right place in the developer console to flip the bit. type Help struct { // URL(s) pointing to additional information on handling the current error. - Links []*Help_Link `protobuf:"bytes,1,rep,name=links" json:"links,omitempty"` + Links []*Help_Link `protobuf:"bytes,1,rep,name=links,proto3" json:"links,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Help) Reset() { *m = Help{} } +func (*Help) ProtoMessage() {} +func (*Help) Descriptor() ([]byte, []int) { + return fileDescriptor_851816e4d6b6361a, []int{8} +} +func (m *Help) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Help) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Help.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Help) XXX_Merge(src proto.Message) { + xxx_messageInfo_Help.Merge(m, src) +} +func (m *Help) XXX_Size() int { + return m.Size() +} +func (m *Help) XXX_DiscardUnknown() { + xxx_messageInfo_Help.DiscardUnknown(m) } -func (m *Help) Reset() { *m = Help{} } -func (*Help) ProtoMessage() {} -func (*Help) Descriptor() ([]byte, []int) { return fileDescriptorErrorDetails, []int{7} } +var xxx_messageInfo_Help proto.InternalMessageInfo func (m *Help) GetLinks() []*Help_Link { if m != nil { @@ -352,17 +844,52 @@ func (m *Help) GetLinks() []*Help_Link { return nil } +func (*Help) XXX_MessageName() string { + return "google.rpc.Help" +} + // Describes a URL link. type Help_Link struct { // 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"` + Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Help_Link) Reset() { *m = Help_Link{} } +func (*Help_Link) ProtoMessage() {} +func (*Help_Link) Descriptor() ([]byte, []int) { + return fileDescriptor_851816e4d6b6361a, []int{8, 0} +} +func (m *Help_Link) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Help_Link) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Help_Link.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Help_Link) XXX_Merge(src proto.Message) { + xxx_messageInfo_Help_Link.Merge(m, src) +} +func (m *Help_Link) XXX_Size() int { + return m.Size() +} +func (m *Help_Link) XXX_DiscardUnknown() { + xxx_messageInfo_Help_Link.DiscardUnknown(m) } -func (m *Help_Link) Reset() { *m = Help_Link{} } -func (*Help_Link) ProtoMessage() {} -func (*Help_Link) Descriptor() ([]byte, []int) { return fileDescriptorErrorDetails, []int{7, 0} } +var xxx_messageInfo_Help_Link proto.InternalMessageInfo func (m *Help_Link) GetDescription() string { if m != nil { @@ -378,6 +905,10 @@ func (m *Help_Link) GetUrl() string { return "" } +func (*Help_Link) XXX_MessageName() string { + return "google.rpc.Help.Link" +} + // Provides a localized error message that is safe to return to the user // which can be attached to an RPC error. type LocalizedMessage struct { @@ -386,12 +917,43 @@ type LocalizedMessage struct { // 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"` + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *LocalizedMessage) Reset() { *m = LocalizedMessage{} } +func (*LocalizedMessage) ProtoMessage() {} +func (*LocalizedMessage) Descriptor() ([]byte, []int) { + return fileDescriptor_851816e4d6b6361a, []int{9} +} +func (m *LocalizedMessage) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *LocalizedMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_LocalizedMessage.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *LocalizedMessage) XXX_Merge(src proto.Message) { + xxx_messageInfo_LocalizedMessage.Merge(m, src) +} +func (m *LocalizedMessage) XXX_Size() int { + return m.Size() +} +func (m *LocalizedMessage) XXX_DiscardUnknown() { + xxx_messageInfo_LocalizedMessage.DiscardUnknown(m) } -func (m *LocalizedMessage) Reset() { *m = LocalizedMessage{} } -func (*LocalizedMessage) ProtoMessage() {} -func (*LocalizedMessage) Descriptor() ([]byte, []int) { return fileDescriptorErrorDetails, []int{8} } +var xxx_messageInfo_LocalizedMessage proto.InternalMessageInfo func (m *LocalizedMessage) GetLocale() string { if m != nil { @@ -407,11 +969,16 @@ func (m *LocalizedMessage) GetMessage() string { return "" } +func (*LocalizedMessage) XXX_MessageName() string { + return "google.rpc.LocalizedMessage" +} func init() { proto.RegisterType((*RetryInfo)(nil), "google.rpc.RetryInfo") proto.RegisterType((*DebugInfo)(nil), "google.rpc.DebugInfo") proto.RegisterType((*QuotaFailure)(nil), "google.rpc.QuotaFailure") proto.RegisterType((*QuotaFailure_Violation)(nil), "google.rpc.QuotaFailure.Violation") + proto.RegisterType((*ErrorInfo)(nil), "google.rpc.ErrorInfo") + proto.RegisterMapType((map[string]string)(nil), "google.rpc.ErrorInfo.MetadataEntry") proto.RegisterType((*PreconditionFailure)(nil), "google.rpc.PreconditionFailure") proto.RegisterType((*PreconditionFailure_Violation)(nil), "google.rpc.PreconditionFailure.Violation") proto.RegisterType((*BadRequest)(nil), "google.rpc.BadRequest") @@ -422,6 +989,58 @@ func init() { proto.RegisterType((*Help_Link)(nil), "google.rpc.Help.Link") proto.RegisterType((*LocalizedMessage)(nil), "google.rpc.LocalizedMessage") } + +func init() { proto.RegisterFile("google/rpc/error_details.proto", fileDescriptor_851816e4d6b6361a) } + +var fileDescriptor_851816e4d6b6361a = []byte{ + // 710 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0x3f, 0x6f, 0xd3, 0x4e, + 0x18, 0xee, 0x25, 0x69, 0x7f, 0x3f, 0xbf, 0x49, 0x4b, 0x31, 0x50, 0x85, 0x48, 0x58, 0xc1, 0x15, + 0x52, 0x11, 0x92, 0x2b, 0x95, 0x05, 0x95, 0x01, 0x29, 0xa4, 0xff, 0xa4, 0x16, 0x82, 0x85, 0x18, + 0x60, 0x88, 0x2e, 0xf6, 0x9b, 0xe8, 0x88, 0xe3, 0x0b, 0x67, 0xbb, 0x28, 0x4c, 0x7c, 0x04, 0x76, + 0x36, 0xa6, 0x7e, 0x05, 0x06, 0xf6, 0x8e, 0x1d, 0x19, 0x49, 0xba, 0x30, 0x76, 0x64, 0x44, 0x77, + 0x3e, 0xa7, 0x6e, 0x53, 0x10, 0xdb, 0x3d, 0xef, 0x3d, 0xf7, 0xdc, 0xfb, 0x3c, 0x7a, 0xef, 0xc0, + 0xea, 0x71, 0xde, 0x0b, 0x70, 0x5d, 0x0c, 0xbd, 0x75, 0x14, 0x82, 0x8b, 0xb6, 0x8f, 0x31, 0x65, + 0x41, 0xe4, 0x0c, 0x05, 0x8f, 0xb9, 0x09, 0xe9, 0xbe, 0x23, 0x86, 0x5e, 0x2d, 0xe3, 0xaa, 0x9d, + 0x4e, 0xd2, 0x5d, 0xf7, 0x13, 0x41, 0x63, 0xc6, 0xc3, 0x94, 0x6b, 0xef, 0x80, 0xe1, 0x62, 0x2c, + 0x46, 0x7b, 0x61, 0x97, 0x9b, 0x9b, 0x50, 0x16, 0x12, 0xb4, 0x7d, 0x0c, 0xe8, 0xa8, 0x4a, 0xea, + 0x64, 0xad, 0xbc, 0x71, 0xdb, 0xd1, 0x72, 0x99, 0x84, 0xd3, 0xd4, 0x12, 0x2e, 0x28, 0x76, 0x53, + 0x92, 0xed, 0x5d, 0x30, 0x9a, 0xd8, 0x49, 0x7a, 0x4a, 0x68, 0x15, 0x16, 0xa3, 0x98, 0x7a, 0xfd, + 0x36, 0x86, 0xb1, 0x60, 0x18, 0x55, 0x49, 0xbd, 0xb8, 0x66, 0xb8, 0x15, 0x55, 0xdc, 0x4a, 0x6b, + 0xe6, 0x0a, 0x2c, 0xa4, 0x7d, 0x57, 0x0b, 0x75, 0xb2, 0x66, 0xb8, 0x1a, 0xd9, 0x9f, 0x09, 0x54, + 0x5e, 0x24, 0x3c, 0xa6, 0xdb, 0x94, 0x05, 0x89, 0x40, 0xb3, 0x01, 0x70, 0xc8, 0x78, 0xa0, 0xee, + 0x4c, 0xa5, 0xca, 0x1b, 0xb6, 0x73, 0x6e, 0xd2, 0xc9, 0xb3, 0x9d, 0x57, 0x19, 0xd5, 0xcd, 0x9d, + 0xaa, 0xed, 0x80, 0x31, 0xdd, 0x30, 0xab, 0xf0, 0x5f, 0x94, 0x74, 0xde, 0xa2, 0x17, 0x2b, 0x8f, + 0x86, 0x9b, 0x41, 0xb3, 0x0e, 0x65, 0x1f, 0x23, 0x4f, 0xb0, 0xa1, 0x24, 0xea, 0xc6, 0xf2, 0x25, + 0xfb, 0x2b, 0x01, 0x63, 0x4b, 0x86, 0xae, 0x8c, 0xae, 0xc0, 0x82, 0x40, 0x1a, 0xf1, 0x50, 0x0b, + 0x69, 0xa4, 0xbc, 0xf1, 0x01, 0x65, 0xe1, 0xd4, 0x9b, 0x42, 0xe6, 0x13, 0xf8, 0x7f, 0x80, 0x31, + 0xf5, 0x69, 0x4c, 0xab, 0x45, 0x65, 0x64, 0x35, 0x6f, 0x64, 0x2a, 0xec, 0x1c, 0x68, 0x96, 0x0c, + 0x6b, 0xe4, 0x4e, 0x0f, 0xd5, 0x1e, 0xc3, 0xe2, 0x85, 0x2d, 0x73, 0x19, 0x8a, 0x7d, 0x1c, 0xe9, + 0xeb, 0xe5, 0xd2, 0xbc, 0x09, 0xf3, 0x87, 0x34, 0x48, 0x50, 0x5f, 0x9d, 0x82, 0xcd, 0xc2, 0x23, + 0x62, 0x7f, 0x23, 0x70, 0xa3, 0x25, 0xd0, 0xe3, 0xa1, 0xcf, 0xa4, 0x99, 0x2c, 0xe0, 0xbd, 0x2b, + 0x02, 0xbe, 0x9f, 0xef, 0xeb, 0x8a, 0x43, 0x7f, 0xc8, 0xf9, 0x4d, 0x3e, 0x67, 0x13, 0x4a, 0xf1, + 0x68, 0x88, 0xba, 0x39, 0xb5, 0xce, 0x67, 0x5f, 0xf8, 0x6b, 0xf6, 0xc5, 0xd9, 0xec, 0x8f, 0x08, + 0x40, 0x83, 0xfa, 0x2e, 0xbe, 0x4b, 0x30, 0x8a, 0xcd, 0x16, 0x2c, 0x77, 0x19, 0x06, 0x7e, 0x7b, + 0xa6, 0xf9, 0x7b, 0xf9, 0xe6, 0xcf, 0x4f, 0x38, 0xdb, 0x92, 0x7e, 0xde, 0xf8, 0xb5, 0xee, 0x05, + 0x1c, 0xd5, 0x76, 0x61, 0xe9, 0x22, 0x45, 0x86, 0xa9, 0x48, 0xda, 0x43, 0x0a, 0xfe, 0x61, 0x4c, + 0x9e, 0x43, 0x59, 0x5f, 0xaa, 0xe6, 0xe4, 0x0e, 0x80, 0x48, 0x61, 0x9b, 0x65, 0x5a, 0x86, 0xae, + 0xec, 0xf9, 0xe6, 0x5d, 0xa8, 0x44, 0x28, 0x0e, 0x59, 0xd8, 0x6b, 0xab, 0xd1, 0xd0, 0x82, 0xba, + 0xd6, 0xa4, 0x31, 0xb5, 0x3f, 0x11, 0xa8, 0xb8, 0x18, 0xf1, 0x44, 0x78, 0x98, 0xbd, 0x31, 0xa1, + 0x71, 0x3b, 0x97, 0x72, 0x25, 0x2b, 0xbe, 0x94, 0x69, 0xe7, 0x49, 0x21, 0x1d, 0x64, 0x33, 0x31, + 0x25, 0x3d, 0xa3, 0x03, 0x94, 0x1e, 0xf9, 0xfb, 0x10, 0x85, 0x8e, 0x3c, 0x05, 0x97, 0x3d, 0x96, + 0x66, 0x3d, 0x72, 0x28, 0xed, 0x62, 0x30, 0x34, 0x1f, 0xc0, 0x7c, 0xc0, 0xc2, 0x7e, 0x16, 0xfe, + 0xad, 0x7c, 0xf8, 0x92, 0xe0, 0xec, 0xb3, 0xb0, 0xef, 0xa6, 0x9c, 0xda, 0x26, 0x94, 0x24, 0xbc, + 0x2c, 0x4f, 0x66, 0xe4, 0xe5, 0x64, 0x27, 0x22, 0xfb, 0x1c, 0xe4, 0xd2, 0x6e, 0xc2, 0xf2, 0x3e, + 0xf7, 0x68, 0xc0, 0x3e, 0xa0, 0x7f, 0x80, 0x51, 0x44, 0x7b, 0x28, 0x5f, 0x5a, 0x20, 0x6b, 0x99, + 0x7f, 0x8d, 0xe4, 0x9c, 0x0d, 0x52, 0x4a, 0x36, 0x67, 0x1a, 0x36, 0xfc, 0x93, 0xb1, 0x35, 0xf7, + 0x7d, 0x6c, 0xcd, 0x9d, 0x8d, 0x2d, 0xf2, 0x6b, 0x6c, 0x91, 0x8f, 0x13, 0x8b, 0x1c, 0x4d, 0x2c, + 0x72, 0x3c, 0xb1, 0xc8, 0xc9, 0xc4, 0x22, 0x3f, 0x26, 0x16, 0xf9, 0x39, 0xb1, 0xe6, 0xce, 0x64, + 0xfd, 0xd4, 0x22, 0xc7, 0xa7, 0x16, 0x81, 0x25, 0x8f, 0x0f, 0x72, 0xc6, 0x1a, 0xd7, 0xd5, 0x5b, + 0x6d, 0xa6, 0x1f, 0x6f, 0x4b, 0x7e, 0x8d, 0x2d, 0xf2, 0xba, 0x28, 0x86, 0xde, 0x97, 0x42, 0xd1, + 0x6d, 0x3d, 0xed, 0x2c, 0xa8, 0xef, 0xf2, 0xe1, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x94, 0xc6, + 0xb7, 0xdd, 0xad, 0x05, 0x00, 0x00, +} + func (this *RetryInfo) Compare(that interface{}) int { if that == nil { if this == nil { @@ -450,6 +1069,9 @@ func (this *RetryInfo) Compare(that interface{}) int { if c := this.RetryDelay.Compare(that1.RetryDelay); c != 0 { return c } + if c := bytes.Compare(this.XXX_unrecognized, that1.XXX_unrecognized); c != 0 { + return c + } return 0 } func (this *DebugInfo) Compare(that interface{}) int { @@ -497,6 +1119,9 @@ func (this *DebugInfo) Compare(that interface{}) int { } return 1 } + if c := bytes.Compare(this.XXX_unrecognized, that1.XXX_unrecognized); c != 0 { + return c + } return 0 } func (this *QuotaFailure) Compare(that interface{}) int { @@ -535,6 +1160,9 @@ func (this *QuotaFailure) Compare(that interface{}) int { return c } } + if c := bytes.Compare(this.XXX_unrecognized, that1.XXX_unrecognized); c != 0 { + return c + } return 0 } func (this *QuotaFailure_Violation) Compare(that interface{}) int { @@ -574,6 +1202,65 @@ func (this *QuotaFailure_Violation) Compare(that interface{}) int { } return 1 } + if c := bytes.Compare(this.XXX_unrecognized, that1.XXX_unrecognized); c != 0 { + return c + } + return 0 +} +func (this *ErrorInfo) Compare(that interface{}) int { + if that == nil { + if this == nil { + return 0 + } + return 1 + } + + that1, ok := that.(*ErrorInfo) + if !ok { + that2, ok := that.(ErrorInfo) + if ok { + that1 = &that2 + } else { + return 1 + } + } + if that1 == nil { + if this == nil { + return 0 + } + return 1 + } else if this == nil { + return -1 + } + if this.Reason != that1.Reason { + if this.Reason < that1.Reason { + return -1 + } + return 1 + } + if this.Domain != that1.Domain { + if this.Domain < that1.Domain { + return -1 + } + return 1 + } + if len(this.Metadata) != len(that1.Metadata) { + if len(this.Metadata) < len(that1.Metadata) { + return -1 + } + return 1 + } + for i := range this.Metadata { + if this.Metadata[i] != that1.Metadata[i] { + if this.Metadata[i] < that1.Metadata[i] { + return -1 + } + return 1 + } + } + if c := bytes.Compare(this.XXX_unrecognized, that1.XXX_unrecognized); c != 0 { + return c + } return 0 } func (this *PreconditionFailure) Compare(that interface{}) int { @@ -612,6 +1299,9 @@ func (this *PreconditionFailure) Compare(that interface{}) int { return c } } + if c := bytes.Compare(this.XXX_unrecognized, that1.XXX_unrecognized); c != 0 { + return c + } return 0 } func (this *PreconditionFailure_Violation) Compare(that interface{}) int { @@ -657,6 +1347,9 @@ func (this *PreconditionFailure_Violation) Compare(that interface{}) int { } return 1 } + if c := bytes.Compare(this.XXX_unrecognized, that1.XXX_unrecognized); c != 0 { + return c + } return 0 } func (this *BadRequest) Compare(that interface{}) int { @@ -695,6 +1388,9 @@ func (this *BadRequest) Compare(that interface{}) int { return c } } + if c := bytes.Compare(this.XXX_unrecognized, that1.XXX_unrecognized); c != 0 { + return c + } return 0 } func (this *BadRequest_FieldViolation) Compare(that interface{}) int { @@ -734,6 +1430,9 @@ func (this *BadRequest_FieldViolation) Compare(that interface{}) int { } return 1 } + if c := bytes.Compare(this.XXX_unrecognized, that1.XXX_unrecognized); c != 0 { + return c + } return 0 } func (this *RequestInfo) Compare(that interface{}) int { @@ -773,6 +1472,9 @@ func (this *RequestInfo) Compare(that interface{}) int { } return 1 } + if c := bytes.Compare(this.XXX_unrecognized, that1.XXX_unrecognized); c != 0 { + return c + } return 0 } func (this *ResourceInfo) Compare(that interface{}) int { @@ -824,6 +1526,9 @@ func (this *ResourceInfo) Compare(that interface{}) int { } return 1 } + if c := bytes.Compare(this.XXX_unrecognized, that1.XXX_unrecognized); c != 0 { + return c + } return 0 } func (this *Help) Compare(that interface{}) int { @@ -862,6 +1567,9 @@ func (this *Help) Compare(that interface{}) int { return c } } + if c := bytes.Compare(this.XXX_unrecognized, that1.XXX_unrecognized); c != 0 { + return c + } return 0 } func (this *Help_Link) Compare(that interface{}) int { @@ -901,6 +1609,9 @@ func (this *Help_Link) Compare(that interface{}) int { } return 1 } + if c := bytes.Compare(this.XXX_unrecognized, that1.XXX_unrecognized); c != 0 { + return c + } return 0 } func (this *LocalizedMessage) Compare(that interface{}) int { @@ -940,6 +1651,9 @@ func (this *LocalizedMessage) Compare(that interface{}) int { } return 1 } + if c := bytes.Compare(this.XXX_unrecognized, that1.XXX_unrecognized); c != 0 { + return c + } return 0 } func (this *RetryInfo) Equal(that interface{}) bool { @@ -964,6 +1678,9 @@ func (this *RetryInfo) Equal(that interface{}) bool { if !this.RetryDelay.Equal(that1.RetryDelay) { return false } + if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) { + return false + } return true } func (this *DebugInfo) Equal(that interface{}) bool { @@ -996,6 +1713,9 @@ func (this *DebugInfo) Equal(that interface{}) bool { if this.Detail != that1.Detail { return false } + if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) { + return false + } return true } func (this *QuotaFailure) Equal(that interface{}) bool { @@ -1025,6 +1745,9 @@ func (this *QuotaFailure) Equal(that interface{}) bool { return false } } + if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) { + return false + } return true } func (this *QuotaFailure_Violation) Equal(that interface{}) bool { @@ -1052,16 +1775,19 @@ func (this *QuotaFailure_Violation) Equal(that interface{}) bool { if this.Description != that1.Description { return false } + if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) { + return false + } return true } -func (this *PreconditionFailure) Equal(that interface{}) bool { +func (this *ErrorInfo) Equal(that interface{}) bool { if that == nil { return this == nil } - that1, ok := that.(*PreconditionFailure) + that1, ok := that.(*ErrorInfo) if !ok { - that2, ok := that.(PreconditionFailure) + that2, ok := that.(ErrorInfo) if ok { that1 = &that2 } else { @@ -1073,24 +1799,33 @@ func (this *PreconditionFailure) Equal(that interface{}) bool { } else if this == nil { return false } - if len(this.Violations) != len(that1.Violations) { + if this.Reason != that1.Reason { return false } - for i := range this.Violations { - if !this.Violations[i].Equal(that1.Violations[i]) { + if this.Domain != that1.Domain { + return false + } + if len(this.Metadata) != len(that1.Metadata) { + return false + } + for i := range this.Metadata { + if this.Metadata[i] != that1.Metadata[i] { return false } } + if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) { + return false + } return true } -func (this *PreconditionFailure_Violation) Equal(that interface{}) bool { +func (this *PreconditionFailure) Equal(that interface{}) bool { if that == nil { return this == nil } - that1, ok := that.(*PreconditionFailure_Violation) + that1, ok := that.(*PreconditionFailure) if !ok { - that2, ok := that.(PreconditionFailure_Violation) + that2, ok := that.(PreconditionFailure) if ok { that1 = &that2 } else { @@ -1102,18 +1837,53 @@ func (this *PreconditionFailure_Violation) Equal(that interface{}) bool { } else if this == nil { return false } - if this.Type != that1.Type { + if len(this.Violations) != len(that1.Violations) { return false } - if this.Subject != that1.Subject { - return false + for i := range this.Violations { + if !this.Violations[i].Equal(that1.Violations[i]) { + return false + } } - if this.Description != that1.Description { + if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) { return false } return true } -func (this *BadRequest) Equal(that interface{}) bool { +func (this *PreconditionFailure_Violation) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PreconditionFailure_Violation) + if !ok { + that2, ok := that.(PreconditionFailure_Violation) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Type != that1.Type { + return false + } + if this.Subject != that1.Subject { + return false + } + if this.Description != that1.Description { + return false + } + if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) { + return false + } + return true +} +func (this *BadRequest) Equal(that interface{}) bool { if that == nil { return this == nil } @@ -1140,6 +1910,9 @@ func (this *BadRequest) Equal(that interface{}) bool { return false } } + if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) { + return false + } return true } func (this *BadRequest_FieldViolation) Equal(that interface{}) bool { @@ -1167,6 +1940,9 @@ func (this *BadRequest_FieldViolation) Equal(that interface{}) bool { if this.Description != that1.Description { return false } + if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) { + return false + } return true } func (this *RequestInfo) Equal(that interface{}) bool { @@ -1194,6 +1970,9 @@ func (this *RequestInfo) Equal(that interface{}) bool { if this.ServingData != that1.ServingData { return false } + if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) { + return false + } return true } func (this *ResourceInfo) Equal(that interface{}) bool { @@ -1227,6 +2006,9 @@ func (this *ResourceInfo) Equal(that interface{}) bool { if this.Description != that1.Description { return false } + if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) { + return false + } return true } func (this *Help) Equal(that interface{}) bool { @@ -1256,6 +2038,9 @@ func (this *Help) Equal(that interface{}) bool { return false } } + if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) { + return false + } return true } func (this *Help_Link) Equal(that interface{}) bool { @@ -1283,6 +2068,9 @@ func (this *Help_Link) Equal(that interface{}) bool { if this.Url != that1.Url { return false } + if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) { + return false + } return true } func (this *LocalizedMessage) Equal(that interface{}) bool { @@ -1310,6 +2098,9 @@ func (this *LocalizedMessage) Equal(that interface{}) bool { if this.Message != that1.Message { return false } + if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) { + return false + } return true } func (this *RetryInfo) GoString() string { @@ -1321,6 +2112,9 @@ func (this *RetryInfo) GoString() string { if this.RetryDelay != nil { s = append(s, "RetryDelay: "+fmt.Sprintf("%#v", this.RetryDelay)+",\n") } + if this.XXX_unrecognized != nil { + s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") + } s = append(s, "}") return strings.Join(s, "") } @@ -1332,6 +2126,9 @@ func (this *DebugInfo) GoString() string { s = append(s, "&rpc.DebugInfo{") s = append(s, "StackEntries: "+fmt.Sprintf("%#v", this.StackEntries)+",\n") s = append(s, "Detail: "+fmt.Sprintf("%#v", this.Detail)+",\n") + if this.XXX_unrecognized != nil { + s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") + } s = append(s, "}") return strings.Join(s, "") } @@ -1344,6 +2141,9 @@ func (this *QuotaFailure) GoString() string { if this.Violations != nil { s = append(s, "Violations: "+fmt.Sprintf("%#v", this.Violations)+",\n") } + if this.XXX_unrecognized != nil { + s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") + } s = append(s, "}") return strings.Join(s, "") } @@ -1355,6 +2155,36 @@ func (this *QuotaFailure_Violation) GoString() string { s = append(s, "&rpc.QuotaFailure_Violation{") s = append(s, "Subject: "+fmt.Sprintf("%#v", this.Subject)+",\n") s = append(s, "Description: "+fmt.Sprintf("%#v", this.Description)+",\n") + if this.XXX_unrecognized != nil { + s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") + } + s = append(s, "}") + return strings.Join(s, "") +} +func (this *ErrorInfo) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 7) + s = append(s, "&rpc.ErrorInfo{") + s = append(s, "Reason: "+fmt.Sprintf("%#v", this.Reason)+",\n") + s = append(s, "Domain: "+fmt.Sprintf("%#v", this.Domain)+",\n") + keysForMetadata := make([]string, 0, len(this.Metadata)) + for k, _ := range this.Metadata { + keysForMetadata = append(keysForMetadata, k) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForMetadata) + mapStringForMetadata := "map[string]string{" + for _, k := range keysForMetadata { + mapStringForMetadata += fmt.Sprintf("%#v: %#v,", k, this.Metadata[k]) + } + mapStringForMetadata += "}" + if this.Metadata != nil { + s = append(s, "Metadata: "+mapStringForMetadata+",\n") + } + if this.XXX_unrecognized != nil { + s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") + } s = append(s, "}") return strings.Join(s, "") } @@ -1367,6 +2197,9 @@ func (this *PreconditionFailure) GoString() string { if this.Violations != nil { s = append(s, "Violations: "+fmt.Sprintf("%#v", this.Violations)+",\n") } + if this.XXX_unrecognized != nil { + s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") + } s = append(s, "}") return strings.Join(s, "") } @@ -1379,6 +2212,9 @@ func (this *PreconditionFailure_Violation) GoString() string { s = append(s, "Type: "+fmt.Sprintf("%#v", this.Type)+",\n") s = append(s, "Subject: "+fmt.Sprintf("%#v", this.Subject)+",\n") s = append(s, "Description: "+fmt.Sprintf("%#v", this.Description)+",\n") + if this.XXX_unrecognized != nil { + s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") + } s = append(s, "}") return strings.Join(s, "") } @@ -1391,6 +2227,9 @@ func (this *BadRequest) GoString() string { if this.FieldViolations != nil { s = append(s, "FieldViolations: "+fmt.Sprintf("%#v", this.FieldViolations)+",\n") } + if this.XXX_unrecognized != nil { + s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") + } s = append(s, "}") return strings.Join(s, "") } @@ -1402,6 +2241,9 @@ func (this *BadRequest_FieldViolation) GoString() string { s = append(s, "&rpc.BadRequest_FieldViolation{") s = append(s, "Field: "+fmt.Sprintf("%#v", this.Field)+",\n") s = append(s, "Description: "+fmt.Sprintf("%#v", this.Description)+",\n") + if this.XXX_unrecognized != nil { + s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") + } s = append(s, "}") return strings.Join(s, "") } @@ -1413,6 +2255,9 @@ func (this *RequestInfo) GoString() string { s = append(s, "&rpc.RequestInfo{") s = append(s, "RequestId: "+fmt.Sprintf("%#v", this.RequestId)+",\n") s = append(s, "ServingData: "+fmt.Sprintf("%#v", this.ServingData)+",\n") + if this.XXX_unrecognized != nil { + s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") + } s = append(s, "}") return strings.Join(s, "") } @@ -1426,6 +2271,9 @@ func (this *ResourceInfo) GoString() string { s = append(s, "ResourceName: "+fmt.Sprintf("%#v", this.ResourceName)+",\n") s = append(s, "Owner: "+fmt.Sprintf("%#v", this.Owner)+",\n") s = append(s, "Description: "+fmt.Sprintf("%#v", this.Description)+",\n") + if this.XXX_unrecognized != nil { + s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") + } s = append(s, "}") return strings.Join(s, "") } @@ -1438,6 +2286,9 @@ func (this *Help) GoString() string { if this.Links != nil { s = append(s, "Links: "+fmt.Sprintf("%#v", this.Links)+",\n") } + if this.XXX_unrecognized != nil { + s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") + } s = append(s, "}") return strings.Join(s, "") } @@ -1449,6 +2300,9 @@ func (this *Help_Link) GoString() string { s = append(s, "&rpc.Help_Link{") s = append(s, "Description: "+fmt.Sprintf("%#v", this.Description)+",\n") s = append(s, "Url: "+fmt.Sprintf("%#v", this.Url)+",\n") + if this.XXX_unrecognized != nil { + s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") + } s = append(s, "}") return strings.Join(s, "") } @@ -1460,6 +2314,9 @@ func (this *LocalizedMessage) GoString() string { s = append(s, "&rpc.LocalizedMessage{") s = append(s, "Locale: "+fmt.Sprintf("%#v", this.Locale)+",\n") s = append(s, "Message: "+fmt.Sprintf("%#v", this.Message)+",\n") + if this.XXX_unrecognized != nil { + s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") + } s = append(s, "}") return strings.Join(s, "") } @@ -1474,7 +2331,7 @@ func valueToGoStringErrorDetails(v interface{}, typ string) string { func (m *RetryInfo) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -1482,27 +2339,38 @@ func (m *RetryInfo) Marshal() (dAtA []byte, err error) { } func (m *RetryInfo) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RetryInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } if m.RetryDelay != nil { - dAtA[i] = 0xa - i++ - i = encodeVarintErrorDetails(dAtA, i, uint64(m.RetryDelay.Size())) - n1, err := m.RetryDelay.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err + { + size, err := m.RetryDelay.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintErrorDetails(dAtA, i, uint64(size)) } - i += n1 + i-- + dAtA[i] = 0xa } - return i, nil + return len(dAtA) - i, nil } func (m *DebugInfo) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -1510,38 +2378,42 @@ func (m *DebugInfo) Marshal() (dAtA []byte, err error) { } func (m *DebugInfo) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *DebugInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l - if len(m.StackEntries) > 0 { - for _, s := range m.StackEntries { - dAtA[i] = 0xa - i++ - l = len(s) - for l >= 1<<7 { - dAtA[i] = uint8(uint64(l)&0x7f | 0x80) - l >>= 7 - i++ - } - dAtA[i] = uint8(l) - i++ - i += copy(dAtA[i:], s) - } + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) } if len(m.Detail) > 0 { - dAtA[i] = 0x12 - i++ + i -= len(m.Detail) + copy(dAtA[i:], m.Detail) i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Detail))) - i += copy(dAtA[i:], m.Detail) + i-- + dAtA[i] = 0x12 } - return i, nil + if len(m.StackEntries) > 0 { + for iNdEx := len(m.StackEntries) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.StackEntries[iNdEx]) + copy(dAtA[i:], m.StackEntries[iNdEx]) + i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.StackEntries[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil } func (m *QuotaFailure) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -1549,29 +2421,40 @@ func (m *QuotaFailure) Marshal() (dAtA []byte, err error) { } func (m *QuotaFailure) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QuotaFailure) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } if len(m.Violations) > 0 { - for _, msg := range m.Violations { - dAtA[i] = 0xa - i++ - i = encodeVarintErrorDetails(dAtA, i, uint64(msg.Size())) - n, err := msg.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err + for iNdEx := len(m.Violations) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Violations[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintErrorDetails(dAtA, i, uint64(size)) } - i += n + i-- + dAtA[i] = 0xa } } - return i, nil + return len(dAtA) - i, nil } func (m *QuotaFailure_Violation) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -1579,29 +2462,100 @@ func (m *QuotaFailure_Violation) Marshal() (dAtA []byte, err error) { } func (m *QuotaFailure_Violation) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QuotaFailure_Violation) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x12 + } if len(m.Subject) > 0 { - dAtA[i] = 0xa - i++ + i -= len(m.Subject) + copy(dAtA[i:], m.Subject) i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Subject))) - i += copy(dAtA[i:], m.Subject) + i-- + dAtA[i] = 0xa } - if len(m.Description) > 0 { + return len(dAtA) - i, nil +} + +func (m *ErrorInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ErrorInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ErrorInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } + if len(m.Metadata) > 0 { + for k := range m.Metadata { + v := m.Metadata[k] + baseI := i + i -= len(v) + copy(dAtA[i:], v) + i = encodeVarintErrorDetails(dAtA, i, uint64(len(v))) + i-- + dAtA[i] = 0x12 + i -= len(k) + copy(dAtA[i:], k) + i = encodeVarintErrorDetails(dAtA, i, uint64(len(k))) + i-- + dAtA[i] = 0xa + i = encodeVarintErrorDetails(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0x1a + } + } + if len(m.Domain) > 0 { + i -= len(m.Domain) + copy(dAtA[i:], m.Domain) + i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Domain))) + i-- dAtA[i] = 0x12 - i++ - i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Description))) - i += copy(dAtA[i:], m.Description) } - return i, nil + if len(m.Reason) > 0 { + i -= len(m.Reason) + copy(dAtA[i:], m.Reason) + i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Reason))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil } func (m *PreconditionFailure) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -1609,29 +2563,40 @@ func (m *PreconditionFailure) Marshal() (dAtA []byte, err error) { } func (m *PreconditionFailure) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PreconditionFailure) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } if len(m.Violations) > 0 { - for _, msg := range m.Violations { - dAtA[i] = 0xa - i++ - i = encodeVarintErrorDetails(dAtA, i, uint64(msg.Size())) - n, err := msg.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err + for iNdEx := len(m.Violations) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Violations[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintErrorDetails(dAtA, i, uint64(size)) } - i += n + i-- + dAtA[i] = 0xa } } - return i, nil + return len(dAtA) - i, nil } func (m *PreconditionFailure_Violation) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -1639,35 +2604,47 @@ func (m *PreconditionFailure_Violation) Marshal() (dAtA []byte, err error) { } func (m *PreconditionFailure_Violation) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PreconditionFailure_Violation) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l - if len(m.Type) > 0 { - dAtA[i] = 0xa - i++ - i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Type))) - i += copy(dAtA[i:], m.Type) + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x1a } if len(m.Subject) > 0 { - dAtA[i] = 0x12 - i++ + i -= len(m.Subject) + copy(dAtA[i:], m.Subject) i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Subject))) - i += copy(dAtA[i:], m.Subject) + i-- + dAtA[i] = 0x12 } - if len(m.Description) > 0 { - dAtA[i] = 0x1a - i++ - i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Description))) - i += copy(dAtA[i:], m.Description) + if len(m.Type) > 0 { + i -= len(m.Type) + copy(dAtA[i:], m.Type) + i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Type))) + i-- + dAtA[i] = 0xa } - return i, nil + return len(dAtA) - i, nil } func (m *BadRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -1675,29 +2652,40 @@ func (m *BadRequest) Marshal() (dAtA []byte, err error) { } func (m *BadRequest) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *BadRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } if len(m.FieldViolations) > 0 { - for _, msg := range m.FieldViolations { - dAtA[i] = 0xa - i++ - i = encodeVarintErrorDetails(dAtA, i, uint64(msg.Size())) - n, err := msg.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err + for iNdEx := len(m.FieldViolations) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.FieldViolations[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintErrorDetails(dAtA, i, uint64(size)) } - i += n + i-- + dAtA[i] = 0xa } } - return i, nil + return len(dAtA) - i, nil } func (m *BadRequest_FieldViolation) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -1705,29 +2693,40 @@ func (m *BadRequest_FieldViolation) Marshal() (dAtA []byte, err error) { } func (m *BadRequest_FieldViolation) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *BadRequest_FieldViolation) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l - if len(m.Field) > 0 { - dAtA[i] = 0xa - i++ - i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Field))) - i += copy(dAtA[i:], m.Field) + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) } if len(m.Description) > 0 { - dAtA[i] = 0x12 - i++ + i -= len(m.Description) + copy(dAtA[i:], m.Description) i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Description))) - i += copy(dAtA[i:], m.Description) + i-- + dAtA[i] = 0x12 } - return i, nil + if len(m.Field) > 0 { + i -= len(m.Field) + copy(dAtA[i:], m.Field) + i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Field))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil } func (m *RequestInfo) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -1735,29 +2734,40 @@ func (m *RequestInfo) Marshal() (dAtA []byte, err error) { } func (m *RequestInfo) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l - if len(m.RequestId) > 0 { - dAtA[i] = 0xa - i++ - i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.RequestId))) - i += copy(dAtA[i:], m.RequestId) + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) } if len(m.ServingData) > 0 { - dAtA[i] = 0x12 - i++ + i -= len(m.ServingData) + copy(dAtA[i:], m.ServingData) i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.ServingData))) - i += copy(dAtA[i:], m.ServingData) + i-- + dAtA[i] = 0x12 } - return i, nil + if len(m.RequestId) > 0 { + i -= len(m.RequestId) + copy(dAtA[i:], m.RequestId) + i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.RequestId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil } func (m *ResourceInfo) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -1765,41 +2775,54 @@ func (m *ResourceInfo) Marshal() (dAtA []byte, err error) { } func (m *ResourceInfo) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResourceInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l - if len(m.ResourceType) > 0 { - dAtA[i] = 0xa - i++ - i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.ResourceType))) - i += copy(dAtA[i:], m.ResourceType) + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) } - if len(m.ResourceName) > 0 { - dAtA[i] = 0x12 - i++ - i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.ResourceName))) - i += copy(dAtA[i:], m.ResourceName) + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x22 } if len(m.Owner) > 0 { - dAtA[i] = 0x1a - i++ + i -= len(m.Owner) + copy(dAtA[i:], m.Owner) i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Owner))) - i += copy(dAtA[i:], m.Owner) + i-- + dAtA[i] = 0x1a } - if len(m.Description) > 0 { - dAtA[i] = 0x22 - i++ - i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Description))) - i += copy(dAtA[i:], m.Description) + if len(m.ResourceName) > 0 { + i -= len(m.ResourceName) + copy(dAtA[i:], m.ResourceName) + i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.ResourceName))) + i-- + dAtA[i] = 0x12 + } + if len(m.ResourceType) > 0 { + i -= len(m.ResourceType) + copy(dAtA[i:], m.ResourceType) + i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.ResourceType))) + i-- + dAtA[i] = 0xa } - return i, nil + return len(dAtA) - i, nil } func (m *Help) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -1807,29 +2830,40 @@ func (m *Help) Marshal() (dAtA []byte, err error) { } func (m *Help) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Help) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } if len(m.Links) > 0 { - for _, msg := range m.Links { - dAtA[i] = 0xa - i++ - i = encodeVarintErrorDetails(dAtA, i, uint64(msg.Size())) - n, err := msg.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err + for iNdEx := len(m.Links) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Links[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintErrorDetails(dAtA, i, uint64(size)) } - i += n + i-- + dAtA[i] = 0xa } } - return i, nil + return len(dAtA) - i, nil } func (m *Help_Link) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -1837,29 +2871,40 @@ func (m *Help_Link) Marshal() (dAtA []byte, err error) { } func (m *Help_Link) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Help_Link) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l - if len(m.Description) > 0 { - dAtA[i] = 0xa - i++ - i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Description))) - i += copy(dAtA[i:], m.Description) + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) } if len(m.Url) > 0 { - dAtA[i] = 0x12 - i++ + i -= len(m.Url) + copy(dAtA[i:], m.Url) i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Url))) - i += copy(dAtA[i:], m.Url) + i-- + dAtA[i] = 0x12 } - return i, nil + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil } func (m *LocalizedMessage) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -1867,40 +2912,54 @@ func (m *LocalizedMessage) Marshal() (dAtA []byte, err error) { } func (m *LocalizedMessage) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *LocalizedMessage) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l - if len(m.Locale) > 0 { - dAtA[i] = 0xa - i++ - i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Locale))) - i += copy(dAtA[i:], m.Locale) + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) } if len(m.Message) > 0 { - dAtA[i] = 0x12 - i++ + i -= len(m.Message) + copy(dAtA[i:], m.Message) i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Message))) - i += copy(dAtA[i:], m.Message) + i-- + dAtA[i] = 0x12 } - return i, nil + if len(m.Locale) > 0 { + i -= len(m.Locale) + copy(dAtA[i:], m.Locale) + i = encodeVarintErrorDetails(dAtA, i, uint64(len(m.Locale))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil } func encodeVarintErrorDetails(dAtA []byte, offset int, v uint64) int { + offset -= sovErrorDetails(v) + base := offset for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) v >>= 7 offset++ } dAtA[offset] = uint8(v) - return offset + 1 + return base } func NewPopulatedRetryInfo(r randyErrorDetails, easy bool) *RetryInfo { this := &RetryInfo{} - if r.Intn(10) != 0 { - this.RetryDelay = google_protobuf1.NewPopulatedDuration(r, easy) + if r.Intn(5) != 0 { + this.RetryDelay = types.NewPopulatedDuration(r, easy) } if !easy && r.Intn(10) != 0 { + this.XXX_unrecognized = randUnrecognizedErrorDetails(r, 2) } return this } @@ -1914,13 +2973,14 @@ func NewPopulatedDebugInfo(r randyErrorDetails, easy bool) *DebugInfo { } this.Detail = string(randStringErrorDetails(r)) if !easy && r.Intn(10) != 0 { + this.XXX_unrecognized = randUnrecognizedErrorDetails(r, 3) } return this } func NewPopulatedQuotaFailure(r randyErrorDetails, easy bool) *QuotaFailure { this := &QuotaFailure{} - if r.Intn(10) != 0 { + if r.Intn(5) != 0 { v2 := r.Intn(5) this.Violations = make([]*QuotaFailure_Violation, v2) for i := 0; i < v2; i++ { @@ -1928,6 +2988,7 @@ func NewPopulatedQuotaFailure(r randyErrorDetails, easy bool) *QuotaFailure { } } if !easy && r.Intn(10) != 0 { + this.XXX_unrecognized = randUnrecognizedErrorDetails(r, 2) } return this } @@ -1937,20 +2998,39 @@ func NewPopulatedQuotaFailure_Violation(r randyErrorDetails, easy bool) *QuotaFa this.Subject = string(randStringErrorDetails(r)) this.Description = string(randStringErrorDetails(r)) if !easy && r.Intn(10) != 0 { + this.XXX_unrecognized = randUnrecognizedErrorDetails(r, 3) + } + return this +} + +func NewPopulatedErrorInfo(r randyErrorDetails, easy bool) *ErrorInfo { + this := &ErrorInfo{} + this.Reason = string(randStringErrorDetails(r)) + this.Domain = string(randStringErrorDetails(r)) + if r.Intn(5) != 0 { + v3 := r.Intn(10) + this.Metadata = make(map[string]string) + for i := 0; i < v3; i++ { + this.Metadata[randStringErrorDetails(r)] = randStringErrorDetails(r) + } + } + if !easy && r.Intn(10) != 0 { + this.XXX_unrecognized = randUnrecognizedErrorDetails(r, 4) } return this } func NewPopulatedPreconditionFailure(r randyErrorDetails, easy bool) *PreconditionFailure { this := &PreconditionFailure{} - if r.Intn(10) != 0 { - v3 := r.Intn(5) - this.Violations = make([]*PreconditionFailure_Violation, v3) - for i := 0; i < v3; i++ { + if r.Intn(5) != 0 { + v4 := r.Intn(5) + this.Violations = make([]*PreconditionFailure_Violation, v4) + for i := 0; i < v4; i++ { this.Violations[i] = NewPopulatedPreconditionFailure_Violation(r, easy) } } if !easy && r.Intn(10) != 0 { + this.XXX_unrecognized = randUnrecognizedErrorDetails(r, 2) } return this } @@ -1961,20 +3041,22 @@ func NewPopulatedPreconditionFailure_Violation(r randyErrorDetails, easy bool) * this.Subject = string(randStringErrorDetails(r)) this.Description = string(randStringErrorDetails(r)) if !easy && r.Intn(10) != 0 { + this.XXX_unrecognized = randUnrecognizedErrorDetails(r, 4) } return this } func NewPopulatedBadRequest(r randyErrorDetails, easy bool) *BadRequest { this := &BadRequest{} - if r.Intn(10) != 0 { - v4 := r.Intn(5) - this.FieldViolations = make([]*BadRequest_FieldViolation, v4) - for i := 0; i < v4; i++ { + if r.Intn(5) != 0 { + v5 := r.Intn(5) + this.FieldViolations = make([]*BadRequest_FieldViolation, v5) + for i := 0; i < v5; i++ { this.FieldViolations[i] = NewPopulatedBadRequest_FieldViolation(r, easy) } } if !easy && r.Intn(10) != 0 { + this.XXX_unrecognized = randUnrecognizedErrorDetails(r, 2) } return this } @@ -1984,6 +3066,7 @@ func NewPopulatedBadRequest_FieldViolation(r randyErrorDetails, easy bool) *BadR this.Field = string(randStringErrorDetails(r)) this.Description = string(randStringErrorDetails(r)) if !easy && r.Intn(10) != 0 { + this.XXX_unrecognized = randUnrecognizedErrorDetails(r, 3) } return this } @@ -1993,6 +3076,7 @@ func NewPopulatedRequestInfo(r randyErrorDetails, easy bool) *RequestInfo { this.RequestId = string(randStringErrorDetails(r)) this.ServingData = string(randStringErrorDetails(r)) if !easy && r.Intn(10) != 0 { + this.XXX_unrecognized = randUnrecognizedErrorDetails(r, 3) } return this } @@ -2004,20 +3088,22 @@ func NewPopulatedResourceInfo(r randyErrorDetails, easy bool) *ResourceInfo { this.Owner = string(randStringErrorDetails(r)) this.Description = string(randStringErrorDetails(r)) if !easy && r.Intn(10) != 0 { + this.XXX_unrecognized = randUnrecognizedErrorDetails(r, 5) } return this } func NewPopulatedHelp(r randyErrorDetails, easy bool) *Help { this := &Help{} - if r.Intn(10) != 0 { - v5 := r.Intn(5) - this.Links = make([]*Help_Link, v5) - for i := 0; i < v5; i++ { + if r.Intn(5) != 0 { + v6 := r.Intn(5) + this.Links = make([]*Help_Link, v6) + for i := 0; i < v6; i++ { this.Links[i] = NewPopulatedHelp_Link(r, easy) } } if !easy && r.Intn(10) != 0 { + this.XXX_unrecognized = randUnrecognizedErrorDetails(r, 2) } return this } @@ -2027,6 +3113,7 @@ func NewPopulatedHelp_Link(r randyErrorDetails, easy bool) *Help_Link { this.Description = string(randStringErrorDetails(r)) this.Url = string(randStringErrorDetails(r)) if !easy && r.Intn(10) != 0 { + this.XXX_unrecognized = randUnrecognizedErrorDetails(r, 3) } return this } @@ -2036,6 +3123,7 @@ func NewPopulatedLocalizedMessage(r randyErrorDetails, easy bool) *LocalizedMess this.Locale = string(randStringErrorDetails(r)) this.Message = string(randStringErrorDetails(r)) if !easy && r.Intn(10) != 0 { + this.XXX_unrecognized = randUnrecognizedErrorDetails(r, 3) } return this } @@ -2059,9 +3147,9 @@ func randUTF8RuneErrorDetails(r randyErrorDetails) rune { return rune(ru + 61) } func randStringErrorDetails(r randyErrorDetails) string { - v6 := r.Intn(100) - tmps := make([]rune, v6) - for i := 0; i < v6; i++ { + v7 := r.Intn(100) + tmps := make([]rune, v7) + for i := 0; i < v7; i++ { tmps[i] = randUTF8RuneErrorDetails(r) } return string(tmps) @@ -2083,11 +3171,11 @@ func randFieldErrorDetails(dAtA []byte, r randyErrorDetails, fieldNumber int, wi switch wire { case 0: dAtA = encodeVarintPopulateErrorDetails(dAtA, uint64(key)) - v7 := r.Int63() + v8 := r.Int63() if r.Intn(2) == 0 { - v7 *= -1 + v8 *= -1 } - dAtA = encodeVarintPopulateErrorDetails(dAtA, uint64(v7)) + dAtA = encodeVarintPopulateErrorDetails(dAtA, uint64(v8)) case 1: dAtA = encodeVarintPopulateErrorDetails(dAtA, uint64(key)) dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256))) @@ -2113,16 +3201,25 @@ func encodeVarintPopulateErrorDetails(dAtA []byte, v uint64) []byte { return dAtA } func (m *RetryInfo) Size() (n int) { + if m == nil { + return 0 + } var l int _ = l if m.RetryDelay != nil { l = m.RetryDelay.Size() n += 1 + l + sovErrorDetails(uint64(l)) } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } return n } func (m *DebugInfo) Size() (n int) { + if m == nil { + return 0 + } var l int _ = l if len(m.StackEntries) > 0 { @@ -2135,10 +3232,16 @@ func (m *DebugInfo) Size() (n int) { if l > 0 { n += 1 + l + sovErrorDetails(uint64(l)) } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } return n } func (m *QuotaFailure) Size() (n int) { + if m == nil { + return 0 + } var l int _ = l if len(m.Violations) > 0 { @@ -2147,10 +3250,16 @@ func (m *QuotaFailure) Size() (n int) { n += 1 + l + sovErrorDetails(uint64(l)) } } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } return n } func (m *QuotaFailure_Violation) Size() (n int) { + if m == nil { + return 0 + } var l int _ = l l = len(m.Subject) @@ -2161,10 +3270,44 @@ func (m *QuotaFailure_Violation) Size() (n int) { if l > 0 { n += 1 + l + sovErrorDetails(uint64(l)) } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + +func (m *ErrorInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Reason) + if l > 0 { + n += 1 + l + sovErrorDetails(uint64(l)) + } + l = len(m.Domain) + if l > 0 { + n += 1 + l + sovErrorDetails(uint64(l)) + } + if len(m.Metadata) > 0 { + for k, v := range m.Metadata { + _ = k + _ = v + mapEntrySize := 1 + len(k) + sovErrorDetails(uint64(len(k))) + 1 + len(v) + sovErrorDetails(uint64(len(v))) + n += mapEntrySize + 1 + sovErrorDetails(uint64(mapEntrySize)) + } + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } return n } func (m *PreconditionFailure) Size() (n int) { + if m == nil { + return 0 + } var l int _ = l if len(m.Violations) > 0 { @@ -2173,10 +3316,16 @@ func (m *PreconditionFailure) Size() (n int) { n += 1 + l + sovErrorDetails(uint64(l)) } } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } return n } func (m *PreconditionFailure_Violation) Size() (n int) { + if m == nil { + return 0 + } var l int _ = l l = len(m.Type) @@ -2191,10 +3340,16 @@ func (m *PreconditionFailure_Violation) Size() (n int) { if l > 0 { n += 1 + l + sovErrorDetails(uint64(l)) } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } return n } func (m *BadRequest) Size() (n int) { + if m == nil { + return 0 + } var l int _ = l if len(m.FieldViolations) > 0 { @@ -2203,10 +3358,16 @@ func (m *BadRequest) Size() (n int) { n += 1 + l + sovErrorDetails(uint64(l)) } } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } return n } func (m *BadRequest_FieldViolation) Size() (n int) { + if m == nil { + return 0 + } var l int _ = l l = len(m.Field) @@ -2217,10 +3378,16 @@ func (m *BadRequest_FieldViolation) Size() (n int) { if l > 0 { n += 1 + l + sovErrorDetails(uint64(l)) } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } return n } func (m *RequestInfo) Size() (n int) { + if m == nil { + return 0 + } var l int _ = l l = len(m.RequestId) @@ -2231,10 +3398,16 @@ func (m *RequestInfo) Size() (n int) { if l > 0 { n += 1 + l + sovErrorDetails(uint64(l)) } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } return n } func (m *ResourceInfo) Size() (n int) { + if m == nil { + return 0 + } var l int _ = l l = len(m.ResourceType) @@ -2253,10 +3426,16 @@ func (m *ResourceInfo) Size() (n int) { if l > 0 { n += 1 + l + sovErrorDetails(uint64(l)) } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } return n } func (m *Help) Size() (n int) { + if m == nil { + return 0 + } var l int _ = l if len(m.Links) > 0 { @@ -2265,10 +3444,16 @@ func (m *Help) Size() (n int) { n += 1 + l + sovErrorDetails(uint64(l)) } } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } return n } func (m *Help_Link) Size() (n int) { + if m == nil { + return 0 + } var l int _ = l l = len(m.Description) @@ -2279,10 +3464,16 @@ func (m *Help_Link) Size() (n int) { if l > 0 { n += 1 + l + sovErrorDetails(uint64(l)) } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } return n } func (m *LocalizedMessage) Size() (n int) { + if m == nil { + return 0 + } var l int _ = l l = len(m.Locale) @@ -2293,18 +3484,14 @@ func (m *LocalizedMessage) Size() (n int) { if l > 0 { n += 1 + l + sovErrorDetails(uint64(l)) } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } return n } func sovErrorDetails(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } - } - return n + return (math_bits.Len64(x|1) + 6) / 7 } func sozErrorDetails(x uint64) (n int) { return sovErrorDetails(uint64((x << 1) ^ uint64((int64(x) >> 63)))) @@ -2314,7 +3501,8 @@ func (this *RetryInfo) String() string { return "nil" } s := strings.Join([]string{`&RetryInfo{`, - `RetryDelay:` + strings.Replace(fmt.Sprintf("%v", this.RetryDelay), "Duration", "google_protobuf1.Duration", 1) + `,`, + `RetryDelay:` + strings.Replace(fmt.Sprintf("%v", this.RetryDelay), "Duration", "types.Duration", 1) + `,`, + `XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`, `}`, }, "") return s @@ -2326,6 +3514,7 @@ func (this *DebugInfo) String() string { s := strings.Join([]string{`&DebugInfo{`, `StackEntries:` + fmt.Sprintf("%v", this.StackEntries) + `,`, `Detail:` + fmt.Sprintf("%v", this.Detail) + `,`, + `XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`, `}`, }, "") return s @@ -2334,8 +3523,14 @@ func (this *QuotaFailure) String() string { if this == nil { return "nil" } + repeatedStringForViolations := "[]*QuotaFailure_Violation{" + for _, f := range this.Violations { + repeatedStringForViolations += strings.Replace(fmt.Sprintf("%v", f), "QuotaFailure_Violation", "QuotaFailure_Violation", 1) + "," + } + repeatedStringForViolations += "}" s := strings.Join([]string{`&QuotaFailure{`, - `Violations:` + strings.Replace(fmt.Sprintf("%v", this.Violations), "QuotaFailure_Violation", "QuotaFailure_Violation", 1) + `,`, + `Violations:` + repeatedStringForViolations + `,`, + `XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`, `}`, }, "") return s @@ -2347,6 +3542,30 @@ func (this *QuotaFailure_Violation) String() string { s := strings.Join([]string{`&QuotaFailure_Violation{`, `Subject:` + fmt.Sprintf("%v", this.Subject) + `,`, `Description:` + fmt.Sprintf("%v", this.Description) + `,`, + `XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`, + `}`, + }, "") + return s +} +func (this *ErrorInfo) String() string { + if this == nil { + return "nil" + } + keysForMetadata := make([]string, 0, len(this.Metadata)) + for k, _ := range this.Metadata { + keysForMetadata = append(keysForMetadata, k) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForMetadata) + mapStringForMetadata := "map[string]string{" + for _, k := range keysForMetadata { + mapStringForMetadata += fmt.Sprintf("%v: %v,", k, this.Metadata[k]) + } + mapStringForMetadata += "}" + s := strings.Join([]string{`&ErrorInfo{`, + `Reason:` + fmt.Sprintf("%v", this.Reason) + `,`, + `Domain:` + fmt.Sprintf("%v", this.Domain) + `,`, + `Metadata:` + mapStringForMetadata + `,`, + `XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`, `}`, }, "") return s @@ -2355,8 +3574,14 @@ func (this *PreconditionFailure) String() string { if this == nil { return "nil" } + repeatedStringForViolations := "[]*PreconditionFailure_Violation{" + for _, f := range this.Violations { + repeatedStringForViolations += strings.Replace(fmt.Sprintf("%v", f), "PreconditionFailure_Violation", "PreconditionFailure_Violation", 1) + "," + } + repeatedStringForViolations += "}" s := strings.Join([]string{`&PreconditionFailure{`, - `Violations:` + strings.Replace(fmt.Sprintf("%v", this.Violations), "PreconditionFailure_Violation", "PreconditionFailure_Violation", 1) + `,`, + `Violations:` + repeatedStringForViolations + `,`, + `XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`, `}`, }, "") return s @@ -2369,6 +3594,7 @@ func (this *PreconditionFailure_Violation) String() string { `Type:` + fmt.Sprintf("%v", this.Type) + `,`, `Subject:` + fmt.Sprintf("%v", this.Subject) + `,`, `Description:` + fmt.Sprintf("%v", this.Description) + `,`, + `XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`, `}`, }, "") return s @@ -2377,8 +3603,14 @@ func (this *BadRequest) String() string { if this == nil { return "nil" } + repeatedStringForFieldViolations := "[]*BadRequest_FieldViolation{" + for _, f := range this.FieldViolations { + repeatedStringForFieldViolations += strings.Replace(fmt.Sprintf("%v", f), "BadRequest_FieldViolation", "BadRequest_FieldViolation", 1) + "," + } + repeatedStringForFieldViolations += "}" s := strings.Join([]string{`&BadRequest{`, - `FieldViolations:` + strings.Replace(fmt.Sprintf("%v", this.FieldViolations), "BadRequest_FieldViolation", "BadRequest_FieldViolation", 1) + `,`, + `FieldViolations:` + repeatedStringForFieldViolations + `,`, + `XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`, `}`, }, "") return s @@ -2390,6 +3622,7 @@ func (this *BadRequest_FieldViolation) String() string { s := strings.Join([]string{`&BadRequest_FieldViolation{`, `Field:` + fmt.Sprintf("%v", this.Field) + `,`, `Description:` + fmt.Sprintf("%v", this.Description) + `,`, + `XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`, `}`, }, "") return s @@ -2401,6 +3634,7 @@ func (this *RequestInfo) String() string { s := strings.Join([]string{`&RequestInfo{`, `RequestId:` + fmt.Sprintf("%v", this.RequestId) + `,`, `ServingData:` + fmt.Sprintf("%v", this.ServingData) + `,`, + `XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`, `}`, }, "") return s @@ -2414,6 +3648,7 @@ func (this *ResourceInfo) String() string { `ResourceName:` + fmt.Sprintf("%v", this.ResourceName) + `,`, `Owner:` + fmt.Sprintf("%v", this.Owner) + `,`, `Description:` + fmt.Sprintf("%v", this.Description) + `,`, + `XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`, `}`, }, "") return s @@ -2422,8 +3657,14 @@ func (this *Help) String() string { if this == nil { return "nil" } + repeatedStringForLinks := "[]*Help_Link{" + for _, f := range this.Links { + repeatedStringForLinks += strings.Replace(fmt.Sprintf("%v", f), "Help_Link", "Help_Link", 1) + "," + } + repeatedStringForLinks += "}" s := strings.Join([]string{`&Help{`, - `Links:` + strings.Replace(fmt.Sprintf("%v", this.Links), "Help_Link", "Help_Link", 1) + `,`, + `Links:` + repeatedStringForLinks + `,`, + `XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`, `}`, }, "") return s @@ -2435,6 +3676,7 @@ func (this *Help_Link) String() string { s := strings.Join([]string{`&Help_Link{`, `Description:` + fmt.Sprintf("%v", this.Description) + `,`, `Url:` + fmt.Sprintf("%v", this.Url) + `,`, + `XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`, `}`, }, "") return s @@ -2446,6 +3688,7 @@ func (this *LocalizedMessage) String() string { s := strings.Join([]string{`&LocalizedMessage{`, `Locale:` + fmt.Sprintf("%v", this.Locale) + `,`, `Message:` + fmt.Sprintf("%v", this.Message) + `,`, + `XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`, `}`, }, "") return s @@ -2473,7 +3716,7 @@ func (m *RetryInfo) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -2501,7 +3744,7 @@ func (m *RetryInfo) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } @@ -2510,11 +3753,14 @@ func (m *RetryInfo) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } if m.RetryDelay == nil { - m.RetryDelay = &google_protobuf1.Duration{} + m.RetryDelay = &types.Duration{} } if err := m.RetryDelay.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -2526,12 +3772,13 @@ func (m *RetryInfo) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthErrorDetails } if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) iNdEx += skippy } } @@ -2556,7 +3803,7 @@ func (m *DebugInfo) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -2584,7 +3831,7 @@ func (m *DebugInfo) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -2594,6 +3841,9 @@ func (m *DebugInfo) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -2613,7 +3863,7 @@ func (m *DebugInfo) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -2623,6 +3873,9 @@ func (m *DebugInfo) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -2634,12 +3887,13 @@ func (m *DebugInfo) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthErrorDetails } if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) iNdEx += skippy } } @@ -2664,7 +3918,7 @@ func (m *QuotaFailure) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -2692,7 +3946,7 @@ func (m *QuotaFailure) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } @@ -2701,6 +3955,9 @@ func (m *QuotaFailure) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -2715,12 +3972,13 @@ func (m *QuotaFailure) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthErrorDetails } if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) iNdEx += skippy } } @@ -2745,7 +4003,7 @@ func (m *QuotaFailure_Violation) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -2773,7 +4031,7 @@ func (m *QuotaFailure_Violation) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -2783,6 +4041,9 @@ func (m *QuotaFailure_Violation) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -2802,7 +4063,7 @@ func (m *QuotaFailure_Violation) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -2812,6 +4073,9 @@ func (m *QuotaFailure_Violation) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -2823,12 +4087,255 @@ func (m *QuotaFailure_Violation) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthErrorDetails + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ErrorInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowErrorDetails + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ErrorInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ErrorInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Reason", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowErrorDetails + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthErrorDetails + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Reason = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Domain", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowErrorDetails + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthErrorDetails + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Domain = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowErrorDetails + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthErrorDetails + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Metadata == nil { + m.Metadata = make(map[string]string) + } + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowErrorDetails + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowErrorDetails + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthErrorDetails + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return ErrInvalidLengthErrorDetails + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowErrorDetails + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthErrorDetails + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue < 0 { + return ErrInvalidLengthErrorDetails + } + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipErrorDetails(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthErrorDetails + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.Metadata[mapkey] = mapvalue + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipErrorDetails(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthErrorDetails } if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) iNdEx += skippy } } @@ -2853,7 +4360,7 @@ func (m *PreconditionFailure) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -2881,7 +4388,7 @@ func (m *PreconditionFailure) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } @@ -2890,6 +4397,9 @@ func (m *PreconditionFailure) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -2904,12 +4414,13 @@ func (m *PreconditionFailure) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthErrorDetails } if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) iNdEx += skippy } } @@ -2934,7 +4445,7 @@ func (m *PreconditionFailure_Violation) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -2962,7 +4473,7 @@ func (m *PreconditionFailure_Violation) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -2972,6 +4483,9 @@ func (m *PreconditionFailure_Violation) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -2991,7 +4505,7 @@ func (m *PreconditionFailure_Violation) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -3001,6 +4515,9 @@ func (m *PreconditionFailure_Violation) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -3020,7 +4537,7 @@ func (m *PreconditionFailure_Violation) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -3030,6 +4547,9 @@ func (m *PreconditionFailure_Violation) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -3041,12 +4561,13 @@ func (m *PreconditionFailure_Violation) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthErrorDetails } if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) iNdEx += skippy } } @@ -3071,7 +4592,7 @@ func (m *BadRequest) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -3099,7 +4620,7 @@ func (m *BadRequest) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } @@ -3108,6 +4629,9 @@ func (m *BadRequest) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -3122,12 +4646,13 @@ func (m *BadRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthErrorDetails } if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) iNdEx += skippy } } @@ -3152,7 +4677,7 @@ func (m *BadRequest_FieldViolation) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -3180,7 +4705,7 @@ func (m *BadRequest_FieldViolation) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -3190,6 +4715,9 @@ func (m *BadRequest_FieldViolation) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -3209,7 +4737,7 @@ func (m *BadRequest_FieldViolation) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -3219,6 +4747,9 @@ func (m *BadRequest_FieldViolation) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -3230,12 +4761,13 @@ func (m *BadRequest_FieldViolation) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthErrorDetails } if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) iNdEx += skippy } } @@ -3260,7 +4792,7 @@ func (m *RequestInfo) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -3288,7 +4820,7 @@ func (m *RequestInfo) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -3298,6 +4830,9 @@ func (m *RequestInfo) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -3317,7 +4852,7 @@ func (m *RequestInfo) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -3327,6 +4862,9 @@ func (m *RequestInfo) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -3338,12 +4876,13 @@ func (m *RequestInfo) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthErrorDetails } if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) iNdEx += skippy } } @@ -3368,7 +4907,7 @@ func (m *ResourceInfo) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -3396,7 +4935,7 @@ func (m *ResourceInfo) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -3406,6 +4945,9 @@ func (m *ResourceInfo) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -3425,7 +4967,7 @@ func (m *ResourceInfo) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -3435,6 +4977,9 @@ func (m *ResourceInfo) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -3454,7 +4999,7 @@ func (m *ResourceInfo) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -3464,6 +5009,9 @@ func (m *ResourceInfo) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -3483,7 +5031,7 @@ func (m *ResourceInfo) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -3493,6 +5041,9 @@ func (m *ResourceInfo) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -3504,12 +5055,13 @@ func (m *ResourceInfo) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthErrorDetails } if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) iNdEx += skippy } } @@ -3534,7 +5086,7 @@ func (m *Help) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -3562,7 +5114,7 @@ func (m *Help) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } @@ -3571,6 +5123,9 @@ func (m *Help) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -3585,12 +5140,13 @@ func (m *Help) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthErrorDetails } if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) iNdEx += skippy } } @@ -3615,7 +5171,7 @@ func (m *Help_Link) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -3643,7 +5199,7 @@ func (m *Help_Link) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -3653,6 +5209,9 @@ func (m *Help_Link) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -3672,7 +5231,7 @@ func (m *Help_Link) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -3682,6 +5241,9 @@ func (m *Help_Link) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -3693,12 +5255,13 @@ func (m *Help_Link) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthErrorDetails } if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) iNdEx += skippy } } @@ -3723,7 +5286,7 @@ func (m *LocalizedMessage) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -3751,7 +5314,7 @@ func (m *LocalizedMessage) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -3761,6 +5324,9 @@ func (m *LocalizedMessage) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -3780,7 +5346,7 @@ func (m *LocalizedMessage) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -3790,6 +5356,9 @@ func (m *LocalizedMessage) Unmarshal(dAtA []byte) error { return ErrInvalidLengthErrorDetails } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErrorDetails + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -3801,12 +5370,13 @@ func (m *LocalizedMessage) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthErrorDetails } if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) iNdEx += skippy } } @@ -3819,6 +5389,7 @@ func (m *LocalizedMessage) Unmarshal(dAtA []byte) error { func skipErrorDetails(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 + depth := 0 for iNdEx < l { var wire uint64 for shift := uint(0); ; shift += 7 { @@ -3850,10 +5421,8 @@ func skipErrorDetails(dAtA []byte) (n int, err error) { break } } - return iNdEx, nil case 1: iNdEx += 8 - return iNdEx, nil case 2: var length int for shift := uint(0); ; shift += 7 { @@ -3870,98 +5439,34 @@ func skipErrorDetails(dAtA []byte) (n int, err error) { break } } - iNdEx += length if length < 0 { return 0, ErrInvalidLengthErrorDetails } - return iNdEx, nil + iNdEx += length case 3: - for { - var innerWire uint64 - var start int = iNdEx - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowErrorDetails - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - innerWire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - innerWireType := int(innerWire & 0x7) - if innerWireType == 4 { - break - } - next, err := skipErrorDetails(dAtA[start:]) - if err != nil { - return 0, err - } - iNdEx = start + next - } - return iNdEx, nil + depth++ case 4: - return iNdEx, nil + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupErrorDetails + } + depth-- case 5: iNdEx += 4 - return iNdEx, nil default: return 0, fmt.Errorf("proto: illegal wireType %d", wireType) } + if iNdEx < 0 { + return 0, ErrInvalidLengthErrorDetails + } + if depth == 0 { + return iNdEx, nil + } } - panic("unreachable") + return 0, io.ErrUnexpectedEOF } var ( - ErrInvalidLengthErrorDetails = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowErrorDetails = fmt.Errorf("proto: integer overflow") + ErrInvalidLengthErrorDetails = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowErrorDetails = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupErrorDetails = fmt.Errorf("proto: unexpected end of group") ) - -func init() { proto.RegisterFile("google/rpc/error_details.proto", fileDescriptorErrorDetails) } - -var fileDescriptorErrorDetails = []byte{ - // 623 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0xbf, 0x6f, 0xd3, 0x4e, - 0x1c, 0xed, 0x35, 0x69, 0xbf, 0xf2, 0x27, 0xf9, 0x96, 0x62, 0x7e, 0x28, 0x44, 0xc2, 0x0a, 0x46, - 0x48, 0x45, 0x48, 0xae, 0x54, 0xb6, 0x8e, 0x21, 0xfd, 0x25, 0x15, 0x08, 0x16, 0x62, 0x80, 0xc1, - 0x5c, 0xec, 0x4f, 0xa2, 0xa3, 0x8e, 0xcf, 0x9c, 0xcf, 0x45, 0x65, 0xe2, 0x4f, 0x60, 0x67, 0x63, - 0xea, 0x3f, 0xc1, 0xce, 0xd8, 0x91, 0x91, 0x84, 0x85, 0xb1, 0x23, 0x23, 0x3a, 0xfb, 0xae, 0x71, - 0x9b, 0x82, 0xd8, 0xfc, 0xde, 0xbd, 0x7b, 0x7e, 0xef, 0xa3, 0xbb, 0x03, 0x67, 0xc4, 0xf9, 0x28, - 0xc6, 0x75, 0x91, 0x86, 0xeb, 0x28, 0x04, 0x17, 0x41, 0x84, 0x92, 0xb2, 0x38, 0xf3, 0x52, 0xc1, - 0x25, 0xb7, 0xa1, 0x5c, 0xf7, 0x44, 0x1a, 0xb6, 0x8d, 0xb6, 0x58, 0x19, 0xe4, 0xc3, 0xf5, 0x28, - 0x17, 0x54, 0x32, 0x9e, 0x94, 0x5a, 0x77, 0x07, 0x2c, 0x1f, 0xa5, 0x38, 0xda, 0x4b, 0x86, 0xdc, - 0xde, 0x84, 0x86, 0x50, 0x20, 0x88, 0x30, 0xa6, 0x47, 0x2d, 0xd2, 0x21, 0x6b, 0x8d, 0x8d, 0x5b, - 0x9e, 0xb6, 0x33, 0x16, 0x5e, 0x4f, 0x5b, 0xf8, 0x50, 0xa8, 0x7b, 0x4a, 0xec, 0xee, 0x82, 0xd5, - 0xc3, 0x41, 0x3e, 0x2a, 0x8c, 0xee, 0xc2, 0xff, 0x99, 0xa4, 0xe1, 0x41, 0x80, 0x89, 0x14, 0x0c, - 0xb3, 0x16, 0xe9, 0xd4, 0xd6, 0x2c, 0xbf, 0x59, 0x90, 0x5b, 0x25, 0x67, 0xdf, 0x84, 0xe5, 0x32, - 0x77, 0x6b, 0xb1, 0x43, 0xd6, 0x2c, 0x5f, 0x23, 0xf7, 0x13, 0x81, 0xe6, 0xb3, 0x9c, 0x4b, 0xba, - 0x4d, 0x59, 0x9c, 0x0b, 0xb4, 0xbb, 0x00, 0x87, 0x8c, 0xc7, 0xc5, 0x3f, 0x4b, 0xab, 0xc6, 0x86, - 0xeb, 0xcd, 0x4a, 0x7a, 0x55, 0xb5, 0xf7, 0xc2, 0x48, 0xfd, 0xca, 0xae, 0xf6, 0x0e, 0x58, 0x67, - 0x0b, 0x76, 0x0b, 0xfe, 0xcb, 0xf2, 0xc1, 0x1b, 0x0c, 0x65, 0xd1, 0xd1, 0xf2, 0x0d, 0xb4, 0x3b, - 0xd0, 0x88, 0x30, 0x0b, 0x05, 0x4b, 0x95, 0x50, 0x07, 0xab, 0x52, 0xee, 0x17, 0x02, 0xd7, 0xfa, - 0x02, 0x43, 0x9e, 0x44, 0x4c, 0x11, 0x26, 0xe4, 0xde, 0x25, 0x21, 0xef, 0x57, 0x43, 0x5e, 0xb2, - 0xe9, 0x0f, 0x59, 0x5f, 0x55, 0xb3, 0xda, 0x50, 0x97, 0x47, 0x29, 0xea, 0xa0, 0xc5, 0x77, 0x35, - 0xff, 0xe2, 0x5f, 0xf3, 0xd7, 0xe6, 0xf3, 0x1f, 0x13, 0x80, 0x2e, 0x8d, 0x7c, 0x7c, 0x9b, 0x63, - 0x26, 0xed, 0x3e, 0xac, 0x0e, 0x19, 0xc6, 0x51, 0x30, 0x17, 0xfe, 0x5e, 0x35, 0xfc, 0x6c, 0x87, - 0xb7, 0xad, 0xe4, 0xb3, 0xe0, 0x57, 0x86, 0xe7, 0x70, 0xd6, 0xde, 0x85, 0x95, 0xf3, 0x12, 0xfb, - 0x3a, 0x2c, 0x15, 0x22, 0xdd, 0xa1, 0x04, 0xff, 0x30, 0xea, 0xa7, 0xd0, 0xd0, 0x3f, 0x2d, 0x0e, - 0xd5, 0x6d, 0x00, 0x51, 0xc2, 0x80, 0x19, 0x2f, 0x4b, 0x33, 0x7b, 0x91, 0x7d, 0x07, 0x9a, 0x19, - 0x8a, 0x43, 0x96, 0x8c, 0x82, 0x88, 0x4a, 0x6a, 0x0c, 0x35, 0xd7, 0xa3, 0x92, 0xba, 0x1f, 0x09, - 0x34, 0x7d, 0xcc, 0x78, 0x2e, 0x42, 0x34, 0xe7, 0x54, 0x68, 0x1c, 0x54, 0xa6, 0xdc, 0x34, 0xe4, - 0x73, 0x35, 0xed, 0xaa, 0x28, 0xa1, 0x63, 0xd4, 0xce, 0x67, 0xa2, 0x27, 0x74, 0x8c, 0xaa, 0x23, - 0x7f, 0x97, 0xa0, 0xd0, 0x23, 0x2f, 0xc1, 0xc5, 0x8e, 0xf5, 0xf9, 0x8e, 0x1c, 0xea, 0xbb, 0x18, - 0xa7, 0xf6, 0x03, 0x58, 0x8a, 0x59, 0x72, 0x60, 0x86, 0x7f, 0xa3, 0x3a, 0x7c, 0x25, 0xf0, 0xf6, - 0x59, 0x72, 0xe0, 0x97, 0x9a, 0xf6, 0x26, 0xd4, 0x15, 0xbc, 0x68, 0x4f, 0xe6, 0xec, 0xed, 0x55, - 0xa8, 0xe5, 0xc2, 0x5c, 0x30, 0xf5, 0xe9, 0xf6, 0x60, 0x75, 0x9f, 0x87, 0x34, 0x66, 0xef, 0x31, - 0x7a, 0x8c, 0x59, 0x46, 0x47, 0xa8, 0x6e, 0x62, 0xac, 0x38, 0xd3, 0x5f, 0x23, 0x75, 0xce, 0xc6, - 0xa5, 0xc4, 0x9c, 0x33, 0x0d, 0xbb, 0xaf, 0x4f, 0x26, 0xce, 0xc2, 0xb7, 0x89, 0xb3, 0x70, 0x3a, - 0x71, 0xc8, 0xaf, 0x89, 0x43, 0x3e, 0x4c, 0x1d, 0x72, 0x3c, 0x75, 0xc8, 0xd7, 0xa9, 0x43, 0x4e, - 0xa6, 0x0e, 0xf9, 0x3e, 0x75, 0xc8, 0xcf, 0xa9, 0xb3, 0x70, 0xaa, 0xf8, 0x1f, 0x0e, 0x81, 0x95, - 0x90, 0x8f, 0x2b, 0xa5, 0xba, 0x57, 0xb7, 0xd4, 0xcb, 0xd5, 0x2b, 0x1f, 0xae, 0xbe, 0x7a, 0x5a, - 0xfa, 0xe4, 0x65, 0x4d, 0xa4, 0xe1, 0xe7, 0xc5, 0x9a, 0xdf, 0x7f, 0x34, 0x58, 0x2e, 0x9e, 0x9b, - 0x87, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x74, 0xed, 0x37, 0x81, 0xed, 0x04, 0x00, 0x00, -} diff --git a/vendor/github.com/gogo/googleapis/google/rpc/error_details.proto b/vendor/github.com/gogo/googleapis/google/rpc/error_details.proto index a62078ba0..7675af663 100644 --- a/vendor/github.com/gogo/googleapis/google/rpc/error_details.proto +++ b/vendor/github.com/gogo/googleapis/google/rpc/error_details.proto @@ -1,4 +1,4 @@ -// Copyright 2017 Google Inc. +// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -24,7 +24,6 @@ option java_outer_classname = "ErrorDetailsProto"; option java_package = "com.google.rpc"; option objc_class_prefix = "RPC"; - // 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. @@ -36,7 +35,7 @@ option objc_class_prefix = "RPC"; // 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 retires have been reached or a maximum retry delay cap has been +// number of retries have been reached or a maximum retry delay cap has been // reached. message RetryInfo { // Clients should wait at least this long between retrying the same request. @@ -61,7 +60,7 @@ message DebugInfo { // a service could respond with the project id and set `service_disabled` // to true. // -// Also see RetryDetail and Help types for other details about handling a +// Also see RetryInfo and Help types for other details about handling a // quota failure. message QuotaFailure { // A message type used to describe a single quota violation. For example, a @@ -86,6 +85,56 @@ message QuotaFailure { repeated Violation violations = 1; } +// 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" +// } +// } +message ErrorInfo { + // 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-Z0-9_]+/. + string reason = 1; + + // 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". + string domain = 2; + + // Additional structured details about this error. + // + // Keys should match /[a-zA-Z0-9-_]/ and 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. + map metadata = 3; +} + // Describes what preconditions have failed. // // For example, if an RPC failed because it required the Terms of Service to be @@ -95,13 +144,13 @@ message PreconditionFailure { // A message type used to describe a single precondition failure. message Violation { // The type of PreconditionFailure. We recommend using a service-specific - // enum type to define the supported precondition violation types. For + // enum type to define the supported precondition violation subjects. For // example, "TOS" for "Terms of Service violation". string type = 1; // 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. + // For example, "google.com/cloud" relative to the "TOS" type would indicate + // which terms of service is being referenced. string subject = 2; // A description of how the precondition failed. Developers can use this diff --git a/vendor/github.com/gogo/googleapis/google/rpc/status.pb.go b/vendor/github.com/gogo/googleapis/google/rpc/status.pb.go index 3eaf273b8..aba2aba6a 100644 --- a/vendor/github.com/gogo/googleapis/google/rpc/status.pb.go +++ b/vendor/github.com/gogo/googleapis/google/rpc/status.pb.go @@ -1,37 +1,19 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. // source: google/rpc/status.proto -/* - Package rpc is a generated protocol buffer package. - - It is generated from these files: - google/rpc/status.proto - google/rpc/error_details.proto - google/rpc/code.proto - - It has these top-level messages: - Status - RetryInfo - DebugInfo - QuotaFailure - PreconditionFailure - BadRequest - RequestInfo - ResourceInfo - Help - LocalizedMessage -*/ package rpc -import proto "github.com/gogo/protobuf/proto" -import fmt "fmt" -import math "math" -import google_protobuf "github.com/gogo/protobuf/types" - -import strings "strings" -import reflect "reflect" - -import io "io" +import ( + bytes "bytes" + fmt "fmt" + proto "github.com/gogo/protobuf/proto" + types "github.com/gogo/protobuf/types" + io "io" + math "math" + math_bits "math/bits" + reflect "reflect" + strings "strings" +) // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal @@ -42,60 +24,15 @@ var _ = math.Inf // is compatible with the proto package it is being compiled against. // A compilation error at this line likely means your copy of the // proto package needs to be updated. -const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package -// The `Status` type defines a logical error model that is suitable for different -// programming environments, including REST APIs and RPC APIs. It is used by -// [gRPC](https://github.com/grpc). The error model is designed to be: -// -// - Simple to use and understand for most users -// - Flexible enough to meet unexpected needs -// -// # Overview -// -// The `Status` message contains three pieces of data: error code, error message, -// and error details. The error code should be an enum value of -// [google.rpc.Code][google.rpc.Code], but it may accept additional error codes if needed. The -// error message should be a developer-facing English message that helps -// developers *understand* and *resolve* the error. If a localized user-facing -// error message is needed, put the localized message in the error details or -// localize it in the client. The optional error details may contain arbitrary -// information about the error. There is a predefined set of error detail types -// in the package `google.rpc` that can be used for common error conditions. -// -// # Language mapping -// -// The `Status` message is the logical representation of the error model, but it -// is not necessarily the actual wire format. When the `Status` message is -// exposed in different client libraries and different wire protocols, it can be -// mapped differently. For example, it will likely be mapped to some exceptions -// in Java, but more likely mapped to some error codes in C. -// -// # Other uses -// -// The error model and the `Status` message can be used in a variety of -// environments, either with or without APIs, to provide a -// consistent developer experience across different environments. -// -// Example uses of this error model include: -// -// - Partial errors. If a service needs to return partial errors to the client, -// it may embed the `Status` in the normal response to indicate the partial -// errors. +// The `Status` type defines a logical error model that is suitable for +// different programming environments, including REST APIs and RPC APIs. It is +// used by [gRPC](https://github.com/grpc). Each `Status` message contains +// three pieces of data: error code, error message, and error details. // -// - Workflow errors. A typical workflow has multiple steps. Each step may -// have a `Status` message for error reporting. -// -// - Batch operations. If a client uses batch request and batch response, the -// `Status` message should be used directly inside batch response, one for -// each error sub-response. -// -// - Asynchronous operations. If an API call embeds asynchronous operation -// results in its response, the status of those operations should be -// represented directly using the `Status` message. -// -// - Logging. If some API errors are stored in logs, the message `Status` could -// be used directly after any stripping needed for security/privacy reasons. +// You can find out more about this error model and how to work with it in the +// [API Design Guide](https://cloud.google.com/apis/design/errors). type Status struct { // The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` @@ -105,12 +42,43 @@ type Status struct { Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` // A list of messages that carry the error details. There is a common set of // message types for APIs to use. - Details []*google_protobuf.Any `protobuf:"bytes,3,rep,name=details" json:"details,omitempty"` + Details []*types.Any `protobuf:"bytes,3,rep,name=details,proto3" json:"details,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Status) Reset() { *m = Status{} } +func (*Status) ProtoMessage() {} +func (*Status) Descriptor() ([]byte, []int) { + return fileDescriptor_24d244abaf643bfe, []int{0} +} +func (m *Status) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Status) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Status.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Status) XXX_Merge(src proto.Message) { + xxx_messageInfo_Status.Merge(m, src) +} +func (m *Status) XXX_Size() int { + return m.Size() +} +func (m *Status) XXX_DiscardUnknown() { + xxx_messageInfo_Status.DiscardUnknown(m) } -func (m *Status) Reset() { *m = Status{} } -func (*Status) ProtoMessage() {} -func (*Status) Descriptor() ([]byte, []int) { return fileDescriptorStatus, []int{0} } +var xxx_messageInfo_Status proto.InternalMessageInfo func (m *Status) GetCode() int32 { if m != nil { @@ -126,16 +94,41 @@ func (m *Status) GetMessage() string { return "" } -func (m *Status) GetDetails() []*google_protobuf.Any { +func (m *Status) GetDetails() []*types.Any { if m != nil { return m.Details } return nil } +func (*Status) XXX_MessageName() string { + return "google.rpc.Status" +} func init() { proto.RegisterType((*Status)(nil), "google.rpc.Status") } + +func init() { proto.RegisterFile("google/rpc/status.proto", fileDescriptor_24d244abaf643bfe) } + +var fileDescriptor_24d244abaf643bfe = []byte{ + // 238 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4f, 0xcf, 0xcf, 0x4f, + 0xcf, 0x49, 0xd5, 0x2f, 0x2a, 0x48, 0xd6, 0x2f, 0x2e, 0x49, 0x2c, 0x29, 0x2d, 0xd6, 0x2b, 0x28, + 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x82, 0x48, 0xe8, 0x15, 0x15, 0x24, 0x4b, 0x49, 0x42, 0x15, 0x81, + 0x65, 0x92, 0x4a, 0xd3, 0xf4, 0x13, 0xf3, 0x2a, 0x21, 0xca, 0x94, 0xd2, 0xb8, 0xd8, 0x82, 0xc1, + 0xda, 0x84, 0x84, 0xb8, 0x58, 0x92, 0xf3, 0x53, 0x52, 0x25, 0x18, 0x15, 0x18, 0x35, 0x58, 0x83, + 0xc0, 0x6c, 0x21, 0x09, 0x2e, 0xf6, 0xdc, 0xd4, 0xe2, 0xe2, 0xc4, 0xf4, 0x54, 0x09, 0x26, 0x05, + 0x46, 0x0d, 0xce, 0x20, 0x18, 0x57, 0x48, 0x8f, 0x8b, 0x3d, 0x25, 0xb5, 0x24, 0x31, 0x33, 0xa7, + 0x58, 0x82, 0x59, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x44, 0x0f, 0x6a, 0x21, 0xcc, 0x12, 0x3d, 0xc7, + 0xbc, 0xca, 0x20, 0x98, 0x22, 0xa7, 0xc4, 0x0b, 0x0f, 0xe5, 0x18, 0x6e, 0x3c, 0x94, 0x63, 0xf8, + 0xf0, 0x50, 0x8e, 0xf1, 0xc7, 0x43, 0x39, 0xc6, 0x86, 0x47, 0x72, 0x8c, 0x2b, 0x1e, 0xc9, 0x31, + 0x9e, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x2f, 0x1e, 0xc9, + 0x31, 0x7c, 0x00, 0x89, 0x3f, 0x96, 0x63, 0x3c, 0xf1, 0x58, 0x8e, 0x91, 0x8b, 0x2f, 0x39, 0x3f, + 0x57, 0x0f, 0xe1, 0x11, 0x27, 0x6e, 0x88, 0x5b, 0x03, 0x40, 0x56, 0x04, 0x30, 0x46, 0x31, 0x17, + 0x15, 0x24, 0xff, 0x60, 0x64, 0x5c, 0xc4, 0xc4, 0x1c, 0x14, 0xe0, 0x9c, 0xc4, 0x06, 0xb6, 0xd9, + 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x16, 0xcd, 0x7b, 0x60, 0x13, 0x01, 0x00, 0x00, +} + func (this *Status) Compare(that interface{}) int { if that == nil { if this == nil { @@ -184,6 +177,9 @@ func (this *Status) Compare(that interface{}) int { return c } } + if c := bytes.Compare(this.XXX_unrecognized, that1.XXX_unrecognized); c != 0 { + return c + } return 0 } func (this *Status) Equal(that interface{}) bool { @@ -219,6 +215,9 @@ func (this *Status) Equal(that interface{}) bool { return false } } + if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) { + return false + } return true } func (this *Status) GoString() string { @@ -232,6 +231,9 @@ func (this *Status) GoString() string { if this.Details != nil { s = append(s, "Details: "+fmt.Sprintf("%#v", this.Details)+",\n") } + if this.XXX_unrecognized != nil { + s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") + } s = append(s, "}") return strings.Join(s, "") } @@ -246,7 +248,7 @@ func valueToGoStringStatus(v interface{}, typ string) string { func (m *Status) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } @@ -254,44 +256,58 @@ func (m *Status) Marshal() (dAtA []byte, err error) { } func (m *Status) MarshalTo(dAtA []byte) (int, error) { - var i int + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Status) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) _ = i var l int _ = l - if m.Code != 0 { - dAtA[i] = 0x8 - i++ - i = encodeVarintStatus(dAtA, i, uint64(m.Code)) - } - if len(m.Message) > 0 { - dAtA[i] = 0x12 - i++ - i = encodeVarintStatus(dAtA, i, uint64(len(m.Message))) - i += copy(dAtA[i:], m.Message) + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) } if len(m.Details) > 0 { - for _, msg := range m.Details { - dAtA[i] = 0x1a - i++ - i = encodeVarintStatus(dAtA, i, uint64(msg.Size())) - n, err := msg.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err + for iNdEx := len(m.Details) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Details[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintStatus(dAtA, i, uint64(size)) } - i += n + i-- + dAtA[i] = 0x1a } } - return i, nil + if len(m.Message) > 0 { + i -= len(m.Message) + copy(dAtA[i:], m.Message) + i = encodeVarintStatus(dAtA, i, uint64(len(m.Message))) + i-- + dAtA[i] = 0x12 + } + if m.Code != 0 { + i = encodeVarintStatus(dAtA, i, uint64(m.Code)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil } func encodeVarintStatus(dAtA []byte, offset int, v uint64) int { + offset -= sovStatus(v) + base := offset for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) v >>= 7 offset++ } dAtA[offset] = uint8(v) - return offset + 1 + return base } func NewPopulatedStatus(r randyStatus, easy bool) *Status { this := &Status{} @@ -300,14 +316,15 @@ func NewPopulatedStatus(r randyStatus, easy bool) *Status { this.Code *= -1 } this.Message = string(randStringStatus(r)) - if r.Intn(10) != 0 { + if r.Intn(5) != 0 { v1 := r.Intn(5) - this.Details = make([]*google_protobuf.Any, v1) + this.Details = make([]*types.Any, v1) for i := 0; i < v1; i++ { - this.Details[i] = google_protobuf.NewPopulatedAny(r, easy) + this.Details[i] = types.NewPopulatedAny(r, easy) } } if !easy && r.Intn(10) != 0 { + this.XXX_unrecognized = randUnrecognizedStatus(r, 4) } return this } @@ -385,6 +402,9 @@ func encodeVarintPopulateStatus(dAtA []byte, v uint64) []byte { return dAtA } func (m *Status) Size() (n int) { + if m == nil { + return 0 + } var l int _ = l if m.Code != 0 { @@ -400,18 +420,14 @@ func (m *Status) Size() (n int) { n += 1 + l + sovStatus(uint64(l)) } } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } return n } func sovStatus(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } - } - return n + return (math_bits.Len64(x|1) + 6) / 7 } func sozStatus(x uint64) (n int) { return sovStatus(uint64((x << 1) ^ uint64((int64(x) >> 63)))) @@ -420,10 +436,16 @@ func (this *Status) String() string { if this == nil { return "nil" } + repeatedStringForDetails := "[]*Any{" + for _, f := range this.Details { + repeatedStringForDetails += strings.Replace(fmt.Sprintf("%v", f), "Any", "types.Any", 1) + "," + } + repeatedStringForDetails += "}" s := strings.Join([]string{`&Status{`, `Code:` + fmt.Sprintf("%v", this.Code) + `,`, `Message:` + fmt.Sprintf("%v", this.Message) + `,`, - `Details:` + strings.Replace(fmt.Sprintf("%v", this.Details), "Any", "google_protobuf.Any", 1) + `,`, + `Details:` + repeatedStringForDetails + `,`, + `XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`, `}`, }, "") return s @@ -451,7 +473,7 @@ func (m *Status) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + wire |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -479,7 +501,7 @@ func (m *Status) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Code |= (int32(b) & 0x7F) << shift + m.Code |= int32(b&0x7F) << shift if b < 0x80 { break } @@ -498,7 +520,7 @@ func (m *Status) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -508,6 +530,9 @@ func (m *Status) Unmarshal(dAtA []byte) error { return ErrInvalidLengthStatus } postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStatus + } if postIndex > l { return io.ErrUnexpectedEOF } @@ -527,7 +552,7 @@ func (m *Status) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } @@ -536,10 +561,13 @@ func (m *Status) Unmarshal(dAtA []byte) error { return ErrInvalidLengthStatus } postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthStatus + } if postIndex > l { return io.ErrUnexpectedEOF } - m.Details = append(m.Details, &google_protobuf.Any{}) + m.Details = append(m.Details, &types.Any{}) if err := m.Details[len(m.Details)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -550,12 +578,13 @@ func (m *Status) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthStatus } if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) iNdEx += skippy } } @@ -568,6 +597,7 @@ func (m *Status) Unmarshal(dAtA []byte) error { func skipStatus(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 + depth := 0 for iNdEx < l { var wire uint64 for shift := uint(0); ; shift += 7 { @@ -599,10 +629,8 @@ func skipStatus(dAtA []byte) (n int, err error) { break } } - return iNdEx, nil case 1: iNdEx += 8 - return iNdEx, nil case 2: var length int for shift := uint(0); ; shift += 7 { @@ -619,74 +647,34 @@ func skipStatus(dAtA []byte) (n int, err error) { break } } - iNdEx += length if length < 0 { return 0, ErrInvalidLengthStatus } - return iNdEx, nil + iNdEx += length case 3: - for { - var innerWire uint64 - var start int = iNdEx - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowStatus - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - innerWire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - innerWireType := int(innerWire & 0x7) - if innerWireType == 4 { - break - } - next, err := skipStatus(dAtA[start:]) - if err != nil { - return 0, err - } - iNdEx = start + next - } - return iNdEx, nil + depth++ case 4: - return iNdEx, nil + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupStatus + } + depth-- case 5: iNdEx += 4 - return iNdEx, nil default: return 0, fmt.Errorf("proto: illegal wireType %d", wireType) } + if iNdEx < 0 { + return 0, ErrInvalidLengthStatus + } + if depth == 0 { + return iNdEx, nil + } } - panic("unreachable") + return 0, io.ErrUnexpectedEOF } var ( - ErrInvalidLengthStatus = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowStatus = fmt.Errorf("proto: integer overflow") + ErrInvalidLengthStatus = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowStatus = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupStatus = fmt.Errorf("proto: unexpected end of group") ) - -func init() { proto.RegisterFile("google/rpc/status.proto", fileDescriptorStatus) } - -var fileDescriptorStatus = []byte{ - // 231 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4f, 0xcf, 0xcf, 0x4f, - 0xcf, 0x49, 0xd5, 0x2f, 0x2a, 0x48, 0xd6, 0x2f, 0x2e, 0x49, 0x2c, 0x29, 0x2d, 0xd6, 0x2b, 0x28, - 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x82, 0x48, 0xe8, 0x15, 0x15, 0x24, 0x4b, 0x49, 0x42, 0x15, 0x81, - 0x65, 0x92, 0x4a, 0xd3, 0xf4, 0x13, 0xf3, 0x2a, 0x21, 0xca, 0x94, 0xd2, 0xb8, 0xd8, 0x82, 0xc1, - 0xda, 0x84, 0x84, 0xb8, 0x58, 0x92, 0xf3, 0x53, 0x52, 0x25, 0x18, 0x15, 0x18, 0x35, 0x58, 0x83, - 0xc0, 0x6c, 0x21, 0x09, 0x2e, 0xf6, 0xdc, 0xd4, 0xe2, 0xe2, 0xc4, 0xf4, 0x54, 0x09, 0x26, 0x05, - 0x46, 0x0d, 0xce, 0x20, 0x18, 0x57, 0x48, 0x8f, 0x8b, 0x3d, 0x25, 0xb5, 0x24, 0x31, 0x33, 0xa7, - 0x58, 0x82, 0x59, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x44, 0x0f, 0x6a, 0x21, 0xcc, 0x12, 0x3d, 0xc7, - 0xbc, 0xca, 0x20, 0x98, 0x22, 0xa7, 0xa8, 0x0b, 0x0f, 0xe5, 0x18, 0x6e, 0x3c, 0x94, 0x63, 0xf8, - 0xf0, 0x50, 0x8e, 0xf1, 0xc7, 0x43, 0x39, 0xc6, 0x86, 0x47, 0x72, 0x8c, 0x2b, 0x1e, 0xc9, 0x31, - 0x9e, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x2f, 0x1e, 0xc9, - 0x31, 0x7c, 0x00, 0x89, 0x3f, 0x96, 0x63, 0xe4, 0xe2, 0x4b, 0xce, 0xcf, 0xd5, 0x43, 0x78, 0xc2, - 0x89, 0x1b, 0xe2, 0xce, 0x00, 0x90, 0xf1, 0x01, 0x8c, 0x51, 0xcc, 0x45, 0x05, 0xc9, 0x8b, 0x98, - 0x98, 0x83, 0x02, 0x9c, 0x93, 0xd8, 0xc0, 0x56, 0x1a, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x81, - 0x26, 0x59, 0x14, 0x0c, 0x01, 0x00, 0x00, -} diff --git a/vendor/github.com/gogo/googleapis/google/rpc/status.proto b/vendor/github.com/gogo/googleapis/google/rpc/status.proto index db3226ee0..4edafe19e 100644 --- a/vendor/github.com/gogo/googleapis/google/rpc/status.proto +++ b/vendor/github.com/gogo/googleapis/google/rpc/status.proto @@ -1,4 +1,4 @@ -// Copyright 2017 Google Inc. +// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,65 +18,20 @@ package google.rpc; import "google/protobuf/any.proto"; +option cc_enable_arenas = true; option go_package = "rpc"; option java_multiple_files = true; option java_outer_classname = "StatusProto"; option java_package = "com.google.rpc"; option objc_class_prefix = "RPC"; - -// The `Status` type defines a logical error model that is suitable for different -// programming environments, including REST APIs and RPC APIs. It is used by -// [gRPC](https://github.com/grpc). The error model is designed to be: -// -// - Simple to use and understand for most users -// - Flexible enough to meet unexpected needs -// -// # Overview -// -// The `Status` message contains three pieces of data: error code, error message, -// and error details. The error code should be an enum value of -// [google.rpc.Code][google.rpc.Code], but it may accept additional error codes if needed. The -// error message should be a developer-facing English message that helps -// developers *understand* and *resolve* the error. If a localized user-facing -// error message is needed, put the localized message in the error details or -// localize it in the client. The optional error details may contain arbitrary -// information about the error. There is a predefined set of error detail types -// in the package `google.rpc` that can be used for common error conditions. -// -// # Language mapping -// -// The `Status` message is the logical representation of the error model, but it -// is not necessarily the actual wire format. When the `Status` message is -// exposed in different client libraries and different wire protocols, it can be -// mapped differently. For example, it will likely be mapped to some exceptions -// in Java, but more likely mapped to some error codes in C. -// -// # Other uses -// -// The error model and the `Status` message can be used in a variety of -// environments, either with or without APIs, to provide a -// consistent developer experience across different environments. -// -// Example uses of this error model include: -// -// - Partial errors. If a service needs to return partial errors to the client, -// it may embed the `Status` in the normal response to indicate the partial -// errors. -// -// - Workflow errors. A typical workflow has multiple steps. Each step may -// have a `Status` message for error reporting. -// -// - Batch operations. If a client uses batch request and batch response, the -// `Status` message should be used directly inside batch response, one for -// each error sub-response. -// -// - Asynchronous operations. If an API call embeds asynchronous operation -// results in its response, the status of those operations should be -// represented directly using the `Status` message. +// The `Status` type defines a logical error model that is suitable for +// different programming environments, including REST APIs and RPC APIs. It is +// used by [gRPC](https://github.com/grpc). Each `Status` message contains +// three pieces of data: error code, error message, and error details. // -// - Logging. If some API errors are stored in logs, the message `Status` could -// be used directly after any stripping needed for security/privacy reasons. +// You can find out more about this error model and how to work with it in the +// [API Design Guide](https://cloud.google.com/apis/design/errors). message Status { // The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. int32 code = 1; diff --git a/vendor/golang.org/x/sys/execabs/execabs.go b/vendor/golang.org/x/sys/execabs/execabs.go new file mode 100644 index 000000000..3bf40fdfe --- /dev/null +++ b/vendor/golang.org/x/sys/execabs/execabs.go @@ -0,0 +1,102 @@ +// 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 new file mode 100644 index 000000000..5627d70e3 --- /dev/null +++ b/vendor/golang.org/x/sys/execabs/execabs_go118.go @@ -0,0 +1,17 @@ +// 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 new file mode 100644 index 000000000..d60ab1b41 --- /dev/null +++ b/vendor/golang.org/x/sys/execabs/execabs_go119.go @@ -0,0 +1,20 @@ +// 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/text/cases/cases.go b/vendor/golang.org/x/text/cases/cases.go new file mode 100644 index 000000000..752cdf031 --- /dev/null +++ b/vendor/golang.org/x/text/cases/cases.go @@ -0,0 +1,162 @@ +// 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 new file mode 100644 index 000000000..e9aa9e193 --- /dev/null +++ b/vendor/golang.org/x/text/cases/context.go @@ -0,0 +1,376 @@ +// 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 new file mode 100644 index 000000000..85cc434fa --- /dev/null +++ b/vendor/golang.org/x/text/cases/fold.go @@ -0,0 +1,34 @@ +// 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 new file mode 100644 index 000000000..db7c237cc --- /dev/null +++ b/vendor/golang.org/x/text/cases/icu.go @@ -0,0 +1,61 @@ +// 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 +#include +#include +#include +#include +*/ +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 new file mode 100644 index 000000000..87a7c3e95 --- /dev/null +++ b/vendor/golang.org/x/text/cases/info.go @@ -0,0 +1,82 @@ +// 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 new file mode 100644 index 000000000..0f7c6a14b --- /dev/null +++ b/vendor/golang.org/x/text/cases/map.go @@ -0,0 +1,816 @@ +// 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 new file mode 100644 index 000000000..bd28ae145 --- /dev/null +++ b/vendor/golang.org/x/text/cases/tables10.0.0.go @@ -0,0 +1,2255 @@ +// 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 new file mode 100644 index 000000000..ce00ce372 --- /dev/null +++ b/vendor/golang.org/x/text/cases/tables11.0.0.go @@ -0,0 +1,2316 @@ +// 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 new file mode 100644 index 000000000..84d841b14 --- /dev/null +++ b/vendor/golang.org/x/text/cases/tables12.0.0.go @@ -0,0 +1,2359 @@ +// 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 new file mode 100644 index 000000000..6187e6b46 --- /dev/null +++ b/vendor/golang.org/x/text/cases/tables13.0.0.go @@ -0,0 +1,2399 @@ +// 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 new file mode 100644 index 000000000..aee0f3108 --- /dev/null +++ b/vendor/golang.org/x/text/cases/tables15.0.0.go @@ -0,0 +1,2527 @@ +// 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 new file mode 100644 index 000000000..3aeb7be6d --- /dev/null +++ b/vendor/golang.org/x/text/cases/tables9.0.0.go @@ -0,0 +1,2215 @@ +// 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 new file mode 100644 index 000000000..4e4d13fe5 --- /dev/null +++ b/vendor/golang.org/x/text/cases/trieval.go @@ -0,0 +1,217 @@ +// 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 new file mode 100644 index 000000000..3cddbbdda --- /dev/null +++ b/vendor/golang.org/x/text/internal/internal.go @@ -0,0 +1,49 @@ +// 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 new file mode 100644 index 000000000..cdfdb7497 --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/common.go @@ -0,0 +1,16 @@ +// 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 new file mode 100644 index 000000000..46a001507 --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/compact.go @@ -0,0 +1,29 @@ +// 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 new file mode 100644 index 000000000..1b36935ef --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/compact/compact.go @@ -0,0 +1,61 @@ +// 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 new file mode 100644 index 000000000..8c1b6666f --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/compact/language.go @@ -0,0 +1,260 @@ +// 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 new file mode 100644 index 000000000..8d810723c --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/compact/parents.go @@ -0,0 +1,120 @@ +// 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 new file mode 100644 index 000000000..a09ed198a --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/compact/tables.go @@ -0,0 +1,1015 @@ +// 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 new file mode 100644 index 000000000..ca135d295 --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/compact/tags.go @@ -0,0 +1,91 @@ +// 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 new file mode 100644 index 000000000..4ae78e0fa --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/compose.go @@ -0,0 +1,167 @@ +// 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 new file mode 100644 index 000000000..9b20b88fe --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/coverage.go @@ -0,0 +1,28 @@ +// 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 new file mode 100644 index 000000000..09d41c736 --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/language.go @@ -0,0 +1,627 @@ +// 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 new file mode 100644 index 000000000..231b4fbde --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/lookup.go @@ -0,0 +1,412 @@ +// 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<> 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 new file mode 100644 index 000000000..75a2dbca7 --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/match.go @@ -0,0 +1,226 @@ +// 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 new file mode 100644 index 000000000..aad1e0acf --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/parse.go @@ -0,0 +1,608 @@ +// 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 - will be normalized to . +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, - tags are equivalent + // to a tag of the form . + 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 -- 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 new file mode 100644 index 000000000..14167e74e --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/tables.go @@ -0,0 +1,3494 @@ +// 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 new file mode 100644 index 000000000..e7afd3188 --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/tags.go @@ -0,0 +1,48 @@ +// 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 new file mode 100644 index 000000000..1cc004a6d --- /dev/null +++ b/vendor/golang.org/x/text/internal/match.go @@ -0,0 +1,67 @@ +// 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 new file mode 100644 index 000000000..b5d348891 --- /dev/null +++ b/vendor/golang.org/x/text/internal/tag/tag.go @@ -0,0 +1,100 @@ +// 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 new file mode 100644 index 000000000..a24fd1a4d --- /dev/null +++ b/vendor/golang.org/x/text/language/coverage.go @@ -0,0 +1,187 @@ +// 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 new file mode 100644 index 000000000..212b77c90 --- /dev/null +++ b/vendor/golang.org/x/text/language/doc.go @@ -0,0 +1,98 @@ +// 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 new file mode 100644 index 000000000..4d9c66121 --- /dev/null +++ b/vendor/golang.org/x/text/language/language.go @@ -0,0 +1,605 @@ +// 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 new file mode 100644 index 000000000..1153baf29 --- /dev/null +++ b/vendor/golang.org/x/text/language/match.go @@ -0,0 +1,735 @@ +// 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 new file mode 100644 index 000000000..4d57222e7 --- /dev/null +++ b/vendor/golang.org/x/text/language/parse.go @@ -0,0 +1,256 @@ +// 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), err +} + +// 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 new file mode 100644 index 000000000..a6573dcb2 --- /dev/null +++ b/vendor/golang.org/x/text/language/tables.go @@ -0,0 +1,298 @@ +// 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 new file mode 100644 index 000000000..42ea79266 --- /dev/null +++ b/vendor/golang.org/x/text/language/tags.go @@ -0,0 +1,145 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +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/modules.txt b/vendor/modules.txt index ff59f6875..060044358 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -10,8 +10,8 @@ github.com/cenkalti/backoff/v4 # github.com/cespare/xxhash/v2 v2.2.0 ## explicit; go 1.11 github.com/cespare/xxhash/v2 -# github.com/cockroachdb/errors v1.8.1 -## explicit; go 1.13 +# github.com/cockroachdb/errors v1.11.1 +## explicit; go 1.19 github.com/cockroachdb/errors github.com/cockroachdb/errors/assert github.com/cockroachdb/errors/barriers @@ -22,6 +22,7 @@ github.com/cockroachdb/errors/errorspb github.com/cockroachdb/errors/errutil github.com/cockroachdb/errors/hintdetail github.com/cockroachdb/errors/issuelink +github.com/cockroachdb/errors/join github.com/cockroachdb/errors/markers github.com/cockroachdb/errors/oserror github.com/cockroachdb/errors/report @@ -30,11 +31,11 @@ github.com/cockroachdb/errors/secondary github.com/cockroachdb/errors/stdstrings github.com/cockroachdb/errors/telemetrykeys github.com/cockroachdb/errors/withstack -# github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f -## explicit +# github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b +## explicit; go 1.16 github.com/cockroachdb/logtags -# github.com/cockroachdb/pebble v0.0.0-20230724234444-7ef7553fd9e1 -## explicit; go 1.19 +# github.com/cockroachdb/pebble v0.0.0-20231114155657-6682fd5e8763 +## explicit; go 1.21 github.com/cockroachdb/pebble github.com/cockroachdb/pebble/bloom github.com/cockroachdb/pebble/internal/arenaskl @@ -42,10 +43,12 @@ github.com/cockroachdb/pebble/internal/base github.com/cockroachdb/pebble/internal/batchskl github.com/cockroachdb/pebble/internal/bytealloc github.com/cockroachdb/pebble/internal/cache +github.com/cockroachdb/pebble/internal/constants github.com/cockroachdb/pebble/internal/crc github.com/cockroachdb/pebble/internal/fastrand github.com/cockroachdb/pebble/internal/humanize github.com/cockroachdb/pebble/internal/intern +github.com/cockroachdb/pebble/internal/invalidating github.com/cockroachdb/pebble/internal/invariants github.com/cockroachdb/pebble/internal/keyspan github.com/cockroachdb/pebble/internal/manifest @@ -66,15 +69,19 @@ github.com/cockroachdb/pebble/record github.com/cockroachdb/pebble/sstable github.com/cockroachdb/pebble/vfs github.com/cockroachdb/pebble/vfs/atomicfs -# github.com/cockroachdb/redact v1.0.8 +# github.com/cockroachdb/redact v1.1.5 ## explicit; go 1.14 github.com/cockroachdb/redact -github.com/cockroachdb/redact/internal -github.com/cockroachdb/redact/internal/fmtsort -# github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 -## explicit; go 1.12 -github.com/cockroachdb/sentry-go -# github.com/cockroachdb/tokenbucket v0.0.0-20230613231145-182959a1fad6 +github.com/cockroachdb/redact/builder +github.com/cockroachdb/redact/interfaces +github.com/cockroachdb/redact/internal/buffer +github.com/cockroachdb/redact/internal/escape +github.com/cockroachdb/redact/internal/fmtforward +github.com/cockroachdb/redact/internal/markers +github.com/cockroachdb/redact/internal/redact +github.com/cockroachdb/redact/internal/rfmt +github.com/cockroachdb/redact/internal/rfmt/fmtsort +# github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 ## explicit; go 1.19 github.com/cockroachdb/tokenbucket # github.com/coreos/go-semver v0.2.0 @@ -102,6 +109,13 @@ github.com/dustin/go-humanize ## explicit; go 1.13 github.com/emicklei/go-restful/v3 github.com/emicklei/go-restful/v3/log +# github.com/getsentry/sentry-go v0.18.0 +## explicit; go 1.19 +github.com/getsentry/sentry-go +github.com/getsentry/sentry-go/internal/debug +github.com/getsentry/sentry-go/internal/otel/baggage +github.com/getsentry/sentry-go/internal/otel/baggage/internal/baggage +github.com/getsentry/sentry-go/internal/ratelimit # github.com/go-logr/logr v1.3.0 ## explicit; go 1.18 github.com/go-logr/logr @@ -124,8 +138,8 @@ github.com/go-openapi/jsonreference/internal # github.com/go-openapi/swag v0.22.3 ## explicit; go 1.18 github.com/go-openapi/swag -# github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a -## explicit +# github.com/gogo/googleapis v1.4.1 +## explicit; go 1.12 github.com/gogo/googleapis/google/rpc # github.com/gogo/protobuf v1.3.2 ## explicit; go 1.15 @@ -423,8 +437,8 @@ go.uber.org/zap/internal/stacktrace go.uber.org/zap/internal/ztest go.uber.org/zap/zapcore go.uber.org/zap/zaptest -# golang.org/x/exp v0.0.0-20221114191408-850992195362 -## explicit; go 1.18 +# golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df +## explicit; go 1.20 golang.org/x/exp/maps golang.org/x/exp/rand # golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 @@ -454,6 +468,7 @@ golang.org/x/sync/errgroup golang.org/x/sync/singleflight # golang.org/x/sys v0.15.0 ## explicit; go 1.18 +golang.org/x/sys/execabs golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows @@ -463,6 +478,12 @@ golang.org/x/sys/windows/registry golang.org/x/term # golang.org/x/text v0.14.0 ## explicit; go 1.18 +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