From 3391026eb753ec53129c4e4b0f390cfc8a36b22f Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Mon, 27 Jul 2026 04:01:58 +0000
Subject: [PATCH] fix(deps): update module
github.com/gofiber/contrib/v3/websocket to v1.2.2
---
src/go.mod | 16 +-
src/go.sum | 16 +
.../github.com/gofiber/schema/.gitignore | 3 +
.../github.com/gofiber/schema/README.md | 5 +-
src/vendor/github.com/gofiber/schema/cache.go | 321 ++++++--
.../github.com/gofiber/schema/converter.go | 152 ++--
.../github.com/gofiber/schema/decoder.go | 452 +++++++----
.../github.com/gofiber/schema/encoder.go | 241 +++++-
.../github.com/gofiber/utils/v2/AGENTS.md | 20 +
.../github.com/gofiber/utils/v2/README.md | 763 ++++++++++--------
.../github.com/gofiber/utils/v2/ascii.go | 104 +++
.../github.com/gofiber/utils/v2/bytes/case.go | 162 ++--
.../github.com/gofiber/utils/v2/byteseq.go | 62 +-
.../github.com/gofiber/utils/v2/common.go | 28 +-
.../github.com/gofiber/utils/v2/convert.go | 41 +-
.../github.com/gofiber/utils/v2/format.go | 35 +
.../github.com/gofiber/utils/v2/http.go | 5 +-
.../utils/v2/internal/caseconv/swar.go | 246 ++++++
.../github.com/gofiber/utils/v2/parse.go | 164 +++-
.../github.com/gofiber/utils/v2/search.go | 321 ++++++++
.../gofiber/utils/v2/strings/case.go | 152 ++--
.../github.com/gofiber/utils/v2/swar/swar.go | 146 ++++
.../github.com/gofiber/utils/v2/time.go | 63 +-
.../github.com/klauspost/compress/README.md | 12 +
.../klauspost/compress/flate/inflate_gen.go | 116 ++-
.../klauspost/compress/s2/encode_all.go | 2 +-
.../klauspost/compress/s2/reader.go | 19 +-
.../compress/zstd/fse_decoder_arm64.s | 13 +-
.../klauspost/compress/zstd/seqdec_arm64.s | 8 +-
.../klauspost/compress/zstd/snappy.go | 7 +-
.../mattn/go-isatty/isatty_others.go | 4 +-
.../fasthttp/{coarseTime.go => coarsetime.go} | 0
.../x/crypto/acme/autocert/autocert.go | 44 +-
.../golang.org/x/crypto/argon2/argon2.go | 35 +-
src/vendor/golang.org/x/net/idna/idna.go | 6 +-
src/vendor/golang.org/x/sys/cpu/parse.go | 62 +-
.../golang.org/x/sys/unix/syscall_linux.go | 1 +
.../x/sys/unix/syscall_linux_386.go | 1 -
.../x/sys/unix/syscall_linux_amd64.go | 1 -
.../x/sys/unix/syscall_linux_arm.go | 1 -
.../x/sys/unix/syscall_linux_arm64.go | 1 -
.../x/sys/unix/syscall_linux_loong64.go | 1 -
.../x/sys/unix/syscall_linux_mips64x.go | 1 -
.../x/sys/unix/syscall_linux_mipsx.go | 1 -
.../x/sys/unix/syscall_linux_ppc.go | 1 -
.../x/sys/unix/syscall_linux_ppc64x.go | 1 -
.../x/sys/unix/syscall_linux_riscv64.go | 1 -
.../x/sys/unix/syscall_linux_s390x.go | 1 -
.../x/sys/unix/syscall_linux_sparc64.go | 1 -
.../golang.org/x/sys/unix/zerrors_linux.go | 8 +-
.../golang.org/x/sys/unix/zsyscall_linux.go | 17 +
.../x/sys/unix/zsyscall_linux_386.go | 17 -
.../x/sys/unix/zsyscall_linux_amd64.go | 17 -
.../x/sys/unix/zsyscall_linux_arm.go | 17 -
.../x/sys/unix/zsyscall_linux_arm64.go | 17 -
.../x/sys/unix/zsyscall_linux_loong64.go | 17 -
.../x/sys/unix/zsyscall_linux_mips.go | 17 -
.../x/sys/unix/zsyscall_linux_mips64.go | 17 -
.../x/sys/unix/zsyscall_linux_mips64le.go | 17 -
.../x/sys/unix/zsyscall_linux_mipsle.go | 17 -
.../x/sys/unix/zsyscall_linux_ppc.go | 17 -
.../x/sys/unix/zsyscall_linux_ppc64.go | 17 -
.../x/sys/unix/zsyscall_linux_ppc64le.go | 17 -
.../x/sys/unix/zsyscall_linux_riscv64.go | 17 -
.../x/sys/unix/zsyscall_linux_s390x.go | 17 -
.../x/sys/unix/zsyscall_linux_sparc64.go | 17 -
.../x/sys/windows/security_windows.go | 36 +
.../x/sys/windows/syscall_windows.go | 8 +-
.../golang.org/x/sys/windows/types_windows.go | 1 +
src/vendor/modules.txt | 19 +-
70 files changed, 2857 insertions(+), 1346 deletions(-)
create mode 100644 src/vendor/github.com/gofiber/utils/v2/AGENTS.md
create mode 100644 src/vendor/github.com/gofiber/utils/v2/ascii.go
create mode 100644 src/vendor/github.com/gofiber/utils/v2/internal/caseconv/swar.go
create mode 100644 src/vendor/github.com/gofiber/utils/v2/search.go
create mode 100644 src/vendor/github.com/gofiber/utils/v2/swar/swar.go
rename src/vendor/github.com/valyala/fasthttp/{coarseTime.go => coarsetime.go} (100%)
diff --git a/src/go.mod b/src/go.mod
index 77f1af98..bed561e9 100644
--- a/src/go.mod
+++ b/src/go.mod
@@ -7,7 +7,7 @@ require (
github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef
github.com/dechristopher/octad/v2 v2.1.0
github.com/go-webauthn/webauthn v0.17.4
- github.com/gofiber/contrib/v3/websocket v1.2.1
+ github.com/gofiber/contrib/v3/websocket v1.2.2
github.com/gofiber/fiber/v3 v3.4.0
github.com/google/uuid v1.6.0
github.com/jackc/pgx/v5 v5.10.0
@@ -21,7 +21,7 @@ require (
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef
github.com/valyala/fastjson v1.6.10
- golang.org/x/crypto v0.53.0
+ golang.org/x/crypto v0.54.0
golang.org/x/image v0.44.0
golang.org/x/sync v0.22.0
golang.org/x/text v0.40.0
@@ -36,19 +36,19 @@ require (
github.com/fxamacker/cbor/v2 v2.9.2 // indirect
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
github.com/go-webauthn/x v0.2.6 // indirect
- github.com/gofiber/schema v1.8.0 // indirect
- github.com/gofiber/utils/v2 v2.1.1 // indirect
+ github.com/gofiber/schema v1.8.3 // indirect
+ github.com/gofiber/utils/v2 v2.2.0 // indirect
github.com/golang-jwt/jwt/v5 v5.3.1 // indirect
github.com/google/go-tpm v0.9.8 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
- github.com/klauspost/compress v1.19.0 // indirect
+ github.com/klauspost/compress v1.19.1 // indirect
github.com/klauspost/cpuid/v2 v2.4.0 // indirect
github.com/klauspost/crc32 v1.3.0 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/mattn/go-colorable v0.1.15 // indirect
- github.com/mattn/go-isatty v0.0.22 // indirect
+ github.com/mattn/go-isatty v0.0.23 // indirect
github.com/mfridman/interpolate v0.0.2 // indirect
github.com/minio/crc64nvme v1.1.1 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
@@ -64,7 +64,7 @@ require (
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
- golang.org/x/net v0.56.0 // indirect
- golang.org/x/sys v0.46.0 // indirect
+ golang.org/x/net v0.57.0 // indirect
+ golang.org/x/sys v0.47.0 // indirect
gopkg.in/ini.v1 v1.67.3 // indirect
)
diff --git a/src/go.sum b/src/go.sum
index 55fb935b..e3c95ece 100644
--- a/src/go.sum
+++ b/src/go.sum
@@ -33,12 +33,18 @@ github.com/go-webauthn/x v0.2.6 h1:TEyDuQAIiEgYpx60nKiBJIX/5nSUC8LxNbH+uf5U9uk=
github.com/go-webauthn/x v0.2.6/go.mod h1:45bA7YEqyQhRcQJ/TiBb46Ww8yqHBGvgEhQ3WWF0aDo=
github.com/gofiber/contrib/v3/websocket v1.2.1 h1:E4I1dVCvNF56ELdKksUJilo1r7dpw7lgt1DmsJd7hOo=
github.com/gofiber/contrib/v3/websocket v1.2.1/go.mod h1:rQO2z0SbC/l8lP36gXTKrD1QZBXzHKwt9E8c5em1IiA=
+github.com/gofiber/contrib/v3/websocket v1.2.2 h1:kmoD+A0f4btoDSOnZJUHzJyBi1tQqL9tNhn4n0nPJSQ=
+github.com/gofiber/contrib/v3/websocket v1.2.2/go.mod h1:H0kwFA9iXc5RJca4QqCjWwc2kIpuOGQSZJONqsxwWXI=
github.com/gofiber/fiber/v3 v3.4.0 h1:F0aND4vwZF7dR7cbvSwFQQEpBU902XHKWxrLsFBkVqw=
github.com/gofiber/fiber/v3 v3.4.0/go.mod h1:nAhJfdxUIJJph2tPWPmqWf8QDIN2iiqQiQf3lENZpdk=
github.com/gofiber/schema v1.8.0 h1:NGsC9toPHmj8Xg4KpznuXBzNmHG6V5YV0tXKpKMcmis=
github.com/gofiber/schema v1.8.0/go.mod h1:lmbXPQ8hvzXSLkdS2DS7pb4kpunC2Roh7Sj3HMjGfzA=
+github.com/gofiber/schema v1.8.3 h1:06ZedxIYjngzc0095PYy7uWnFnbRflWFpikvZH61fDc=
+github.com/gofiber/schema v1.8.3/go.mod h1:jWnnZdhcW1mHyV+VnfRxKJDPNcepJsTZ9RIWxrr32Ng=
github.com/gofiber/utils/v2 v2.1.1 h1:kGnoGjwEnFW6w0x45W+kLlmMJvqBGkuUA4oMWKn/T/I=
github.com/gofiber/utils/v2 v2.1.1/go.mod h1:DdOgEVwQTi8cou/AKWPqhXOR4fHGRVhA/rEWL3IXG7Q=
+github.com/gofiber/utils/v2 v2.2.0 h1:YSSmCzQponq/f9uSOg2HtXC5qK1Dmor0o6DqaQVz8GE=
+github.com/gofiber/utils/v2 v2.2.0/go.mod h1:Ieopk6sQh7rbhQ12aBNCJtJuG0gxAg0nz63sFCrrOmE=
github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY=
github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
@@ -61,6 +67,8 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/klauspost/compress v1.19.0 h1:sXLILfc9jV2QYWkzFOPWStmcUVH2RHEB1JCdY2oVvCQ=
github.com/klauspost/compress v1.19.0/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
+github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk=
+github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.4.0 h1:S6Hrbc7+ywsr0r+RLapfGBHfyefhCTwEh3A0tV913Dw=
github.com/klauspost/cpuid/v2 v2.4.0/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU=
@@ -76,6 +84,8 @@ github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy
github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4=
github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
+github.com/mattn/go-isatty v0.0.23 h1:cYwCQTQf3HB6xUC+BtyCLZNr7IzbOmoZbmssVNzSyiQ=
+github.com/mattn/go-isatty v0.0.23/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A=
github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY=
github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg=
github.com/minio/crc64nvme v1.1.1 h1:8dwx/Pz49suywbO+auHCBpCtlW1OfpcLN7wYgVR6wAI=
@@ -152,14 +162,20 @@ go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto=
golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio=
+golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
+golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
golang.org/x/image v0.44.0 h1:+tDekMZED9+LrtB3G5xzRggpVh9CARjZqROla3R3R+I=
golang.org/x/image v0.44.0/go.mod h1:V8K3KE9KKKE+pLpQDOeN18w9oacNSvy1tDOirTu4xtY=
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
+golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
+golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU=
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
+golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
+golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
diff --git a/src/vendor/github.com/gofiber/schema/.gitignore b/src/vendor/github.com/gofiber/schema/.gitignore
index 0cafd84a..67d029be 100644
--- a/src/vendor/github.com/gofiber/schema/.gitignore
+++ b/src/vendor/github.com/gofiber/schema/.gitignore
@@ -2,3 +2,6 @@ coverage.coverprofile
vendor
.idea
+
+# Binaries
+*.test
diff --git a/src/vendor/github.com/gofiber/schema/README.md b/src/vendor/github.com/gofiber/schema/README.md
index 5bc767d7..649cf7cd 100644
--- a/src/vendor/github.com/gofiber/schema/README.md
+++ b/src/vendor/github.com/gofiber/schema/README.md
@@ -2,6 +2,8 @@
Package gofiber/schema converts structs to and from form values.
+Per-commit benchmark charts:
+
## Example
Here's a quick example: we parse POST form values and then decode them into a struct:
@@ -111,12 +113,13 @@ The `default` tag option is supported for the following types:
Fiber is an open-source project that runs on donations to pay the bills, e.g., our domain name, hosting, and serverless infrastructure. If you want to support Fiber, please become a [GitHub Sponsor](https://github.com/sponsors/gofiber).
+
### 📅 Monthly Sponsors
| 🔥 Fiber Guardian |  |
| ☕ Fiber Supporter |  |
-| 🪴 Fiber Friend |  |
+| 🪴 Fiber Friend |  |
### 🎁 One-time Sponsors
diff --git a/src/vendor/github.com/gofiber/schema/cache.go b/src/vendor/github.com/gofiber/schema/cache.go
index df00d9b6..82866999 100644
--- a/src/vendor/github.com/gofiber/schema/cache.go
+++ b/src/vendor/github.com/gofiber/schema/cache.go
@@ -6,12 +6,15 @@ package schema
import (
"errors"
+ "maps"
"reflect"
"strings"
"sync"
+ "sync/atomic"
utils "github.com/gofiber/utils/v2"
utilstrings "github.com/gofiber/utils/v2/strings"
+ "github.com/gofiber/utils/v2/swar"
)
const maxParserIndex = 1000
@@ -24,32 +27,45 @@ var (
// newCache returns a new cache.
func newCache() *cache {
c := cache{
- m: make(map[reflect.Type]*structInfo),
- pathCache: make(map[pathCacheKey][]pathPart),
- regconv: make(map[reflect.Type]Converter),
- tag: "schema",
+ tag: "schema",
}
return &c
}
// cache caches meta-data about a struct.
type cache struct {
- l sync.RWMutex
- m map[reflect.Type]*structInfo
- pathCache map[pathCacheKey][]pathPart
- regconv map[reflect.Type]Converter
- tag string
+ l sync.RWMutex // serializes configuration writes (tag, regconv)
+ m sync.Map // map[reflect.Type]cacheEntry
+ // regconv holds the registered converters as an immutable map published
+ // atomically: registerConverter replaces the whole map (copy-on-write
+ // under l), so readers never touch a map that is being written.
+ regconv atomic.Pointer[map[reflect.Type]Converter]
+ tag string
+ // gen is bumped (under l) before m is cleared on configuration changes;
+ // cached entries are tagged with the generation they were built under
+ // and ignored on mismatch, so any call starting after a reconfiguration
+ // returns observes the new configuration even if a racing build stored
+ // a stale entry after the clear.
+ gen atomic.Uint64
}
-type pathCacheKey struct {
- path string
- typ reflect.Type
+// cacheEntry tags a structInfo with the configuration generation it was
+// built under; entries are stored by pointer in c.m (matching the encoder's
+// encPlan pattern).
+type cacheEntry struct {
+ info *structInfo
+ gen uint64
}
// registerConverter registers a converter function for a custom type.
func (c *cache) registerConverter(value interface{}, converterFunc Converter) {
c.l.Lock()
- c.regconv[reflect.TypeOf(value)] = converterFunc
+ next := make(map[reflect.Type]Converter)
+ if prev := c.regconv.Load(); prev != nil {
+ maps.Copy(next, *prev)
+ }
+ next[reflect.TypeOf(value)] = converterFunc
+ c.regconv.Store(&next)
c.reset()
c.l.Unlock()
}
@@ -61,26 +77,28 @@ func (c *cache) registerConverter(value interface{}, converterFunc Converter) {
// reflect.Value.FieldByString(). Multiple parts are required for slices of
// structs.
func (c *cache) parsePath(p string, t reflect.Type) ([]pathPart, error) {
- cacheKey := pathCacheKey{path: p, typ: t}
- c.l.RLock()
- cached, ok := c.pathCache[cacheKey]
- c.l.RUnlock()
- if ok {
- return cached, nil
+ if t.Kind() != reflect.Struct {
+ return nil, errInvalidPath
}
+ return c.parsePathInfo(p, c.get(t))
+}
- var struc *structInfo
+// parsePathInfo is parsePath with the root struct's info already resolved,
+// letting Decode look it up once per call instead of once per key. The
+// parsed-path cache lives on that structInfo, keyed by the plain path
+// string, which hashes much cheaper than a composite key.
+func (c *cache) parsePathInfo(p string, rootInfo *structInfo) ([]pathPart, error) {
+ if cached, ok := rootInfo.paths.Load(p); ok {
+ return cached.([]pathPart), nil
+ }
+
+ struc := rootInfo
+ var t reflect.Type
var field *fieldInfo
var index64 int64
var parts []pathPart
- var path []string
+ var hops []pathHop
for keyStart := 0; ; {
- if t.Kind() != reflect.Struct {
- return nil, errInvalidPath
- }
- if struc = c.get(t); struc == nil {
- return nil, errInvalidPath
- }
keyEnd, segment, err := nextPathSegment(p, keyStart)
if err != nil {
return nil, errInvalidPath
@@ -88,9 +106,11 @@ func (c *cache) parsePath(p string, t reflect.Type) ([]pathPart, error) {
if field = struc.get(segment); field == nil {
return nil, errInvalidPath
}
- // Valid field. Append index.
- path = append(path, field.name)
- if field.isSliceOfStructs && !isMultipartField(field.typ) && (!field.unmarshalerInfo.IsValid || (field.unmarshalerInfo.IsValid && field.unmarshalerInfo.IsSliceElement)) {
+ // Valid field. Append the hop; the field's index chain was resolved
+ // when the structInfo was built, so the decoder walks plain indices
+ // instead of repeating FieldByName lookups on every Decode call.
+ hops = append(hops, pathHop{index: field.index, ensure: struc.anonymousPtrFields})
+ if field.isSliceOfStructs && !field.isMultipart && (!field.unmarshalerInfo.IsValid || (field.unmarshalerInfo.IsValid && field.unmarshalerInfo.IsSliceElement)) {
// Parse a special case: slices of structs.
// i+1 must be the slice index.
//
@@ -113,11 +133,11 @@ func (c *cache) parsePath(p string, t reflect.Type) ([]pathPart, error) {
return nil, errIndexTooLarge
}
parts = append(parts, pathPart{
- path: path,
+ hops: hops,
field: field,
index: int(index64),
})
- path = nil
+ hops = nil
// Get the next struct type, dropping ptrs.
if field.typ.Kind() == reflect.Ptr {
@@ -144,27 +164,44 @@ func (c *cache) parsePath(p string, t reflect.Type) ([]pathPart, error) {
if keyStart >= len(p) {
return nil, errInvalidPath
}
+ if t.Kind() != reflect.Struct {
+ return nil, errInvalidPath
+ }
+ struc = c.get(t)
}
- // Add the remaining.
+ // Add the remaining. A part without hops means the path terminated at a
+ // slice index ("a.0"), so the decoder receives a slice element there.
parts = append(parts, pathPart{
- path: path,
+ hops: hops,
field: field,
index: -1,
+ elem: len(hops) == 0,
})
- c.l.Lock()
- if cached, ok := c.pathCache[cacheKey]; ok {
- c.l.Unlock()
- return cached, nil
+ // Detach the key: callers may pass strings aliasing reused request buffers.
+ if cached, loaded := rootInfo.paths.LoadOrStore(strings.Clone(p), parts); loaded {
+ return cached.([]pathPart), nil
}
- c.pathCache[cacheKey] = parts
- c.l.Unlock()
return parts, nil
}
+// dotBroadcast is the SWAR needle for '.'; hoisted so the word loop in
+// nextPathSegment pays no per-call broadcast cost.
+var dotBroadcast = swar.Broadcast('.')
+
func nextPathSegment(path string, start int) (int, string, error) {
end := start
+ for end+swar.WordLen <= len(path) {
+ if m := swar.ZeroLanes(swar.Load8(path, end) ^ dotBroadcast); m != 0 {
+ end += swar.FirstLane(m)
+ if start == end {
+ return 0, "", errInvalidPath
+ }
+ return end, path[start:end], nil
+ }
+ end += swar.WordLen
+ }
for end < len(path) && path[end] != '.' {
end++
}
@@ -176,37 +213,66 @@ func nextPathSegment(path string, start int) (int, string, error) {
// get returns a cached structInfo, creating it if necessary.
func (c *cache) get(t reflect.Type) *structInfo {
- c.l.RLock()
- info := c.m[t]
- c.l.RUnlock()
- if info == nil {
- info = c.create(t, "")
- c.l.Lock()
- c.m[t] = info
- c.l.Unlock()
+ gen := c.gen.Load()
+ if v, ok := c.m.Load(t); ok {
+ // Ignore entries built under an older configuration: a build racing
+ // a reconfiguration may store one after the clear. Hit-validation
+ // guarantees that any call starting after the reconfiguration
+ // returned observes the new configuration (a call already in flight
+ // during the reconfiguration may still briefly use old metadata,
+ // which is inherent to concurrent reconfiguration).
+ if e := v.(*cacheEntry); e.gen == gen {
+ return e.info
+ }
}
+ info := c.create(t, "")
+ if c.gen.Load() == gen {
+ c.m.Store(t, &cacheEntry{info: info, gen: gen})
+ }
+ // If the configuration changed while building, serve the result once
+ // without caching it (or with a stale tag that hit-validation ignores);
+ // the next call rebuilds fresh.
return info
}
-// reset clears cached metadata and must be called with c.l held.
+// reset clears cached metadata and must be called with c.l held. Parsed
+// path caches live on the structInfos, so dropping them drops those too.
func (c *cache) reset() {
- c.m = make(map[reflect.Type]*structInfo)
- c.pathCache = make(map[pathCacheKey][]pathPart)
+ c.gen.Add(1)
+ c.m.Clear()
+}
+
+// aliasTag returns the configured tag name under the configuration lock, so
+// metadata builds racing SetAliasTag read a consistent value.
+func (c *cache) aliasTag() string {
+ c.l.RLock()
+ tag := c.tag
+ c.l.RUnlock()
+ return tag
}
// create creates a structInfo with meta-data about a struct.
func (c *cache) create(t reflect.Type, parentAlias string) *structInfo {
+ // Snapshot the alias tag once so every field of this type is analyzed
+ // under a consistent configuration and we don't churn the config lock
+ // per field.
+ tag := c.aliasTag()
info := &structInfo{}
var anonymousInfos []*structInfo
+ var anonymousIdx [][]int
for i := 0; i < t.NumField(); i++ {
structField := t.Field(i)
- if structField.Anonymous && structField.Type.Kind() == reflect.Ptr {
+ // Only exported anonymous pointers can be allocated; unexported ones
+ // are not settable and Set would panic.
+ if structField.Anonymous && structField.Type.Kind() == reflect.Ptr && structField.IsExported() {
info.anonymousPtrFields = append(info.anonymousPtrFields, i)
}
- if f := c.createField(structField, parentAlias); f != nil {
+ if f := c.createField(structField, parentAlias, tag); f != nil {
+ f.index = structField.Index
info.fields = append(info.fields, f)
if ft := indirectType(f.typ); ft.Kind() == reflect.Struct && f.isAnonymous {
anonymousInfos = append(anonymousInfos, c.create(ft, f.canonicalAlias))
+ anonymousIdx = append(anonymousIdx, structField.Index)
}
}
}
@@ -216,7 +282,12 @@ func (c *cache) create(t reflect.Type, parentAlias string) *structInfo {
others = append(others, anonymousInfos[i+1:]...)
for _, f := range a.fields {
if !containsAlias(others, f.alias) {
- info.fields = append(info.fields, f)
+ // Copy the promoted field so its index chain can be prefixed
+ // with the embedded field's index; the original stays valid
+ // for the embedded type's own structInfo.
+ pf := *f
+ pf.index = append(append(make([]int, 0, len(anonymousIdx[i])+len(f.index)), anonymousIdx[i]...), f.index...)
+ info.fields = append(info.fields, &pf)
}
}
}
@@ -227,12 +298,51 @@ func (c *cache) create(t reflect.Type, parentAlias string) *structInfo {
}
}
info.requiredFields = c.buildRequiredFields(info)
+ // The setDefaults walk also allocates nil anonymous embedded pointers,
+ // so it can only be skipped when neither defaults nor such pointers
+ // exist anywhere in the tree.
+ info.needsDefaultsWalk = c.needsDefaultsWalk(t, tag, map[reflect.Type]bool{})
return info
}
-// createField creates a fieldInfo for the given field.
-func (c *cache) createField(field reflect.StructField, parentAlias string) *fieldInfo {
- alias, options := fieldAlias(field, c.tag)
+// needsDefaultsWalk reports whether the setDefaults walk can have any effect
+// on the struct tree rooted at t: it declares a default tag option, or has an
+// (exported) anonymous pointer field the walk allocates, anywhere in the
+// tree. visited guards against recursive types. tag is the alias tag
+// snapshot for this build, so no per-field config lock is taken.
+func (c *cache) needsDefaultsWalk(t reflect.Type, tag string, visited map[reflect.Type]bool) bool {
+ if t.Kind() == reflect.Ptr {
+ t = t.Elem()
+ }
+ if t.Kind() != reflect.Struct || visited[t] {
+ return false
+ }
+ visited[t] = true
+ for i := 0; i < t.NumField(); i++ {
+ field := t.Field(i)
+ // Mirror the anonymousPtrFields filter: only exported anonymous
+ // pointers are ever allocated, so only they justify the walk.
+ if field.Anonymous && field.Type.Kind() == reflect.Ptr && field.IsExported() {
+ return true
+ }
+ alias, options := fieldAlias(field, tag)
+ if alias == "-" {
+ continue
+ }
+ if options.getDefaultOptionValue() != "" {
+ return true
+ }
+ if c.needsDefaultsWalk(field.Type, tag, visited) {
+ return true
+ }
+ }
+ return false
+}
+
+// createField creates a fieldInfo for the given field. tag is the alias tag
+// snapshot for the enclosing type's build.
+func (c *cache) createField(field reflect.StructField, parentAlias, tag string) *fieldInfo {
+ alias, options := fieldAlias(field, tag)
if alias == "-" {
// Ignore this field.
return nil
@@ -268,6 +378,18 @@ func (c *cache) createField(field reflect.StructField, parentAlias string) *fiel
}
}
+ // Reuse the unmarshaler facts when the successive type unwrappings land
+ // on the same type (the common non-pointer, non-slice case).
+ derefT := indirectType(field.Type)
+ derefU := m
+ if derefT != field.Type {
+ derefU = isTextUnmarshaler(reflect.Zero(derefT))
+ }
+ elemU := derefU
+ if ft != derefT {
+ elemU = isTextUnmarshaler(reflect.Zero(ft))
+ }
+
return &fieldInfo{
typ: field.Type,
name: field.Name,
@@ -275,6 +397,9 @@ func (c *cache) createField(field reflect.StructField, parentAlias string) *fiel
aliasLower: utilstrings.ToLower(alias),
canonicalAlias: canonicalAlias,
unmarshalerInfo: m,
+ derefUnmarshaler: derefU,
+ elemUnmarshaler: elemU,
+ isMultipart: isMultipartField(field.Type),
isSliceOfStructs: isSlice && isStruct,
isAnonymous: field.Anonymous,
isRequired: options.Contains("required"),
@@ -284,7 +409,11 @@ func (c *cache) createField(field reflect.StructField, parentAlias string) *fiel
// converter returns the converter for a type.
func (c *cache) converter(t reflect.Type) Converter {
- return c.regconv[t]
+ reg := c.regconv.Load()
+ if reg == nil {
+ return nil
+ }
+ return (*reg)[t]
}
// ----------------------------------------------------------------------------
@@ -294,6 +423,15 @@ type structInfo struct {
fieldsByName map[string]*fieldInfo
anonymousPtrFields []int
requiredFields map[string][]fieldWithPrefix
+ // paths caches parsed paths rooted at this struct type
+ // (map[string][]pathPart); keys are cloned so they never alias reused
+ // request buffers.
+ paths sync.Map
+ // needsDefaultsWalk reports whether the setDefaults walk can have any
+ // effect on this struct tree: it is set when a default tag option or an
+ // anonymous embedded pointer field (which the walk allocates) exists
+ // anywhere in the tree, letting the decoder skip the walk otherwise.
+ needsDefaultsWalk bool
}
func (i *structInfo) get(alias string) *fieldInfo {
@@ -314,18 +452,15 @@ func (c *cache) buildRequiredFields(info *structInfo) map[string][]fieldWithPref
for key, fields := range nested.requiredFields {
requiredKey := field.canonicalAlias + "." + key
for _, nestedField := range fields {
- requiredFields = appendRequiredField(requiredFields, requiredKey, fieldWithPrefix{
- fieldInfo: nestedField.fieldInfo,
- prefix: nestedPrefix + nestedField.prefix,
- })
+ requiredFields = appendRequiredField(requiredFields, requiredKey,
+ newFieldWithPrefix(nestedField.fieldInfo, nestedPrefix+nestedField.prefix))
}
}
}
}
if field.isRequired {
- requiredFields = appendRequiredField(requiredFields, field.canonicalAlias, fieldWithPrefix{
- fieldInfo: field,
- })
+ requiredFields = appendRequiredField(requiredFields, field.canonicalAlias,
+ newFieldWithPrefix(field, ""))
}
}
return requiredFields
@@ -343,6 +478,10 @@ func containsAlias(infos []*structInfo, alias string) bool {
type fieldInfo struct {
typ reflect.Type
+ // index is the field index chain relative to the struct type whose
+ // structInfo holds this fieldInfo; promoted fields carry the full chain
+ // through the embedded structs (a copy is made per promotion level).
+ index []int
// name is the field name in the struct.
name string
alias string
@@ -357,6 +496,20 @@ type fieldInfo struct {
// unmarshalerInfo contains information regarding the
// encoding.TextUnmarshaler implementation of the field type.
unmarshalerInfo unmarshaler
+ // derefUnmarshaler caches the encoding.TextUnmarshaler information for
+ // the field type after one pointer dereference, which is what the
+ // decoder sees after walking to the field. Only the type-level flags are
+ // meaningful; the decoder binds instances to live values itself.
+ derefUnmarshaler unmarshaler
+ // elemUnmarshaler is like derefUnmarshaler but for the fully unwrapped
+ // slice element type; the decoder uses it when a path terminates at a
+ // slice index (e.g. "a.0") and the value at hand is an element rather
+ // than the slice field itself.
+ elemUnmarshaler unmarshaler
+ // isMultipart indicates whether the field type is one of the supported
+ // multipart file header shapes, precomputed so the decoder can skip the
+ // type comparisons on every other field.
+ isMultipart bool
// isSliceOfStructs indicates if the field type is a slice of structs.
isSliceOfStructs bool
// isAnonymous indicates whether the field is embedded in the struct.
@@ -374,8 +527,22 @@ func (f *fieldInfo) paths(prefix string) []string {
type pathPart struct {
field *fieldInfo
- path []string // path to the field: walks structs using field names.
- index int // struct index in slices of structs.
+ hops []pathHop // path to the field: walks structs using field indices.
+ index int // struct index in slices of structs.
+ // elem marks a terminal part whose path ended at a slice index ("a.0"):
+ // the decoder's value is then an element of the slice field rather than
+ // the field itself.
+ elem bool
+}
+
+// pathHop describes one named-field lookup along a path. index is the field
+// index chain relative to the struct at this level (more than one element
+// when the field is promoted from embedded structs), and ensure lists the
+// anonymous pointer fields of that struct which must be allocated before the
+// walk so promoted fields stay reachable.
+type pathHop struct {
+ index []int
+ ensure []int
}
// ----------------------------------------------------------------------------
@@ -399,21 +566,26 @@ func fieldAlias(field reflect.StructField, tagName string) (alias string, option
}
// tagOptions is the string following a comma in a struct field's tag, or
-// the empty string. It does not include the leading comma.
-type tagOptions []string
+// the empty string. It does not include the leading comma. Keeping the raw
+// comma-separated string avoids the []string allocation of strings.Split on
+// hot paths (the encoder parses tags on every Encode call).
+type tagOptions string
// parseTag splits a struct field's url tag into its name and comma-separated
// options.
func parseTag(tag string) (string, tagOptions) {
if idx := strings.IndexByte(tag, ','); idx != -1 {
- return tag[:idx], strings.Split(tag[idx+1:], ",")
+ return tag[:idx], tagOptions(tag[idx+1:])
}
- return tag, nil
+ return tag, ""
}
// Contains checks whether the tagOptions contains the specified option.
func (o tagOptions) Contains(option string) bool {
- for _, s := range o {
+ if o == "" {
+ return false
+ }
+ for s := range strings.SplitSeq(string(o), ",") {
if s == option {
return true
}
@@ -422,7 +594,10 @@ func (o tagOptions) Contains(option string) bool {
}
func (o tagOptions) getDefaultOptionValue() string {
- for _, s := range o {
+ if o == "" {
+ return ""
+ }
+ for s := range strings.SplitSeq(string(o), ",") {
if value, ok := strings.CutPrefix(s, "default:"); ok {
return value
}
diff --git a/src/vendor/github.com/gofiber/schema/converter.go b/src/vendor/github.com/gofiber/schema/converter.go
index 0162c7d0..27aa76bb 100644
--- a/src/vendor/github.com/gofiber/schema/converter.go
+++ b/src/vendor/github.com/gofiber/schema/converter.go
@@ -89,8 +89,14 @@ func convertFloat64(value string) reflect.Value {
return invalidValue
}
+// Native int/uint parsing goes through utils.ParseInt/ParseUint (which have
+// a SWAR fast path) with an inline native-fit guard: `int64(int(v)) == v`
+// compiles away on 64-bit and rejects values on 32-bit that a plain int()
+// conversion would silently truncate. The guard is written inline at each
+// call site so the ~8ns parse doesn't pay a wrapper call frame.
+
func convertInt(value string) reflect.Value {
- if v, err := utils.ParseInt(value); err == nil {
+ if v, err := utils.ParseInt(value); err == nil && int64(int(v)) == v {
return reflect.ValueOf(int(v))
}
return invalidValue
@@ -129,7 +135,7 @@ func convertString(value string) reflect.Value {
}
func convertUint(value string) reflect.Value {
- if v, err := utils.ParseUint(value); err == nil {
+ if v, err := utils.ParseUint(value); err == nil && uint64(uint(v)) == v {
return reflect.ValueOf(uint(v))
}
return invalidValue
@@ -163,56 +169,98 @@ func convertUint64(value string) reflect.Value {
return invalidValue
}
-func convertPointer(k reflect.Kind, value string) reflect.Value {
- conv := getBuiltinConverter(k)
- if conv == nil {
- return invalidValue
- }
- if v := conv(value); v.IsValid() {
- switch k {
- case boolType:
- converted := v.Bool()
- return reflect.ValueOf(&converted)
- case float32Type:
- converted := float32(v.Float())
- return reflect.ValueOf(&converted)
- case float64Type:
- converted := v.Float()
- return reflect.ValueOf(&converted)
- case intType:
- converted := int(v.Int())
- return reflect.ValueOf(&converted)
- case int8Type:
- converted := int8(v.Int())
- return reflect.ValueOf(&converted)
- case int16Type:
- converted := int16(v.Int())
- return reflect.ValueOf(&converted)
- case int32Type:
- converted := int32(v.Int())
- return reflect.ValueOf(&converted)
- case int64Type:
- converted := v.Int()
- return reflect.ValueOf(&converted)
- case stringType:
- converted := v.String()
- return reflect.ValueOf(&converted)
- case uintType:
- converted := uint(v.Uint())
- return reflect.ValueOf(&converted)
- case uint8Type:
- converted := uint8(v.Uint())
- return reflect.ValueOf(&converted)
- case uint16Type:
- converted := uint16(v.Uint())
- return reflect.ValueOf(&converted)
- case uint32Type:
- converted := uint32(v.Uint())
- return reflect.ValueOf(&converted)
- case uint64Type:
- converted := v.Uint()
- return reflect.ValueOf(&converted)
+// setBuiltinKind parses val and assigns it directly into v for builtin
+// convertible kinds, avoiding the reflect.Value boxing of the Converter API.
+// handled reports whether the kind is builtin-convertible; ok reports whether
+// val parsed successfully. v is only modified on success.
+func setBuiltinKind(v reflect.Value, k reflect.Kind, val string) (handled, ok bool) {
+ switch k {
+ case boolType:
+ if val == "on" {
+ v.SetBool(true)
+ return true, true
+ }
+ b, err := strconv.ParseBool(val)
+ if err != nil {
+ return true, false
+ }
+ v.SetBool(b)
+ case stringType:
+ v.SetString(val)
+ case intType:
+ n, err := utils.ParseInt(val)
+ if err != nil || int64(int(n)) != n {
+ return true, false
+ }
+ v.SetInt(n)
+ case int8Type:
+ n, err := utils.ParseInt8(val)
+ if err != nil {
+ return true, false
+ }
+ v.SetInt(int64(n))
+ case int16Type:
+ n, err := utils.ParseInt16(val)
+ if err != nil {
+ return true, false
+ }
+ v.SetInt(int64(n))
+ case int32Type:
+ n, err := utils.ParseInt32(val)
+ if err != nil {
+ return true, false
+ }
+ v.SetInt(int64(n))
+ case int64Type:
+ n, err := utils.ParseInt(val)
+ if err != nil {
+ return true, false
}
+ v.SetInt(n)
+ case uintType:
+ n, err := utils.ParseUint(val)
+ if err != nil || uint64(uint(n)) != n {
+ return true, false
+ }
+ v.SetUint(n)
+ case uint8Type:
+ n, err := utils.ParseUint8(val)
+ if err != nil {
+ return true, false
+ }
+ v.SetUint(uint64(n))
+ case uint16Type:
+ n, err := utils.ParseUint16(val)
+ if err != nil {
+ return true, false
+ }
+ v.SetUint(uint64(n))
+ case uint32Type:
+ n, err := utils.ParseUint32(val)
+ if err != nil {
+ return true, false
+ }
+ v.SetUint(uint64(n))
+ case uint64Type:
+ n, err := utils.ParseUint(val)
+ if err != nil {
+ return true, false
+ }
+ v.SetUint(n)
+ case float32Type:
+ f, err := utils.ParseFloat32(val)
+ if err != nil {
+ return true, false
+ }
+ v.SetFloat(float64(f))
+ case float64Type:
+ f, err := utils.ParseFloat64(val)
+ if err != nil {
+ return true, false
+ }
+ v.SetFloat(f)
+ default:
+ return false, false
}
- return invalidValue
+ return true, true
}
diff --git a/src/vendor/github.com/gofiber/schema/decoder.go b/src/vendor/github.com/gofiber/schema/decoder.go
index 08540878..0b8b6bcf 100644
--- a/src/vendor/github.com/gofiber/schema/decoder.go
+++ b/src/vendor/github.com/gofiber/schema/decoder.go
@@ -8,6 +8,7 @@ import (
"encoding"
"errors"
"fmt"
+ "maps"
"mime/multipart"
"reflect"
"strings"
@@ -18,6 +19,10 @@ const (
defaultMaxSize = 16000
)
+// errNotPointerToStruct is returned by Decode for invalid destinations;
+// hoisted so the check does not allocate on every call.
+var errNotPointerToStruct = errors.New("schema: interface must be a pointer to struct")
+
var decodeValueBufferPool = sync.Pool{
New: func() any {
buf := make([]reflect.Value, 0, 8)
@@ -92,24 +97,14 @@ func (d *Decoder) RegisterConverter(value interface{}, converterFunc Converter)
//
// See the package documentation for a full explanation of the mechanics.
func (d *Decoder) Decode(dst interface{}, src map[string][]string, files ...map[string][]*multipart.FileHeader) (err error) {
- var multipartFiles map[string][]*multipart.FileHeader
-
- if len(files) > 0 {
- multipartFiles = files[0]
- }
-
- // Add files as empty string values to src in order to make path parsing work easily
- for path := range multipartFiles {
- src[path] = []string{""}
- }
-
v := reflect.ValueOf(dst)
if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
- return errors.New("schema: interface must be a pointer to struct")
+ return errNotPointerToStruct
}
// Catch panics from the decoder and return them as an error.
- // This is needed because the decoder calls reflect and reflect panics
+ // This is needed because the decoder calls reflect and reflect panics.
+ // Installed before any other work so nothing can crash the caller.
defer func() {
if r := recover(); r != nil {
if e, ok := r.(error); ok {
@@ -120,19 +115,37 @@ func (d *Decoder) Decode(dst interface{}, src map[string][]string, files ...map[
}
}()
+ var multipartFiles map[string][]*multipart.FileHeader
+
+ if len(files) > 0 {
+ multipartFiles = files[0]
+ }
+
+ // Add files as empty string values to the decode view so path parsing
+ // works uniformly. Work on a copy: the caller's src map must not be
+ // mutated (and a caller-provided value under a file's key must not be
+ // overwritten in it).
+ if len(multipartFiles) > 0 {
+ merged := make(map[string][]string, len(src)+len(multipartFiles))
+ maps.Copy(merged, src)
+ for path := range multipartFiles {
+ merged[path] = []string{""}
+ }
+ src = merged
+ }
+
v = v.Elem()
t := v.Type()
+ rootInfo := d.cache.get(t)
var multiErrors MultiError
for path, values := range src {
- if parts, err := d.cache.parsePath(path, t); err == nil {
- if filesSlice, ok := multipartFiles[path]; ok {
- if err = d.decode(v, path, parts, values, filesSlice); err != nil {
- multiErrors = appendError(multiErrors, path, err)
- }
- } else {
- if err = d.decode(v, path, parts, values, nil); err != nil {
- multiErrors = appendError(multiErrors, path, err)
- }
+ if parts, err := d.cache.parsePathInfo(path, rootInfo); err == nil {
+ var filesSlice []*multipart.FileHeader
+ if multipartFiles != nil {
+ filesSlice = multipartFiles[path]
+ }
+ if err = d.decode(v, path, parts, values, filesSlice); err != nil {
+ multiErrors = appendError(multiErrors, path, err)
}
} else {
if errors.Is(err, errIndexTooLarge) {
@@ -142,8 +155,10 @@ func (d *Decoder) Decode(dst interface{}, src map[string][]string, files ...map[
}
}
}
- multiErrors = mergeErrors(multiErrors, d.setDefaults(t, v, src, ""))
- multiErrors = mergeErrors(multiErrors, d.checkRequired(t, src))
+ if rootInfo.needsDefaultsWalk {
+ multiErrors = mergeErrors(multiErrors, d.setDefaults(t, v, src, ""))
+ }
+ multiErrors = mergeErrors(multiErrors, d.checkRequired(rootInfo, src))
if len(multiErrors) > 0 {
return multiErrors
}
@@ -155,24 +170,29 @@ func (d *Decoder) Decode(dst interface{}, src map[string][]string, files ...map[
// nested structs can also have default tags
func (d *Decoder) setDefaults(t reflect.Type, v reflect.Value, src map[string][]string, prefix string) MultiError {
struc := d.cache.get(t)
- if struc == nil {
- // unexpected, cache.get never return nil
- return MultiError{"default-" + t.Name(): errors.New("cache fail")}
+ // Skip the walk entirely when it can have no effect (no default tags and
+ // no anonymous embedded pointers to allocate anywhere in the tree) — the
+ // overwhelmingly common case.
+ if !struc.needsDefaultsWalk {
+ return nil
}
- errs := MultiError{}
+ var errs MultiError
- if v.Type().Kind() == reflect.Struct {
- for i := 0; i < v.NumField(); i++ {
- field := v.Field(i)
- if field.Type().Kind() == reflect.Ptr && field.IsNil() && v.Type().Field(i).Anonymous {
- field.Set(reflect.New(field.Type().Elem()))
- }
+ // Allocate nil anonymous embedded pointer fields so their promoted
+ // fields stay reachable.
+ for _, idx := range struc.anonymousPtrFields {
+ if field := v.Field(idx); field.IsNil() {
+ field.Set(reflect.New(field.Type().Elem()))
}
}
for _, f := range struc.fields {
- vCurrent := v.FieldByName(f.name)
+ vCurrent := walkIndexChain(v, f.index)
+ if !vCurrent.IsValid() {
+ // Unreachable behind an unsettable nil embedded pointer.
+ continue
+ }
if vCurrent.Type().Kind() == reflect.Struct && f.defaultValue == "" {
errs = mergeErrors(errs, d.setDefaults(vCurrent.Type(), vCurrent, src, prefix+f.canonicalAlias+"."))
@@ -186,8 +206,6 @@ func (d *Decoder) setDefaults(t reflect.Type, v reflect.Value, src map[string][]
if f.typ.Kind() == reflect.Struct {
errs = appendError(errs, "default-"+f.name, errors.New("default option is supported only on: bool, float variants, string, unit variants types or their corresponding pointers or slices"))
} else if f.typ.Kind() == reflect.Slice {
- vals := strings.Split(f.defaultValue, "|")
-
// check if slice has one of the supported types for defaults
conv := getBuiltinConverter(f.typ.Elem().Kind())
if conv == nil {
@@ -195,15 +213,19 @@ func (d *Decoder) setDefaults(t reflect.Type, v reflect.Value, src map[string][]
continue
}
- defaultSlice := reflect.MakeSlice(f.typ, 0, cap(vals))
- for _, val := range vals {
+ elemT := f.typ.Elem()
+ defaultSlice := reflect.MakeSlice(f.typ, 0, strings.Count(f.defaultValue, "|")+1)
+ for val := range strings.SplitSeq(f.defaultValue, "|") {
// this check is to handle if the wrong value is provided
convertedVal := conv(val)
if !convertedVal.IsValid() {
errs = appendError(errs, "default-"+f.name, fmt.Errorf("failed setting default: %s is not compatible with field %s type", val, f.name))
break
}
- defaultSlice = reflect.Append(defaultSlice, convertedVal)
+ // Builtin converters return the underlying kind; convert to
+ // the (possibly named) element type before appending, else
+ // reflect.Append panics for e.g. []MyInt.
+ defaultSlice = reflect.Append(defaultSlice, convertedVal.Convert(elemT))
}
vCurrent.Set(defaultSlice)
} else if f.typ.Kind() == reflect.Ptr {
@@ -214,8 +236,19 @@ func (d *Decoder) setDefaults(t reflect.Type, v reflect.Value, src map[string][]
}
// this check is to handle if the wrong value is provided
- if convertedVal := convertPointer(t1.Kind(), f.defaultValue); convertedVal.IsValid() {
- vCurrent.Set(convertedVal)
+ if conv := getBuiltinConverter(t1.Kind()); conv != nil {
+ if convertedVal := conv(f.defaultValue); convertedVal.IsValid() {
+ // Build a pointer of the field's actual element type:
+ // the converter yields the underlying kind, which is
+ // convertible to the (possibly named) element type,
+ // and *elem is assignable to the field even when the
+ // field's type is itself a named pointer type (e.g.
+ // type MyIntPtr *MyInt), where converting a *int
+ // directly would panic.
+ p := reflect.New(t1)
+ p.Elem().Set(convertedVal.Convert(t1))
+ vCurrent.Set(p)
+ }
}
} else {
// this check is to handle if the wrong value is provided
@@ -223,7 +256,9 @@ func (d *Decoder) setDefaults(t reflect.Type, v reflect.Value, src map[string][]
if conv == nil {
errs = appendError(errs, "default-"+f.name, errors.New("default option is supported only on: bool, float variants, string, unit variants types or their corresponding pointers or slices"))
} else if convertedVal := conv(f.defaultValue); convertedVal.IsValid() {
- vCurrent.Set(convertedVal)
+ // Builtin converters return the underlying kind; convert to
+ // the field's (possibly named) type before assigning.
+ vCurrent.Set(convertedVal.Convert(f.typ))
}
}
}
@@ -247,15 +282,14 @@ func fieldProvided(src map[string][]string, prefix string, f *fieldInfo) bool {
// checkRequired checks whether required fields are empty
//
-// check type t recursively if t has struct fields.
+// The set of required fields (including those of nested structs) is
+// precomputed once per struct type in structInfo.requiredFields, so this
+// only performs the per-request emptiness checks against src.
//
// src is the source map for decoding, we use it here to see if those required fields are included in src
-func (d *Decoder) checkRequired(t reflect.Type, src map[string][]string) MultiError {
- m, errs := d.findRequiredFields(t, "", "")
- if len(m) == 0 {
- return errs
- }
- for key, fields := range m {
+func (d *Decoder) checkRequired(info *structInfo, src map[string][]string) MultiError {
+ var errs MultiError
+ for key, fields := range info.requiredFields {
if isEmptyFields(fields, src) {
errs = appendError(errs, key, EmptyFieldError{Key: key})
}
@@ -263,58 +297,41 @@ func (d *Decoder) checkRequired(t reflect.Type, src map[string][]string) MultiEr
return errs
}
-// findRequiredFields recursively searches the struct type t for required fields.
-//
-// canonicalPrefix and searchPrefix are used to resolve full paths in dotted notation
-// for nested struct fields. canonicalPrefix is a complete path which never omits
-// any embedded struct fields. searchPrefix is a user-friendly path which may omit
-// some embedded struct fields to point promoted fields.
-func (d *Decoder) findRequiredFields(t reflect.Type, canonicalPrefix, searchPrefix string) (map[string][]fieldWithPrefix, MultiError) {
- struc := d.cache.get(t)
- if struc == nil {
- // unexpected, cache.get never return nil
- return nil, MultiError{canonicalPrefix + "*": errors.New("cache fail")}
- }
-
- m := map[string][]fieldWithPrefix{}
- errs := MultiError{}
- for _, f := range struc.fields {
- if f.typ.Kind() == reflect.Struct {
- fcprefix := canonicalPrefix + f.canonicalAlias + "."
- for _, fspath := range f.paths(searchPrefix) {
- fm, ferrs := d.findRequiredFields(f.typ, fcprefix, fspath+".")
- for key, fields := range fm {
- m[key] = append(m[key], fields...)
- }
- errs.merge(ferrs)
- }
- }
- if f.isRequired {
- key := canonicalPrefix + f.canonicalAlias
- m[key] = append(m[key], fieldWithPrefix{
- fieldInfo: f,
- prefix: searchPrefix,
- })
- }
- }
- return m, errs
-}
-
type fieldWithPrefix struct {
*fieldInfo
prefix string
+ // searchPaths lists the src keys this required field answers to, and
+ // searchPathDots the corresponding nested-key prefixes; both are
+ // precomputed at cache-build time so per-request checks allocate
+ // nothing.
+ searchPaths []string
+ searchPathDots []string
+}
+
+func newFieldWithPrefix(f *fieldInfo, prefix string) fieldWithPrefix {
+ paths := f.paths(prefix)
+ dots := make([]string, len(paths))
+ for i, p := range paths {
+ dots[i] = p + "."
+ }
+ return fieldWithPrefix{
+ fieldInfo: f,
+ prefix: prefix,
+ searchPaths: paths,
+ searchPathDots: dots,
+ }
}
// isEmptyFields returns true if all of specified fields are empty.
func isEmptyFields(fields []fieldWithPrefix, src map[string][]string) bool {
for _, f := range fields {
- for _, path := range f.paths(f.prefix) {
+ for i, path := range f.searchPaths {
v, ok := src[path]
if ok && !isEmpty(f.typ, v) {
return false
}
// Check for nested keys that match this field.
- pathDot := path + "."
+ pathDot := f.searchPathDots[i]
for key, val := range src {
if len(val) == 0 {
continue
@@ -337,7 +354,10 @@ func isEmpty(t reflect.Type, value []string) bool {
return true
}
switch t.Kind() {
- case boolType, float32Type, float64Type, intType, int8Type, int32Type, int64Type, stringType, uint8Type, uint16Type, uint32Type, uint64Type:
+ case boolType, float32Type, float64Type,
+ intType, int8Type, int16Type, int32Type, int64Type,
+ stringType,
+ uintType, uint8Type, uint16Type, uint32Type, uint64Type:
return len(value[0]) == 0
}
return false
@@ -415,11 +435,38 @@ func isMultipartField(typ reflect.Type) bool {
return false
}
+// walkIndexChain walks v along a struct field index chain. Chains longer
+// than one element traverse embedded structs; intermediate nil pointers are
+// allocated so promoted fields stay reachable. It returns the zero Value
+// when the chain is blocked by a nil pointer that cannot be set (an
+// unexported embedded pointer), which callers treat as an unreachable
+// field.
+func walkIndexChain(v reflect.Value, chain []int) reflect.Value {
+ for j, fi := range chain {
+ if j > 0 && v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ if !v.CanSet() {
+ return reflect.Value{}
+ }
+ v.Set(reflect.New(v.Type().Elem()))
+ }
+ v = v.Elem()
+ }
+ v = v.Field(fi)
+ }
+ return v
+}
+
// decode fills a struct field using a parsed path.
func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values []string, files []*multipart.FileHeader) error {
// Get the field walking the struct fields by index.
- for _, name := range parts[0].path {
- if v.Type().Kind() == reflect.Ptr {
+ for _, hop := range parts[0].hops {
+ // A previous hop may have been blocked by an unsettable nil
+ // embedded pointer; the field is unreachable then.
+ if !v.IsValid() {
+ return nil
+ }
+ if v.Kind() == reflect.Ptr {
if v.IsNil() {
v.Set(reflect.New(v.Type().Elem()))
}
@@ -427,11 +474,13 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
}
// Allocate embedded anonymous pointers required for promoted fields.
- if v.Type().Kind() == reflect.Struct {
- d.ensureAnonymousPtrs(v)
+ for _, idx := range hop.ensure {
+ if f := v.Field(idx); f.IsNil() {
+ f.Set(reflect.New(f.Type().Elem()))
+ }
}
- v = v.FieldByName(name)
+ v = walkIndexChain(v, hop.index)
}
// Don't even bother for unexported fields.
@@ -440,7 +489,7 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
}
// Check multipart files
- if mp := handleMultipartField(v, files); mp {
+ if parts[0].field.isMultipart && handleMultipartField(v, files) {
return nil
}
@@ -462,8 +511,11 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
return fmt.Errorf("%v index %d is larger than the configured maxSize %d", v.Kind(), idx, d.maxSize)
}
if v.IsNil() || v.Len() < idx+1 {
+ // Grow into a fresh backing array: extending within existing
+ // capacity would write into memory the caller may still share
+ // through other slices aliasing the original array.
value := reflect.MakeSlice(t, idx+1, idx+1)
- if v.Len() < idx+1 {
+ if v.Len() > 0 {
// Resize it.
reflect.Copy(value, v)
}
@@ -474,15 +526,15 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
// Get the converter early in case there is one for a slice type.
conv := d.cache.converter(t)
- m := isTextUnmarshaler(v)
+ // The encoding.TextUnmarshaler facts for v's type are precomputed per
+ // field; instances are bound to live values where needed below. For an
+ // elem part (path terminated at a slice index) v is an element of the
+ // slice field, so the element type's facts apply.
+ m := parts[0].field.derefUnmarshaler
+ if parts[0].elem {
+ m = parts[0].field.elemUnmarshaler
+ }
if conv == nil && t.Kind() == reflect.Slice && m.IsSliceElement {
- itemsBuf := decodeValueBufferPool.Get().(*[]reflect.Value)
- items := (*itemsBuf)[:0]
- defer func() {
- clear(items)
- *itemsBuf = items[:0]
- decodeValueBufferPool.Put(itemsBuf)
- }()
elemT := t.Elem()
isPtrElem := elemT.Kind() == reflect.Ptr
if isPtrElem {
@@ -490,7 +542,8 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
}
// Try to get a converter for the element type.
- conv := d.cache.converter(elemT)
+ customConv := d.cache.converter(elemT)
+ conv := customConv
if conv == nil {
conv = getBuiltinConverter(elemT.Kind())
if conv == nil {
@@ -500,10 +553,25 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
}
}
+ // Fast path: builtin element kinds without unmarshalers, custom
+ // converters or pointer elements decode straight into a fresh slice,
+ // avoiding one reflect.Value allocation per element.
+ if customConv == nil && !m.IsValid && !isPtrElem {
+ return d.decodeBuiltinSlice(v, t, path, values)
+ }
+
+ itemsBuf := decodeValueBufferPool.Get().(*[]reflect.Value)
+ items := (*itemsBuf)[:0]
+ defer func() {
+ clear(items)
+ *itemsBuf = items[:0]
+ decodeValueBufferPool.Put(itemsBuf)
+ }()
+
for key, value := range values {
if value == "" {
if d.zeroEmpty {
- items = append(items, reflect.Zero(elemT))
+ items = append(items, reflect.Zero(t.Elem()))
}
} else if m.IsValid {
u := reflect.New(elemT)
@@ -521,39 +589,22 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
}
if m.IsSliceElementPtr {
items = append(items, u.Elem().Addr())
- } else if u.Kind() == reflect.Ptr {
- items = append(items, u.Elem())
} else {
- items = append(items, u)
+ // u is always a pointer from reflect.New; store the
+ // pointed-to value.
+ items = append(items, u.Elem())
}
} else if item := conv(value); item.IsValid() {
- if isPtrElem {
- ptr := reflect.New(elemT)
- ptr.Elem().Set(item)
- item = ptr
- }
- if item.Type() != elemT && !isPtrElem {
- item = item.Convert(elemT)
- }
- items = append(items, item)
+ items = appendConvertedItem(items, item, elemT, isPtrElem)
} else {
- if strings.Contains(value, ",") {
- values := strings.Split(value, ",")
- for _, value := range values {
+ if strings.IndexByte(value, ',') != -1 {
+ for value := range strings.SplitSeq(value, ",") {
if value == "" {
if d.zeroEmpty {
- items = append(items, reflect.Zero(elemT))
+ items = append(items, reflect.Zero(t.Elem()))
}
} else if item := conv(value); item.IsValid() {
- if isPtrElem {
- ptr := reflect.New(elemT)
- ptr.Elem().Set(item)
- item = ptr
- }
- if item.Type() != elemT && !isPtrElem {
- item = item.Convert(elemT)
- }
- items = append(items, item)
+ items = appendConvertedItem(items, item, elemT, isPtrElem)
} else {
return ConversionError{
Key: path,
@@ -571,7 +622,10 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
}
}
}
- value := reflect.Append(reflect.MakeSlice(t, 0, 0), items...)
+ value := reflect.MakeSlice(t, len(items), len(items))
+ for i, item := range items {
+ value.Index(i).Set(item)
+ }
v.Set(value)
} else {
val := ""
@@ -605,8 +659,10 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
v.Set(reflect.Indirect(u))
} else {
// If the value implements the encoding.TextUnmarshaler interface
- // apply UnmarshalText as the converter
- if err := m.Unmarshaler.UnmarshalText([]byte(val)); err != nil {
+ // apply UnmarshalText as the converter, binding it to the
+ // live value.
+ um, _ := reflect.TypeAssert[encoding.TextUnmarshaler](v)
+ if err := um.UnmarshalText([]byte(val)); err != nil {
return ConversionError{
Key: path,
Type: t,
@@ -619,10 +675,8 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
if d.zeroEmpty {
v.Set(reflect.Zero(t))
}
- } else if conv := getBuiltinConverter(t.Kind()); conv != nil {
- if value := conv(val); value.IsValid() {
- v.Set(value.Convert(t))
- } else {
+ } else if handled, ok := setBuiltinKind(v, t.Kind(), val); handled {
+ if !ok {
return ConversionError{
Key: path,
Type: t,
@@ -636,26 +690,102 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
return nil
}
-func (d *Decoder) ensureAnonymousPtrs(v reflect.Value) {
- info := d.cache.get(v.Type())
- for _, idx := range info.anonymousPtrFields {
- field := v.Field(idx)
- if field.IsNil() {
- field.Set(reflect.New(field.Type().Elem()))
+// appendConvertedItem converts a builtin/custom converter result to the slice
+// element type and appends it, wrapping it in a freshly allocated pointer for
+// pointer-element slices. The conversion must happen before the pointer wrap:
+// builtin converters return the underlying kind (e.g. int for a named
+// `type MyInt int`), which is not assignable to the named element type, so
+// Set-ing it into a *MyInt without converting first panics.
+func appendConvertedItem(items []reflect.Value, item reflect.Value, elemT reflect.Type, isPtrElem bool) []reflect.Value {
+ if item.Type() != elemT {
+ item = item.Convert(elemT)
+ }
+ if isPtrElem {
+ ptr := reflect.New(elemT)
+ ptr.Elem().Set(item)
+ item = ptr
+ }
+ return append(items, item)
+}
+
+// decodeBuiltinSlice decodes values into the slice field v of type t whose
+// elements are builtin-convertible kinds, parsing directly into slice slots
+// instead of boxing every element in a reflect.Value. The slice is built
+// detached and only assigned to v when every value parsed, matching the
+// all-or-nothing behavior of the generic path.
+//
+// A value that fails to parse as a whole is retried as a comma-separated
+// list. For non-string kinds a value containing a comma can never parse as a
+// whole (no builtin syntax admits commas — pinned by a test), and string
+// values always parse, so item boundaries are knowable upfront: the slice is
+// sized by a cheap comma count (an upper bound, since empty items may be
+// skipped) and truncated to the filled length at the end.
+func (d *Decoder) decodeBuiltinSlice(v reflect.Value, t reflect.Type, path string, values []string) error {
+ elemT := t.Elem()
+ k := elemT.Kind()
+ split := k != reflect.String
+
+ n := 0
+ for _, value := range values {
+ if split {
+ n += strings.Count(value, ",")
+ }
+ n++
+ }
+
+ sl := reflect.MakeSlice(t, n, n)
+ i := 0
+ for key, value := range values {
+ switch {
+ case value == "":
+ if d.zeroEmpty {
+ i++ // slot stays zero
+ }
+ case split && strings.IndexByte(value, ',') != -1:
+ for item := range strings.SplitSeq(value, ",") {
+ if item == "" {
+ if d.zeroEmpty {
+ i++ // slot stays zero
+ }
+ continue
+ }
+ if _, ok := setBuiltinKind(sl.Index(i), k, item); !ok {
+ return ConversionError{
+ Key: path,
+ Type: elemT,
+ Index: key,
+ }
+ }
+ i++
+ }
+ default:
+ if _, ok := setBuiltinKind(sl.Index(i), k, value); !ok {
+ return ConversionError{
+ Key: path,
+ Type: elemT,
+ Index: key,
+ }
+ }
+ i++
}
}
+ if i < n {
+ sl = sl.Slice(0, i)
+ }
+ v.Set(sl)
+ return nil
}
func isTextUnmarshaler(v reflect.Value) unmarshaler {
// Create a new unmarshaller instance
m := unmarshaler{}
- if m.Unmarshaler, m.IsValid = reflect.TypeAssert[encoding.TextUnmarshaler](v); m.IsValid {
+ if _, m.IsValid = reflect.TypeAssert[encoding.TextUnmarshaler](v); m.IsValid {
return m
}
// As the UnmarshalText function should be applied to the pointer of the
// type, we check that type to see if it implements the necessary
// method.
- if m.Unmarshaler, m.IsValid = reflect.TypeAssert[encoding.TextUnmarshaler](reflect.New(v.Type())); m.IsValid {
+ if _, m.IsValid = reflect.TypeAssert[encoding.TextUnmarshaler](reflect.New(v.Type())); m.IsValid {
m.IsPtr = true
return m
}
@@ -666,31 +796,27 @@ func isTextUnmarshaler(v reflect.Value) unmarshaler {
t = t.Elem()
}
if t.Kind() == reflect.Slice {
- // Check if the slice implements encoding.TextUnmarshaller
- if m.Unmarshaler, m.IsValid = reflect.TypeAssert[encoding.TextUnmarshaler](v); m.IsValid {
- return m
- }
- // If t is a pointer slice, check if its elements implement
- // encoding.TextUnmarshaler
+ // The slice type itself cannot implement encoding.TextUnmarshaler
+ // here: the value-level assert above already covered it. Check
+ // whether the elements do.
m.IsSliceElement = true
if t = t.Elem(); t.Kind() == reflect.Ptr {
t = reflect.PointerTo(t.Elem())
- v = reflect.Zero(t)
m.IsSliceElementPtr = true
- m.Unmarshaler, m.IsValid = reflect.TypeAssert[encoding.TextUnmarshaler](v)
+ _, m.IsValid = reflect.TypeAssert[encoding.TextUnmarshaler](reflect.Zero(t))
return m
}
}
- v = reflect.New(t)
- m.Unmarshaler, m.IsValid = reflect.TypeAssert[encoding.TextUnmarshaler](v)
+ _, m.IsValid = reflect.TypeAssert[encoding.TextUnmarshaler](reflect.New(t))
return m
}
// TextUnmarshaler helpers ----------------------------------------------------
-// unmarshaller contains information about a TextUnmarshaler type
+// unmarshaler describes how a type relates to encoding.TextUnmarshaler.
+// It carries type-level facts only; the decoder binds instances to live
+// values at the point of use.
type unmarshaler struct {
- Unmarshaler encoding.TextUnmarshaler
// IsValid indicates whether the resolved type indicated by the other
// flags implements the encoding.TextUnmarshaler interface.
IsValid bool
@@ -772,14 +898,6 @@ func (e MultiError) Error() string {
return fmt.Sprintf("%s (and %d other errors)", s, len(e)-1)
}
-func (e MultiError) merge(errors MultiError) {
- for key, err := range errors {
- if e[key] == nil {
- e[key] = err
- }
- }
-}
-
func appendRequiredField(m map[string][]fieldWithPrefix, key string, field fieldWithPrefix) map[string][]fieldWithPrefix {
if m == nil {
m = make(map[string][]fieldWithPrefix)
diff --git a/src/vendor/github.com/gofiber/schema/encoder.go b/src/vendor/github.com/gofiber/schema/encoder.go
index d8f0a1e8..b1d53b36 100644
--- a/src/vendor/github.com/gofiber/schema/encoder.go
+++ b/src/vendor/github.com/gofiber/schema/encoder.go
@@ -5,16 +5,66 @@ import (
"fmt"
"reflect"
"strconv"
+ "sync"
+ "sync/atomic"
utils "github.com/gofiber/utils/v2"
)
type encoderFunc func(reflect.Value) string
+// errNotStruct is returned by Encode for invalid sources; hoisted so the
+// check does not allocate on every call.
+var errNotStruct = errors.New("schema: interface must be a struct")
+
+// errNilDst is returned by Encode when the destination map is nil, which
+// would otherwise panic on the first map assignment.
+var errNilDst = errors.New("schema: dst map must not be nil")
+
// Encoder encodes values from a struct into url.Values.
type Encoder struct {
cache *cache
regenc map[reflect.Type]encoderFunc
+ // encCache memoizes the per-struct-type encoding plan
+ // (map[reflect.Type][]encField) so tags are parsed and encoder
+ // functions resolved once per type instead of on every Encode call.
+ encCache sync.Map
+ // encGen is bumped before encCache is cleared on configuration changes;
+ // structInfo snapshots it before building a plan and refuses to store
+ // the plan if it changed, so a build racing a reconfiguration cannot
+ // re-insert a stale plan after the clear.
+ encGen atomic.Uint64
+}
+
+// encPlan tags a per-type encoding plan with the configuration generation it
+// was built under: hit-validation ignores plans from older generations, so
+// any Encode starting after a reconfiguration returns observes the new
+// configuration even if a racing build stored a stale plan after the clear.
+type encPlan struct {
+ fields []encField
+ gen uint64
+}
+
+// encField is the precomputed encoding plan for one struct field.
+type encField struct {
+ name string
+ enc encoderFunc // immediate encoder; nil for structs and slices
+ elemEnc encoderFunc // slice element encoder, when the field is a slice
+ idx int
+ omitEmpty bool
+ // recurseStructPtr marks pointer-to-struct fields without a custom
+ // encoder: non-nil values are encoded by recursing into the element.
+ recurseStructPtr bool
+ isStruct bool
+ // nilAsNull marks pointer fields whose element has no immediate
+ // encoder (structs recursed via recurseStructPtr, or unsupported
+ // types): nil values encode as "null", matching the closure behavior
+ // pointer fields with encodable elements get.
+ nilAsNull bool
+ // elemPtrNil marks slice fields whose element is a pointer type with no
+ // encoder (e.g. []*Struct): nil elements encode as "null" (as they did
+ // historically), while a non-nil such element is an error.
+ elemPtrNil bool
}
// NewEncoder returns a new Encoder with defaults.
@@ -25,7 +75,23 @@ func NewEncoder() *Encoder {
// Encode encodes a struct into map[string][]string.
//
// Intended for use with url.Values.
-func (e *Encoder) Encode(src interface{}, dst map[string][]string) error {
+func (e *Encoder) Encode(src interface{}, dst map[string][]string) (err error) {
+ if dst == nil {
+ return errNilDst
+ }
+
+ // Catch panics from reflection or user-registered encoders and return
+ // them as an error instead of crashing the caller, mirroring Decode.
+ defer func() {
+ if r := recover(); r != nil {
+ if e, ok := r.(error); ok {
+ err = e
+ } else {
+ err = fmt.Errorf("schema: panic while encoding: %v", r)
+ }
+ }
+ }()
+
v := reflect.ValueOf(src)
return e.encode(v, dst)
@@ -33,18 +99,79 @@ func (e *Encoder) Encode(src interface{}, dst map[string][]string) error {
// RegisterEncoder registers a converter for encoding a custom type.
func (e *Encoder) RegisterEncoder(value interface{}, encoder func(reflect.Value) string) {
+ e.cache.l.Lock()
e.regenc[reflect.TypeOf(value)] = encoder
+ e.cache.l.Unlock()
+ e.encGen.Add(1)
+ e.encCache.Clear()
}
// SetAliasTag changes the tag used to locate custom field aliases.
// The default tag is "schema".
func (e *Encoder) SetAliasTag(tag string) {
+ e.cache.l.Lock()
e.cache.tag = tag
+ e.cache.l.Unlock()
+ e.encGen.Add(1)
+ e.encCache.Clear()
}
-// isValidStructPointer test if input value is a valid struct pointer.
-func isValidStructPointer(v reflect.Value) bool {
- return v.Type().Kind() == reflect.Ptr && v.Elem().IsValid() && v.Elem().Type().Kind() == reflect.Struct
+// structInfo returns the cached encoding plan for struct type t, building it
+// on first use. The build reads the tag and registered encoders under the
+// configuration lock; the generation re-checks around the cache store keep a
+// build racing a reconfiguration from inserting a stale plan.
+func (e *Encoder) structInfo(t reflect.Type) []encField {
+ gen := e.encGen.Load()
+ if cached, ok := e.encCache.Load(t); ok {
+ // Ignore plans built under an older configuration; fall through and
+ // rebuild (the fresh plan overwrites the stale entry).
+ if p := cached.(*encPlan); p.gen == gen {
+ return p.fields
+ }
+ }
+ e.cache.l.RLock()
+ tag := e.cache.tag
+ fields := make([]encField, 0, t.NumField())
+ for i := 0; i < t.NumField(); i++ {
+ sf := t.Field(i)
+ name, opts := fieldAlias(sf, tag)
+ if name == "-" {
+ continue
+ }
+ ft := sf.Type
+ f := encField{
+ idx: i,
+ name: name,
+ omitEmpty: opts.Contains("omitempty"),
+ recurseStructPtr: ft.Kind() == reflect.Ptr &&
+ ft.Elem().Kind() == reflect.Struct &&
+ !e.hasCustomEncoder(ft),
+ enc: typeEncoder(ft, e.regenc),
+ }
+ if f.enc == nil {
+ switch ft.Kind() {
+ case reflect.Struct:
+ f.isStruct = true
+ case reflect.Slice:
+ f.elemEnc = typeEncoder(ft.Elem(), e.regenc)
+ if f.elemEnc == nil && ft.Elem().Kind() == reflect.Ptr {
+ f.elemPtrNil = true
+ }
+ case reflect.Ptr:
+ f.nilAsNull = true
+ }
+ }
+ fields = append(fields, f)
+ }
+ e.cache.l.RUnlock()
+ // Don't cache a plan whose inputs (tag, registered encoders) changed
+ // while it was being built; the next call rebuilds it fresh. Even if a
+ // stale plan slips in after the clear, its generation tag keeps it from
+ // ever being served.
+ if e.encGen.Load() == gen {
+ e.encCache.Store(t, &encPlan{fields: fields, gen: gen})
+ }
+ return fields
}
func isZero(v reflect.Value) bool {
@@ -81,75 +208,105 @@ func (e *Encoder) encode(v reflect.Value, dst map[string][]string) error {
v = v.Elem()
}
if v.Kind() != reflect.Struct {
- return errors.New("schema: interface must be a struct")
+ return errNotStruct
}
- t := v.Type()
- errors := MultiError{}
+ var errs MultiError
- for i := 0; i < v.NumField(); i++ {
- fieldValue := v.Field(i)
- fieldType := fieldValue.Type()
- name, opts := fieldAlias(t.Field(i), e.cache.tag)
- if name == "-" {
- continue
- }
+ fields := e.structInfo(v.Type())
+ for i := range fields {
+ f := &fields[i]
+ fieldValue := v.Field(f.idx)
// Encode struct pointer types if the field is a valid pointer and a struct.
- if isValidStructPointer(fieldValue) && !e.hasCustomEncoder(fieldType) {
- err := e.encode(fieldValue.Elem(), dst)
- if err != nil {
- errors[fieldValue.Elem().Type().String()] = err
+ if f.recurseStructPtr && !fieldValue.IsNil() {
+ if err := e.encode(fieldValue.Elem(), dst); err != nil {
+ errs = setError(errs, fieldValue.Elem().Type().String(), err)
}
continue
}
- encFunc := typeEncoder(fieldType, e.regenc)
-
// Encode non-slice types and custom implementations immediately.
- if encFunc != nil {
- if opts.Contains("omitempty") && isZero(fieldValue) {
+ if f.enc != nil {
+ if f.omitEmpty && isZero(fieldValue) {
continue
}
- value := encFunc(fieldValue)
- dst[name] = append(dst[name], value)
+ dst[f.name] = append(dst[f.name], f.enc(fieldValue))
continue
}
- if fieldType.Kind() == reflect.Struct {
- err := e.encode(fieldValue, dst)
- if err != nil {
- errors[fieldType.String()] = err
+ if f.nilAsNull && fieldValue.IsNil() {
+ if f.omitEmpty {
+ continue
}
+ dst[f.name] = append(dst[f.name], "null")
continue
}
- if fieldType.Kind() == reflect.Slice {
- encFunc = typeEncoder(fieldType.Elem(), e.regenc)
+ if f.isStruct {
+ if err := e.encode(fieldValue, dst); err != nil {
+ errs = setError(errs, fieldValue.Type().String(), err)
+ }
+ continue
}
- if encFunc == nil {
- errors[fieldType.String()] = fmt.Errorf("schema: encoder not found for %v", fieldValue)
+ // A non-slice field with no encoder (map, chan, array, or a non-nil
+ // pointer to an unencodable type), or a slice whose element type is
+ // itself unencodable and not a pointer (e.g. []Struct), cannot be
+ // encoded — historically this errored unconditionally.
+ if fieldValue.Kind() != reflect.Slice || (f.elemEnc == nil && !f.elemPtrNil) {
+ errs = setError(errs, fieldValue.Type().String(), fmt.Errorf("schema: encoder not found for %v", fieldValue))
continue
}
- // Encode a slice.
- if fieldValue.Len() == 0 && opts.Contains("omitempty") {
+ // Encode a slice. An empty slice has nothing to encode, so it is
+ // skipped under omitempty (and otherwise emitted empty).
+ n := fieldValue.Len()
+ if n == 0 && f.omitEmpty {
continue
}
- dst[name] = []string{}
- for j := 0; j < fieldValue.Len(); j++ {
- dst[name] = append(dst[name], encFunc(fieldValue.Index(j)))
+ values := make([]string, n)
+ if f.elemEnc == nil {
+ // Pointer elements with no encoder (elemPtrNil): nil encodes as
+ // "null" (as historically), a non-nil such element is an error.
+ bad := false
+ for j := 0; j < n; j++ {
+ if fieldValue.Index(j).IsNil() {
+ values[j] = "null"
+ continue
+ }
+ errs = setError(errs, fieldValue.Type().String(), fmt.Errorf("schema: encoder not found for %v", fieldValue))
+ bad = true
+ break
+ }
+ if bad {
+ continue
+ }
+ } else {
+ for j := 0; j < n; j++ {
+ values[j] = f.elemEnc(fieldValue.Index(j))
+ }
}
+ dst[f.name] = values
}
- if len(errors) > 0 {
- return errors
+ if len(errs) > 0 {
+ return errs
}
return nil
}
+// setError lazily allocates m and stores err under key, overwriting any
+// previous entry (matching the historical encoder error semantics).
+func setError(m MultiError, key string, err error) MultiError {
+ if m == nil {
+ m = make(MultiError)
+ }
+ m[key] = err
+ return m
+}
+
func (e *Encoder) hasCustomEncoder(t reflect.Type) bool {
_, exists := e.regenc[t]
return exists
@@ -173,6 +330,12 @@ func typeEncoder(t reflect.Type, reg map[reflect.Type]encoderFunc) encoderFunc {
return encodeFloat64
case reflect.Ptr:
f := typeEncoder(t.Elem(), reg)
+ if f == nil {
+ // No encoder for the element: report unsupported instead of
+ // returning a closure that would panic on non-nil values.
+ // Nil handling for such fields is done by encField.nilAsNull.
+ return nil
+ }
return func(v reflect.Value) string {
if v.IsNil() {
return "null"
diff --git a/src/vendor/github.com/gofiber/utils/v2/AGENTS.md b/src/vendor/github.com/gofiber/utils/v2/AGENTS.md
new file mode 100644
index 00000000..dce12257
--- /dev/null
+++ b/src/vendor/github.com/gofiber/utils/v2/AGENTS.md
@@ -0,0 +1,20 @@
+# AGENTS.md
+
+Guidance for AI coding agents working in this repository.
+
+## What this repository is
+
+gofiber/utils is a helper library for [Fiber](https://github.com/gofiber/fiber) and its middleware ecosystem. It exports fast, low-allocation helpers; the consumers live in other modules (fiber itself, middleware, user code).
+
+## Reviewing and proposing API changes
+
+- Exported functions without in-module callers are by design. Do not argue that a new public function or package should move to `internal/` because grep finds no non-test usage inside this module. In-module usage counts say nothing about the value of the API; exporting helpers for downstream modules is the purpose of this repository.
+- Judge new exported API instead by: contract clarity (documented preconditions, aliasing rules, edge cases), test coverage (including property or fuzz tests for bit-twiddling code), naming consistency with the existing surface, and benchmark evidence for performance claims.
+- Additive API is not a SemVer break, but it is a long-term maintenance commitment. Call out sharp-edged contracts (unchecked preconditions, approximate results, unsafe memory semantics) explicitly so maintainers approve them consciously.
+
+## Conventions
+
+- Performance claims are verified with benchstat (base vs. head on the same machine, at least `-count=10`), never with single runs.
+- `make test` runs the suite with race detector and shuffle; `make lint` runs golangci-lint; `make format` applies gofumpt; `make benchfmt` aligns the benchmark tables in README.md.
+- README.md is a function catalog with benchmark blocks. New exported functions need a README section, and benchmark numbers for touched paths should be regenerated in the same run.
+- Code, comments, commit messages, and PR text are always written in English.
diff --git a/src/vendor/github.com/gofiber/utils/v2/README.md b/src/vendor/github.com/gofiber/utils/v2/README.md
index 46242a0f..3e8afccb 100644
--- a/src/vendor/github.com/gofiber/utils/v2/README.md
+++ b/src/vendor/github.com/gofiber/utils/v2/README.md
@@ -4,12 +4,15 @@



+[](https://gofiber.github.io/utils/benchmarks/)
[](https://gofiber.io/discord)
A collection of common functions for [Fiber](https://github.com/gofiber/fiber) with better performance, fewer allocations, and fewer dependencies.
## Benchmarks
+Per-commit benchmark charts:
+
Environment:
goos: darwin
goarch: arm64
@@ -18,351 +21,477 @@ cpu: Apple M2 Pro
```text
// go test ./... -benchmem -run=^$ -bench=Benchmark_ -count=1
+// (swar's Benchmark_Load8_Fusion, an advisory codegen guard, is deliberately omitted)
# Case Conversion
-Benchmark_ToLowerBytes/empty/fiber-12 593913379 1.975 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLowerBytes/empty/fiber/unsafe-12 657748088 1.845 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLowerBytes/empty/default-12 367040010 3.281 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLowerBytes/http-get/fiber-12 365235189 3.393 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLowerBytes/http-get/fiber/unsafe-12 239092582 5.144 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLowerBytes/http-get/default-12 63143354 18.46 ns/op 8 B/op 1 allocs/op
-Benchmark_ToLowerBytes/http-get-upper/fiber-12 94304095 12.86 ns/op 3 B/op 1 allocs/op
-Benchmark_ToLowerBytes/http-get-upper/fiber/unsafe-12 239366296 5.057 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLowerBytes/http-get-upper/default-12 86047208 14.00 ns/op 8 B/op 1 allocs/op
-Benchmark_ToLowerBytes/header-content-type-mixed/fiber-12 45169880 26.27 ns/op 48 B/op 1 allocs/op
-Benchmark_ToLowerBytes/header-content-type-mixed/fiber/unsafe-12 95687102 12.70 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLowerBytes/header-content-type-mixed/default-12 25045154 47.56 ns/op 48 B/op 1 allocs/op
-Benchmark_ToLowerBytes/large-lower/fiber-12 43856107 28.39 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLowerBytes/large-lower/fiber/unsafe-12 62907780 19.56 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLowerBytes/large-lower/default-12 17712895 69.18 ns/op 64 B/op 1 allocs/op
-Benchmark_ToLowerBytes/large-upper/fiber-12 34286121 34.08 ns/op 64 B/op 1 allocs/op
-Benchmark_ToLowerBytes/large-upper/fiber/unsafe-12 61959598 19.37 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLowerBytes/large-upper/default-12 16091281 75.42 ns/op 64 B/op 1 allocs/op
-Benchmark_ToLowerBytes/large-mixed/fiber-12 33481714 35.06 ns/op 64 B/op 1 allocs/op
-Benchmark_ToLowerBytes/large-mixed/fiber/unsafe-12 62478574 19.36 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLowerBytes/large-mixed/default-12 16091731 75.18 ns/op 64 B/op 1 allocs/op
-Benchmark_ToUpperBytes/empty/fiber-12 620292880 1.946 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpperBytes/empty/fiber/unsafe-12 642997940 1.840 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpperBytes/empty/default-12 366694138 3.324 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpperBytes/http-get/fiber-12 95312475 12.75 ns/op 3 B/op 1 allocs/op
-Benchmark_ToUpperBytes/http-get/fiber/unsafe-12 236603360 5.055 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpperBytes/http-get/default-12 86667109 14.19 ns/op 8 B/op 1 allocs/op
-Benchmark_ToUpperBytes/http-get-upper/fiber-12 360987979 3.425 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpperBytes/http-get-upper/fiber/unsafe-12 236142552 5.096 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpperBytes/http-get-upper/default-12 61760695 19.24 ns/op 8 B/op 1 allocs/op
-Benchmark_ToUpperBytes/header-content-type-mixed/fiber-12 44394090 27.55 ns/op 48 B/op 1 allocs/op
-Benchmark_ToUpperBytes/header-content-type-mixed/fiber/unsafe-12 94647172 12.75 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpperBytes/header-content-type-mixed/default-12 25090692 47.83 ns/op 48 B/op 1 allocs/op
-Benchmark_ToUpperBytes/large-lower/fiber-12 35558892 34.73 ns/op 64 B/op 1 allocs/op
-Benchmark_ToUpperBytes/large-lower/fiber/unsafe-12 62620129 19.31 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpperBytes/large-lower/default-12 15487833 76.16 ns/op 64 B/op 1 allocs/op
-Benchmark_ToUpperBytes/large-upper/fiber-12 43901836 27.54 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpperBytes/large-upper/fiber/unsafe-12 62027790 20.57 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpperBytes/large-upper/default-12 14579604 82.82 ns/op 64 B/op 1 allocs/op
-Benchmark_ToUpperBytes/large-mixed/fiber-12 33719427 35.99 ns/op 64 B/op 1 allocs/op
-Benchmark_ToUpperBytes/large-mixed/fiber/unsafe-12 62008428 21.01 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpperBytes/large-mixed/default-12 15469116 77.21 ns/op 64 B/op 1 allocs/op
-Benchmark_ToUpper/empty/fiber-12 613156160 1.955 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpper/empty/fiber/unsafe-12 649026514 1.838 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpper/empty/default-12 650956171 1.831 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpper/http-get/fiber-12 92095164 12.77 ns/op 3 B/op 1 allocs/op
-Benchmark_ToUpper/http-get/fiber/unsafe-12 235750344 5.036 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpper/http-get/default-12 60473330 20.50 ns/op 8 B/op 1 allocs/op
-Benchmark_ToUpper/http-get-upper/fiber-12 398272657 3.048 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpper/http-get-upper/fiber/unsafe-12 220124466 5.078 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpper/http-get-upper/default-12 233645295 5.051 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpper/header-content-type-mixed/fiber-12 36106831 33.14 ns/op 48 B/op 1 allocs/op
-Benchmark_ToUpper/header-content-type-mixed/fiber/unsafe-12 93201168 12.83 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpper/header-content-type-mixed/default-12 11069166 107.7 ns/op 48 B/op 1 allocs/op
-Benchmark_ToUpper/large-lower/fiber-12 29007373 41.16 ns/op 64 B/op 1 allocs/op
-Benchmark_ToUpper/large-lower/fiber/unsafe-12 61283246 19.47 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpper/large-lower/default-12 6855549 174.0 ns/op 64 B/op 1 allocs/op
-Benchmark_ToUpper/large-upper/fiber-12 43965034 28.00 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpper/large-upper/fiber/unsafe-12 53715409 20.68 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpper/large-upper/default-12 18805570 65.60 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpper/large-mixed/fiber-12 27005611 43.54 ns/op 64 B/op 1 allocs/op
-Benchmark_ToUpper/large-mixed/fiber/unsafe-12 60924529 20.57 ns/op 0 B/op 0 allocs/op
-Benchmark_ToUpper/large-mixed/default-12 5662490 212.0 ns/op 64 B/op 1 allocs/op
-Benchmark_ToLower/empty/fiber-12 607541103 1.972 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLower/empty/fiber/unsafe-12 631531857 1.969 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLower/empty/default-12 638706405 1.872 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLower/http-get/fiber-12 390062401 3.080 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLower/http-get/fiber/unsafe-12 231204609 5.190 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLower/http-get/default-12 278482443 4.408 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLower/http-get-upper/fiber-12 91051068 13.16 ns/op 3 B/op 1 allocs/op
-Benchmark_ToLower/http-get-upper/fiber/unsafe-12 233437356 5.168 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLower/http-get-upper/default-12 59555317 22.03 ns/op 8 B/op 1 allocs/op
-Benchmark_ToLower/header-content-type-mixed/fiber-12 32247734 35.17 ns/op 48 B/op 1 allocs/op
-Benchmark_ToLower/header-content-type-mixed/fiber/unsafe-12 92616117 12.98 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLower/header-content-type-mixed/default-12 16339488 74.21 ns/op 48 B/op 1 allocs/op
-Benchmark_ToLower/large-lower/fiber-12 37544337 33.77 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLower/large-lower/fiber/unsafe-12 61856332 19.83 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLower/large-lower/default-12 23513985 50.17 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLower/large-upper/fiber-12 28177750 44.45 ns/op 64 B/op 1 allocs/op
-Benchmark_ToLower/large-upper/fiber/unsafe-12 61319127 20.23 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLower/large-upper/default-12 6700268 180.1 ns/op 64 B/op 1 allocs/op
-Benchmark_ToLower/large-mixed/fiber-12 26804186 45.68 ns/op 64 B/op 1 allocs/op
-Benchmark_ToLower/large-mixed/fiber/unsafe-12 61659141 19.97 ns/op 0 B/op 0 allocs/op
-Benchmark_ToLower/large-mixed/default-12 5614172 213.1 ns/op 64 B/op 1 allocs/op
+Benchmark_ToLowerBytes/empty/fiber-12 599341221 1.970 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLowerBytes/empty/fiber/unsafe-12 613673802 1.951 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLowerBytes/empty/default-12 363300402 3.316 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLowerBytes/http-get/fiber-12 350302147 3.434 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLowerBytes/http-get/fiber/unsafe-12 250488015 4.803 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLowerBytes/http-get/default-12 65883986 18.03 ns/op 8 B/op 1 allocs/op
+Benchmark_ToLowerBytes/http-get-upper/fiber-12 95234625 12.53 ns/op 3 B/op 1 allocs/op
+Benchmark_ToLowerBytes/http-get-upper/fiber/unsafe-12 242418936 4.802 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLowerBytes/http-get-upper/default-12 86405012 13.85 ns/op 8 B/op 1 allocs/op
+Benchmark_ToLowerBytes/header-content-type-mixed/fiber-12 52263289 22.74 ns/op 48 B/op 1 allocs/op
+Benchmark_ToLowerBytes/header-content-type-mixed/fiber/unsafe-12 131711175 9.101 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLowerBytes/header-content-type-mixed/default-12 25312339 47.13 ns/op 48 B/op 1 allocs/op
+Benchmark_ToLowerBytes/large-lower/fiber-12 120148472 10.02 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLowerBytes/large-lower/fiber/unsafe-12 100000000 10.57 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLowerBytes/large-lower/default-12 16746064 71.43 ns/op 64 B/op 1 allocs/op
+Benchmark_ToLowerBytes/large-upper/fiber-12 46270634 26.82 ns/op 64 B/op 1 allocs/op
+Benchmark_ToLowerBytes/large-upper/fiber/unsafe-12 100000000 10.71 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLowerBytes/large-upper/default-12 15734505 76.92 ns/op 64 B/op 1 allocs/op
+Benchmark_ToLowerBytes/large-mixed/fiber-12 46607823 26.06 ns/op 64 B/op 1 allocs/op
+Benchmark_ToLowerBytes/large-mixed/fiber/unsafe-12 100000000 10.86 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLowerBytes/large-mixed/default-12 16291084 73.76 ns/op 64 B/op 1 allocs/op
+Benchmark_ToUpperBytes/empty/fiber-12 607678140 1.976 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpperBytes/empty/fiber/unsafe-12 611928006 1.981 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpperBytes/empty/default-12 362632894 3.309 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpperBytes/http-get/fiber-12 95358867 12.55 ns/op 3 B/op 1 allocs/op
+Benchmark_ToUpperBytes/http-get/fiber/unsafe-12 249490471 4.905 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpperBytes/http-get/default-12 79248020 14.63 ns/op 8 B/op 1 allocs/op
+Benchmark_ToUpperBytes/http-get-upper/fiber-12 365516280 3.330 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpperBytes/http-get-upper/fiber/unsafe-12 249981619 4.803 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpperBytes/http-get-upper/default-12 64343162 19.01 ns/op 8 B/op 1 allocs/op
+Benchmark_ToUpperBytes/header-content-type-mixed/fiber-12 52506741 22.69 ns/op 48 B/op 1 allocs/op
+Benchmark_ToUpperBytes/header-content-type-mixed/fiber/unsafe-12 130478352 9.350 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpperBytes/header-content-type-mixed/default-12 22415607 54.44 ns/op 48 B/op 1 allocs/op
+Benchmark_ToUpperBytes/large-lower/fiber-12 44765679 26.92 ns/op 64 B/op 1 allocs/op
+Benchmark_ToUpperBytes/large-lower/fiber/unsafe-12 100000000 13.68 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpperBytes/large-lower/default-12 14464340 110.7 ns/op 64 B/op 1 allocs/op
+Benchmark_ToUpperBytes/large-upper/fiber-12 100000000 11.98 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpperBytes/large-upper/fiber/unsafe-12 83808488 13.94 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpperBytes/large-upper/default-12 13142096 87.35 ns/op 64 B/op 1 allocs/op
+Benchmark_ToUpperBytes/large-mixed/fiber-12 33038661 32.75 ns/op 64 B/op 1 allocs/op
+Benchmark_ToUpperBytes/large-mixed/fiber/unsafe-12 100000000 10.93 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpperBytes/large-mixed/default-12 15034422 98.27 ns/op 64 B/op 1 allocs/op
+Benchmark_ToUpper/empty/fiber-12 595298628 2.309 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpper/empty/fiber/unsafe-12 595273404 2.021 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpper/empty/default-12 636980288 1.883 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpper/http-get/fiber-12 97025577 12.40 ns/op 3 B/op 1 allocs/op
+Benchmark_ToUpper/http-get/fiber/unsafe-12 244711635 4.857 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpper/http-get/default-12 59790234 19.54 ns/op 8 B/op 1 allocs/op
+Benchmark_ToUpper/http-get-upper/fiber-12 383218539 3.056 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpper/http-get-upper/fiber/unsafe-12 247851331 4.864 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpper/http-get-upper/default-12 223044249 5.182 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpper/header-content-type-mixed/fiber-12 52628502 24.13 ns/op 48 B/op 1 allocs/op
+Benchmark_ToUpper/header-content-type-mixed/fiber/unsafe-12 127726341 9.233 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpper/header-content-type-mixed/default-12 11549816 104.0 ns/op 48 B/op 1 allocs/op
+Benchmark_ToUpper/large-lower/fiber-12 42409070 26.04 ns/op 64 B/op 1 allocs/op
+Benchmark_ToUpper/large-lower/fiber/unsafe-12 100000000 11.00 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpper/large-lower/default-12 7051911 169.0 ns/op 64 B/op 1 allocs/op
+Benchmark_ToUpper/large-upper/fiber-12 123837582 9.590 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpper/large-upper/fiber/unsafe-12 100000000 10.83 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpper/large-upper/default-12 19115356 61.51 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpper/large-mixed/fiber-12 45872143 27.77 ns/op 64 B/op 1 allocs/op
+Benchmark_ToUpper/large-mixed/fiber/unsafe-12 100000000 11.00 ns/op 0 B/op 0 allocs/op
+Benchmark_ToUpper/large-mixed/default-12 5927710 203.1 ns/op 64 B/op 1 allocs/op
+Benchmark_ToLower/empty/fiber-12 613625554 1.952 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLower/empty/fiber/unsafe-12 572670608 1.989 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLower/empty/default-12 644769141 1.863 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLower/http-get/fiber-12 395302272 3.034 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLower/http-get/fiber/unsafe-12 252231990 4.813 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLower/http-get/default-12 284202345 4.219 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLower/http-get-upper/fiber-12 100000000 12.08 ns/op 3 B/op 1 allocs/op
+Benchmark_ToLower/http-get-upper/fiber/unsafe-12 252859507 4.816 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLower/http-get-upper/default-12 60415860 19.54 ns/op 8 B/op 1 allocs/op
+Benchmark_ToLower/header-content-type-mixed/fiber-12 53446660 22.49 ns/op 48 B/op 1 allocs/op
+Benchmark_ToLower/header-content-type-mixed/fiber/unsafe-12 131152108 9.153 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLower/header-content-type-mixed/default-12 18039788 66.79 ns/op 48 B/op 1 allocs/op
+Benchmark_ToLower/large-lower/fiber-12 120227584 9.982 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLower/large-lower/fiber/unsafe-12 100000000 10.68 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLower/large-lower/default-12 24070928 48.79 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLower/large-upper/fiber-12 44699118 25.92 ns/op 64 B/op 1 allocs/op
+Benchmark_ToLower/large-upper/fiber/unsafe-12 100000000 10.74 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLower/large-upper/default-12 7075200 170.0 ns/op 64 B/op 1 allocs/op
+Benchmark_ToLower/large-mixed/fiber-12 46426453 26.01 ns/op 64 B/op 1 allocs/op
+Benchmark_ToLower/large-mixed/fiber/unsafe-12 100000000 10.74 ns/op 0 B/op 0 allocs/op
+Benchmark_ToLower/large-mixed/default-12 5682778 204.3 ns/op 64 B/op 1 allocs/op
# Add Trailing Slash
-Benchmark_AddTrailingSlashBytes/empty-12 1000000000 0.6118 ns/op 0 B/op 0 allocs/op
-Benchmark_AddTrailingSlashBytes/slash-only-12 1000000000 0.9030 ns/op 0 B/op 0 allocs/op
-Benchmark_AddTrailingSlashBytes/short-no-slash-12 100000000 12.17 ns/op 4 B/op 1 allocs/op
-Benchmark_AddTrailingSlashBytes/short-with-slash-12 1000000000 0.9096 ns/op 0 B/op 0 allocs/op
-Benchmark_AddTrailingSlashBytes/path-no-slash-12 79386301 13.31 ns/op 16 B/op 1 allocs/op
-Benchmark_AddTrailingSlashBytes/path-with-slash-12 1000000000 0.9079 ns/op 0 B/op 0 allocs/op
-Benchmark_AddTrailingSlashString/empty-12 1000000000 0.3001 ns/op 0 B/op 0 allocs/op
-Benchmark_AddTrailingSlashString/slash-only-12 1000000000 0.5217 ns/op 0 B/op 0 allocs/op
-Benchmark_AddTrailingSlashString/short-no-slash-12 100000000 13.37 ns/op 4 B/op 1 allocs/op
-Benchmark_AddTrailingSlashString/short-with-slash-12 1000000000 0.4548 ns/op 0 B/op 0 allocs/op
-Benchmark_AddTrailingSlashString/path-no-slash-12 84763720 16.71 ns/op 16 B/op 1 allocs/op
-Benchmark_AddTrailingSlashString/path-with-slash-12 1000000000 0.4536 ns/op 0 B/op 0 allocs/op
+Benchmark_AddTrailingSlashBytes/empty-12 1000000000 0.5857 ns/op 0 B/op 0 allocs/op
+Benchmark_AddTrailingSlashBytes/slash-only-12 1000000000 0.8694 ns/op 0 B/op 0 allocs/op
+Benchmark_AddTrailingSlashBytes/short-no-slash-12 100000000 11.65 ns/op 4 B/op 1 allocs/op
+Benchmark_AddTrailingSlashBytes/short-with-slash-12 1000000000 0.8867 ns/op 0 B/op 0 allocs/op
+Benchmark_AddTrailingSlashBytes/path-no-slash-12 93543546 13.36 ns/op 16 B/op 1 allocs/op
+Benchmark_AddTrailingSlashBytes/path-with-slash-12 1000000000 0.9011 ns/op 0 B/op 0 allocs/op
+Benchmark_AddTrailingSlashString/empty-12 1000000000 0.2926 ns/op 0 B/op 0 allocs/op
+Benchmark_AddTrailingSlashString/slash-only-12 1000000000 0.4482 ns/op 0 B/op 0 allocs/op
+Benchmark_AddTrailingSlashString/short-no-slash-12 100000000 11.37 ns/op 4 B/op 1 allocs/op
+Benchmark_AddTrailingSlashString/short-with-slash-12 1000000000 0.4502 ns/op 0 B/op 0 allocs/op
+Benchmark_AddTrailingSlashString/path-no-slash-12 82427726 14.41 ns/op 16 B/op 1 allocs/op
+Benchmark_AddTrailingSlashString/path-with-slash-12 1000000000 0.4529 ns/op 0 B/op 0 allocs/op
# EqualFold
-Benchmark_EqualFoldBytes/fiber-12 34227160 35.89 ns/op 0 B/op 0 allocs/op
-Benchmark_EqualFoldBytes/default-12 17905046 68.31 ns/op 0 B/op 0 allocs/op
-Benchmark_EqualFold/fiber-12 34215410 36.76 ns/op 0 B/op 0 allocs/op
-Benchmark_EqualFold/default-12 17103853 69.62 ns/op 0 B/op 0 allocs/op
+Benchmark_EqualFoldBytes/fiber-12 67368261 18.48 ns/op 0 B/op 0 allocs/op
+Benchmark_EqualFoldBytes/default-12 17774803 65.91 ns/op 0 B/op 0 allocs/op
+Benchmark_EqualFold/fiber-12 80501566 14.75 ns/op 0 B/op 0 allocs/op
+Benchmark_EqualFold/default-12 18314365 65.96 ns/op 0 B/op 0 allocs/op
+
+# Search
+Benchmark_IndexAny2/7B/swar-12 282163779 4.297 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny2/7B/scalar-12 314553402 3.826 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny2/7B/stdlib-indexany-12 50085909 23.97 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny2/8B/swar-12 522780714 2.289 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny2/8B/scalar-12 271494799 4.206 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny2/8B/stdlib-indexany-12 44831599 26.78 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny2/16B/swar-12 393245086 3.047 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny2/16B/scalar-12 168476984 7.117 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny2/16B/stdlib-indexany-12 100000000 10.03 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny2/32B/swar-12 252199587 4.802 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny2/32B/scalar-12 84105762 14.27 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny2/32B/stdlib-indexany-12 70291048 17.37 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny2/64B/swar-12 144335962 8.290 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny2/64B/scalar-12 42694686 28.60 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny2/64B/stdlib-indexany-12 37615540 32.23 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny2/512B/swar-12 20231538 59.71 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny2/512B/scalar-12 5071586 233.6 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny2/512B/stdlib-indexany-12 4448119 274.2 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny3/7B/swar-12 221889592 5.397 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny3/7B/scalar-12 240859849 4.977 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny3/8B/swar-12 445742876 2.689 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny3/8B/scalar-12 211981612 5.620 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny3/16B/swar-12 326475568 3.739 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny3/16B/scalar-12 100000000 10.31 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny3/32B/swar-12 196365920 6.112 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny3/32B/scalar-12 60021255 19.81 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny3/64B/swar-12 100000000 10.98 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny3/64B/scalar-12 31180405 38.97 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny3/512B/swar-12 15466316 79.22 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexAny3/512B/scalar-12 3911382 307.1 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexFold/miss-8B/swar-12 332497509 3.634 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexFold/miss-8B/scalar-12 491493494 2.408 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexFold/miss-32B/swar-12 149769112 7.928 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexFold/miss-32B/scalar-12 44041342 27.13 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexFold/hit-32B/swar-12 138732252 8.758 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexFold/hit-32B/scalar-12 33871633 30.73 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexFold/hit-tail/swar-12 100000000 12.34 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexFold/hit-tail/scalar-12 16138168 75.39 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexFold/miss-64B/swar-12 100000000 11.37 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexFold/miss-64B/scalar-12 17902330 67.78 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexFold/miss-512B/swar-12 17640939 67.65 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexFold/miss-512B/scalar-12 2211582 544.4 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexFold/long-hit-64B/swar-12 100000000 11.58 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexFold/long-hit-64B/scalar-12 23906326 51.33 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexFold/long-miss-64B/swar-12 100000000 11.33 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexFold/long-miss-64B/scalar-12 23553600 50.27 ns/op 0 B/op 0 allocs/op
+
+# ASCII
+Benchmark_IsASCII/7B/swar-12 238699563 5.001 ns/op 0 B/op 0 allocs/op
+Benchmark_IsASCII/7B/scalar-12 292669958 4.064 ns/op 0 B/op 0 allocs/op
+Benchmark_IsASCII/8B/swar-12 439961722 2.687 ns/op 0 B/op 0 allocs/op
+Benchmark_IsASCII/8B/scalar-12 274732192 4.364 ns/op 0 B/op 0 allocs/op
+Benchmark_IsASCII/16B/swar-12 367179319 3.255 ns/op 0 B/op 0 allocs/op
+Benchmark_IsASCII/16B/scalar-12 179331987 6.706 ns/op 0 B/op 0 allocs/op
+Benchmark_IsASCII/32B/swar-12 368345228 3.271 ns/op 0 B/op 0 allocs/op
+Benchmark_IsASCII/32B/scalar-12 100000000 11.62 ns/op 0 B/op 0 allocs/op
+Benchmark_IsASCII/64B/swar-12 265505815 4.486 ns/op 0 B/op 0 allocs/op
+Benchmark_IsASCII/64B/scalar-12 57864440 21.33 ns/op 0 B/op 0 allocs/op
+Benchmark_IsASCII/512B/swar-12 47664915 25.14 ns/op 0 B/op 0 allocs/op
+Benchmark_IsASCII/512B/scalar-12 7081790 169.5 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexNonQuotable/7B/swar-12 142234436 8.424 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexNonQuotable/7B/scalar-12 142394628 8.174 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexNonQuotable/8B/swar-12 401721262 3.099 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexNonQuotable/8B/scalar-12 138047568 8.654 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexNonQuotable/16B/swar-12 244592613 5.059 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexNonQuotable/16B/scalar-12 75413396 15.94 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexNonQuotable/32B/swar-12 138857455 8.875 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexNonQuotable/32B/scalar-12 39539425 30.18 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexNonQuotable/64B/swar-12 75193269 16.46 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexNonQuotable/64B/scalar-12 20898807 57.81 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexNonQuotable/512B/swar-12 9634008 124.9 ns/op 0 B/op 0 allocs/op
+Benchmark_IndexNonQuotable/512B/scalar-12 2619062 460.6 ns/op 0 B/op 0 allocs/op
# Trim
-Benchmark_TrimRight/fiber-12 556198228 2.195 ns/op 0 B/op 0 allocs/op
-Benchmark_TrimRight/default-12 394761454 3.080 ns/op 0 B/op 0 allocs/op
-Benchmark_TrimRightBytes/fiber-12 552028600 2.188 ns/op 0 B/op 0 allocs/op
-Benchmark_TrimRightBytes/default-12 364481850 3.382 ns/op 0 B/op 0 allocs/op
-Benchmark_TrimLeft/fiber-12 493763746 2.439 ns/op 0 B/op 0 allocs/op
-Benchmark_TrimLeft/default-12 394974064 3.147 ns/op 0 B/op 0 allocs/op
-Benchmark_TrimLeftBytes/fiber-12 533978953 2.129 ns/op 0 B/op 0 allocs/op
-Benchmark_TrimLeftBytes/default-12 390162962 3.090 ns/op 0 B/op 0 allocs/op
-Benchmark_Trim/fiber-12 303470884 4.120 ns/op 0 B/op 0 allocs/op
-Benchmark_Trim/default-12 238874899 4.889 ns/op 0 B/op 0 allocs/op
-Benchmark_Trim/default.trimspace-12 230900814 5.395 ns/op 0 B/op 0 allocs/op
-Benchmark_TrimBytes/fiber-12 302062202 3.963 ns/op 0 B/op 0 allocs/op
-Benchmark_TrimBytes/default-12 245799558 5.052 ns/op 0 B/op 0 allocs/op
-Benchmark_TrimBytes/default.trimspace-12 217547649 5.520 ns/op 0 B/op 0 allocs/op
-Benchmark_TrimSpace/fiber/empty-12 1000000000 0.3031 ns/op 0 B/op 0 allocs/op
-Benchmark_TrimSpace/default/empty-12 554941630 2.211 ns/op 0 B/op 0 allocs/op
-Benchmark_TrimSpace/fiber/spaces-12 378650127 3.139 ns/op 955.63 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpace/default/spaces-12 313411838 3.929 ns/op 763.64 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpace/fiber/ascii-word-12 325986266 3.682 ns/op 2444.19 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpace/default/ascii-word-12 260590963 4.751 ns/op 1894.19 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpace/fiber/auth-header-bearer-12 278654619 4.279 ns/op 5608.46 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpace/default/auth-header-bearer-12 217345236 5.665 ns/op 4236.48 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpace/fiber/auth-header-basic-12 374732025 3.245 ns/op 11711.17 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpace/default/auth-header-basic-12 245032184 5.138 ns/op 7395.35 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpace/fiber/accept-encoding-12 322936750 3.772 ns/op 5567.24 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpace/default/accept-encoding-12 259551775 4.791 ns/op 4383.20 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpace/fiber/content-type-12 327816716 3.700 ns/op 5404.76 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpace/default/content-type-12 261473678 4.851 ns/op 4122.61 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpace/fiber/x-forwarded-for-12 430371238 3.136 ns/op 8929.40 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpace/default/x-forwarded-for-12 259204014 4.351 ns/op 6434.58 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpace/fiber/query-params-12 297618063 3.686 ns/op 5425.87 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpace/default/query-params-12 260095944 4.591 ns/op 4356.73 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpace/fiber/ascii-long-12 244683963 4.594 ns/op 22203.55 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpace/default/ascii-long-12 196174795 6.097 ns/op 16728.77 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpace/fiber/no-trim-12 1000000000 0.6452 ns/op 7750.12 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpace/default/no-trim-12 431454468 2.758 ns/op 1813.07 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpace/fiber/mixed-whitespace-12 279402585 4.522 ns/op 3759.80 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpace/default/mixed-whitespace-12 216711007 5.540 ns/op 3068.59 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/fiber/empty-12 1000000000 0.3096 ns/op 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/default/empty-12 486190254 2.466 ns/op 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/fiber/spaces-12 350271897 3.119 ns/op 961.83 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/default/spaces-12 294683720 4.188 ns/op 716.36 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/fiber/ascii-word-12 328983026 3.690 ns/op 2438.91 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/default/ascii-word-12 242798146 5.181 ns/op 1737.10 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/fiber/auth-header-bearer-12 276373491 4.299 ns/op 5582.44 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/default/auth-header-bearer-12 203176566 6.066 ns/op 3956.37 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/fiber/auth-header-basic-12 371498816 3.203 ns/op 11863.40 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/default/auth-header-basic-12 233269664 5.123 ns/op 7417.55 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/fiber/accept-encoding-12 331386438 3.740 ns/op 5614.74 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/default/accept-encoding-12 248029371 5.101 ns/op 4116.44 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/fiber/content-type-12 324414853 3.624 ns/op 5518.54 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/default/content-type-12 250866906 4.764 ns/op 4198.35 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/fiber/x-forwarded-for-12 448704225 2.690 ns/op 10409.74 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/default/x-forwarded-for-12 267864716 5.395 ns/op 5189.83 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/fiber/query-params-12 298958100 3.821 ns/op 5234.49 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/default/query-params-12 247046188 4.859 ns/op 4116.00 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/fiber/ascii-long-12 259565295 4.594 ns/op 22201.52 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/default/ascii-long-12 188316823 6.343 ns/op 16079.55 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/fiber/no-trim-12 1000000000 0.6094 ns/op 8204.80 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/default/no-trim-12 395805396 3.032 ns/op 1649.01 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/fiber/mixed-whitespace-12 281619982 4.206 ns/op 4041.49 MB/s 0 B/op 0 allocs/op
-Benchmark_TrimSpaceBytes/default/mixed-whitespace-12 209473969 5.716 ns/op 2974.30 MB/s 0 B/op 0 allocs/op
+Benchmark_TrimRight/fiber-12 587360972 2.043 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimRight/default-12 417142952 2.887 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimRightBytes/fiber-12 590828253 2.067 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimRightBytes/default-12 374548395 3.236 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimLeft/fiber-12 590822072 2.030 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimLeft/default-12 408184784 2.967 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimLeftBytes/fiber-12 592875732 2.033 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimLeftBytes/default-12 405921434 2.967 ns/op 0 B/op 0 allocs/op
+Benchmark_Trim/fiber-12 317625432 3.758 ns/op 0 B/op 0 allocs/op
+Benchmark_Trim/default-12 250173384 4.735 ns/op 0 B/op 0 allocs/op
+Benchmark_Trim/default.trimspace-12 241883282 5.022 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimBytes/fiber-12 308885211 3.858 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimBytes/default-12 254064188 4.802 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimBytes/default.trimspace-12 224231778 5.330 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/fiber/empty-12 1000000000 0.3017 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/default/empty-12 583064172 2.074 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/fiber/spaces-12 387354229 3.059 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/default/spaces-12 320059388 3.651 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/fiber/ascii-word-12 345078337 3.535 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/default/ascii-word-12 270603267 4.465 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/fiber/auth-header-bearer-12 291494109 4.141 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/default/auth-header-bearer-12 224087944 5.329 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/fiber/auth-header-basic-12 390765345 3.047 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/default/auth-header-basic-12 258943531 4.718 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/fiber/accept-encoding-12 344369745 3.490 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/default/accept-encoding-12 277203638 4.347 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/fiber/content-type-12 344263705 3.506 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/default/content-type-12 276213367 4.343 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/fiber/x-forwarded-for-12 460119685 2.653 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/default/x-forwarded-for-12 296468840 4.058 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/fiber/query-params-12 330053276 3.520 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/default/query-params-12 275688495 4.352 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/fiber/ascii-long-12 275511898 4.342 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/default/ascii-long-12 206143018 5.807 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/fiber/no-trim-12 1000000000 0.5914 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/default/no-trim-12 451842741 2.634 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/fiber/mixed-whitespace-12 296083767 4.054 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpace/default/mixed-whitespace-12 224007750 5.294 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/fiber/empty-12 1000000000 0.2914 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/default/empty-12 519488766 2.352 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/fiber/spaces-12 410959255 2.966 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/default/spaces-12 315602949 3.827 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/fiber/ascii-word-12 341217429 3.519 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/default/ascii-word-12 247799318 4.667 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/fiber/auth-header-bearer-12 295130076 4.182 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/default/auth-header-bearer-12 209162235 5.685 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/fiber/auth-header-basic-12 393366796 3.053 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/default/auth-header-basic-12 240882009 4.930 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/fiber/accept-encoding-12 343673244 3.512 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/default/accept-encoding-12 250962042 4.642 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/fiber/content-type-12 344382758 3.516 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/default/content-type-12 250622116 4.693 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/fiber/x-forwarded-for-12 459435145 2.621 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/default/x-forwarded-for-12 276595178 4.359 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/fiber/query-params-12 341144192 3.526 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/default/query-params-12 255843174 4.873 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/fiber/ascii-long-12 270183530 4.445 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/default/ascii-long-12 189740618 6.335 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/fiber/no-trim-12 1000000000 0.5969 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/default/no-trim-12 406072189 2.941 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/fiber/mixed-whitespace-12 289382116 4.057 ns/op 0 B/op 0 allocs/op
+Benchmark_TrimSpaceBytes/default/mixed-whitespace-12 218559462 5.493 ns/op 0 B/op 0 allocs/op
# Convert
-Benchmark_ConvertToBytes/fiber-12 305651658 3.974 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString/int-12 494480786 2.455 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString/int8-12 601754490 2.009 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString/int16-12 480638928 2.507 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString/int32-12 483084573 2.505 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString/int64-12 485630560 2.572 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString/uint-12 542968509 2.126 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString/uint8-12 603426201 2.082 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString/uint16-12 568713753 2.111 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString/uint32-12 567709288 2.106 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString/uint64-12 568810574 2.180 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString/string-12 606042240 2.191 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString/[]uint8-12 94285881 12.78 ns/op 16 B/op 1 allocs/op
-Benchmark_ToString/bool-12 601565197 1.995 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString/float32-12 24979378 48.10 ns/op 4 B/op 1 allocs/op
-Benchmark_ToString/float64-12 17121148 70.77 ns/op 4 B/op 1 allocs/op
-Benchmark_ToString/time.Time-12 12894415 93.74 ns/op 24 B/op 1 allocs/op
-Benchmark_ToString/time.Time#01-12 12970261 95.06 ns/op 24 B/op 1 allocs/op
-Benchmark_ToString/[]string-12 52706324 26.62 ns/op 16 B/op 1 allocs/op
-Benchmark_ToString/[]int-12 51370597 24.19 ns/op 8 B/op 1 allocs/op
-Benchmark_ToString/[2]int-12 31207941 38.93 ns/op 16 B/op 1 allocs/op
-Benchmark_ToString/[][]int-12 8454266 142.9 ns/op 112 B/op 6 allocs/op
-Benchmark_ToString/[]interface_{}-12 9656547 133.4 ns/op 72 B/op 3 allocs/op
-Benchmark_ToString/utils.MyStringer-12 390543688 3.060 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString/utils.CustomType-12 11184109 106.9 ns/op 16 B/op 1 allocs/op
-Benchmark_ToString_concurrency/int-12 1000000000 0.3039 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString_concurrency/int8-12 1000000000 0.2423 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString_concurrency/int16-12 1000000000 0.2901 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString_concurrency/int32-12 1000000000 0.2935 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString_concurrency/int64-12 1000000000 0.2856 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString_concurrency/uint-12 1000000000 0.3382 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString_concurrency/uint8-12 1000000000 0.2279 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString_concurrency/uint16-12 1000000000 0.2460 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString_concurrency/uint32-12 1000000000 0.2469 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString_concurrency/uint64-12 1000000000 0.2615 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString_concurrency/string-12 1000000000 0.2305 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString_concurrency/[]uint8-12 176655307 6.047 ns/op 16 B/op 1 allocs/op
-Benchmark_ToString_concurrency/bool-12 1000000000 0.2306 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString_concurrency/float32-12 183723876 8.276 ns/op 4 B/op 1 allocs/op
-Benchmark_ToString_concurrency/float64-12 121188367 9.445 ns/op 4 B/op 1 allocs/op
-Benchmark_ToString_concurrency/time.Time-12 68860974 17.98 ns/op 24 B/op 1 allocs/op
-Benchmark_ToString_concurrency/time.Time#01-12 65536016 18.02 ns/op 24 B/op 1 allocs/op
-Benchmark_ToString_concurrency/[]string-12 159027694 8.212 ns/op 16 B/op 1 allocs/op
-Benchmark_ToString_concurrency/[]int-12 203055362 5.631 ns/op 8 B/op 1 allocs/op
-Benchmark_ToString_concurrency/[2]int-12 131550500 9.186 ns/op 16 B/op 1 allocs/op
-Benchmark_ToString_concurrency/[][]int-12 21128588 55.64 ns/op 112 B/op 6 allocs/op
-Benchmark_ToString_concurrency/[]interface_{}-12 30081375 38.26 ns/op 72 B/op 3 allocs/op
-Benchmark_ToString_concurrency/utils.MyStringer-12 1000000000 0.3727 ns/op 0 B/op 0 allocs/op
-Benchmark_ToString_concurrency/utils.CustomType-12 49417796 29.59 ns/op 16 B/op 1 allocs/op
-Benchmark_UnsafeBytes/unsafe-12 1000000000 0.5450 ns/op 0 B/op 0 allocs/op
-Benchmark_UnsafeBytes/default-12 80875700 14.54 ns/op 16 B/op 1 allocs/op
-Benchmark_UnsafeString/unsafe-12 1000000000 0.3579 ns/op 0 B/op 0 allocs/op
-Benchmark_UnsafeString/default-12 99855757 12.15 ns/op 16 B/op 1 allocs/op
-Benchmark_ByteSize/0-12 394155170 3.023 ns/op 0 B/op 0 allocs/op
-Benchmark_ByteSize/1-12 64058362 18.38 ns/op 16 B/op 1 allocs/op
-Benchmark_ByteSize/500-12 58149043 21.64 ns/op 16 B/op 1 allocs/op
-Benchmark_ByteSize/1024-12 58947781 20.26 ns/op 16 B/op 1 allocs/op
-Benchmark_ByteSize/1126-12 52060172 23.14 ns/op 16 B/op 1 allocs/op
-Benchmark_ByteSize/1048576-12 60832776 19.66 ns/op 16 B/op 1 allocs/op
-Benchmark_ByteSize/1153024-12 51995977 22.68 ns/op 16 B/op 1 allocs/op
-Benchmark_ByteSize/1073741824-12 61154545 19.64 ns/op 16 B/op 1 allocs/op
-Benchmark_ByteSize/1180696576-12 52380780 23.06 ns/op 16 B/op 1 allocs/op
-Benchmark_ByteSize/1099511627776-12 62655552 19.10 ns/op 16 B/op 1 allocs/op
-Benchmark_ByteSize/1209033293824-12 53917438 23.08 ns/op 16 B/op 1 allocs/op
-Benchmark_ByteSize/1125899906842624-12 60970962 18.98 ns/op 16 B/op 1 allocs/op
-Benchmark_ByteSize/1238050092875776-12 55339809 21.64 ns/op 16 B/op 1 allocs/op
-Benchmark_ByteSize/1152921504606846976-12 63578542 18.73 ns/op 16 B/op 1 allocs/op
-Benchmark_ByteSize/1267763295104794624-12 55347254 21.74 ns/op 16 B/op 1 allocs/op
+Benchmark_ConvertToBytes/fiber-12 320332576 3.787 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString/int-12 499429904 2.382 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString/int8-12 614406423 1.965 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString/int16-12 486644316 2.463 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString/int32-12 495227163 2.422 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString/int64-12 502362236 2.429 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString/uint-12 561693333 2.101 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString/uint8-12 611239028 1.965 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString/uint16-12 573383422 2.127 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString/uint32-12 575723191 2.093 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString/uint64-12 575901750 2.089 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString/string-12 613909396 1.959 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString/[]uint8-12 96832432 12.11 ns/op 16 B/op 1 allocs/op
+Benchmark_ToString/bool-12 608058547 1.990 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString/float32-12 23195016 47.11 ns/op 4 B/op 1 allocs/op
+Benchmark_ToString/float64-12 17204126 70.24 ns/op 4 B/op 1 allocs/op
+Benchmark_ToString/time.Time-12 13103935 91.85 ns/op 24 B/op 1 allocs/op
+Benchmark_ToString/time.Time#01-12 13198113 91.22 ns/op 24 B/op 1 allocs/op
+Benchmark_ToString/[]string-12 65187865 18.35 ns/op 16 B/op 1 allocs/op
+Benchmark_ToString/[]int-12 54417859 21.53 ns/op 8 B/op 1 allocs/op
+Benchmark_ToString/[2]int-12 32691942 36.57 ns/op 16 B/op 1 allocs/op
+Benchmark_ToString/[][]int-12 9382754 128.8 ns/op 112 B/op 6 allocs/op
+Benchmark_ToString/[]interface_{}-12 10584483 114.5 ns/op 72 B/op 3 allocs/op
+Benchmark_ToString/utils.MyStringer-12 365979882 3.277 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString/utils.CustomType-12 11649330 102.5 ns/op 16 B/op 1 allocs/op
+Benchmark_ToString_concurrency/int-12 1000000000 0.2619 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString_concurrency/int8-12 1000000000 0.2202 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString_concurrency/int16-12 1000000000 0.2708 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString_concurrency/int32-12 1000000000 0.2658 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString_concurrency/int64-12 1000000000 0.2658 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString_concurrency/uint-12 1000000000 0.2281 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString_concurrency/uint8-12 1000000000 0.2223 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString_concurrency/uint16-12 1000000000 0.2396 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString_concurrency/uint32-12 1000000000 0.2273 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString_concurrency/uint64-12 1000000000 0.2271 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString_concurrency/string-12 1000000000 0.2117 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString_concurrency/[]uint8-12 213842515 5.718 ns/op 16 B/op 1 allocs/op
+Benchmark_ToString_concurrency/bool-12 1000000000 0.2118 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString_concurrency/float32-12 201081819 6.011 ns/op 4 B/op 1 allocs/op
+Benchmark_ToString_concurrency/float64-12 142000966 8.799 ns/op 4 B/op 1 allocs/op
+Benchmark_ToString_concurrency/time.Time-12 71451783 18.04 ns/op 24 B/op 1 allocs/op
+Benchmark_ToString_concurrency/time.Time#01-12 69313578 17.74 ns/op 24 B/op 1 allocs/op
+Benchmark_ToString_concurrency/[]string-12 187564670 6.455 ns/op 16 B/op 1 allocs/op
+Benchmark_ToString_concurrency/[]int-12 262707805 4.498 ns/op 8 B/op 1 allocs/op
+Benchmark_ToString_concurrency/[2]int-12 129274200 8.777 ns/op 16 B/op 1 allocs/op
+Benchmark_ToString_concurrency/[][]int-12 22638411 52.65 ns/op 112 B/op 6 allocs/op
+Benchmark_ToString_concurrency/[]interface_{}-12 34120837 35.36 ns/op 72 B/op 3 allocs/op
+Benchmark_ToString_concurrency/utils.MyStringer-12 1000000000 0.4259 ns/op 0 B/op 0 allocs/op
+Benchmark_ToString_concurrency/utils.CustomType-12 54806094 25.95 ns/op 16 B/op 1 allocs/op
+Benchmark_UnsafeBytes/unsafe-12 1000000000 0.5658 ns/op 0 B/op 0 allocs/op
+Benchmark_UnsafeBytes/default-12 88407558 13.50 ns/op 16 B/op 1 allocs/op
+Benchmark_UnsafeString/unsafe-12 1000000000 0.3545 ns/op 0 B/op 0 allocs/op
+Benchmark_UnsafeString/default-12 100000000 12.09 ns/op 16 B/op 1 allocs/op
+Benchmark_ByteSize/0-12 395954607 3.023 ns/op 0 B/op 0 allocs/op
+Benchmark_ByteSize/1-12 65295756 18.15 ns/op 16 B/op 1 allocs/op
+Benchmark_ByteSize/500-12 58264801 20.92 ns/op 16 B/op 1 allocs/op
+Benchmark_ByteSize/1024-12 60886531 19.80 ns/op 16 B/op 1 allocs/op
+Benchmark_ByteSize/1126-12 53409986 22.69 ns/op 16 B/op 1 allocs/op
+Benchmark_ByteSize/1048576-12 60969927 19.41 ns/op 16 B/op 1 allocs/op
+Benchmark_ByteSize/1153024-12 53647869 22.12 ns/op 16 B/op 1 allocs/op
+Benchmark_ByteSize/1073741824-12 63792180 19.05 ns/op 16 B/op 1 allocs/op
+Benchmark_ByteSize/1180696576-12 54560540 22.02 ns/op 16 B/op 1 allocs/op
+Benchmark_ByteSize/1099511627776-12 64080169 18.85 ns/op 16 B/op 1 allocs/op
+Benchmark_ByteSize/1209033293824-12 52957434 22.01 ns/op 16 B/op 1 allocs/op
+Benchmark_ByteSize/1125899906842624-12 65629659 18.33 ns/op 16 B/op 1 allocs/op
+Benchmark_ByteSize/1238050092875776-12 56535770 21.73 ns/op 16 B/op 1 allocs/op
+Benchmark_ByteSize/1152921504606846976-12 64569356 18.56 ns/op 16 B/op 1 allocs/op
+Benchmark_ByteSize/1267763295104794624-12 56481996 21.10 ns/op 16 B/op 1 allocs/op
# Format and Append
-Benchmark_FormatUint/small/fiber-12 1000000000 0.3025 ns/op 0 B/op 0 allocs/op
-Benchmark_FormatUint/small/strconv-12 584345623 2.084 ns/op 0 B/op 0 allocs/op
-Benchmark_FormatUint/medium/fiber-12 125524198 10.04 ns/op 0 B/op 0 allocs/op
-Benchmark_FormatUint/medium/strconv-12 57687223 21.13 ns/op 16 B/op 1 allocs/op
-Benchmark_FormatUint/large/fiber-12 64259034 18.67 ns/op 0 B/op 0 allocs/op
-Benchmark_FormatUint/large/strconv-12 44394020 26.98 ns/op 24 B/op 1 allocs/op
-Benchmark_FormatInt/small_pos/fiber-12 609931978 1.994 ns/op 0 B/op 0 allocs/op
-Benchmark_FormatInt/small_pos/strconv-12 579927732 2.046 ns/op 0 B/op 0 allocs/op
-Benchmark_FormatInt/small_neg/fiber-12 611030502 1.969 ns/op 0 B/op 0 allocs/op
-Benchmark_FormatInt/small_neg/strconv-12 82791925 14.13 ns/op 3 B/op 1 allocs/op
-Benchmark_FormatInt/medium_pos/fiber-12 61593342 19.56 ns/op 16 B/op 1 allocs/op
-Benchmark_FormatInt/medium_pos/strconv-12 58425434 21.66 ns/op 16 B/op 1 allocs/op
-Benchmark_FormatInt/medium_neg/fiber-12 60677822 19.54 ns/op 16 B/op 1 allocs/op
-Benchmark_FormatInt/medium_neg/strconv-12 59446896 20.23 ns/op 16 B/op 1 allocs/op
-Benchmark_FormatInt/large_pos/fiber-12 46969258 25.61 ns/op 24 B/op 1 allocs/op
-Benchmark_FormatInt/large_pos/strconv-12 44999648 26.57 ns/op 24 B/op 1 allocs/op
-Benchmark_FormatInt/large_neg/fiber-12 45581593 26.18 ns/op 24 B/op 1 allocs/op
-Benchmark_FormatInt/large_neg/strconv-12 45468108 26.83 ns/op 24 B/op 1 allocs/op
-Benchmark_FormatUint32/fiber-12 126955321 9.411 ns/op 0 B/op 0 allocs/op
-Benchmark_FormatUint32/strconv-12 58030117 21.34 ns/op 16 B/op 1 allocs/op
-Benchmark_FormatInt32/fiber-12 60967604 19.60 ns/op 16 B/op 1 allocs/op
-Benchmark_FormatInt32/strconv-12 59480410 20.12 ns/op 16 B/op 1 allocs/op
-Benchmark_FormatUint16/fiber-12 164073385 7.314 ns/op 0 B/op 0 allocs/op
-Benchmark_FormatUint16/strconv-12 74532424 16.78 ns/op 5 B/op 1 allocs/op
-Benchmark_FormatInt16/fiber-12 74833182 15.94 ns/op 8 B/op 1 allocs/op
-Benchmark_FormatInt16/strconv-12 75867136 16.05 ns/op 8 B/op 1 allocs/op
-Benchmark_FormatUint8/fiber-12 1000000000 0.2999 ns/op 0 B/op 0 allocs/op
-Benchmark_FormatUint8/strconv-12 82306642 14.64 ns/op 3 B/op 1 allocs/op
-Benchmark_FormatInt8/fiber-12 1000000000 0.3015 ns/op 0 B/op 0 allocs/op
-Benchmark_FormatInt8/strconv-12 80331591 14.71 ns/op 4 B/op 1 allocs/op
-Benchmark_AppendUint/fiber-12 135872859 8.812 ns/op 0 B/op 0 allocs/op
-Benchmark_AppendUint/strconv-12 100000000 10.44 ns/op 0 B/op 0 allocs/op
-Benchmark_AppendInt/small_neg/fiber-12 345227787 3.321 ns/op 0 B/op 0 allocs/op
-Benchmark_AppendInt/small_neg/strconv-12 210340929 5.744 ns/op 0 B/op 0 allocs/op
-Benchmark_AppendInt/medium_neg/fiber-12 121853198 9.739 ns/op 0 B/op 0 allocs/op
-Benchmark_AppendInt/medium_neg/strconv-12 100000000 10.04 ns/op 0 B/op 0 allocs/op
+Benchmark_FormatUint/small/fiber-12 607527520 1.966 ns/op 0 B/op 0 allocs/op
+Benchmark_FormatUint/small/strconv-12 607521366 1.973 ns/op 0 B/op 0 allocs/op
+Benchmark_FormatUint/medium/fiber-12 64427509 19.04 ns/op 16 B/op 1 allocs/op
+Benchmark_FormatUint/medium/strconv-12 59566404 20.42 ns/op 16 B/op 1 allocs/op
+Benchmark_FormatUint/large/fiber-12 45395149 26.16 ns/op 24 B/op 1 allocs/op
+Benchmark_FormatUint/large/strconv-12 45620366 26.38 ns/op 24 B/op 1 allocs/op
+Benchmark_FormatInt/small_pos/fiber-12 608898928 1.963 ns/op 0 B/op 0 allocs/op
+Benchmark_FormatInt/small_pos/strconv-12 598721480 1.976 ns/op 0 B/op 0 allocs/op
+Benchmark_FormatInt/small_neg/fiber-12 616958124 1.946 ns/op 0 B/op 0 allocs/op
+Benchmark_FormatInt/small_neg/strconv-12 87181050 13.77 ns/op 3 B/op 1 allocs/op
+Benchmark_FormatInt/medium_pos/fiber-12 63105722 19.12 ns/op 16 B/op 1 allocs/op
+Benchmark_FormatInt/medium_pos/strconv-12 57454753 20.70 ns/op 16 B/op 1 allocs/op
+Benchmark_FormatInt/medium_neg/fiber-12 63631222 19.10 ns/op 16 B/op 1 allocs/op
+Benchmark_FormatInt/medium_neg/strconv-12 61296942 20.17 ns/op 16 B/op 1 allocs/op
+Benchmark_FormatInt/large_pos/fiber-12 48604558 25.08 ns/op 24 B/op 1 allocs/op
+Benchmark_FormatInt/large_pos/strconv-12 45605844 26.25 ns/op 24 B/op 1 allocs/op
+Benchmark_FormatInt/large_neg/fiber-12 47388217 25.09 ns/op 24 B/op 1 allocs/op
+Benchmark_FormatInt/large_neg/strconv-12 45871998 26.10 ns/op 24 B/op 1 allocs/op
+Benchmark_FormatUint32/fiber-12 63452196 18.63 ns/op 16 B/op 1 allocs/op
+Benchmark_FormatUint32/strconv-12 59485942 20.08 ns/op 16 B/op 1 allocs/op
+Benchmark_FormatInt32/fiber-12 63030724 18.98 ns/op 16 B/op 1 allocs/op
+Benchmark_FormatInt32/strconv-12 61887302 19.69 ns/op 16 B/op 1 allocs/op
+Benchmark_FormatUint16/fiber-12 80149611 14.48 ns/op 5 B/op 1 allocs/op
+Benchmark_FormatUint16/strconv-12 77022440 15.43 ns/op 5 B/op 1 allocs/op
+Benchmark_FormatInt16/fiber-12 79013646 15.23 ns/op 8 B/op 1 allocs/op
+Benchmark_FormatInt16/strconv-12 79695165 15.24 ns/op 8 B/op 1 allocs/op
+Benchmark_FormatUint8/fiber-12 599811685 1.947 ns/op 0 B/op 0 allocs/op
+Benchmark_FormatUint8/strconv-12 84144096 14.18 ns/op 3 B/op 1 allocs/op
+Benchmark_FormatInt8/fiber-12 630717244 1.985 ns/op 0 B/op 0 allocs/op
+Benchmark_FormatInt8/strconv-12 83826201 14.24 ns/op 4 B/op 1 allocs/op
+Benchmark_AppendUint/fiber-12 130817422 9.139 ns/op 0 B/op 0 allocs/op
+Benchmark_AppendUint/strconv-12 100000000 10.08 ns/op 0 B/op 0 allocs/op
+Benchmark_AppendInt/small_neg/fiber-12 369512403 3.266 ns/op 0 B/op 0 allocs/op
+Benchmark_AppendInt/small_neg/strconv-12 213341739 5.627 ns/op 0 B/op 0 allocs/op
+Benchmark_AppendInt/medium_neg/fiber-12 125937435 9.531 ns/op 0 B/op 0 allocs/op
+Benchmark_AppendInt/medium_neg/strconv-12 122490632 9.791 ns/op 0 B/op 0 allocs/op
# Token
-Benchmark_GenerateSecureToken/16_bytes-12 4445361 284.0 ns/op 24 B/op 1 allocs/op
-Benchmark_GenerateSecureToken/32_bytes-12 4071276 291.0 ns/op 48 B/op 1 allocs/op
-Benchmark_TokenGenerators/UUIDv4-12 4021219 327.0 ns/op 64 B/op 2 allocs/op
-Benchmark_TokenGenerators/SecureToken-12 4073481 287.3 ns/op 48 B/op 1 allocs/op
+Benchmark_GenerateSecureToken/16_bytes-12 4565527 258.6 ns/op 24 B/op 1 allocs/op
+Benchmark_GenerateSecureToken/32_bytes-12 4306404 280.8 ns/op 48 B/op 1 allocs/op
+Benchmark_TokenGenerators/UUIDv4-12 4019139 288.2 ns/op 64 B/op 2 allocs/op
+Benchmark_TokenGenerators/SecureToken-12 4360036 276.9 ns/op 48 B/op 1 allocs/op
# HTTP
-Benchmark_GetMIME/fiber-12 29202141 41.13 ns/op 0 B/op 0 allocs/op
-Benchmark_GetMIME/default-12 16953927 73.52 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseVendorSpecificContentType/vendorContentType-12 154110751 7.784 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseVendorSpecificContentType/defaultContentType-12 396583869 3.023 ns/op 0 B/op 0 allocs/op
-Benchmark_StatusMessage/fiber-12 1000000000 0.3396 ns/op 0 B/op 0 allocs/op
-Benchmark_StatusMessage/default-12 447403729 2.694 ns/op 0 B/op 0 allocs/op
+Benchmark_GetMIME/fiber-12 22321272 53.90 ns/op 0 B/op 0 allocs/op
+Benchmark_GetMIME/default-12 17492530 68.46 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseVendorSpecificContentType/vendorContentType-12 125467813 9.619 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseVendorSpecificContentType/defaultContentType-12 404169172 2.974 ns/op 0 B/op 0 allocs/op
+Benchmark_StatusMessage/fiber-12 1000000000 0.3349 ns/op 0 B/op 0 allocs/op
+Benchmark_StatusMessage/default-12 460456902 2.610 ns/op 0 B/op 0 allocs/op
# IP
-Benchmark_IsIPv4/fiber-12 82770516 14.99 ns/op 0 B/op 0 allocs/op
-Benchmark_IsIPv4/default-12 52222729 22.87 ns/op 0 B/op 0 allocs/op
-Benchmark_IsIPv6/fiber-12 27058488 44.28 ns/op 0 B/op 0 allocs/op
-Benchmark_IsIPv6/default-12 19518978 63.64 ns/op 0 B/op 0 allocs/op
+Benchmark_IsIPv4/fiber-12 80408070 14.58 ns/op 0 B/op 0 allocs/op
+Benchmark_IsIPv4/default-12 54025154 21.99 ns/op 0 B/op 0 allocs/op
+Benchmark_IsIPv6/fiber-12 28283431 42.67 ns/op 0 B/op 0 allocs/op
+Benchmark_IsIPv6/default-12 20747964 58.18 ns/op 0 B/op 0 allocs/op
# Parse
-Benchmark_ParseUint/fiber-12 171968007 6.984 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseUint/fiber_bytes-12 162498577 7.444 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseUint/default-12 87571795 13.70 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseInt/fiber-12 186597552 6.331 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseInt/fiber_bytes-12 180017686 6.686 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseInt/default-12 76678334 15.73 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseInt32/fiber-12 155367661 7.717 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseInt32/fiber_bytes-12 144681208 8.325 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseInt32/default-12 76537323 15.73 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseInt16/fiber-12 228710796 5.222 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseInt16/fiber_bytes-12 223933951 5.322 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseInt16/default-12 100000000 11.05 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseInt8/fiber-12 257930811 4.626 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseInt8/fiber_bytes-12 240602468 4.588 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseInt8/default-12 138314644 8.609 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseUint32/fiber-12 170833845 7.138 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseUint32/fiber_bytes-12 162105060 7.443 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseUint32/default-12 85408747 13.70 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseUint16/fiber-12 262682311 4.547 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseUint16/fiber_bytes-12 257359222 4.658 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseUint16/default-12 134532823 8.902 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseUint8/fiber-12 350422557 3.416 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseUint8/fiber_bytes-12 327501829 3.700 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseUint8/default-12 182633575 6.816 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseFloat64/fiber-12 100000000 10.73 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseFloat64/fiber_bytes-12 100000000 10.86 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseFloat64/default-12 50053615 24.18 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseFloat32/fiber-12 100000000 11.62 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseFloat32/fiber_bytes-12 100000000 11.97 ns/op 0 B/op 0 allocs/op
-Benchmark_ParseFloat32/default-12 46590180 25.98 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseUint/fiber-12 236748204 5.049 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseUint/fiber_bytes-12 224650773 5.348 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseUint/default-12 88588122 13.75 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseUint_DigitRuns/6digit-12 207540178 5.769 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseUint_DigitRuns/8digit-12 222360716 5.403 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseUint_DigitRuns/12digit-12 156132950 7.699 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseUint_DigitRuns/19digit-12 135049720 8.880 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseUint_DigitRuns/1digit-12 338642533 3.553 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseUint_DigitRuns/4digit-12 212370570 5.672 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseInt/fiber-12 299791800 3.981 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseInt/fiber_bytes-12 288714712 4.165 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseInt/default-12 76370292 15.48 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseInt32/fiber-12 200451391 5.988 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseInt32/fiber_bytes-12 201629558 5.956 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseInt32/default-12 78384832 15.71 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseInt16/fiber-12 220670613 5.462 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseInt16/fiber_bytes-12 220175068 5.430 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseInt16/default-12 100000000 10.71 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseInt8/fiber-12 277948545 4.279 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseInt8/fiber_bytes-12 264784368 4.566 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseInt8/default-12 142184748 8.373 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseUint32/fiber-12 238916116 5.025 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseUint32/fiber_bytes-12 222286592 5.409 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseUint32/default-12 90395479 13.33 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseUint16/fiber-12 251398184 4.828 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseUint16/fiber_bytes-12 248772012 4.838 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseUint16/default-12 137015901 8.788 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseUint8/fiber-12 360430984 3.427 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseUint8/fiber_bytes-12 327526336 3.659 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseUint8/default-12 181904056 6.438 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseFloat64/fiber-12 82912768 14.76 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseFloat64/fiber_bytes-12 95692504 12.68 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseFloat64/default-12 50109265 25.05 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseFloat32/fiber-12 76648135 15.76 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseFloat32/fiber_bytes-12 86422119 13.63 ns/op 0 B/op 0 allocs/op
+Benchmark_ParseFloat32/default-12 47198646 25.41 ns/op 0 B/op 0 allocs/op
# Time
-Benchmark_CalculateTimestamp/fiber-12 1000000000 0.3029 ns/op 0 B/op 0 allocs/op
-Benchmark_CalculateTimestamp/default-12 36542426 32.77 ns/op 0 B/op 0 allocs/op
-Benchmark_CalculateTimestamp/fiber_asserted-12 4240807 276.8 ns/op 13 B/op 2 allocs/op
-Benchmark_CalculateTimestamp/default_asserted-12 3974042 305.6 ns/op 8 B/op 2 allocs/op
+Benchmark_CalculateTimestamp/fiber-12 1000000000 0.3366 ns/op 0 B/op 0 allocs/op
+Benchmark_CalculateTimestamp/default-12 36163686 32.69 ns/op 0 B/op 0 allocs/op
+Benchmark_CalculateTimestamp/fiber_asserted-12 4471299 267.8 ns/op 12 B/op 2 allocs/op
+Benchmark_CalculateTimestamp/default_asserted-12 3991147 298.7 ns/op 8 B/op 2 allocs/op
# XML
-Benchmark_GolangXMLEncoder-12 591470 2025 ns/op 4864 B/op 12 allocs/op
-Benchmark_DefaultXMLEncoder-12 563848 2124 ns/op 4864 B/op 12 allocs/op
-Benchmark_DefaultXMLDecoder-12 329698 3513 ns/op 2857 B/op 57 allocs/op
+Benchmark_GolangXMLEncoder-12 574852 2040 ns/op 4864 B/op 12 allocs/op
+Benchmark_DefaultXMLEncoder-12 593738 2012 ns/op 4864 B/op 12 allocs/op
+Benchmark_DefaultXMLDecoder-12 309031 3876 ns/op 2892 B/op 57 allocs/op
```
See all the benchmarks under
+## Case-insensitive matching helpers
+
+`EqualFold`, `IndexFold`, `ContainsFold`, `HasPrefixFold`, and
+`HasSuffixFold` compare ASCII case-insensitively using the SWAR word
+loops: only `A`..`Z`/`a`..`z` fold, every other byte (including bytes
+>= 0x80) must match exactly. `HasPrefixFold` and `HasSuffixFold` cover
+the header checks Fiber otherwise spells as an allocation-prone
+`ToLower` + `HasPrefix`/`HasSuffix` pair (authorization schemes such as
+`Bearer`, content-type prefixes such as `multipart/form-data`, suffixes
+such as `+json`), and like the other Fold helpers they take the needle
+as a plain string because call sites pass constant tokens. Their
+`Benchmark_HasPrefixFold`/`Benchmark_HasSuffixFold` numbers are tracked
+on the [benchmark charts](https://gofiber.github.io/utils/benchmarks/)
+and join the catalog above on its next regeneration.
+
+## SWAR primitives
+
+The [`swar`](swar/) package exports the SWAR (SIMD within a register)
+building blocks the helpers above are composed from: `Load8`/`Store8`,
+`Broadcast`, `ZeroLanes`, `MatchByteMask`/`MatchRangeMask`,
+`ToLowerWord`/`ToUpperWord`, `FirstLane`/`LastLane`, and the `WordLen`,
+`Ones`, `HighBits`, and `LowSeven` constants. They are exported so
+downstream packages (Fiber itself, middleware) can fuse their own byte
+scans — for example, finding a delimiter while classifying the bytes
+before it — without re-deriving the bit tricks. The contracts (unchecked
+bounds preconditions, `ZeroLanes`' approximate mask, the little-endian
+lane order) and runnable examples live in the package documentation.
+
+The package benchmarks its primitives against their stdlib counterparts
+the same way the helpers above do, measuring the canonical loops composed
+from them: `Load8`/`Store8` vs `encoding/binary`'s little-endian
+`Uint64`/`PutUint64`, a `ZeroLanes` first-match scan vs
+`strings.IndexByte`, a `MatchByteMask`+`LastLane` reverse scan vs
+`bytes.LastIndexByte`, a `MatchRangeMask` digit scan vs
+`strings.IndexAny`, and an in-place `ToLowerWord` loop vs
+`bytes.ToLower`. The composed loops are pinned to the stdlib results by a
+dedicated test, and the numbers are tracked per commit on the
+[benchmark charts](https://gofiber.github.io/utils/benchmarks/). Note
+that `strings.IndexByte` is hand-written SIMD assembly and overtakes the
+portable SWAR scan on large inputs; the SWAR primitives earn their keep
+on short HTTP-sized inputs and on fused scans the stdlib has no single
+function for. The package's remaining benchmark, `Benchmark_Load8_Fusion`,
+is an advisory codegen guard rather than an API performance promise, so
+it is deliberately not part of the catalog above.
+
## ☕ Supporters
Fiber is an open-source project that runs on donations to pay the bills, e.g., our domain name, hosting, and serverless infrastructure. If you want to support Fiber, please become a [GitHub Sponsor](https://github.com/sponsors/gofiber).
diff --git a/src/vendor/github.com/gofiber/utils/v2/ascii.go b/src/vendor/github.com/gofiber/utils/v2/ascii.go
new file mode 100644
index 00000000..a16018c7
--- /dev/null
+++ b/src/vendor/github.com/gofiber/utils/v2/ascii.go
@@ -0,0 +1,104 @@
+package utils
+
+import (
+ "github.com/gofiber/utils/v2/swar"
+)
+
+// quoteLanes and backslashLanes broadcast '"' and '\\' to every lane.
+const (
+ quoteLanes = uint64('"') * swar.Ones
+ backslashLanes = uint64('\\') * swar.Ones
+)
+
+// IsASCII reports whether s contains only ASCII bytes (no byte >= 0x80).
+// It ORs four words per iteration where possible (no index is needed, so
+// detection can be deferred to one test per 32 bytes), then tests word-wise;
+// inputs of 8+ bytes finish with one overlapping word at n-8, shorter ones
+// byte-wise.
+func IsASCII[S byteSeq](s S) bool {
+ n := len(s)
+ i := 0
+ for ; i+32 <= n; i += 32 {
+ acc := swar.Load8(s, i) | swar.Load8(s, i+8) | swar.Load8(s, i+16) | swar.Load8(s, i+24)
+ if acc&swar.HighBits != 0 {
+ return false
+ }
+ }
+ for ; i+8 <= n; i += 8 {
+ if swar.Load8(s, i)&swar.HighBits != 0 {
+ return false
+ }
+ }
+ if i == n {
+ return true
+ }
+ if n >= 8 {
+ return swar.Load8(s, n-8)&swar.HighBits == 0
+ }
+ for ; i < n; i++ {
+ if s[i] >= 0x80 {
+ return false
+ }
+ }
+ return true
+}
+
+// IndexNonQuotable returns the index of the first byte of s that cannot
+// appear verbatim inside an RFC 9110 quoted-string — that is, a byte
+// matching c == '\\' || c == '"' || (c < 0x20 && c != '\t') || c == 0x7f —
+// or -1 if every byte is quotable. qdtext is HTAB / SP / %x21 / %x23-5B /
+// %x5D-7E / obs-text, so HTAB and bytes >= 0x80 are quotable. Returning the
+// index (rather than a bool) lets callers copy the clean prefix and start
+// escaping exactly at the offending byte. Inputs of 8+ bytes finish with
+// one overlapping word at n-8, shorter ones byte-wise.
+func IndexNonQuotable[S byteSeq](s S) int {
+ n := len(s)
+ i := 0
+ // Two words per branch: the masks compute independently, and if only the
+ // second word matched, its first set lane is still exact.
+ for ; i+16 <= n; i += 16 {
+ m0 := nonQuotableMask(swar.Load8(s, i))
+ m1 := nonQuotableMask(swar.Load8(s, i+8))
+ if m0|m1 != 0 {
+ if m0 != 0 {
+ return i + swar.FirstLane(m0)
+ }
+ return i + 8 + swar.FirstLane(m1)
+ }
+ }
+ for ; i+8 <= n; i += 8 {
+ if m := nonQuotableMask(swar.Load8(s, i)); m != 0 {
+ return i + swar.FirstLane(m)
+ }
+ }
+ if i == n {
+ return -1
+ }
+ if n >= 8 {
+ if m := nonQuotableMask(swar.Load8(s, n-8)); m != 0 {
+ return n - 8 + swar.FirstLane(m)
+ }
+ return -1
+ }
+ for ; i < n; i++ {
+ if c := s[i]; c == '\\' || c == '"' || (c < 0x20 && c != '\t') || c == 0x7f {
+ return i
+ }
+ }
+ return -1
+}
+
+// nonQuotableMask marks the lanes of w holding bytes that need RFC 9110
+// quoted-string escaping. Like swar.ZeroLanes, the result is exact in and below
+// the first marked lane, which is all the first-match scan above consumes.
+func nonQuotableMask(w uint64) uint64 {
+ // Controls (< 0x20) and DEL (0x7F) share one biased range test:
+ // t := ((c & 0x7F) + 1) & 0x7F maps DEL to 0 and controls to 0x01..0x20,
+ // so t <= 0x20 captures exactly both; lanes with the high bit set
+ // (obs-text, always quotable) are excluded by the &^ w term. HTAB is
+ // quotable qdtext, so its lanes are cleared with an exact match mask —
+ // an approximate one could wrongly clear a control lane above a tab.
+ t := ((w & swar.LowSeven) + swar.Ones) & swar.LowSeven
+ ctl := ^(t + (0x80-0x21)*swar.Ones) &^ w & swar.HighBits &^ swar.MatchByteMask(w, '\t')
+ return ctl | swar.ZeroLanes(w^quoteLanes) | swar.ZeroLanes(w^backslashLanes)
+}
diff --git a/src/vendor/github.com/gofiber/utils/v2/bytes/case.go b/src/vendor/github.com/gofiber/utils/v2/bytes/case.go
index 483d5b7b..8ad483e9 100644
--- a/src/vendor/github.com/gofiber/utils/v2/bytes/case.go
+++ b/src/vendor/github.com/gofiber/utils/v2/bytes/case.go
@@ -4,128 +4,102 @@ import (
"github.com/gofiber/utils/v2/internal/caseconv"
)
+// swarMinLen is the smallest input length worth routing through the
+// word-at-a-time (SWAR) helpers; shorter inputs are cheaper byte-by-byte.
+const swarMinLen = caseconv.WordLen
+
// ToLower converts an ASCII byte slice to lower-case without modifying the input.
func ToLower(b []byte) []byte {
n := len(b)
- if n == 0 {
+ if n < swarMinLen {
+ table := caseconv.ToLowerTable
+ for i := 0; i < n; i++ {
+ c := b[i]
+ low := table[c]
+ if low != c {
+ dst := make([]byte, n)
+ copy(dst, b[:i])
+ dst[i] = low
+ for i++; i < n; i++ {
+ dst[i] = table[b[i]]
+ }
+ return dst
+ }
+ }
return b
}
- table := caseconv.ToLowerTable
- i := 0
- for i < n {
- c := b[i]
- low := table[c]
- if low != c {
- dst := make([]byte, n)
- copy(dst, b[:i])
- dst[i] = low
- i++
- limit := i + ((n - i) &^ 3)
- for i < limit {
- dst[i+0] = table[b[i+0]]
- dst[i+1] = table[b[i+1]]
- dst[i+2] = table[b[i+2]]
- dst[i+3] = table[b[i+3]]
- i += 4
- }
- for i < n {
- dst[i] = table[b[i]]
- i++
- }
- return dst
- }
- i++
+ i := caseconv.FirstUpperIndex(b)
+ if i < 0 {
+ return b
}
- return b
+
+ dst := make([]byte, n)
+ // Copy the unchanged prefix up to the word containing the first
+ // uppercase byte, then convert the rest word-at-a-time.
+ from := i &^ (caseconv.WordLen - 1)
+ copy(dst, b[:from])
+ caseconv.ToLowerCopy(dst, b, from)
+ return dst
}
// ToUpper converts an ASCII byte slice to upper-case without modifying the input.
func ToUpper(b []byte) []byte {
n := len(b)
- if n == 0 {
+ if n < swarMinLen {
+ table := caseconv.ToUpperTable
+ for i := 0; i < n; i++ {
+ c := b[i]
+ up := table[c]
+ if up != c {
+ dst := make([]byte, n)
+ copy(dst, b[:i])
+ dst[i] = up
+ for i++; i < n; i++ {
+ dst[i] = table[b[i]]
+ }
+ return dst
+ }
+ }
return b
}
- table := caseconv.ToUpperTable
- i := 0
- for i < n {
- c := b[i]
- up := table[c]
- if up != c {
- dst := make([]byte, n)
- copy(dst, b[:i])
- dst[i] = up
- i++
- limit := i + ((n - i) &^ 3)
- for i < limit {
- dst[i+0] = table[b[i+0]]
- dst[i+1] = table[b[i+1]]
- dst[i+2] = table[b[i+2]]
- dst[i+3] = table[b[i+3]]
- i += 4
- }
- for i < n {
- dst[i] = table[b[i]]
- i++
- }
- return dst
- }
- i++
+ i := caseconv.FirstLowerIndex(b)
+ if i < 0 {
+ return b
}
- return b
+
+ dst := make([]byte, n)
+ from := i &^ (caseconv.WordLen - 1)
+ copy(dst, b[:from])
+ caseconv.ToUpperCopy(dst, b, from)
+ return dst
}
// UnsafeToLower converts an ASCII byte slice to lower-case in-place.
// The passed slice content is modified and the same slice is returned.
func UnsafeToLower(b []byte) []byte {
- table := caseconv.ToLowerTable
- n := len(b)
- i := 0
- limit := n &^ 3
- for i < limit {
- b0 := b[i+0]
- b1 := b[i+1]
- b2 := b[i+2]
- b3 := b[i+3]
-
- b[i+0] = table[b0]
- b[i+1] = table[b1]
- b[i+2] = table[b2]
- b[i+3] = table[b3]
-
- i += 4
- }
- for i < n {
- b[i] = table[b[i]]
- i++
+ if len(b) < swarMinLen {
+ table := caseconv.ToLowerTable
+ for i := range b {
+ b[i] = table[b[i]]
+ }
+ return b
}
+ caseconv.ToLowerInPlace(b)
return b
}
// UnsafeToUpper converts an ASCII byte slice to upper-case in-place.
// The passed slice content is modified and the same slice is returned.
func UnsafeToUpper(b []byte) []byte {
- table := caseconv.ToUpperTable
- n := len(b)
- i := 0
- limit := n &^ 3
- for i < limit {
- b0 := b[i+0]
- b1 := b[i+1]
- b2 := b[i+2]
- b3 := b[i+3]
-
- b[i+0] = table[b0]
- b[i+1] = table[b1]
- b[i+2] = table[b2]
- b[i+3] = table[b3]
-
- i += 4
- }
- for i < n {
- b[i] = table[b[i]]
- i++
+ if len(b) < swarMinLen {
+ table := caseconv.ToUpperTable
+ for i := range b {
+ b[i] = table[b[i]]
+ }
+ return b
}
+ caseconv.ToUpperInPlace(b)
return b
}
diff --git a/src/vendor/github.com/gofiber/utils/v2/byteseq.go b/src/vendor/github.com/gofiber/utils/v2/byteseq.go
index abc9c063..707df64a 100644
--- a/src/vendor/github.com/gofiber/utils/v2/byteseq.go
+++ b/src/vendor/github.com/gofiber/utils/v2/byteseq.go
@@ -2,6 +2,7 @@ package utils
import (
"github.com/gofiber/utils/v2/internal/caseconv"
+ "github.com/gofiber/utils/v2/swar"
)
type byteSeq interface {
@@ -10,54 +11,43 @@ type byteSeq interface {
// EqualFold tests ascii strings or bytes for equality case-insensitively
func EqualFold[S byteSeq](b, s S) bool {
- if len(b) != len(s) {
+ n := len(b)
+ if n != len(s) {
return false
}
- table := caseconv.ToUpperTable
- n := len(b)
+ // Compare 8 bytes per iteration; case-fold with SWAR only when the raw
+ // words differ, so byte-identical input skips both folds entirely.
i := 0
-
- // Unroll by 4 to match other hot paths and drive instruction-level parallelism.
- limit := n &^ 3
- for i < limit {
- b0 := b[i+0]
- s0 := s[i+0]
- if table[b0] != table[s0] {
+ for ; i+8 <= n; i += 8 {
+ x := swar.Load8(b, i)
+ y := swar.Load8(s, i)
+ if x != y && swar.ToUpperWord(x) != swar.ToUpperWord(y) {
return false
}
-
- b1 := b[i+1]
- s1 := s[i+1]
- if table[b1] != table[s1] {
- return false
- }
-
- b2 := b[i+2]
- s2 := s[i+2]
- if table[b2] != table[s2] {
- return false
- }
-
- b3 := b[i+3]
- s3 := s[i+3]
- if table[b3] != table[s3] {
- return false
- }
-
- i += 4
+ }
+ if i == n {
+ return true
+ }
+ if n >= 8 {
+ // Handle the tail with one overlapping word compare; re-checking
+ // bytes that were already equal cannot change the outcome.
+ x := swar.Load8(b, n-8)
+ y := swar.Load8(s, n-8)
+ return x == y || swar.ToUpperWord(x) == swar.ToUpperWord(y)
}
- for i < n {
+ table := caseconv.ToUpperTable
+ for ; i < n; i++ {
if table[b[i]] != table[s[i]] {
return false
}
- i++
}
return true
}
-// TrimLeft is the equivalent of strings/bytes.TrimLeft
+// TrimLeft removes all leading occurrences of the byte cutset from s.
+// Unlike strings/bytes.TrimLeft, cutset is a single byte, not a set of characters.
func TrimLeft[S byteSeq](s S, cutset byte) S {
lenStr, start := len(s), 0
for start < lenStr && s[start] == cutset {
@@ -66,7 +56,8 @@ func TrimLeft[S byteSeq](s S, cutset byte) S {
return s[start:]
}
-// Trim is the equivalent of strings/bytes.Trim
+// Trim removes all leading and trailing occurrences of the byte cutset from s.
+// Unlike strings/bytes.Trim, cutset is a single byte, not a set of characters.
func Trim[S byteSeq](s S, cutset byte) S {
i, j := 0, len(s)-1
for ; i <= j; i++ {
@@ -83,7 +74,8 @@ func Trim[S byteSeq](s S, cutset byte) S {
return s[i : j+1]
}
-// TrimRight is the equivalent of strings/bytes.TrimRight
+// TrimRight removes all trailing occurrences of the byte cutset from s.
+// Unlike strings/bytes.TrimRight, cutset is a single byte, not a set of characters.
func TrimRight[S byteSeq](s S, cutset byte) S {
lenStr := len(s)
for lenStr > 0 && s[lenStr-1] == cutset {
diff --git a/src/vendor/github.com/gofiber/utils/v2/common.go b/src/vendor/github.com/gofiber/utils/v2/common.go
index 8618f510..bf266808 100644
--- a/src/vendor/github.com/gofiber/utils/v2/common.go
+++ b/src/vendor/github.com/gofiber/utils/v2/common.go
@@ -127,7 +127,10 @@ func IncrementIPRange(ip net.IP) {
}
// ConvertToBytes returns integer size of bytes from human-readable string, ex. 42kb, 42M
-// Returns 0 if string is unrecognized
+// Decimal units are powers of 1000 (42k = 42000); binary units with an 'i' infix
+// are powers of 1024 (42Ki = 43008). Note that ByteSize formats with powers of 1024,
+// so use binary suffixes for a lossless round-trip.
+// Returns 0 if the string is unrecognized or negative.
func ConvertToBytes(humanReadableString string) int {
strLen := len(humanReadableString)
if strLen == 0 {
@@ -189,7 +192,7 @@ func ConvertToBytes(humanReadableString string) int {
if strings.IndexByte(numPart, '.') >= 0 {
var err error
size, err = ParseFloat64(numPart)
- if err != nil {
+ if err != nil || size < 0 {
return 0
}
} else {
@@ -201,17 +204,28 @@ func ConvertToBytes(humanReadableString string) int {
}
if unitPrefixPos > 0 {
+ // An 'i' after the unit prefix selects binary units (KiB = 1024).
+ binary := unitPrefixPos+1 < strLen &&
+ (humanReadableString[unitPrefixPos+1] == 'i' || humanReadableString[unitPrefixPos+1] == 'I')
+ var decMul, binMul float64
switch humanReadableString[unitPrefixPos] {
case 'k', 'K':
- size *= 1e3
+ decMul, binMul = 1e3, 1<<10
case 'm', 'M':
- size *= 1e6
+ decMul, binMul = 1e6, 1<<20
case 'g', 'G':
- size *= 1e9
+ decMul, binMul = 1e9, 1<<30
case 't', 'T':
- size *= 1e12
+ decMul, binMul = 1e12, 1<<40
case 'p', 'P':
- size *= 1e15
+ decMul, binMul = 1e15, 1<<50
+ default:
+ decMul, binMul = 1, 1
+ }
+ if binary {
+ size *= binMul
+ } else {
+ size *= decMul
}
}
diff --git a/src/vendor/github.com/gofiber/utils/v2/convert.go b/src/vendor/github.com/gofiber/utils/v2/convert.go
index 21422e5e..bd2f346c 100644
--- a/src/vendor/github.com/gofiber/utils/v2/convert.go
+++ b/src/vendor/github.com/gofiber/utils/v2/convert.go
@@ -150,6 +150,9 @@ func ToString(arg any, timeFormat ...string) string {
return ""
}
return ToString(v.Interface(), timeFormat...)
+ // error before fmt.Stringer to match the fmt package's precedence
+ case error:
+ return v.Error()
case fmt.Stringer:
return v.String()
// Handle common pointer types directly to avoid reflection
@@ -188,32 +191,42 @@ func ToString(arg any, timeFormat ...string) string {
if len(v) == 0 {
return "[]"
}
- var buf strings.Builder
- buf.Grow(len(v) * 8) // Pre-allocate approximate size
- buf.WriteByte('[')
+ // Compute the exact output size for a single allocation:
+ // '[' + ']' + one separating space per gap + all element bytes.
+ size := len(v) + 1
+ for _, s := range v {
+ size += len(s)
+ }
+ buf := make([]byte, 0, size)
+ buf = append(buf, '[')
for i, s := range v {
if i > 0 {
- buf.WriteByte(' ')
+ buf = append(buf, ' ')
}
- buf.WriteString(s)
+ buf = append(buf, s...)
}
- buf.WriteByte(']')
- return buf.String()
+ buf = append(buf, ']')
+ return UnsafeString(buf)
case []int:
if len(v) == 0 {
return "[]"
}
- var buf strings.Builder
- buf.Grow(len(v) * 4) // Pre-allocate approximate size
- buf.WriteByte('[')
+ // Compute the exact output size for a single allocation:
+ // '[' + ']' + one separating space per gap + all element digits.
+ size := len(v) + 1
+ for _, n := range v {
+ size += intDigits(int64(n))
+ }
+ buf := make([]byte, 0, size)
+ buf = append(buf, '[')
for i, n := range v {
if i > 0 {
- buf.WriteByte(' ')
+ buf = append(buf, ' ')
}
- buf.WriteString(FormatInt(int64(n)))
+ buf = AppendInt(buf, int64(n))
}
- buf.WriteByte(']')
- return buf.String()
+ buf = append(buf, ']')
+ return UnsafeString(buf)
default:
// Check if the type is a pointer by using reflection
rv := reflect.ValueOf(arg)
diff --git a/src/vendor/github.com/gofiber/utils/v2/format.go b/src/vendor/github.com/gofiber/utils/v2/format.go
index ad85b007..6c81d14a 100644
--- a/src/vendor/github.com/gofiber/utils/v2/format.go
+++ b/src/vendor/github.com/gofiber/utils/v2/format.go
@@ -1,5 +1,9 @@
package utils
+import (
+ "math/bits"
+)
+
// smallInts contains precomputed string representations for small integers 0-99
var smallInts [100]string
@@ -189,6 +193,37 @@ func FormatInt8(n int8) string {
return int8Strs[uint8(n)]
}
+// pow10 holds the powers of ten representable in a uint64.
+var pow10 = [20]uint64{
+ 1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+ 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+}
+
+// uintDigits returns the number of decimal digits in n. It is loop-free so it
+// inlines into per-element sizing passes.
+func uintDigits(n uint64) int {
+ if n < 10 {
+ return 1
+ }
+ // floor(log10(n)) approximated from floor(log2(n)): 1233/4096 ~= log10(2).
+ t := (bits.Len64(n) * 1233) >> 12
+ if n < pow10[t] {
+ return t
+ }
+ return t + 1
+}
+
+// intDigits returns the length of the decimal string representation of n,
+// including the '-' sign for negative values.
+func intDigits(n int64) int {
+ if n < 0 {
+ // uint64(-n) yields the absolute value for all negatives via two's
+ // complement, including math.MinInt64.
+ return 1 + uintDigits(uint64(-n))
+ }
+ return uintDigits(uint64(n))
+}
+
// AppendUint appends the decimal string representation of n to dst.
func AppendUint(dst []byte, n uint64) []byte {
if n < 100 {
diff --git a/src/vendor/github.com/gofiber/utils/v2/http.go b/src/vendor/github.com/gofiber/utils/v2/http.go
index 8baaf3e6..99e762bd 100644
--- a/src/vendor/github.com/gofiber/utils/v2/http.go
+++ b/src/vendor/github.com/gofiber/utils/v2/http.go
@@ -36,8 +36,9 @@ func GetMIME(extension string) string {
extWithDot = "." + extension
}
- // Single map lookup with normalized key
- if foundMime := mimeExtensions[extWithoutDot]; len(foundMime) > 0 {
+ // Single map lookup with normalized key. Extensions are matched
+ // case-insensitively; ToLower only allocates for upper-case input.
+ if foundMime := mimeExtensions[casestrings.ToLower(extWithoutDot)]; len(foundMime) > 0 {
return foundMime
}
diff --git a/src/vendor/github.com/gofiber/utils/v2/internal/caseconv/swar.go b/src/vendor/github.com/gofiber/utils/v2/internal/caseconv/swar.go
new file mode 100644
index 00000000..5bbf3a84
--- /dev/null
+++ b/src/vendor/github.com/gofiber/utils/v2/internal/caseconv/swar.go
@@ -0,0 +1,246 @@
+package caseconv
+
+import (
+ "encoding/binary"
+
+ "github.com/gofiber/utils/v2/swar"
+)
+
+// Word-at-a-time ASCII case conversion built on the public SWAR primitives
+// in github.com/gofiber/utils/v2/swar. Byte order inside a word does not
+// matter for the case folds themselves (every operation is per byte lane),
+// so these helpers are correct on both little- and big-endian platforms.
+//
+// Words move through encoding/binary rather than swar.Load8/swar.Store8 on
+// purpose: the binary.LittleEndian forms measure ~9% faster in the in-place
+// word loops here (benchstat -count=10, Go 1.25, Apple M2 Pro). The lane
+// order is identical, so swar words and binary.LittleEndian loads/stores
+// can be mixed freely.
+
+// WordLen is the SWAR word width in bytes, re-exported for the case
+// conversion callers in the strings and bytes packages: they route inputs
+// shorter than WordLen to byte-wise paths and align offsets they pass (such
+// as ToLowerCopy's from) with WordLen-derived masks.
+const WordLen = swar.WordLen
+
+// FirstUpperIndex returns the index of the first ASCII uppercase byte in b,
+// or -1 if b contains none. b is only ever read; it may be an unsafe view
+// over immutable string memory.
+func FirstUpperIndex(b []byte) int {
+ n := len(b)
+ i := 0
+ if n >= 32 {
+ // Check the first word alone: canonical mixed-case values
+ // ("Content-Type") change case right at the start, and that path
+ // must stay one mask.
+ if m := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[0:8]), 'A', 'Z'); m != 0 {
+ return swar.FirstLane(m)
+ }
+ // Then four words per branch: the masks compute independently, so
+ // the common no-uppercase case pays one test per 32 bytes. The
+ // MatchRangeMask computations stay inline so their constant ranges
+ // fold; only the cold hit-resolution ladder is shared, and it
+ // inlines (the no-match loop never reaches it).
+ for i = 8; i+32 <= n; i += 32 {
+ m0 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i:i+8]), 'A', 'Z')
+ m1 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+8:i+16]), 'A', 'Z')
+ m2 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+16:i+24]), 'A', 'Z')
+ m3 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+24:i+32]), 'A', 'Z')
+ if m0|m1|m2|m3 != 0 {
+ return firstSetLane32(i, m0, m1, m2, m3)
+ }
+ }
+ if i == n {
+ return -1
+ }
+ // Finish with one overlapping block at n-32. MatchRangeMask is
+ // per-lane exact, so re-scanned lanes are known non-matching and the
+ // first set lane always falls in the new bytes.
+ i = n - 32
+ m0 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i:i+8]), 'A', 'Z')
+ m1 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+8:i+16]), 'A', 'Z')
+ m2 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+16:i+24]), 'A', 'Z')
+ m3 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+24:i+32]), 'A', 'Z')
+ if m0|m1|m2|m3 != 0 {
+ return firstSetLane32(i, m0, m1, m2, m3)
+ }
+ return -1
+ }
+ for ; i+8 <= n; i += 8 {
+ if m := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i:i+8]), 'A', 'Z'); m != 0 {
+ return i + swar.FirstLane(m)
+ }
+ }
+ if i == n {
+ return -1
+ }
+ if n >= 8 {
+ // Scan the tail with one overlapping word; lanes that were already
+ // scanned are known to be zero, so FirstLane lands in the new bytes.
+ if m := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[n-8:n]), 'A', 'Z'); m != 0 {
+ return n - 8 + swar.FirstLane(m)
+ }
+ return -1
+ }
+ for ; i < n; i++ {
+ if c := b[i]; c >= 'A' && c <= 'Z' {
+ return i
+ }
+ }
+ return -1
+}
+
+// FirstLowerIndex returns the index of the first ASCII lowercase byte in b,
+// or -1 if b contains none. b is only ever read; it may be an unsafe view
+// over immutable string memory.
+// firstSetLane32 resolves a hit inside a 32-byte block: given the block's
+// four per-word masks, it returns the index of the first marked byte
+// relative to base, the block's starting offset. It runs at most once per
+// scan — only after a block's combined mask tested non-zero — and is small
+// enough to inline, so the hot no-match loops pay nothing for the sharing.
+func firstSetLane32(base int, m0, m1, m2, m3 uint64) int {
+ if m0 != 0 {
+ return base + swar.FirstLane(m0)
+ }
+ if m1 != 0 {
+ return base + 8 + swar.FirstLane(m1)
+ }
+ if m2 != 0 {
+ return base + 16 + swar.FirstLane(m2)
+ }
+ return base + 24 + swar.FirstLane(m3)
+}
+
+func FirstLowerIndex(b []byte) int {
+ n := len(b)
+ i := 0
+ if n >= 32 {
+ // Structure and rationale mirror FirstUpperIndex.
+ if m := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[0:8]), 'a', 'z'); m != 0 {
+ return swar.FirstLane(m)
+ }
+ for i = 8; i+32 <= n; i += 32 {
+ m0 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i:i+8]), 'a', 'z')
+ m1 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+8:i+16]), 'a', 'z')
+ m2 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+16:i+24]), 'a', 'z')
+ m3 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+24:i+32]), 'a', 'z')
+ if m0|m1|m2|m3 != 0 {
+ return firstSetLane32(i, m0, m1, m2, m3)
+ }
+ }
+ if i == n {
+ return -1
+ }
+ i = n - 32
+ m0 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i:i+8]), 'a', 'z')
+ m1 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+8:i+16]), 'a', 'z')
+ m2 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+16:i+24]), 'a', 'z')
+ m3 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+24:i+32]), 'a', 'z')
+ if m0|m1|m2|m3 != 0 {
+ return firstSetLane32(i, m0, m1, m2, m3)
+ }
+ return -1
+ }
+ for ; i+8 <= n; i += 8 {
+ if m := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i:i+8]), 'a', 'z'); m != 0 {
+ return i + swar.FirstLane(m)
+ }
+ }
+ if i == n {
+ return -1
+ }
+ if n >= 8 {
+ if m := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[n-8:n]), 'a', 'z'); m != 0 {
+ return n - 8 + swar.FirstLane(m)
+ }
+ return -1
+ }
+ for ; i < n; i++ {
+ if c := b[i]; c >= 'a' && c <= 'z' {
+ return i
+ }
+ }
+ return -1
+}
+
+// ToLowerInPlace lower-cases every ASCII uppercase byte of b in place.
+func ToLowerInPlace(b []byte) {
+ n := len(b)
+ i := 0
+ for ; i+8 <= n; i += 8 {
+ binary.LittleEndian.PutUint64(b[i:i+8], swar.ToLowerWord(binary.LittleEndian.Uint64(b[i:i+8])))
+ }
+ // Finish byte-wise: an overlapping word here would partially overlap the
+ // previous 8-byte store and stall on store-to-load forwarding.
+ for ; i < n; i++ {
+ b[i] = ToLowerTable[b[i]]
+ }
+}
+
+// ToUpperInPlace upper-cases every ASCII lowercase byte of b in place.
+func ToUpperInPlace(b []byte) {
+ n := len(b)
+ i := 0
+ for ; i+8 <= n; i += 8 {
+ binary.LittleEndian.PutUint64(b[i:i+8], swar.ToUpperWord(binary.LittleEndian.Uint64(b[i:i+8])))
+ }
+ for ; i < n; i++ {
+ b[i] = ToUpperTable[b[i]]
+ }
+}
+
+// ToLowerCopy writes the lower-cased content of src into dst starting at
+// byte offset from. Bytes before from must already be present in dst, and
+// len(dst) must equal len(src). src is only ever read — the strings package
+// passes an unsafe view over a string's immutable backing memory — so no
+// code path here may write through src.
+//
+// from must be a multiple of WordLen and at or below the index of the first
+// byte that lower-casing changes: when len(src) >= WordLen the overlapping
+// tail store rewrites dst[n-WordLen:from) with case-converted bytes, which is
+// only a no-op under that precondition.
+//
+// Callers currently invoke this only with len(src) >= WordLen; the byte-wise
+// tail below keeps the helper correct standalone for shorter inputs.
+func ToLowerCopy(dst, src []byte, from int) {
+ n := len(src)
+ i := from
+ for ; i+8 <= n; i += 8 {
+ binary.LittleEndian.PutUint64(dst[i:i+8], swar.ToLowerWord(binary.LittleEndian.Uint64(src[i:i+8])))
+ }
+ if i == n {
+ return
+ }
+ if n >= 8 {
+ binary.LittleEndian.PutUint64(dst[n-8:n], swar.ToLowerWord(binary.LittleEndian.Uint64(src[n-8:n])))
+ return
+ }
+ for ; i < n; i++ {
+ dst[i] = ToLowerTable[src[i]]
+ }
+}
+
+// ToUpperCopy writes the upper-cased content of src into dst starting at
+// byte offset from. Bytes before from must already be present in dst, and
+// len(dst) must equal len(src).
+//
+// from must be a multiple of WordLen and at or below the index of the first
+// byte that upper-casing changes; see ToLowerCopy for why, including the
+// note on the byte-wise tail and the requirement that src is never written.
+func ToUpperCopy(dst, src []byte, from int) {
+ n := len(src)
+ i := from
+ for ; i+8 <= n; i += 8 {
+ binary.LittleEndian.PutUint64(dst[i:i+8], swar.ToUpperWord(binary.LittleEndian.Uint64(src[i:i+8])))
+ }
+ if i == n {
+ return
+ }
+ if n >= 8 {
+ binary.LittleEndian.PutUint64(dst[n-8:n], swar.ToUpperWord(binary.LittleEndian.Uint64(src[n-8:n])))
+ return
+ }
+ for ; i < n; i++ {
+ dst[i] = ToUpperTable[src[i]]
+ }
+}
diff --git a/src/vendor/github.com/gofiber/utils/v2/parse.go b/src/vendor/github.com/gofiber/utils/v2/parse.go
index e3f5e1d7..2df8ae7c 100644
--- a/src/vendor/github.com/gofiber/utils/v2/parse.go
+++ b/src/vendor/github.com/gofiber/utils/v2/parse.go
@@ -3,10 +3,11 @@ package utils
import (
"math"
"strconv"
+
+ "github.com/gofiber/utils/v2/swar"
)
const (
- maxFracDigits = 16
maxUint64Cutoff = math.MaxUint64 / 10
maxUint64Cutlim = math.MaxUint64 % 10
)
@@ -34,8 +35,24 @@ func ParseNativeUint[S byteSeq](s S) (uint, error) {
// Returns the parsed value and nil on success, else 0 and an error.
func ParseInt[S byteSeq](s S) (int64, error) {
if len(s) > 0 && s[0] != '-' && s[0] != '+' && len(s) <= 19 {
+ // At most 19 digits fit here, so two 8-digit SWAR steps plus a
+ // scalar remainder can never overflow before the final range check.
+ // A word with a non-digit lane falls through to the scalar loop,
+ // which reports the syntax error. The body deliberately duplicates
+ // the parseDigitsBig structure: routing through parseDigitsBig
+ // instead costs +22% on the 9-digit shape (benchstat -count=10,
+ // Go 1.25, Apple M2 Pro), mostly digit bookkeeping and the extra
+ // call frame.
var n uint64
- for i := range len(s) {
+ i := 0
+ for ; len(s)-i >= 8; i += 8 {
+ w := swar.Load8(s, i)
+ if !isEightDigits(w) {
+ break
+ }
+ n = n*100000000 + parse8Digits(w)
+ }
+ for ; i < len(s); i++ {
c := s[i] - '0'
if c > 9 {
return 0, &strconv.NumError{Func: "ParseInt", Num: string(s), Err: strconv.ErrSyntax}
@@ -146,11 +163,67 @@ func ParseUint8[S byteSeq](s S) (uint8, error) {
return parseUnsigned[S, uint8]("ParseUint8", s, uint8(math.MaxUint8))
}
-// parseDigits parses a sequence of digits and returns the uint64 value.
-// It returns an error if any non-digit is encountered or overflow happens.
+// isEightDigits reports whether every lane of w is an ASCII digit ('0'..'9').
+// High nibbles must all be 3 and low nibbles must not carry past 9 when 6 is
+// added. A lane >= 0xFA can carry into its neighbor's sum, but such a lane
+// already fails its own high-nibble test, so the answer stays exact.
+func isEightDigits(w uint64) bool {
+ const (
+ highNibbles = 0xF0F0F0F0F0F0F0F0
+ sixes = 0x0606060606060606
+ threes = 0x3333333333333333
+ )
+ return (w&highNibbles)|((w+sixes)&highNibbles)>>4 == threes
+}
+
+// parse8Digits converts a word of 8 ASCII digit bytes (first digit in lane 0,
+// most significant) to its numeric value using two pairwise multiply-combine
+// steps. The caller must have validated that every lane is '0'..'9'.
+func parse8Digits(w uint64) uint64 {
+ const (
+ digitZeros = 0x3030303030303030 // '0' in every lane
+ pairMask = 0x000000FF000000FF
+ mul1 = 100 + (1000000 << 32)
+ mul2 = 1 + (10000 << 32)
+ )
+ w -= digitZeros
+ w = w*10 + w>>8 // adjacent digit pairs -> 2-digit values in even lanes
+ return ((w&pairMask)*mul1 + (w>>16&pairMask)*mul2) >> 32
+}
+
+// parseDigits parses a run of fewer than 8 digits and returns the uint64
+// value, or an error on the first non-digit. Callers must route runs of 8+
+// bytes to parseDigitsBig — that is what makes overflow impossible here (at
+// most 7 digits) and keeps this body under the inlining budget.
func parseDigits[S byteSeq](s S, i int) (uint64, error) {
+ var n uint64
+ for ; i < len(s); i++ {
+ c := s[i] - '0'
+ if c > 9 {
+ return 0, strconv.ErrSyntax
+ }
+ n = n*10 + uint64(c)
+ }
+ return n, nil
+}
+
+// parseDigitsBig parses digit runs of 8+ bytes, consuming 8 digits per word
+// while the running value is guaranteed to still fit: two full steps reach 16
+// digits, and any value with <= 19 digits fits in uint64. A word with any
+// non-digit lane falls through to the scalar loop, which reports syntax
+// errors byte-precisely and applies the overflow checks.
+func parseDigitsBig[S byteSeq](s S, i int) (uint64, error) {
var n uint64
digits := 0
+ for len(s)-i >= 8 && digits+8 <= 19 {
+ w := swar.Load8(s, i)
+ if !isEightDigits(w) {
+ break
+ }
+ n = n*100000000 + parse8Digits(w)
+ digits += 8
+ i += 8
+ }
for ; i < len(s); i++ {
c := s[i] - '0'
if c > 9 {
@@ -187,8 +260,14 @@ func parseSigned[S byteSeq, T Signed](fn string, s S, minRange, maxRange T) (T,
return 0, &strconv.NumError{Func: fn, Num: string(s), Err: strconv.ErrSyntax}
}
- // Parse digits.
- n, err := parseDigits(s, i)
+ // Parse digits, taking the 8-digits-per-word path for long runs.
+ var n uint64
+ var err error
+ if len(s)-i >= 8 {
+ n, err = parseDigitsBig(s, i)
+ } else {
+ n, err = parseDigits(s, i)
+ }
if err != nil {
return 0, &strconv.NumError{Func: fn, Num: string(s), Err: err}
}
@@ -217,8 +296,15 @@ func parseUnsigned[S byteSeq, T Unsigned](fn string, s S, maxRange T) (T, error)
return 0, &strconv.NumError{Func: fn, Num: "", Err: strconv.ErrSyntax}
}
- // Parse digits directly from index 0.
- n, err := parseDigits(s, 0)
+ // Parse digits directly from index 0, taking the 8-digits-per-word path
+ // for long runs.
+ var n uint64
+ var err error
+ if len(s) >= 8 {
+ n, err = parseDigitsBig(s, 0)
+ } else {
+ n, err = parseDigits(s, 0)
+ }
if err != nil {
return 0, &strconv.NumError{Func: fn, Num: string(s), Err: err}
}
@@ -249,22 +335,26 @@ func parseFloat[S byteSeq](fn string, s S) (float64, error) {
return 0, &strconv.NumError{Func: fn, Num: string(s), Err: strconv.ErrSyntax}
}
- var intPart uint64
+ // Collect integer and fractional digits into a single mantissa and track
+ // the decimal exponent. Digits beyond uint64 precision are dropped: integer
+ // digits shift the exponent up, fractional digits are simply ignored.
+ var mantissa uint64
+ var exp10 int
+ digits := 0
for i < len(s) {
c := s[i] - '0'
if c > 9 {
break
}
- if intPart > maxUint64Cutoff || (intPart == maxUint64Cutoff && uint64(c) > maxUint64Cutlim) {
- return 0, &strconv.NumError{Func: fn, Num: string(s), Err: strconv.ErrRange}
+ if mantissa > maxUint64Cutoff || (mantissa == maxUint64Cutoff && uint64(c) > maxUint64Cutlim) {
+ exp10++
+ } else {
+ mantissa = mantissa*10 + uint64(c)
}
- intPart = intPart*10 + uint64(c)
+ digits++
i++
}
- var fracPart uint64
- var fracDiv uint64 = 1
- var fracDigits int
if i < len(s) && s[i] == '.' {
i++
for i < len(s) {
@@ -272,16 +362,19 @@ func parseFloat[S byteSeq](fn string, s S) (float64, error) {
if c > 9 {
break
}
- if fracDigits >= maxFracDigits {
- return 0, &strconv.NumError{Func: fn, Num: string(s), Err: strconv.ErrRange}
+ if mantissa < maxUint64Cutoff || (mantissa == maxUint64Cutoff && uint64(c) <= maxUint64Cutlim) {
+ mantissa = mantissa*10 + uint64(c)
+ exp10--
}
- fracPart = fracPart*10 + uint64(c)
- fracDiv *= 10
- fracDigits++
+ digits++
i++
}
}
+ if digits == 0 {
+ return 0, &strconv.NumError{Func: fn, Num: string(s), Err: strconv.ErrSyntax}
+ }
+
var expSign bool
var exp int64
if i < len(s) && (s[i] == 'e' || s[i] == 'E') {
@@ -299,17 +392,17 @@ func parseFloat[S byteSeq](fn string, s S) (float64, error) {
if i == len(s) {
return 0, &strconv.NumError{Func: fn, Num: string(s), Err: strconv.ErrSyntax}
}
+ // Saturate the parsed exponent far beyond anything exp10 (bounded by
+ // the input length) could pull back into range. Clamping to the final
+ // range must wait until both are combined below.
+ const maxParsedExp = int64(1) << 50
for i < len(s) {
c := s[i] - '0'
if c > 9 {
return 0, &strconv.NumError{Func: fn, Num: string(s), Err: strconv.ErrSyntax}
}
- exp = exp*10 + int64(c)
- if !expSign && exp > 308 {
- exp = 309
- }
- if expSign && exp > 324 {
- exp = 325
+ if exp < maxParsedExp {
+ exp = exp*10 + int64(c)
}
i++
}
@@ -321,12 +414,21 @@ func parseFloat[S byteSeq](fn string, s S) (float64, error) {
if expSign {
exp = -exp
}
-
- f := float64(intPart)
- if fracPart > 0 {
- f += float64(fracPart) / float64(fracDiv)
+ // Clamp the combined exponent to math.Pow10's saturation range so the
+ // int conversion below cannot wrap on 32-bit platforms for extremely
+ // long digit strings; larger magnitudes overflow (Inf, caught below) or
+ // underflow (Pow10 returns 0) anyway.
+ exp += int64(exp10)
+ if exp > 309 {
+ exp = 309
+ } else if exp < -325 {
+ exp = -325
}
- if exp != 0 {
+
+ f := float64(mantissa)
+ // Skip scaling for a zero mantissa: 0 * Pow10(309) would be 0 * Inf = NaN
+ // and turn inputs like "0e400" into a spurious range error.
+ if exp != 0 && f != 0 {
f *= math.Pow10(int(exp))
}
if neg {
diff --git a/src/vendor/github.com/gofiber/utils/v2/search.go b/src/vendor/github.com/gofiber/utils/v2/search.go
new file mode 100644
index 00000000..58df1e45
--- /dev/null
+++ b/src/vendor/github.com/gofiber/utils/v2/search.go
@@ -0,0 +1,321 @@
+package utils
+
+import (
+ "github.com/gofiber/utils/v2/internal/caseconv"
+ "github.com/gofiber/utils/v2/swar"
+)
+
+// Multi-needle and case-insensitive searching, built on swar.ZeroLanes
+// first-match masks with needle broadcasts hoisted out of the word loops.
+// IndexAny2/IndexAny3 scan words while i+8 <= n and finish 8+ byte inputs
+// with one overlapping word at n-8 (pure loads; already-scanned lanes are
+// known non-matching, so the first set lane falls in the new bytes).
+// IndexFold instead scans candidate start positions only up to n-k, so its
+// word loop hands the final partial word to a scalar remainder; the
+// overlapping-window trick appears there only inside the verify reads.
+// Inputs shorter than a word use scalar loops throughout.
+
+// IndexAny2 returns the index of the first occurrence in s of either a or b,
+// or -1 if neither is present.
+func IndexAny2[S byteSeq](s S, a, b byte) int {
+ n := len(s)
+ if n >= 8 {
+ // The needle broadcasts are hoisted here so sub-word inputs never
+ // pay for the multiplies.
+ bcA := swar.Broadcast(a)
+ bcB := swar.Broadcast(b)
+ i := 0
+ // Two words per branch: the masks compute independently, and if only
+ // the second word matched, its first set lane is still exact.
+ for ; i+16 <= n; i += 16 {
+ w0 := swar.Load8(s, i)
+ w1 := swar.Load8(s, i+8)
+ m0 := swar.ZeroLanes(w0^bcA) | swar.ZeroLanes(w0^bcB)
+ m1 := swar.ZeroLanes(w1^bcA) | swar.ZeroLanes(w1^bcB)
+ if m0|m1 != 0 {
+ if m0 != 0 {
+ return i + swar.FirstLane(m0)
+ }
+ return i + 8 + swar.FirstLane(m1)
+ }
+ }
+ for ; i+8 <= n; i += 8 {
+ w := swar.Load8(s, i)
+ if m := swar.ZeroLanes(w^bcA) | swar.ZeroLanes(w^bcB); m != 0 {
+ return i + swar.FirstLane(m)
+ }
+ }
+ if i == n {
+ return -1
+ }
+ w := swar.Load8(s, n-8)
+ if m := swar.ZeroLanes(w^bcA) | swar.ZeroLanes(w^bcB); m != 0 {
+ return n - 8 + swar.FirstLane(m)
+ }
+ return -1
+ }
+ for i := range n {
+ if s[i] == a || s[i] == b {
+ return i
+ }
+ }
+ return -1
+}
+
+// IndexAny3 returns the index of the first occurrence in s of a, b, or c,
+// or -1 if none is present.
+func IndexAny3[S byteSeq](s S, a, b, c byte) int {
+ n := len(s)
+ if n >= 8 {
+ bcA := swar.Broadcast(a)
+ bcB := swar.Broadcast(b)
+ bcC := swar.Broadcast(c)
+ i := 0
+ // Two words per branch; see IndexAny2.
+ for ; i+16 <= n; i += 16 {
+ w0 := swar.Load8(s, i)
+ w1 := swar.Load8(s, i+8)
+ m0 := swar.ZeroLanes(w0^bcA) | swar.ZeroLanes(w0^bcB) | swar.ZeroLanes(w0^bcC)
+ m1 := swar.ZeroLanes(w1^bcA) | swar.ZeroLanes(w1^bcB) | swar.ZeroLanes(w1^bcC)
+ if m0|m1 != 0 {
+ if m0 != 0 {
+ return i + swar.FirstLane(m0)
+ }
+ return i + 8 + swar.FirstLane(m1)
+ }
+ }
+ for ; i+8 <= n; i += 8 {
+ w := swar.Load8(s, i)
+ if m := swar.ZeroLanes(w^bcA) | swar.ZeroLanes(w^bcB) | swar.ZeroLanes(w^bcC); m != 0 {
+ return i + swar.FirstLane(m)
+ }
+ }
+ if i == n {
+ return -1
+ }
+ w := swar.Load8(s, n-8)
+ if m := swar.ZeroLanes(w^bcA) | swar.ZeroLanes(w^bcB) | swar.ZeroLanes(w^bcC); m != 0 {
+ return n - 8 + swar.FirstLane(m)
+ }
+ return -1
+ }
+ for i := range n {
+ if s[i] == a || s[i] == b || s[i] == c {
+ return i
+ }
+ }
+ return -1
+}
+
+// IndexFold returns the index of the first ASCII case-insensitive occurrence
+// of needle in s, or -1 if absent. An empty needle matches at index 0. Only
+// 'A'..'Z'/'a'..'z' fold; every other byte (including >= 0x80) must match
+// exactly, so e.g. "no\rcache" does NOT match the needle "no-cache".
+// The needle is a plain string by design: call sites pass constant tokens,
+// and a []byte needle would cost its callers a conversion either way.
+func IndexFold[S byteSeq](s S, needle string) int {
+ n, k := len(s), len(needle)
+ if k == 0 {
+ return 0
+ }
+ if k > n {
+ return -1
+ }
+
+ table := caseconv.ToLowerTable
+ first := table[needle[0]]
+ last := n - k // last valid start position
+
+ if n >= 8 {
+ // Scan candidate positions 8 at a time by matching the needle's
+ // first byte in both case variants (no need to fold the haystack),
+ // then verify each candidate. Approximate-mask false positives just
+ // cost a verify; the candidate order stays low-to-high, so the
+ // pos > last cutoff remains a valid global exit.
+ bc1 := swar.Broadcast(first)
+ bc2 := bc1
+ if first >= 'a' && first <= 'z' {
+ bc2 = swar.Broadcast(first - 0x20)
+ }
+
+ // For needles up to one word the verify is a single masked word
+ // compare against the folded needle, built lazily on the first
+ // candidate; longer needles fold-compare word-at-a-time. The lazy
+ // build is load-bearing: building eagerly costs the no-candidate
+ // path +44% on 8-byte misses and +13% to +17% on 32-64B misses
+ // (benchstat -count=10, Go 1.25, Apple M2 Pro). foldPrep keeps the
+ // pair computation in one place for both build sites below.
+ var fn foldedNeedle
+ built := false
+
+ i := 0
+ for ; i+8 <= n; i += 8 {
+ w := swar.Load8(s, i)
+ cand := swar.ZeroLanes(w^bc1) | swar.ZeroLanes(w^bc2)
+ for cand != 0 {
+ pos := i + swar.FirstLane(cand)
+ if pos > last {
+ return -1
+ }
+ if k <= 8 {
+ if !built {
+ fn = foldPrep(needle)
+ built = true
+ }
+ if foldedWindowAt(s, pos, fn.mask) == fn.word {
+ return pos
+ }
+ } else if foldEqualAt(s, pos, needle) {
+ return pos
+ }
+ cand &= cand - 1
+ }
+ }
+ // Candidate starts in the final partial word: positions [i, last].
+ // Here i is the word loop's exit index n - n%8, so this region is
+ // non-empty only when k <= n%8 <= 7 — the needle always fits in one
+ // word and only the short-needle verify can apply.
+ for ; i <= last; i++ {
+ if table[s[i]] == first {
+ if !built {
+ fn = foldPrep(needle)
+ built = true
+ }
+ if foldedWindowAt(s, i, fn.mask) == fn.word {
+ return i
+ }
+ }
+ }
+ return -1
+ }
+
+ // Scalar path: s shorter than a word (so k <= n < 8).
+outer:
+ for i := 0; i <= last; i++ {
+ if table[s[i]] != first {
+ continue
+ }
+ for j := 1; j < k; j++ {
+ if table[s[i+j]] != table[needle[j]] {
+ continue outer
+ }
+ }
+ return i
+ }
+ return -1
+}
+
+// foldedNeedle is the short-needle (k <= 8) verify state: the needle
+// lower-cased into one word plus the mask covering its lanes.
+type foldedNeedle struct {
+ word, mask uint64
+}
+
+// foldPrep builds the foldedNeedle pair; it exists so IndexFold's two lazy
+// build sites share one definition.
+func foldPrep(needle string) foldedNeedle {
+ return foldedNeedle{foldNeedle(needle), ^uint64(0) >> ((8 - len(needle)) * 8)}
+}
+
+// foldNeedle returns needle lower-cased into one little-endian word, lane 0
+// holding needle[0]. len(needle) must be 1..8; lanes past the needle are
+// zero, matching the ^uint64(0) >> ((8-k)*8) mask callers apply to windows.
+func foldNeedle(needle string) uint64 {
+ k := len(needle)
+ if k == 8 {
+ return swar.ToLowerWord(swar.Load8(needle, 0))
+ }
+ table := caseconv.ToLowerTable
+ var word uint64
+ for j := k - 1; j >= 0; j-- {
+ word = word<<8 | uint64(table[needle[j]])
+ }
+ return word
+}
+
+// foldedWindowAt returns the lower-cased window of s starting at pos, masked
+// to the needle length. Requires len(s) >= 8 and the window to fit in s;
+// windows running past len(s)-8 are read through one overlapping load at
+// len(s)-8 and shifted so lane 0 is s[pos].
+func foldedWindowAt[S byteSeq](s S, pos int, lenMask uint64) uint64 {
+ if pos+8 <= len(s) {
+ return swar.ToLowerWord(swar.Load8(s, pos)) & lenMask
+ }
+ from := len(s) - 8
+ w := swar.ToLowerWord(swar.Load8(s, from)) >> (8 * (pos - from))
+ return w & lenMask
+}
+
+// foldEqualAt reports whether s[pos:pos+len(needle)] equals needle ASCII
+// case-insensitively. len(needle) must be >= 8 and pos+len(needle) must be
+// within s; the tail is one overlapping word compare.
+func foldEqualAt[S byteSeq](s S, pos int, needle string) bool {
+ k := len(needle)
+ i := 0
+ for ; i+8 <= k; i += 8 {
+ if swar.ToLowerWord(swar.Load8(s, pos+i)) != swar.ToLowerWord(swar.Load8(needle, i)) {
+ return false
+ }
+ }
+ if i == k {
+ return true
+ }
+ return swar.ToLowerWord(swar.Load8(s, pos+k-8)) == swar.ToLowerWord(swar.Load8(needle, k-8))
+}
+
+// ContainsFold reports whether s contains needle, ASCII case-insensitively.
+func ContainsFold[S byteSeq](s S, needle string) bool {
+ return IndexFold(s, needle) >= 0
+}
+
+// HasPrefixFold reports whether s begins with prefix, ASCII
+// case-insensitively: only 'A'..'Z'/'a'..'z' fold, every other byte
+// (including >= 0x80) must match exactly, mirroring IndexFold. An empty
+// prefix matches any s. Like the other Fold helpers the needle is a plain
+// string, since call sites pass constant tokens.
+func HasPrefixFold[S byteSeq](s S, prefix string) bool {
+ k := len(prefix)
+ if len(s) < k {
+ return false
+ }
+ table := caseconv.ToLowerTable
+ if k >= 8 {
+ // First-byte pre-check: typical misses differ immediately, and two
+ // table loads reject them without the word-compare setup.
+ if table[s[0]] != table[prefix[0]] {
+ return false
+ }
+ return foldEqualAt(s, 0, prefix)
+ }
+ for j := range k {
+ if table[s[j]] != table[prefix[j]] {
+ return false
+ }
+ }
+ return true
+}
+
+// HasSuffixFold reports whether s ends with suffix, ASCII
+// case-insensitively, under the same folding contract as HasPrefixFold.
+// An empty suffix matches any s.
+func HasSuffixFold[S byteSeq](s S, suffix string) bool {
+ k := len(suffix)
+ n := len(s)
+ if n < k {
+ return false
+ }
+ table := caseconv.ToLowerTable
+ if k >= 8 {
+ // Pre-check the last byte; see HasPrefixFold.
+ if table[s[n-1]] != table[suffix[k-1]] {
+ return false
+ }
+ return foldEqualAt(s, n-k, suffix)
+ }
+ for j := range k {
+ if table[s[n-k+j]] != table[suffix[j]] {
+ return false
+ }
+ }
+ return true
+}
diff --git a/src/vendor/github.com/gofiber/utils/v2/strings/case.go b/src/vendor/github.com/gofiber/utils/v2/strings/case.go
index 59860553..c50654cb 100644
--- a/src/vendor/github.com/gofiber/utils/v2/strings/case.go
+++ b/src/vendor/github.com/gofiber/utils/v2/strings/case.go
@@ -5,66 +5,78 @@ import (
"github.com/gofiber/utils/v2/internal/unsafeconv"
)
+// swarMinLen is the smallest input length worth routing through the
+// word-at-a-time (SWAR) helpers; shorter inputs are cheaper byte-by-byte.
+const swarMinLen = caseconv.WordLen
+
// ToLower converts an ASCII string to lower-case without modifying the input.
func ToLower(s string) string {
n := len(s)
- if n == 0 {
+ if n < swarMinLen {
+ table := caseconv.ToLowerTable
+ for i := 0; i < n; i++ {
+ c := s[i]
+ low := table[c]
+ if low != c {
+ res := make([]byte, n)
+ copy(res, s[:i])
+ res[i] = low
+ for i++; i < n; i++ {
+ res[i] = table[s[i]]
+ }
+ return unsafeconv.UnsafeString(res)
+ }
+ }
return s
}
- table := caseconv.ToLowerTable
- for i := range n {
- c := s[i]
- low := table[c]
- if low != c {
- res := make([]byte, n)
- copy(res, s[:i])
- res[i] = low
- j := i + 1
- for ; j+3 < n; j += 4 {
- res[j+0] = table[s[j+0]]
- res[j+1] = table[s[j+1]]
- res[j+2] = table[s[j+2]]
- res[j+3] = table[s[j+3]]
- }
- for ; j < n; j++ {
- res[j] = table[s[j]]
- }
- return unsafeconv.UnsafeString(res)
- }
+ src := unsafeconv.UnsafeBytes(s)
+ i := caseconv.FirstUpperIndex(src)
+ if i < 0 {
+ return s
}
- return s
+
+ res := make([]byte, n)
+ // Copy the unchanged prefix up to the word containing the first
+ // uppercase byte, then convert the rest word-at-a-time.
+ from := i &^ (caseconv.WordLen - 1)
+ copy(res, src[:from])
+ caseconv.ToLowerCopy(res, src, from)
+ return unsafeconv.UnsafeString(res)
}
// ToUpper converts an ASCII string to upper-case without modifying the input.
func ToUpper(s string) string {
n := len(s)
- if n == 0 {
+ if n < swarMinLen {
+ table := caseconv.ToUpperTable
+ for i := 0; i < n; i++ {
+ c := s[i]
+ up := table[c]
+ if up != c {
+ res := make([]byte, n)
+ copy(res, s[:i])
+ res[i] = up
+ for i++; i < n; i++ {
+ res[i] = table[s[i]]
+ }
+ return unsafeconv.UnsafeString(res)
+ }
+ }
return s
}
- table := caseconv.ToUpperTable
- for i := range n {
- c := s[i]
- up := table[c]
- if up != c {
- res := make([]byte, n)
- copy(res, s[:i])
- res[i] = up
- j := i + 1
- for ; j+3 < n; j += 4 {
- res[j+0] = table[s[j+0]]
- res[j+1] = table[s[j+1]]
- res[j+2] = table[s[j+2]]
- res[j+3] = table[s[j+3]]
- }
- for ; j < n; j++ {
- res[j] = table[s[j]]
- }
- return unsafeconv.UnsafeString(res)
- }
+ src := unsafeconv.UnsafeBytes(s)
+ i := caseconv.FirstLowerIndex(src)
+ if i < 0 {
+ return s
}
- return s
+
+ res := make([]byte, n)
+ from := i &^ (caseconv.WordLen - 1)
+ copy(res, src[:from])
+ caseconv.ToUpperCopy(res, src, from)
+ return unsafeconv.UnsafeString(res)
}
// UnsafeToLower converts an ASCII string to lower-case by mutating its backing bytes in-place.
@@ -72,26 +84,14 @@ func ToUpper(s string) string {
// string is known to reference mutable memory.
func UnsafeToLower(s string) string {
b := unsafeconv.UnsafeBytes(s)
- table := caseconv.ToLowerTable
- n := len(b)
- i := 0
- limit := n &^ 3
- for i < limit {
- b0 := b[i+0]
- b1 := b[i+1]
- b2 := b[i+2]
- b3 := b[i+3]
-
- b[i+0] = table[b0]
- b[i+1] = table[b1]
- b[i+2] = table[b2]
- b[i+3] = table[b3]
- i += 4
- }
- for i < n {
- b[i] = table[b[i]]
- i++
+ if len(b) < swarMinLen {
+ table := caseconv.ToLowerTable
+ for i := range b {
+ b[i] = table[b[i]]
+ }
+ return s
}
+ caseconv.ToLowerInPlace(b)
return s
}
@@ -100,25 +100,13 @@ func UnsafeToLower(s string) string {
// string is known to reference mutable memory.
func UnsafeToUpper(s string) string {
b := unsafeconv.UnsafeBytes(s)
- table := caseconv.ToUpperTable
- n := len(b)
- i := 0
- limit := n &^ 3
- for i < limit {
- b0 := b[i+0]
- b1 := b[i+1]
- b2 := b[i+2]
- b3 := b[i+3]
-
- b[i+0] = table[b0]
- b[i+1] = table[b1]
- b[i+2] = table[b2]
- b[i+3] = table[b3]
- i += 4
- }
- for i < n {
- b[i] = table[b[i]]
- i++
+ if len(b) < swarMinLen {
+ table := caseconv.ToUpperTable
+ for i := range b {
+ b[i] = table[b[i]]
+ }
+ return s
}
+ caseconv.ToUpperInPlace(b)
return s
}
diff --git a/src/vendor/github.com/gofiber/utils/v2/swar/swar.go b/src/vendor/github.com/gofiber/utils/v2/swar/swar.go
new file mode 100644
index 00000000..6290a000
--- /dev/null
+++ b/src/vendor/github.com/gofiber/utils/v2/swar/swar.go
@@ -0,0 +1,146 @@
+// Package swar provides SWAR (SIMD within a register) primitives for
+// processing eight ASCII bytes per uint64 word. The building blocks here are
+// the ones the rest of gofiber/utils composes into case conversion,
+// multi-needle scanning, and validation loops, and they are exported so that
+// downstream packages (fiber itself, middleware) can fuse their own scans —
+// e.g. finding a delimiter while simultaneously classifying the bytes before
+// it — without re-deriving the bit tricks.
+//
+// Every operation yields per-lane results (exactly for the Match* masks,
+// approximately for ZeroLanes, whose contract allows false positives above
+// the first hit), so results are identical on little- and big-endian
+// platforms. Load8 and Store8 always use little-endian lane order: lane 0
+// (the least significant byte) is the lowest byte index, which is what
+// FirstLane and LastLane assume. The empty-mask sentinels differ on
+// purpose: FirstLane(0) == 8 lets forward scans step past the current word
+// arithmetically, while LastLane(0) == -1 is the conventional not-found
+// result for reverse scans.
+//
+// No unsafe is used anywhere in this package.
+package swar
+
+import (
+ "math/bits"
+)
+
+const (
+ // WordLen is the SWAR word width in bytes. Word loops should iterate
+ // while i+WordLen <= len(s) and route shorter inputs to scalar code.
+ WordLen = 8
+
+ // Ones has 0x01 in every byte lane.
+ Ones = 0x0101010101010101
+ // HighBits has 0x80 in every byte lane; w&HighBits != 0 iff some byte
+ // has its high bit set, and Match* masks equal HighBits iff every lane
+ // matched.
+ HighBits = 0x8080808080808080
+ // LowSeven has 0x7F in every byte lane.
+ LowSeven = 0x7f7f7f7f7f7f7f7f
+)
+
+// Load8 assembles s[i:i+8] into a little-endian uint64: s[i] becomes the
+// least significant byte (lane 0). The caller must guarantee i+8 <= len(s);
+// the reslice below turns a violation into a bounds panic. The 8-byte
+// reslice pins the length so the constant-index reads are bounds-check free,
+// and the compiler fuses them into a single 8-byte load on little-endian
+// targets (verified for both the string and []byte instantiations).
+func Load8[S ~string | ~[]byte](s S, i int) uint64 {
+ w := s[i : i+8]
+ return uint64(w[0]) |
+ uint64(w[1])<<8 |
+ uint64(w[2])<<16 |
+ uint64(w[3])<<24 |
+ uint64(w[4])<<32 |
+ uint64(w[5])<<40 |
+ uint64(w[6])<<48 |
+ uint64(w[7])<<56
+}
+
+// Store8 writes w into b[i:i+8] in Load8's lane order: lane 0 (the least
+// significant byte) lands at the lowest byte index, so a Load8/Store8 round
+// trip is the identity. The caller must guarantee i+8 <= len(b); the
+// reslice below turns a violation into a bounds panic. Like Load8, the
+// constant-index writes are bounds-check free and fuse into a single 8-byte
+// store on little-endian targets.
+func Store8(b []byte, i int, w uint64) {
+ d := b[i : i+8]
+ d[0] = byte(w)
+ d[1] = byte(w >> 8)
+ d[2] = byte(w >> 16)
+ d[3] = byte(w >> 24)
+ d[4] = byte(w >> 32)
+ d[5] = byte(w >> 40)
+ d[6] = byte(w >> 48)
+ d[7] = byte(w >> 56)
+}
+
+// Broadcast returns a word with c in every byte lane, the needle form that
+// ZeroLanes scans consume. Hoist the result out of word loops; it compiles
+// to a single multiply.
+func Broadcast(c byte) uint64 {
+ return uint64(c) * Ones
+}
+
+// ToLowerWord lower-cases every 'A'..'Z' lane in w. All other bytes,
+// including those >= 0x80, pass through unchanged — bit-identical to the
+// ASCII case-conversion tables used elsewhere in this module.
+func ToLowerWord(w uint64) uint64 {
+ return w | MatchRangeMask(w, 'A', 'Z')>>2 // 0x80>>2 == 0x20: set bit 5
+}
+
+// ToUpperWord upper-cases every 'a'..'z' lane in w. All other bytes,
+// including those >= 0x80, pass through unchanged.
+func ToUpperWord(w uint64) uint64 {
+ return w &^ (MatchRangeMask(w, 'a', 'z') >> 2) // clear bit 5 on matched lanes
+}
+
+// ZeroLanes returns a mask whose lowest set lane is the lowest zero-byte
+// lane of x; higher lanes may carry false positives (borrows propagate
+// strictly upward from true zero lanes), and the mask is zero iff x has no
+// zero byte. It is two ops cheaper than MatchByteMask, which makes it the
+// right primitive for first-match scans, typically as
+// ZeroLanes(w ^ Broadcast(c)) with the broadcast hoisted out of the word
+// loop. Use MatchByteMask when every lane must be exact.
+func ZeroLanes(x uint64) uint64 {
+ return (x - Ones) &^ x & HighBits
+}
+
+// MatchByteMask returns a word with 0x80 set in exactly the lanes of w whose
+// byte equals c, and zero in all other lanes. The result is per-lane exact
+// (no false positives in lanes above a match), so it is safe to feed to
+// LastLane or to arbitrary lane masking, not just first-match scans; for
+// pure first-match scanning ZeroLanes is cheaper.
+func MatchByteMask(w uint64, c byte) uint64 {
+ x := w ^ (uint64(c) * Ones)
+ // Setting the high bit before the per-lane subtraction keeps every lane
+ // >= 0x80, so borrows cannot cross lanes and the test stays exact:
+ // after the subtraction the high bit is clear only where the lane was 0,
+ // and OR-ing x back in rejects lanes that had their own high bit set.
+ return ^(((x | HighBits) - Ones) | x) & HighBits
+}
+
+// MatchRangeMask returns a word with 0x80 set in exactly the lanes of w
+// whose byte is within [lo, hi]. It requires lo <= hi <= 0x7F; lanes with
+// the high bit set (bytes >= 0x80) never match.
+func MatchRangeMask(w uint64, lo, hi byte) uint64 {
+ b := w & LowSeven
+ // After masking, every lane is <= 0x7F, so the biased additions below
+ // cannot carry into a neighboring lane.
+ ge := b + (0x80-uint64(lo))*Ones // high bit set where lane >= lo
+ gt := b + (0x80-uint64(hi)-1)*Ones // high bit set where lane > hi
+ return ge &^ gt &^ w & HighBits
+}
+
+// FirstLane returns the index (0..7) of the lowest-addressed set lane in
+// mask — the smallest byte index, given Load8's lane order — or 8 if mask
+// is zero. mask must contain only 0x80 lane markers, as produced by the
+// Match* functions.
+func FirstLane(mask uint64) int {
+ return bits.TrailingZeros64(mask) >> 3
+}
+
+// LastLane returns the index (0..7) of the highest-addressed set lane in
+// mask, or -1 if mask is zero. mask must contain only 0x80 lane markers.
+func LastLane(mask uint64) int {
+ return (63 - bits.LeadingZeros64(mask)) >> 3
+}
diff --git a/src/vendor/github.com/gofiber/utils/v2/time.go b/src/vendor/github.com/gofiber/utils/v2/time.go
index 394a23c8..91b970af 100644
--- a/src/vendor/github.com/gofiber/utils/v2/time.go
+++ b/src/vendor/github.com/gofiber/utils/v2/time.go
@@ -8,7 +8,7 @@ import (
var (
timestamp atomic.Uint32
- updaterOnce sync.Once
+ updaterMu sync.Mutex
stopUpdater chan struct{}
updaterDone chan struct{}
)
@@ -20,39 +20,46 @@ func Timestamp() uint32 {
}
// StartTimeStampUpdater launches a background goroutine that updates the cached timestamp every second.
-// It is safe to call multiple times; only the first call will start the updater.
+// It is safe to call multiple times and from multiple goroutines; only one updater runs at a time.
func StartTimeStampUpdater() {
- updaterOnce.Do(func() {
- timestamp.Store(uint32(time.Now().Unix()))
- stopUpdater = make(chan struct{})
- updaterDone = make(chan struct{})
-
- go func() {
- ticker := time.NewTicker(time.Second)
- defer ticker.Stop()
- defer close(updaterDone)
-
- for {
- select {
- case <-ticker.C:
- timestamp.Store(uint32(time.Now().Unix()))
- case <-stopUpdater:
- return
- }
+ updaterMu.Lock()
+ defer updaterMu.Unlock()
+ if stopUpdater != nil {
+ return
+ }
+
+ timestamp.Store(uint32(time.Now().Unix()))
+ stopUpdater = make(chan struct{})
+ updaterDone = make(chan struct{})
+
+ go func(stop, done chan struct{}) {
+ ticker := time.NewTicker(time.Second)
+ defer ticker.Stop()
+ defer close(done)
+
+ for {
+ select {
+ case <-ticker.C:
+ timestamp.Store(uint32(time.Now().Unix()))
+ case <-stop:
+ return
}
- }()
- })
+ }
+ }(stopUpdater, updaterDone)
}
// StopTimeStampUpdater stops the background updater goroutine.
// Call this on app shutdown to avoid leaking goroutines.
+// It is safe to call multiple times and from multiple goroutines.
func StopTimeStampUpdater() {
- if stopUpdater != nil {
- close(stopUpdater)
- <-updaterDone
- // Reset the sync.Once so StartTimeStampUpdater can be called again
- updaterOnce = sync.Once{}
- stopUpdater = nil
- updaterDone = nil
+ updaterMu.Lock()
+ defer updaterMu.Unlock()
+ if stopUpdater == nil {
+ return
}
+
+ close(stopUpdater)
+ <-updaterDone
+ stopUpdater = nil
+ updaterDone = nil
}
diff --git a/src/vendor/github.com/klauspost/compress/README.md b/src/vendor/github.com/klauspost/compress/README.md
index fb023f2c..0e9f170d 100644
--- a/src/vendor/github.com/klauspost/compress/README.md
+++ b/src/vendor/github.com/klauspost/compress/README.md
@@ -27,6 +27,18 @@ Use the links above for more information on each.
# changelog
+* Jul 1st, 2026 [1.19.0](https://github.com/klauspost/compress/releases/tag/v1.19.0)
+ * zstd: Add true concurrent stream encodingin https://github.com/klauspost/compress/pull/1136
+ * zstd: arm64 decoder asm by @lizthegrey in https://github.com/klauspost/compress/pull/1160
+ * flate: Add inflate checkpoints in https://github.com/klauspost/compress/pull/1154
+ * zstd: avoid unused BuildDict encoder allocation by @snissn in https://github.com/klauspost/compress/pull/1147
+ * snappy/s2: Limit length of varint in `decodedLen` by @eustas in https://github.com/klauspost/compress/pull/1148
+ * gzhttp: match qvalue parameter case-insensitively (RFC 7231) by @z9z in https://github.com/klauspost/compress/pull/1149
+ * zip: add NameDecoder callback for legacy encoding rewrite by @SAY-5 in https://github.com/klauspost/compress/pull/1150
+ * huff0: Allow building tables from histogram in https://github.com/klauspost/compress/pull/1155
+ * huff0: Allow building table from oversized histogram in https://github.com/klauspost/compress/pull/1156
+ * s2sx: Clean symlink targets in https://github.com/klauspost/compress/pull/1163
+
* Feb 9th, 2026 [1.18.4](https://github.com/klauspost/compress/releases/tag/v1.18.4)
* gzhttp: Add zstandard to server handler wrapper https://github.com/klauspost/compress/pull/1121
* zstd: Add ResetWithOptions to encoder/decoder https://github.com/klauspost/compress/pull/1122
diff --git a/src/vendor/github.com/klauspost/compress/flate/inflate_gen.go b/src/vendor/github.com/klauspost/compress/flate/inflate_gen.go
index 2b2f993f..e80f1965 100644
--- a/src/vendor/github.com/klauspost/compress/flate/inflate_gen.go
+++ b/src/vendor/github.com/klauspost/compress/flate/inflate_gen.go
@@ -10,6 +10,15 @@ import (
"strings"
)
+func peekBufio(fr *bufio.Reader) ([]byte, error) {
+ if fr.Buffered() == 0 {
+ if _, err := fr.Peek(1); err != nil && fr.Buffered() == 0 {
+ return nil, err
+ }
+ }
+ return fr.Peek(fr.Buffered())
+}
+
// Decode a single Huffman block from f.
// hl and hd are the Huffman states for the lit/length values
// and the distance values, respectively. If hd == nil, using the
@@ -527,6 +536,8 @@ func (f *decompressor) huffmanBufioReader() {
// but is smart enough to keep local variables in registers, so use nb and b,
// inline call to moreBits and reassign b,nb back to f on return.
fnb, fb, dict := f.nb, f.b, &f.dict
+ pbuf, _ := fr.Peek(fr.Buffered())
+ pos := 0
switch f.stepState {
case stateInit:
@@ -548,12 +559,19 @@ readLiteral:
n := uint(f.hl.maxRead)
for {
for fnb < n {
- c, err := fr.ReadByte()
- if err != nil {
- f.b, f.nb = fb, fnb
- f.err = noEOF(err)
- return
+ if pos >= len(pbuf) {
+ fr.Discard(pos)
+ var err error
+ pbuf, err = peekBufio(fr)
+ pos = 0
+ if len(pbuf) == 0 {
+ f.b, f.nb = fb, fnb
+ f.err = noEOF(err)
+ return
+ }
}
+ c := pbuf[pos]
+ pos++
f.roffset++
fb |= uint32(c) << (fnb & regSizeMaskUint32)
fnb += 8
@@ -566,6 +584,7 @@ readLiteral:
}
if n <= fnb {
if n == 0 {
+ fr.Discard(pos)
f.b, f.nb = fb, fnb
if debugDecode {
fmt.Println("huffsym: n==0")
@@ -586,6 +605,7 @@ readLiteral:
case v < 256:
dict.writeByte(byte(v))
if dict.availWrite() == 0 {
+ fr.Discard(pos)
f.toRead = dict.readFlush()
f.step = huffmanBufioReader
f.stepState = stateInit
@@ -594,6 +614,7 @@ readLiteral:
}
goto readLiteral
case v == 256:
+ fr.Discard(pos)
f.b, f.nb = fb, fnb
f.finishBlock()
return
@@ -605,15 +626,22 @@ readLiteral:
length = int(val.length) + 3
n := uint(val.extra)
for fnb < n {
- c, err := fr.ReadByte()
- if err != nil {
- f.b, f.nb = fb, fnb
- if debugDecode {
- fmt.Println("morebits n>0:", err)
+ if pos >= len(pbuf) {
+ fr.Discard(pos)
+ var err error
+ pbuf, err = peekBufio(fr)
+ pos = 0
+ if len(pbuf) == 0 {
+ f.b, f.nb = fb, fnb
+ if debugDecode {
+ fmt.Println("morebits n>0:", err)
+ }
+ f.err = err
+ return
}
- f.err = err
- return
}
+ c := pbuf[pos]
+ pos++
f.roffset++
fb |= uint32(c) << (fnb & regSizeMaskUint32)
fnb += 8
@@ -622,6 +650,7 @@ readLiteral:
fb >>= n & regSizeMaskUint32
fnb -= n
default:
+ fr.Discard(pos)
if debugDecode {
fmt.Println(v, ">= maxNumLit")
}
@@ -633,15 +662,22 @@ readLiteral:
var dist uint32
if f.hd == nil {
for fnb < 5 {
- c, err := fr.ReadByte()
- if err != nil {
- f.b, f.nb = fb, fnb
- if debugDecode {
- fmt.Println("morebits f.nb<5:", err)
+ if pos >= len(pbuf) {
+ fr.Discard(pos)
+ var err error
+ pbuf, err = peekBufio(fr)
+ pos = 0
+ if len(pbuf) == 0 {
+ f.b, f.nb = fb, fnb
+ if debugDecode {
+ fmt.Println("morebits f.nb<5:", err)
+ }
+ f.err = err
+ return
}
- f.err = err
- return
}
+ c := pbuf[pos]
+ pos++
f.roffset++
fb |= uint32(c) << (fnb & regSizeMaskUint32)
fnb += 8
@@ -660,12 +696,19 @@ readLiteral:
// inline call to moreBits and reassign b,nb back to f on return.
for {
for fnb < n {
- c, err := fr.ReadByte()
- if err != nil {
- f.b, f.nb = fb, fnb
- f.err = noEOF(err)
- return
+ if pos >= len(pbuf) {
+ fr.Discard(pos)
+ var err error
+ pbuf, err = peekBufio(fr)
+ pos = 0
+ if len(pbuf) == 0 {
+ f.b, f.nb = fb, fnb
+ f.err = noEOF(err)
+ return
+ }
}
+ c := pbuf[pos]
+ pos++
f.roffset++
fb |= uint32(c) << (fnb & regSizeMaskUint32)
fnb += 8
@@ -678,6 +721,7 @@ readLiteral:
}
if n <= fnb {
if n == 0 {
+ fr.Discard(pos)
f.b, f.nb = fb, fnb
if debugDecode {
fmt.Println("huffsym: n==0")
@@ -701,15 +745,22 @@ readLiteral:
// have 1 bit in bottom of dist, need nb more.
extra := (dist & 1) << (nb & regSizeMaskUint32)
for fnb < nb {
- c, err := fr.ReadByte()
- if err != nil {
- f.b, f.nb = fb, fnb
- if debugDecode {
- fmt.Println("morebits f.nb= len(pbuf) {
+ fr.Discard(pos)
+ var err error
+ pbuf, err = peekBufio(fr)
+ pos = 0
+ if len(pbuf) == 0 {
+ f.b, f.nb = fb, fnb
+ if debugDecode {
+ fmt.Println("morebits f.nb uint32(dict.histSize()) {
+ fr.Discard(pos)
f.b, f.nb = fb, fnb
if debugDecode {
fmt.Println("dist > dict.histSize():", dist, dict.histSize())
@@ -752,6 +805,7 @@ copyHistory:
f.copyLen -= cnt
if dict.availWrite() == 0 || f.copyLen > 0 {
+ fr.Discard(pos)
f.toRead = dict.readFlush()
f.step = huffmanBufioReader // We need to continue this work
f.stepState = stateDict
diff --git a/src/vendor/github.com/klauspost/compress/s2/encode_all.go b/src/vendor/github.com/klauspost/compress/s2/encode_all.go
index 9d12c44f..794ec8a6 100644
--- a/src/vendor/github.com/klauspost/compress/s2/encode_all.go
+++ b/src/vendor/github.com/klauspost/compress/s2/encode_all.go
@@ -981,7 +981,7 @@ searchDict:
cv = load64(src, s)
continue
}
- } else if uint32(cv>>(checkRep*8)) == load32(src, s-repeat+checkRep) {
+ } else if repeat > 0 && uint32(cv>>(checkRep*8)) == load32(src, s-repeat+checkRep) {
base := s + checkRep
// Extend back
for i := base - repeat; base > nextEmit && i > 0 && src[i-1] == src[base-1]; {
diff --git a/src/vendor/github.com/klauspost/compress/s2/reader.go b/src/vendor/github.com/klauspost/compress/s2/reader.go
index 4d01c419..17443e2c 100644
--- a/src/vendor/github.com/klauspost/compress/s2/reader.go
+++ b/src/vendor/github.com/klauspost/compress/s2/reader.go
@@ -216,13 +216,18 @@ func (r *Reader) skippable(tmp []byte, n int, allowEOF bool, id uint8) (ok bool)
return r.err == nil
}
if rs, ok := r.r.(io.ReadSeeker); ok {
- _, err := rs.Seek(int64(n), io.SeekCurrent)
- if err == nil {
- return true
- }
- if err == io.ErrUnexpectedEOF || (r.err == io.EOF && !allowEOF) {
- r.err = ErrCorrupt
- return false
+ if cur, err := rs.Seek(0, io.SeekCurrent); err == nil {
+ if end, err := rs.Seek(0, io.SeekEnd); err == nil {
+ if cur+int64(n) <= end {
+ if _, err := rs.Seek(cur+int64(n), io.SeekStart); err == nil {
+ return true
+ }
+ }
+ if _, err := rs.Seek(cur, io.SeekStart); err != nil {
+ r.err = ErrCorrupt
+ return false
+ }
+ }
}
}
for n > 0 {
diff --git a/src/vendor/github.com/klauspost/compress/zstd/fse_decoder_arm64.s b/src/vendor/github.com/klauspost/compress/zstd/fse_decoder_arm64.s
index 661761fb..77ee3913 100644
--- a/src/vendor/github.com/klauspost/compress/zstd/fse_decoder_arm64.s
+++ b/src/vendor/github.com/klauspost/compress/zstd/fse_decoder_arm64.s
@@ -28,7 +28,10 @@ TEXT ·buildDtable_asm(SB), $0-24
init_main_loop:
ADD R8<<1, R1, R15
MOVH (R15), R9
- CMN $1, R9
+ AND $0xffff, R9, R15
+ MOVD $-1, R16
+ AND $0xffff, R16, R16
+ CMP R16, R15
BNE do_not_update_high_threshold
ADD R7<<3, R5, R15
MOVB R8, 1(R15)
@@ -126,9 +129,13 @@ build_table_main_table:
RET
build_table_check1_ok:
- TST R1, R1
+ AND $0xff, R1, R15
+ AND $0xff, R1, R16
+ TST R16, R15
BNE build_table_check2_ok
- CMP R6, R7
+ AND $0xffff, R7, R15
+ AND $0xffff, R6, R16
+ CMP R16, R15
BNE build_table_check2_ok
MOVD ctx+8(FP), R0
MOVD R7, 24(R0)
diff --git a/src/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.s b/src/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.s
index 75b19d73..a468e5fc 100644
--- a/src/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.s
+++ b/src/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.s
@@ -670,9 +670,9 @@ error_overread:
MOVD R16, ret+24(FP)
RET
-// skipped sequenceDecs_decode_bmi2 (BMI2 not available on arm64)
+// skipped sequenceDecs_decode_bmi2 (generic twin preferred on arm64)
-// skipped sequenceDecs_decode_56_bmi2 (BMI2 not available on arm64)
+// skipped sequenceDecs_decode_56_bmi2 (generic twin preferred on arm64)
// func sequenceDecs_executeSimple_amd64(ctx *executeAsmContext) bool
// Requires: SSE
@@ -1966,7 +1966,7 @@ error_not_enough_space:
MOVD R16, ret+24(FP)
RET
-// skipped sequenceDecs_decodeSync_bmi2 (BMI2 not available on arm64)
+// skipped sequenceDecs_decodeSync_bmi2 (generic twin preferred on arm64)
// func sequenceDecs_decodeSync_safe_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int
// Requires: CMOV, SSE
@@ -2702,4 +2702,4 @@ error_not_enough_space:
MOVD R16, ret+24(FP)
RET
-// skipped sequenceDecs_decodeSync_safe_bmi2 (BMI2 not available on arm64)
+// skipped sequenceDecs_decodeSync_safe_bmi2 (generic twin preferred on arm64)
diff --git a/src/vendor/github.com/klauspost/compress/zstd/snappy.go b/src/vendor/github.com/klauspost/compress/zstd/snappy.go
index 336c2889..36c56f36 100644
--- a/src/vendor/github.com/klauspost/compress/zstd/snappy.go
+++ b/src/vendor/github.com/klauspost/compress/zstd/snappy.go
@@ -334,9 +334,10 @@ func decodeSnappy(blk *blockEnc, src []byte) error {
return errUnsupportedLiteralLength
}
- //if length > snappyMaxBlockSize-d || uint32(length) > len(src)-s {
- // return ErrSnappyCorrupt
- //}
+ if length > len(src)-s {
+ println("length > len(src)-s", length, len(src)-s)
+ return ErrSnappyCorrupt
+ }
blk.literals = append(blk.literals, src[s:s+length]...)
//println(length, "litLen")
diff --git a/src/vendor/github.com/mattn/go-isatty/isatty_others.go b/src/vendor/github.com/mattn/go-isatty/isatty_others.go
index b24a2fad..569113ea 100644
--- a/src/vendor/github.com/mattn/go-isatty/isatty_others.go
+++ b/src/vendor/github.com/mattn/go-isatty/isatty_others.go
@@ -1,5 +1,5 @@
-//go:build (appengine || js || nacl || tinygo || wasm || wasip1 || wasip2) && !windows
-// +build appengine js nacl tinygo wasm wasip1 wasip2
+//go:build (appengine || js || nacl || tinygo || wasm || wasip1 || wasip2 || haiku) && !windows
+// +build appengine js nacl tinygo wasm wasip1 wasip2 haiku
// +build !windows
package isatty
diff --git a/src/vendor/github.com/valyala/fasthttp/coarseTime.go b/src/vendor/github.com/valyala/fasthttp/coarsetime.go
similarity index 100%
rename from src/vendor/github.com/valyala/fasthttp/coarseTime.go
rename to src/vendor/github.com/valyala/fasthttp/coarsetime.go
diff --git a/src/vendor/golang.org/x/crypto/acme/autocert/autocert.go b/src/vendor/golang.org/x/crypto/acme/autocert/autocert.go
index 69461e31..bee6de9c 100644
--- a/src/vendor/golang.org/x/crypto/acme/autocert/autocert.go
+++ b/src/vendor/golang.org/x/crypto/acme/autocert/autocert.go
@@ -564,24 +564,21 @@ func encodeECDSAKey(w io.Writer, key *ecdsa.PrivateKey) error {
// If the domain is already being verified, it waits for the existing verification to complete.
// Either way, createCert blocks for the duration of the whole process.
func (m *Manager) createCert(ctx context.Context, ck certKey) (*tls.Certificate, error) {
- // TODO: maybe rewrite this whole piece using sync.Once
- state, err := m.certState(ck)
+ state, owner, err := m.certState(ck)
if err != nil {
return nil, err
}
- // state may exist if another goroutine is already working on it
- // in which case just wait for it to finish
- if !state.locked {
+ // If another goroutine is already working on this state, wait for it
+ // to finish by taking the read lock
+ if !owner {
state.RLock()
defer state.RUnlock()
return state.tlscert()
}
- // We are the first; state is locked.
- // Unblock the readers when domain ownership is verified
- // and we got the cert or the process failed.
+ // We are the first to work on this certKey, so state is write-locked.
+ // Unblock the readers when our work is complete.
defer state.Unlock()
- state.locked = false
der, leaf, err := m.authorizedCert(ctx, state.key, ck)
if err != nil {
@@ -611,10 +608,15 @@ func (m *Manager) createCert(ctx context.Context, ck certKey) (*tls.Certificate,
return state.tlscert()
}
-// certState returns a new or existing certState.
-// If a new certState is returned, state.exist is false and the state is locked.
+// certState returns a new or existing certState along with a boolean
+// indicating whether the caller is the owner of the state.
+//
+// The owner of the state is responsible for performing the ACME work and
+// must unlock the state's write lock when done. Non-owner callers should
+// wait on the state's read lock for the owner to finish.
+//
// The returned error is non-nil only in the case where a new state could not be created.
-func (m *Manager) certState(ck certKey) (*certState, error) {
+func (m *Manager) certState(ck certKey) (*certState, bool, error) {
m.stateMu.Lock()
defer m.stateMu.Unlock()
if m.state == nil {
@@ -622,7 +624,7 @@ func (m *Manager) certState(ck certKey) (*certState, error) {
}
// existing state
if state, ok := m.state[ck]; ok {
- return state, nil
+ return state, false, nil
}
// new locked state
@@ -636,16 +638,13 @@ func (m *Manager) certState(ck certKey) (*certState, error) {
key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
}
if err != nil {
- return nil, err
+ return nil, false, err
}
- state := &certState{
- key: key,
- locked: true,
- }
+ state := &certState{key: key}
state.Lock() // will be unlocked by m.certState caller
m.state[ck] = state
- return state, nil
+ return state, true, nil
}
// authorizedCert starts the domain ownership verification process and requests a new cert upon success.
@@ -1035,10 +1034,9 @@ func (m *Manager) now() time.Time {
// certState is ready when its mutex is unlocked for reading.
type certState struct {
sync.RWMutex
- locked bool // locked for read/write
- key crypto.Signer // private key for cert
- cert [][]byte // DER encoding
- leaf *x509.Certificate // parsed cert[0]; always non-nil if cert != nil
+ key crypto.Signer // private key for cert
+ cert [][]byte // DER encoding
+ leaf *x509.Certificate // parsed cert[0]; always non-nil if cert != nil
}
// tlscert creates a tls.Certificate from s.key and s.cert.
diff --git a/src/vendor/golang.org/x/crypto/argon2/argon2.go b/src/vendor/golang.org/x/crypto/argon2/argon2.go
index 2b65ec91..57ab8371 100644
--- a/src/vendor/golang.org/x/crypto/argon2/argon2.go
+++ b/src/vendor/golang.org/x/crypto/argon2/argon2.go
@@ -17,8 +17,8 @@
// It uses data-independent memory access, which is preferred for password
// hashing and password-based key derivation. Argon2i requires more passes over
// memory than Argon2id to protect from trade-off attacks. The recommended
-// parameters (taken from [RFC 9106 Section 7.3]) for non-interactive operations are time=3 and to
-// use the maximum available memory.
+// parameters (taken from [RFC 9106 Section 7.3]) for non-interactive
+// operations are time=3 and to use the maximum available memory.
//
// # Argon2id
//
@@ -26,11 +26,14 @@
// Argon2i and Argon2d. It uses data-independent memory access for the first
// half of the first iteration over the memory and data-dependent memory access
// for the rest. Argon2id is side-channel resistant and provides better brute-
-// force cost savings due to time-memory tradeoffs than Argon2i. The recommended
-// parameters for non-interactive operations (taken from [RFC 9106 Section 7.3]) are time=1 and to
-// use the maximum available memory.
+// force cost savings due to time-memory tradeoffs than Argon2i. [RFC 9106
+// Section 4] recommends time=1, memory=2*1024*1024 KiB (2 GiB), and threads=4
+// as the first recommended option. If much less memory is available, it
+// recommends time=3, memory=64*1024 KiB (64 MiB), and threads=4 as the second
+// recommended option.
//
// [argon2-specs.pdf]: https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf
+// [RFC 9106 Section 4]: https://www.rfc-editor.org/rfc/rfc9106.html#section-4
// [RFC 9106 Section 7.3]: https://www.rfc-editor.org/rfc/rfc9106.html#section-7.3
package argon2
@@ -59,9 +62,9 @@ const (
//
// key := argon2.Key([]byte("some password"), salt, 3, 32*1024, 4, 32)
//
-// [RFC 9106 Section 7.3] recommends time=3, and memory=32*1024 as a sensible number.
-// If using that amount of memory (32 MB) is not possible in some contexts then
-// the time parameter can be increased to compensate.
+// The example above uses time=3 and memory=32*1024. Argon2i generally
+// requires more passes over memory than Argon2id. If in doubt, prefer IDKey
+// and its Argon2id parameter recommendations.
//
// The time parameter specifies the number of passes over the memory and the
// memory parameter specifies the size of the memory in KiB. For example
@@ -69,8 +72,6 @@ const (
// adjusted to the number of available CPUs. The cost parameters should be
// increased as memory latency and CPU parallelism increases. Remember to get a
// good random salt.
-//
-// [RFC 9106 Section 7.3]: https://www.rfc-editor.org/rfc/rfc9106.html#section-7.3
func Key(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte {
return deriveKey(argon2i, password, salt, nil, nil, time, memory, threads, keyLen)
}
@@ -83,20 +84,20 @@ func Key(password, salt []byte, time, memory uint32, threads uint8, keyLen uint3
// For example, you can get a derived key for e.g. AES-256 (which needs a
// 32-byte key) by doing:
//
-// key := argon2.IDKey([]byte("some password"), salt, 1, 64*1024, 4, 32)
+// key := argon2.IDKey([]byte("some password"), salt, 1, 2*1024*1024, 4, 32)
//
-// [RFC 9106 Section 7.3] recommends time=1, and memory=64*1024 as a sensible number.
-// If using that amount of memory (64 MB) is not possible in some contexts then
-// the time parameter can be increased to compensate.
+// The example above uses the first [RFC 9106 Section 4] recommended option.
+// If much less memory is available, the second recommended option is time=3,
+// memory=64*1024 KiB (64 MiB), and threads=4.
//
// The time parameter specifies the number of passes over the memory and the
// memory parameter specifies the size of the memory in KiB. For example
-// memory=64*1024 sets the memory cost to ~64 MB. The number of threads can be
-// adjusted to the numbers of available CPUs. The cost parameters should be
+// memory=2*1024*1024 sets the memory cost to ~2 GiB. The number of threads can
+// be adjusted to the numbers of available CPUs. The cost parameters should be
// increased as memory latency and CPU parallelism increases. Remember to get a
// good random salt.
//
-// [RFC 9106 Section 7.3]: https://www.rfc-editor.org/rfc/rfc9106.html#section-7.3
+// [RFC 9106 Section 4]: https://www.rfc-editor.org/rfc/rfc9106.html#section-4
func IDKey(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte {
return deriveKey(argon2id, password, salt, nil, nil, time, memory, threads, keyLen)
}
diff --git a/src/vendor/golang.org/x/net/idna/idna.go b/src/vendor/golang.org/x/net/idna/idna.go
index 22767125..e2f28fed 100644
--- a/src/vendor/golang.org/x/net/idna/idna.go
+++ b/src/vendor/golang.org/x/net/idna/idna.go
@@ -400,7 +400,11 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
// Spec says keep the old label.
continue
}
- if unicode16 && err == nil && len(u) > 0 && isASCII(u) {
+ if err == nil && len(u) > 0 && isASCII(u) {
+ // UTS 43 pre-revision 33 doesn't classify a xn-- label
+ // which contains only ASCII characters as an error,
+ // but that's a specification bug and a security issue.
+ // Always return an error in this case.
err = punyError(enc)
}
isBidi = isBidi || bidirule.DirectionString(u) != bidi.LeftToRight
diff --git a/src/vendor/golang.org/x/sys/cpu/parse.go b/src/vendor/golang.org/x/sys/cpu/parse.go
index 56a7e1a1..12a99af5 100644
--- a/src/vendor/golang.org/x/sys/cpu/parse.go
+++ b/src/vendor/golang.org/x/sys/cpu/parse.go
@@ -6,38 +6,50 @@ package cpu
import "strconv"
-// parseRelease parses a dot-separated version number. It follows the semver
-// syntax, but allows the minor and patch versions to be elided.
+// parseRelease parses a dot-separated version number from the prefix
+// of rel. It returns ok=true only if at least the major and minor
+// components were successfully parsed; the patch component is
+// best-effort. Trailing vendor or build suffixes such as
+// "-generic", "+", "_hi3535", or "-rc1" are ignored.
//
// This is a copy of the Go runtime's parseRelease from
-// https://golang.org/cl/209597.
+// https://golang.org/cl/209597, updated in https://golang.org/cl/781800.
func parseRelease(rel string) (major, minor, patch int, ok bool) {
- // Strip anything after a dash or plus.
- for i := range len(rel) {
- if rel[i] == '-' || rel[i] == '+' {
- rel = rel[:i]
- break
+ // next consumes a run of decimal digits from the front of rel,
+ // returning the parsed value. If the digits are followed by a
+ // '.', it is consumed and more is set so the caller knows to
+ // parse another component; otherwise scanning terminates and
+ // the rest of rel is discarded.
+ next := func() (n int, more, ok bool) {
+ i := 0
+ for i < len(rel) && rel[i] >= '0' && rel[i] <= '9' {
+ i++
}
- }
-
- next := func() (int, bool) {
- for i := range len(rel) {
- if rel[i] == '.' {
- ver, err := strconv.Atoi(rel[:i])
- rel = rel[i+1:]
- return ver, err == nil
- }
+ if i == 0 {
+ return 0, false, false
+ }
+ n, err := strconv.Atoi(rel[:i])
+ if err != nil {
+ return 0, false, false
+ }
+ if i < len(rel) && rel[i] == '.' {
+ rel = rel[i+1:]
+ return n, true, true
}
- ver, err := strconv.Atoi(rel)
rel = ""
- return ver, err == nil
+ return n, false, true
+ }
+
+ var more bool
+ if major, more, ok = next(); !ok || !more {
+ return 0, 0, 0, false
}
- if major, ok = next(); !ok || rel == "" {
- return
+ if minor, more, ok = next(); !ok {
+ return 0, 0, 0, false
}
- if minor, ok = next(); !ok || rel == "" {
- return
+ if !more {
+ return major, minor, 0, true
}
- patch, ok = next()
- return
+ patch, _, _ = next()
+ return major, minor, patch, true
}
diff --git a/src/vendor/golang.org/x/sys/unix/syscall_linux.go b/src/vendor/golang.org/x/sys/unix/syscall_linux.go
index ce4d7ab1..21e2bfa3 100644
--- a/src/vendor/golang.org/x/sys/unix/syscall_linux.go
+++ b/src/vendor/golang.org/x/sys/unix/syscall_linux.go
@@ -1874,6 +1874,7 @@ func Dup2(oldfd, newfd int) error {
//sys Dup3(oldfd int, newfd int, flags int) (err error)
//sysnb EpollCreate1(flag int) (fd int, err error)
//sysnb EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error)
+//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT
//sys Eventfd(initval uint, flags int) (fd int, err error) = SYS_EVENTFD2
//sys Exit(code int) = SYS_EXIT_GROUP
//sys Fallocate(fd int, mode uint32, off int64, len int64) (err error)
diff --git a/src/vendor/golang.org/x/sys/unix/syscall_linux_386.go b/src/vendor/golang.org/x/sys/unix/syscall_linux_386.go
index 506dafa7..210d545c 100644
--- a/src/vendor/golang.org/x/sys/unix/syscall_linux_386.go
+++ b/src/vendor/golang.org/x/sys/unix/syscall_linux_386.go
@@ -20,7 +20,6 @@ func setTimeval(sec, usec int64) Timeval {
// 64-bit file system and 32-bit uid calls
// (386 default is 32-bit file system and 16-bit uid).
-//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64_64
//sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
diff --git a/src/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go b/src/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go
index d557cf8d..a9a52f23 100644
--- a/src/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go
+++ b/src/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go
@@ -6,7 +6,6 @@
package unix
-//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
//sys Fchown(fd int, uid int, gid int) (err error)
//sys Fstat(fd int, stat *Stat_t) (err error)
diff --git a/src/vendor/golang.org/x/sys/unix/syscall_linux_arm.go b/src/vendor/golang.org/x/sys/unix/syscall_linux_arm.go
index ecf92bfa..54474c20 100644
--- a/src/vendor/golang.org/x/sys/unix/syscall_linux_arm.go
+++ b/src/vendor/golang.org/x/sys/unix/syscall_linux_arm.go
@@ -44,7 +44,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
// 64-bit file system and 32-bit uid calls
// (16-bit uid calls are not always supported in newer kernels)
-//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
//sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
diff --git a/src/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go b/src/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go
index 17373807..e9f30db9 100644
--- a/src/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go
+++ b/src/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go
@@ -8,7 +8,6 @@ package unix
import "unsafe"
-//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
//sys Fchown(fd int, uid int, gid int) (err error)
//sys Fstat(fd int, stat *Stat_t) (err error)
diff --git a/src/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go b/src/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go
index a3fd1d0b..6f09ca20 100644
--- a/src/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go
+++ b/src/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go
@@ -8,7 +8,6 @@ package unix
import "unsafe"
-//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
//sys Fchown(fd int, uid int, gid int) (err error)
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
diff --git a/src/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go b/src/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go
index 70963a95..ca3b5659 100644
--- a/src/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go
+++ b/src/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go
@@ -6,7 +6,6 @@
package unix
-//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
//sys Fchown(fd int, uid int, gid int) (err error)
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
diff --git a/src/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go b/src/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go
index c218ebd2..54ba667b 100644
--- a/src/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go
+++ b/src/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go
@@ -13,7 +13,6 @@ import (
func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
-//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
//sys Fchown(fd int, uid int, gid int) (err error)
//sys Ftruncate(fd int, length int64) (err error) = SYS_FTRUNCATE64
diff --git a/src/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go b/src/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go
index e6c48500..ce462859 100644
--- a/src/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go
+++ b/src/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go
@@ -11,7 +11,6 @@ import (
"unsafe"
)
-//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fchown(fd int, uid int, gid int) (err error)
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
//sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
diff --git a/src/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go b/src/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go
index 7286a9aa..33f7af38 100644
--- a/src/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go
+++ b/src/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go
@@ -6,7 +6,6 @@
package unix
-//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
//sys Fchown(fd int, uid int, gid int) (err error)
//sys Fstat(fd int, stat *Stat_t) (err error)
diff --git a/src/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go b/src/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go
index fc5543c5..c658871e 100644
--- a/src/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go
+++ b/src/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go
@@ -8,7 +8,6 @@ package unix
import "unsafe"
-//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
//sys Fchown(fd int, uid int, gid int) (err error)
//sys Fstat(fd int, stat *Stat_t) (err error)
diff --git a/src/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go b/src/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go
index 66f31210..2c858769 100644
--- a/src/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go
+++ b/src/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go
@@ -10,7 +10,6 @@ import (
"unsafe"
)
-//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
//sys Fchown(fd int, uid int, gid int) (err error)
//sys Fstat(fd int, stat *Stat_t) (err error)
diff --git a/src/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go b/src/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go
index 11d1f169..4964119a 100644
--- a/src/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go
+++ b/src/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go
@@ -6,7 +6,6 @@
package unix
-//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
//sys Fchown(fd int, uid int, gid int) (err error)
//sys Fstat(fd int, stat *Stat_t) (err error)
diff --git a/src/vendor/golang.org/x/sys/unix/zerrors_linux.go b/src/vendor/golang.org/x/sys/unix/zerrors_linux.go
index 9d72a6b7..5bb51d7a 100644
--- a/src/vendor/golang.org/x/sys/unix/zerrors_linux.go
+++ b/src/vendor/golang.org/x/sys/unix/zerrors_linux.go
@@ -1359,6 +1359,7 @@ const (
FAN_UNLIMITED_MARKS = 0x20
FAN_UNLIMITED_QUEUE = 0x10
FD_CLOEXEC = 0x1
+ FD_PIDFS_ROOT = -0x2712
FD_SETSIZE = 0x400
FF0 = 0x0
FIB_RULE_DEV_DETACHED = 0x8
@@ -1970,6 +1971,8 @@ const (
MADV_DONTNEED = 0x4
MADV_DONTNEED_LOCKED = 0x18
MADV_FREE = 0x8
+ MADV_GUARD_INSTALL = 0x66
+ MADV_GUARD_REMOVE = 0x67
MADV_HUGEPAGE = 0xe
MADV_HWPOISON = 0x64
MADV_KEEPONFORK = 0x13
@@ -2114,7 +2117,7 @@ const (
MS_NOSEC = 0x10000000
MS_NOSUID = 0x2
MS_NOSYMFOLLOW = 0x100
- MS_NOUSER = -0x80000000
+ MS_NOUSER = 0x80000000
MS_POSIXACL = 0x10000
MS_PRIVATE = 0x40000
MS_RDONLY = 0x1
@@ -3786,6 +3789,9 @@ const (
TCPOPT_TIMESTAMP = 0x8
TCPOPT_TSTAMP_HDR = 0x101080a
TCPOPT_WINDOW = 0x3
+ TCP_AO_KEYF_EXCLUDE_OPT = 0x2
+ TCP_AO_KEYF_IFINDEX = 0x1
+ TCP_AO_MAXKEYLEN = 0x50
TCP_CC_INFO = 0x1a
TCP_CM_INQ = 0x24
TCP_CONGESTION = 0xd
diff --git a/src/vendor/golang.org/x/sys/unix/zsyscall_linux.go b/src/vendor/golang.org/x/sys/unix/zsyscall_linux.go
index 80f40e40..5788c2a5 100644
--- a/src/vendor/golang.org/x/sys/unix/zsyscall_linux.go
+++ b/src/vendor/golang.org/x/sys/unix/zsyscall_linux.go
@@ -700,6 +700,23 @@ func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(events) > 0 {
+ _p0 = unsafe.Pointer(&events[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall6(SYS_EPOLL_PWAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
func Eventfd(initval uint, flags int) (fd int, err error) {
r0, _, e1 := Syscall(SYS_EVENTFD2, uintptr(initval), uintptr(flags), 0)
fd = int(r0)
diff --git a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go
index 4def3e9f..254f3398 100644
--- a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go
+++ b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go
@@ -45,23 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(events) > 0 {
- _p0 = unsafe.Pointer(&events[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func Fadvise(fd int, offset int64, length int64, advice int) (err error) {
_, _, e1 := Syscall6(SYS_FADVISE64_64, uintptr(fd), uintptr(offset), uintptr(offset>>32), uintptr(length), uintptr(length>>32), uintptr(advice))
if e1 != 0 {
diff --git a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go
index fef2bc8b..27c05db1 100644
--- a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go
+++ b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go
@@ -45,23 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(events) > 0 {
- _p0 = unsafe.Pointer(&events[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func Fadvise(fd int, offset int64, length int64, advice int) (err error) {
_, _, e1 := Syscall6(SYS_FADVISE64, uintptr(fd), uintptr(offset), uintptr(length), uintptr(advice), 0, 0)
if e1 != 0 {
diff --git a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go
index a9fd76a8..840d85bf 100644
--- a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go
+++ b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go
@@ -213,23 +213,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(events) > 0 {
- _p0 = unsafe.Pointer(&events[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func Fchown(fd int, uid int, gid int) (err error) {
_, _, e1 := Syscall(SYS_FCHOWN32, uintptr(fd), uintptr(uid), uintptr(gid))
if e1 != 0 {
diff --git a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go
index 46006502..fe414498 100644
--- a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go
+++ b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go
@@ -45,23 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(events) > 0 {
- _p0 = unsafe.Pointer(&events[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := Syscall6(SYS_EPOLL_PWAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func Fadvise(fd int, offset int64, length int64, advice int) (err error) {
_, _, e1 := Syscall6(SYS_FADVISE64, uintptr(fd), uintptr(offset), uintptr(length), uintptr(advice), 0, 0)
if e1 != 0 {
diff --git a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_loong64.go b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_loong64.go
index c8987d26..eb358ce0 100644
--- a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_loong64.go
+++ b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_loong64.go
@@ -45,23 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(events) > 0 {
- _p0 = unsafe.Pointer(&events[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := Syscall6(SYS_EPOLL_PWAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func Fadvise(fd int, offset int64, length int64, advice int) (err error) {
_, _, e1 := Syscall6(SYS_FADVISE64, uintptr(fd), uintptr(offset), uintptr(length), uintptr(advice), 0, 0)
if e1 != 0 {
diff --git a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go
index 921f4306..c437622f 100644
--- a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go
+++ b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go
@@ -45,23 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(events) > 0 {
- _p0 = unsafe.Pointer(&events[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func Fadvise(fd int, offset int64, length int64, advice int) (err error) {
_, _, e1 := Syscall9(SYS_FADVISE64, uintptr(fd), 0, uintptr(offset>>32), uintptr(offset), uintptr(length>>32), uintptr(length), uintptr(advice), 0, 0)
if e1 != 0 {
diff --git a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go
index 44f06782..bc4ca255 100644
--- a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go
+++ b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go
@@ -45,23 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(events) > 0 {
- _p0 = unsafe.Pointer(&events[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func Fadvise(fd int, offset int64, length int64, advice int) (err error) {
_, _, e1 := Syscall6(SYS_FADVISE64, uintptr(fd), uintptr(offset), uintptr(length), uintptr(advice), 0, 0)
if e1 != 0 {
diff --git a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go
index e7fa0abf..5051435c 100644
--- a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go
+++ b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go
@@ -45,23 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(events) > 0 {
- _p0 = unsafe.Pointer(&events[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func Fadvise(fd int, offset int64, length int64, advice int) (err error) {
_, _, e1 := Syscall6(SYS_FADVISE64, uintptr(fd), uintptr(offset), uintptr(length), uintptr(advice), 0, 0)
if e1 != 0 {
diff --git a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go
index 8c512567..33aa5418 100644
--- a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go
+++ b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go
@@ -45,23 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(events) > 0 {
- _p0 = unsafe.Pointer(&events[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func Fadvise(fd int, offset int64, length int64, advice int) (err error) {
_, _, e1 := Syscall9(SYS_FADVISE64, uintptr(fd), 0, uintptr(offset), uintptr(offset>>32), uintptr(length), uintptr(length>>32), uintptr(advice), 0, 0)
if e1 != 0 {
diff --git a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go
index 7392fd45..3bef8ef1 100644
--- a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go
+++ b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go
@@ -45,23 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(events) > 0 {
- _p0 = unsafe.Pointer(&events[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func Fchown(fd int, uid int, gid int) (err error) {
_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
if e1 != 0 {
diff --git a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go
index 41180434..fc1bd4e2 100644
--- a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go
+++ b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go
@@ -45,23 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(events) > 0 {
- _p0 = unsafe.Pointer(&events[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func Fadvise(fd int, offset int64, length int64, advice int) (err error) {
_, _, e1 := Syscall6(SYS_FADVISE64, uintptr(fd), uintptr(offset), uintptr(length), uintptr(advice), 0, 0)
if e1 != 0 {
diff --git a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go
index 40c6ce7a..d78fe7da 100644
--- a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go
+++ b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go
@@ -45,23 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(events) > 0 {
- _p0 = unsafe.Pointer(&events[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func Fadvise(fd int, offset int64, length int64, advice int) (err error) {
_, _, e1 := Syscall6(SYS_FADVISE64, uintptr(fd), uintptr(offset), uintptr(length), uintptr(advice), 0, 0)
if e1 != 0 {
diff --git a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go
index 2cfe34ad..76dcf87d 100644
--- a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go
+++ b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go
@@ -45,23 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(events) > 0 {
- _p0 = unsafe.Pointer(&events[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := Syscall6(SYS_EPOLL_PWAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func Fadvise(fd int, offset int64, length int64, advice int) (err error) {
_, _, e1 := Syscall6(SYS_FADVISE64, uintptr(fd), uintptr(offset), uintptr(length), uintptr(advice), 0, 0)
if e1 != 0 {
diff --git a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go
index 61e6f070..2cf020f2 100644
--- a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go
+++ b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go
@@ -45,23 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(events) > 0 {
- _p0 = unsafe.Pointer(&events[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func Fadvise(fd int, offset int64, length int64, advice int) (err error) {
_, _, e1 := Syscall6(SYS_FADVISE64, uintptr(fd), uintptr(offset), uintptr(length), uintptr(advice), 0, 0)
if e1 != 0 {
diff --git a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go
index 834b8420..52763762 100644
--- a/src/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go
+++ b/src/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go
@@ -45,23 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(events) > 0 {
- _p0 = unsafe.Pointer(&events[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func Fadvise(fd int, offset int64, length int64, advice int) (err error) {
_, _, e1 := Syscall6(SYS_FADVISE64, uintptr(fd), uintptr(offset), uintptr(length), uintptr(advice), 0, 0)
if e1 != 0 {
diff --git a/src/vendor/golang.org/x/sys/windows/security_windows.go b/src/vendor/golang.org/x/sys/windows/security_windows.go
index 6c955cea..78362156 100644
--- a/src/vendor/golang.org/x/sys/windows/security_windows.go
+++ b/src/vendor/golang.org/x/sys/windows/security_windows.go
@@ -1109,17 +1109,53 @@ const (
)
// This type is the union inside of TRUSTEE and must be created using one of the TrusteeValueFrom* functions.
+//
+// Go pointers stored in a TrusteeValue must be pinned using [runtime.Pinner]
+// for the lifetime of the TrusteeValue.
type TrusteeValue uintptr
+// TrusteeValueFromString is unsafe and should not be used.
+//
+// It returns a uintptr containing a reference to newly-allocated memory
+// which will be freed by the garbage collector.
+// There is no way for the caller to safely reference this memory.
+//
+// To create a [TrusteeValue] from a string, use:
+//
+// p, err := windows.UTF16PtrFromString(s)
+// if err != nil {
+// // handle error
+// }
+//
+// // Pin the string for as long as it is used.
+// var pinner runtime.Pinner
+// pinner.Pin(p)
+// defer pinner.Unpin()
+//
+// tv := TrusteeValue(unsafe.Pointer(p))
+//
+// Deprecated: TrusteeValueFromString is unsafe and should not be used.
func TrusteeValueFromString(str string) TrusteeValue {
return TrusteeValue(unsafe.Pointer(StringToUTF16Ptr(str)))
}
+
+// TrusteeValueFromSID returns a [TrusteeValue] referencing sid.
+//
+// The caller must pin sid using a [runtime.Pinner] for the lifetime of the TrusteeValue.
func TrusteeValueFromSID(sid *SID) TrusteeValue {
return TrusteeValue(unsafe.Pointer(sid))
}
+
+// TrusteeValueFromObjectsAndSid returns a [TrusteeValue] referencing objectsAndSid.
+//
+// The caller must pin objectsAndSid using a [runtime.Pinner] for the lifetime of the TrusteeValue.
func TrusteeValueFromObjectsAndSid(objectsAndSid *OBJECTS_AND_SID) TrusteeValue {
return TrusteeValue(unsafe.Pointer(objectsAndSid))
}
+
+// TrusteeValueFromObjectsAndName returns a [TrusteeValue] referencing objectsAndName.
+//
+// The caller must pin objectsAndName using a [runtime.Pinner] for the lifetime of the TrusteeValue.
func TrusteeValueFromObjectsAndName(objectsAndName *OBJECTS_AND_NAME) TrusteeValue {
return TrusteeValue(unsafe.Pointer(objectsAndName))
}
diff --git a/src/vendor/golang.org/x/sys/windows/syscall_windows.go b/src/vendor/golang.org/x/sys/windows/syscall_windows.go
index 9755bca9..e6966b4c 100644
--- a/src/vendor/golang.org/x/sys/windows/syscall_windows.go
+++ b/src/vendor/golang.org/x/sys/windows/syscall_windows.go
@@ -1728,11 +1728,15 @@ func (s *NTUnicodeString) String() string {
// the more common *uint16 string type.
func NewNTString(s string) (*NTString, error) {
var nts NTString
- s8, err := BytePtrFromString(s)
+ s8, err := ByteSliceFromString(s)
if err != nil {
return nil, err
}
- RtlInitString(&nts, s8)
+ // The source string plus its terminating NUL must fit within MAX_USHORT.
+ if len(s8) > MAX_USHORT {
+ return nil, syscall.EINVAL
+ }
+ RtlInitString(&nts, &s8[0])
return &nts, nil
}
diff --git a/src/vendor/golang.org/x/sys/windows/types_windows.go b/src/vendor/golang.org/x/sys/windows/types_windows.go
index d2574a73..75a50b31 100644
--- a/src/vendor/golang.org/x/sys/windows/types_windows.go
+++ b/src/vendor/golang.org/x/sys/windows/types_windows.go
@@ -169,6 +169,7 @@ const (
FORMAT_MESSAGE_ARGUMENT_ARRAY = 8192
FORMAT_MESSAGE_MAX_WIDTH_MASK = 255
+ MAX_USHORT = 0xffff
MAX_PATH = 260
MAX_LONG_PATH = 32768
diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt
index 475a0dde..5378b47b 100644
--- a/src/vendor/modules.txt
+++ b/src/vendor/modules.txt
@@ -46,7 +46,7 @@ github.com/go-webauthn/webauthn/webauthn
## explicit; go 1.25.0
github.com/go-webauthn/x/encoding/asn1
github.com/go-webauthn/x/revoke
-# github.com/gofiber/contrib/v3/websocket v1.2.1
+# github.com/gofiber/contrib/v3/websocket v1.2.2
## explicit; go 1.25.0
github.com/gofiber/contrib/v3/websocket
# github.com/gofiber/fiber/v3 v3.4.0
@@ -68,16 +68,17 @@ github.com/gofiber/fiber/v3/middleware/logger
github.com/gofiber/fiber/v3/middleware/recover
github.com/gofiber/fiber/v3/middleware/requestid
github.com/gofiber/fiber/v3/middleware/static
-# github.com/gofiber/schema v1.8.0
+# github.com/gofiber/schema v1.8.3
## explicit; go 1.25.0
github.com/gofiber/schema
-# github.com/gofiber/utils/v2 v2.1.1
+# github.com/gofiber/utils/v2 v2.2.0
## explicit; go 1.25.0
github.com/gofiber/utils/v2
github.com/gofiber/utils/v2/bytes
github.com/gofiber/utils/v2/internal/caseconv
github.com/gofiber/utils/v2/internal/unsafeconv
github.com/gofiber/utils/v2/strings
+github.com/gofiber/utils/v2/swar
# github.com/golang-jwt/jwt/v5 v5.3.1
## explicit; go 1.21
github.com/golang-jwt/jwt/v5
@@ -118,7 +119,7 @@ github.com/jackc/puddle/v2/internal/genstack
# github.com/joho/godotenv v1.5.1
## explicit; go 1.12
github.com/joho/godotenv
-# github.com/klauspost/compress v1.19.0
+# github.com/klauspost/compress v1.19.1
## explicit; go 1.24
github.com/klauspost/compress
github.com/klauspost/compress/flate
@@ -147,8 +148,8 @@ github.com/looplab/fsm
# github.com/mattn/go-colorable v0.1.15
## explicit; go 1.18
github.com/mattn/go-colorable
-# github.com/mattn/go-isatty v0.0.22
-## explicit; go 1.21
+# github.com/mattn/go-isatty v0.0.23
+## explicit; go 1.20
github.com/mattn/go-isatty
# github.com/mfridman/interpolate v0.0.2
## explicit; go 1.19
@@ -269,7 +270,7 @@ go.uber.org/multierr
# go.yaml.in/yaml/v3 v3.0.4
## explicit; go 1.16
go.yaml.in/yaml/v3
-# golang.org/x/crypto v0.53.0
+# golang.org/x/crypto v0.54.0
## explicit; go 1.25.0
golang.org/x/crypto/acme
golang.org/x/crypto/acme/autocert
@@ -284,7 +285,7 @@ golang.org/x/image/font/opentype
golang.org/x/image/font/sfnt
golang.org/x/image/math/fixed
golang.org/x/image/vector
-# golang.org/x/net v0.56.0
+# golang.org/x/net v0.57.0
## explicit; go 1.25.0
golang.org/x/net/html
golang.org/x/net/html/atom
@@ -298,7 +299,7 @@ golang.org/x/net/publicsuffix
## explicit; go 1.25.0
golang.org/x/sync/errgroup
golang.org/x/sync/semaphore
-# golang.org/x/sys v0.46.0
+# golang.org/x/sys v0.47.0
## explicit; go 1.25.0
golang.org/x/sys/cpu
golang.org/x/sys/unix