diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 0d4973e..7d37f72 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -51,7 +51,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go: ["1.24", "1.25"] + go: ["1.25", "1.26"] steps: - name: Check out code uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 @@ -73,8 +73,8 @@ jobs: - name: Set up Go uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: - go-version: "1.24" + go-version: "1.25" - name: Test with -race run: | cd go/sdk - go test -v -race ./... \ No newline at end of file + go test -v -race ./... diff --git a/.github/workflows/status-check.yml b/.github/workflows/status-check.yml index 28a3cdf..d47e352 100644 --- a/.github/workflows/status-check.yml +++ b/.github/workflows/status-check.yml @@ -79,9 +79,8 @@ jobs: ], go: [ 'Go CI / Linting', - 'Go CI / Unit Tests (1.23)', - 'Go CI / Unit Tests (1.24)', 'Go CI / Unit Tests (1.25)', + 'Go CI / Unit Tests (1.26)', 'Go CI / Race Detection' ], typescript: [ @@ -145,4 +144,4 @@ jobs: core.setFailed(`Required checks have not passed:\\n${failureMessage}`); } else { console.log(`All required checks passed:\\n${failureMessage}`); - } \ No newline at end of file + } diff --git a/go/sdk/README.md b/go/sdk/README.md index 47ca48b..2d59399 100644 --- a/go/sdk/README.md +++ b/go/sdk/README.md @@ -3,8 +3,6 @@ Go implementation of the MCP Interceptor Extension based on [SEP-2624](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/2624). -Note: Currently the MCP SDK is vendored, in-order to add the Protocol Methods needed for interceptors. - ## Quick Start ```go @@ -36,7 +34,9 @@ ext.AddInterceptor(&interceptors.Validator{ }) // Install on the server and create a chain for middleware. -ext.Install(mcpServer) +if err := ext.Install(mcpServer); err != nil { + log.Fatal(err) +} chain, err := ext.LocalChain(ctx, mcpServer) mcpServer.AddReceivingMiddleware(gomiddleware.Middleware(chain)) diff --git a/go/sdk/doc/CONFORMANCE.md b/go/sdk/doc/CONFORMANCE.md index aef5463..e3abdcf 100644 --- a/go/sdk/doc/CONFORMANCE.md +++ b/go/sdk/doc/CONFORMANCE.md @@ -9,8 +9,9 @@ Status of this Go SDK implementation against the SEP-2624 interceptor proposal. | Validation interceptors | Parallel execution, severity-based blocking, fail-open support | | Mutation interceptors | Sequential execution, priority ordering, payload threading via `json.RawMessage` | | Interceptor metadata | Name, version, description, events, phase, priorityHint (polymorphic JSON), compat, configSchema, mode, failOpen | -| Event names | Constants for all standard server-side MCP methods; JSON-RPC method names used directly as event names | +| Event names | Constants for common server-side MCP methods; other JSON-RPC method names can be used directly as event names | | Protocol methods | `interceptors/list` for discovery, `interceptor/invoke` for invocation — both registered as custom JSON-RPC methods | +| MCP Go SDK integration | Uses `github.com/modelcontextprotocol/go-sdk` custom method APIs (`AddReceivingCustomMethod`, `AddSendingCustomMethod`, `CallCustomMethod`, `ParamsBase`, `ResultBase`) from v1.7.0; no vendored SDK patch is required | | `InterceptorChain` (SEP) | `chain.Chain` type with `chain.ChainEntry` objects pairing interceptor descriptors with MCP client sessions | | `ChainEntry` (SEP) | `chain.ChainEntry` struct holds `InterceptorInfo` + `*mcp.ClientSession` | | Chain discovery | `chain.Chain.AddMCPServer()` calls `interceptors/list` to discover interceptors from an MCP server | @@ -23,9 +24,9 @@ Status of this Go SDK implementation against the SEP-2624 interceptor proposal. | Fail-open behavior | `FailOpen: true` interceptors log errors without aborting the chain | | Audit mode | `ModeAudit` records results without blocking; mutated payloads not propagated | | Timeout & context | Per-interceptor timeouts via `InvokeParams.TimeoutMs`, chain-level context cancellation, `InvocationContext` with principal/traceId | -| Receiving direction (client → server) | All server-side method calls intercepted via `AddReceivingMiddleware` | +| Receiving direction (client → server) | Server-side messages routed through `AddReceivingMiddleware` are intercepted, except skipped lifecycle and interceptor methods | | Capability declaration | Interceptor metadata injected into `initialize` response via `Capabilities.Extensions` | -| First-party (in-process) deployment | `Server.LocalChain()` creates an in-memory transport `chain.Chain`; interceptors invoked via JSON-RPC even in-process | +| First-party (in-process) deployment | `extension.Extension.LocalChain()` creates an in-memory transport `chain.Chain`; interceptors invoked via JSON-RPC even in-process | | Third-party and hybrid deployment | Chain entries can point to any `*mcp.ClientSession` — local (in-memory), stdio, or HTTP transport | | `json.RawMessage` payloads | Interceptor handlers receive `json.RawMessage` via `interceptor/invoke`, matching the SEP's JSON-level payload model | @@ -33,7 +34,8 @@ Status of this Go SDK implementation against the SEP-2624 interceptor proposal. | Area | SEP expects | Notes | |------|-------------|-------| -| Wildcard event matching | `"*/request"`, `"*/response"`, `"*"` | `matchesEvent` does exact match only; wildcard patterns are planned | -| Server → client interception | Client features as interceptable events: `"sampling/createMessage"`, `"elicitation/create"`, `"roots/list"` | Requires `Server.AddSendingMiddleware` support in the go-sdk | -| Per-interceptor config passthrough | `ChainExecutionParams.Config` map | Wired through to `InvokeParams.Config` but not yet used by middleware | -| Remote interceptor servers | Connecting chain to external MCP servers over stdio/HTTP | Infrastructure is ready (`chain.Chain.AddMCPServer` accepts any `*mcp.ClientSession`); no convenience helpers yet | +| Wildcard event matching | `"*"` MUST match all lifecycle events; namespace wildcards such as `"tools/*"` MAY be supported | `matchesHooks` does exact event matching only today | +| Sending-side interception | Sending flow uses `Mutate → Validate → Send` for client→server and server→client boundaries | Only the server receiving middleware integration exists. `go-sdk` v1.7.0 now provides `Client.AddSendingMiddleware` and `Server.AddSendingMiddleware`, so this is a local implementation gap rather than an upstream SDK blocker | +| Client feature events | `"sampling/createMessage"`, `"elicitation/create"`, `"roots/list"` | No client-side middleware integration yet; callers may still use raw method-name strings as events | +| Per-interceptor config source and validation | `ChainExecutionParams.Config` overrides and `configSchema` validation | `ExecutionParams.Config` is passed through to `InvokeParams.Config`, but middleware does not load config and `configSchema` is not validated | +| Remote interceptor server helpers | Convenient setup for stdio/HTTP interceptor servers | Infrastructure is ready (`chain.Chain.AddMCPServer` accepts any `*mcp.ClientSession`); no config-driven or transport-specific helper APIs yet | diff --git a/go/sdk/doc/DESIGN.md b/go/sdk/doc/DESIGN.md index 6343d70..b48a52a 100644 --- a/go/sdk/doc/DESIGN.md +++ b/go/sdk/doc/DESIGN.md @@ -38,9 +38,10 @@ server via in-memory transport. Under the hood it: 1. Creates an `InMemoryTransport` pair via `mcp.NewInMemoryTransports()` 2. Connects the server side via `mcp.Server.Connect(ctx, serverTransport)` 3. Creates an MCP client and connects via the client transport -4. Calls `chain.AddMCPServer(ctx, clientSession)` which discovers +4. Registers the interceptor custom sending methods on the client +5. Calls `chain.AddMCPServer(ctx, clientSession)` which discovers interceptors via `interceptors/list` -5. Returns the ready-to-use chain +6. Returns the ready-to-use chain This means interceptors are invoked through the full MCP JSON-RPC pathway — even when running in the same process — ensuring the same @@ -59,22 +60,24 @@ The capability payload includes: ## Request/Response Lifecycle -When a JSON-RPC request arrives, `gomiddleware.Middleware` runs: +When a JSON-RPC request or notification reaches the server receiving +middleware, `gomiddleware.Middleware` runs: ``` -0. If method is skipped (initialize, notifications/*, interceptor/*) → passthrough +0. If method is skipped → passthrough 1. Marshal request params to json.RawMessage 2. chain.Execute(ctx, {event, PhaseRequest, payload}) → For each interceptor: interceptor/invoke RPC via ClientSession 3. If aborted → return JSON-RPC error 4. Unmarshal mutated payload back into request params 5. Call next handler next(ctx, method, req) -6. Marshal response result to json.RawMessage -7. chain.Execute(ctx, {event, PhaseResponse, payload}) +6. If the handler returns nil result (notification) → return +7. Marshal response result to json.RawMessage +8. chain.Execute(ctx, {event, PhaseResponse, payload}) → For each interceptor: interceptor/invoke RPC via ClientSession -8. If aborted → return JSON-RPC error -9. Unmarshal mutated payload back into response result -10. Return result +9. If aborted → return JSON-RPC error +10. Unmarshal mutated payload back into response result +11. Return result ``` ### JSON-RPC Payload Model @@ -82,7 +85,8 @@ When a JSON-RPC request arrives, `gomiddleware.Middleware` runs: Interceptor handlers receive `json.RawMessage` as `inv.Payload` when invoked via `interceptor/invoke`. This is the SEP-correct behavior — payloads are JSON at the protocol level. Handlers unmarshal, inspect or -modify, and (for mutators) set the updated JSON back on `inv.Payload`: +modify, and (for mutators) return the updated JSON in +`MutationResult.Payload`: ```go // Validator — unmarshal, inspect, return: @@ -118,7 +122,9 @@ avoid intercepting lifecycle events: ### Intercepted -All JSON-RPC **method calls** routed through the server's receiving middleware: +All JSON-RPC messages routed through the server's receiving middleware +except the skipped methods above. The current integration is server-side +receiving middleware only. | Method | Event | |--------|-------| @@ -130,8 +136,9 @@ All JSON-RPC **method calls** routed through the server's receiving middleware: | `resources/list` | `EventResourcesList` | | `resources/subscribe` | `EventResourcesSubscribe` | -Unknown methods pass through the middleware and are intercepted normally -(the JSON-RPC method name is used as the event name). +Custom methods registered with the Go SDK's receiving custom-method API +also pass through the middleware and are intercepted using the JSON-RPC +method name as the event name. ### Not Intercepted @@ -175,9 +182,9 @@ Response-phase validators see the post-mutation payload. ### Mutator execution - Mutators run sequentially, ordered by `PriorityHint.Resolve(phase)` (ascending), with alphabetical name tiebreak. -- Each mutator receives `json.RawMessage`, unmarshals, modifies, and sets - the updated JSON back on `inv.Payload`. The chain passes the mutated - payload from each mutator to the next. +- Each mutator receives `json.RawMessage`, unmarshals, modifies, and + returns updated JSON in `MutationResult.Payload`. The chain passes the + returned payload from each mutator to the next. - If any mutator fails (and is not `FailOpen`), the chain aborts. - In `ModeAudit`, the mutated payload is not propagated to subsequent interceptors. @@ -198,7 +205,7 @@ Response-phase validators see the post-mutation payload. |------|---------------| | `interceptor.go` | Interceptor interface, enums (Phase, Mode, InterceptorType, Severity), Metadata/Compat/Hook, Validator/Mutator structs and handler types, Invocation/InvocationContext/Principal, result types (ValidationResult, MutationResult) | | `priority.go` | Priority struct, NewPriority, Resolve, MarshalJSON, UnmarshalJSON | -| `wire.go` | JSON-RPC method/event constants, wire types (ListParams, ListResult, InvokeParams, InvokeResult, InterceptorInfo) | +| `wire.go` | Interceptor JSON-RPC method names, public event constants for common server methods, wire types (ListParams, ListResult, InvokeParams, InvokeResult, InterceptorInfo) | ### `interceptors/chain/` — chain orchestrator @@ -212,8 +219,8 @@ Response-phase validators see the post-mutation payload. | File | Responsibility | |------|---------------| | `server.go` | `Extension`, interceptor management, `Install`, `LocalChain`, capability declaration | +| `client.go` | `RegisterSendingMethods`, which registers interceptor custom methods on an MCP client before connecting | | `rpc.go` | `handleList` and `handleInvoke` JSON-RPC method handlers | -| `events.go` | Event name constants for standard MCP methods | ### `interceptors/integrations/gomiddleware/` — middleware diff --git a/go/sdk/doc/PERFORMANCE.md b/go/sdk/doc/PERFORMANCE.md index 2965ccc..43ce8f8 100644 --- a/go/sdk/doc/PERFORMANCE.md +++ b/go/sdk/doc/PERFORMANCE.md @@ -8,8 +8,8 @@ Analysis of per-request costs and allocation patterns. The interceptor chain follows the SEP execution model: each interceptor is invoked via `interceptor/invoke` JSON-RPC calls through an MCP client -session. For in-process interceptors, `Server.LocalChain()` creates an -in-memory transport, so the JSON-RPC overhead is minimal (no network I/O). +session. For in-process interceptors, `Extension.LocalChain(ctx, server)` +creates an in-memory transport, so there is no network I/O. Payloads are `json.RawMessage` at the protocol level. The middleware marshals request params and response results once per phase, and @@ -37,7 +37,7 @@ With interceptors active, each active phase incurs: | 1 | Marshal request params / response result | 1 `json.RawMessage` | 1 marshal | | 2 | `ChainExecutionResult` struct (with pre-allocated `Results` slice) | 1 struct + 1 slice | 0 | | 3 | Per-interceptor `interceptor/invoke` RPC | 1 `InvokeParams` + 1 `InvokeResult` per interceptor | 1 marshal + 1 unmarshal per interceptor (handled by go-sdk JSON-RPC layer) | -| 4 | Validator execution (N=1 inline, N>1 goroutines) | 0 (N=1) / goroutines (N>1) | Handler-specific | +| 4 | Validator execution | 1 goroutine per validator | Handler-specific | | 5 | Mutator payload threading | 0 | Payload passed as `json.RawMessage` between mutators | | 6 | Unmarshal mutated payload back to params/result | 0 | 1 unmarshal (if mutated) | diff --git a/go/sdk/examples/mutator/main.go b/go/sdk/examples/mutator/main.go index fe3f125..ac4685d 100644 --- a/go/sdk/examples/mutator/main.go +++ b/go/sdk/examples/mutator/main.go @@ -77,7 +77,9 @@ func main() { // resources via interceptors/list and interceptor/invoke). ext := extension.New() ext.AddInterceptor(m) - ext.Install(mcpServer) + if err := ext.Install(mcpServer); err != nil { + log.Fatal(err) + } // Create a chain connected via in-memory transport. chain, err := ext.LocalChain(context.Background(), mcpServer) diff --git a/go/sdk/examples/validator/main.go b/go/sdk/examples/validator/main.go index b12516d..38436ed 100644 --- a/go/sdk/examples/validator/main.go +++ b/go/sdk/examples/validator/main.go @@ -74,7 +74,9 @@ func main() { // resources via interceptors/list and interceptor/invoke). ext := extension.New() ext.AddInterceptor(v) - ext.Install(mcpServer) + if err := ext.Install(mcpServer); err != nil { + log.Fatal(err) + } // Create a chain connected via in-memory transport. chain, err := ext.LocalChain(context.Background(), mcpServer) diff --git a/go/sdk/go.mod b/go/sdk/go.mod index 4303b25..50c64ef 100644 --- a/go/sdk/go.mod +++ b/go/sdk/go.mod @@ -1,22 +1,22 @@ module github.com/modelcontextprotocol/ext-interceptors/go/sdk -go 1.24.0 - -toolchain go1.24.3 +go 1.25.0 require ( - github.com/modelcontextprotocol/go-sdk v1.4.0 + github.com/modelcontextprotocol/go-sdk v1.7.0 github.com/stretchr/testify v1.11.1 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect - github.com/google/jsonschema-go v0.4.2 // indirect + github.com/google/jsonschema-go v0.4.3 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/segmentio/asm v1.1.3 // indirect - github.com/segmentio/encoding v0.5.3 // indirect + github.com/segmentio/encoding v0.5.4 // indirect github.com/yosida95/uritemplate/v3 v3.0.2 // indirect - golang.org/x/oauth2 v0.34.0 // indirect - golang.org/x/sys v0.40.0 // indirect + golang.org/x/oauth2 v0.35.0 // indirect + golang.org/x/sync v0.20.0 // indirect + golang.org/x/sys v0.41.0 // indirect + golang.org/x/time v0.15.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go/sdk/go.sum b/go/sdk/go.sum index dacfe34..870a390 100644 --- a/go/sdk/go.sum +++ b/go/sdk/go.sum @@ -1,29 +1,33 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= -github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= +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= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/jsonschema-go v0.4.2 h1:tmrUohrwoLZZS/P3x7ex0WAVknEkBZM46iALbcqoRA8= -github.com/google/jsonschema-go v0.4.2/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= -github.com/modelcontextprotocol/go-sdk v1.4.0 h1:u0kr8lbJc1oBcawK7Df+/ajNMpIDFE41OEPxdeTLOn8= -github.com/modelcontextprotocol/go-sdk v1.4.0/go.mod h1:Nxc2n+n/GdCebUaqCOhTetptS17SXXNu9IfNTaLDi1E= +github.com/google/jsonschema-go v0.4.3 h1:/DBOLZTfDow7pe2GmaJNhltueGTtDKICi8V8p+DQPd0= +github.com/google/jsonschema-go v0.4.3/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= +github.com/modelcontextprotocol/go-sdk v1.7.0 h1:yqjY2dsbKAC0LSuWZVBMrHgiG8ukXv6NRo0JiALay44= +github.com/modelcontextprotocol/go-sdk v1.7.0/go.mod h1:dL7u98E/zjJTGzEq+j30jQ8K2k1mb6LeAH4inEcSGts= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/segmentio/asm v1.1.3 h1:WM03sfUOENvvKexOLp+pCqgb/WDjsi7EK8gIsICtzhc= github.com/segmentio/asm v1.1.3/go.mod h1:Ld3L4ZXGNcSLRg4JBsZ3//1+f/TjYl0Mzen/DQy1EJg= -github.com/segmentio/encoding v0.5.3 h1:OjMgICtcSFuNvQCdwqMCv9Tg7lEOXGwm1J5RPQccx6w= -github.com/segmentio/encoding v0.5.3/go.mod h1:HS1ZKa3kSN32ZHVZ7ZLPLXWvOVIiZtyJnO1gPH1sKt0= +github.com/segmentio/encoding v0.5.4 h1:OW1VRern8Nw6ITAtwSZ7Idrl3MXCFwXHPgqESYfvNt0= +github.com/segmentio/encoding v0.5.4/go.mod h1:HS1ZKa3kSN32ZHVZ7ZLPLXWvOVIiZtyJnO1gPH1sKt0= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4= -golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= -golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= -golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= +golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ= +golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= +golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= +golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/go/sdk/interceptors/chain/chain.go b/go/sdk/interceptors/chain/chain.go index 471ad90..5d2f36b 100644 --- a/go/sdk/interceptors/chain/chain.go +++ b/go/sdk/interceptors/chain/chain.go @@ -116,12 +116,18 @@ type ExecutionResult struct { // AddMCPServer discovers interceptors from an MCP server via // interceptors/list and adds entries for each. The client session's // transport determines how interceptor/invoke calls are made -// (in-memory, stdio, HTTP, etc.). +// (in-memory, stdio, HTTP, etc.). The session's client must have been +// configured with the interceptor extension's sending methods before connecting. func (c *Chain) AddMCPServer(ctx context.Context, cs *mcp.ClientSession) error { - var result interceptors.ListResult - if err := cs.CallCustom(ctx, interceptors.MethodList, nil, &result); err != nil { + result, err := mcp.CallCustomMethod[*interceptors.ListParams, *interceptors.ListResult]( + ctx, cs, interceptors.MethodList, nil, + ) + if err != nil { return err } + if result == nil { + return nil + } c.mu.Lock() defer c.mu.Unlock() @@ -142,7 +148,7 @@ func (c *Chain) AddMCPServer(ctx context.Context, cs *mcp.ClientSession) error { // - Sort mutators by priorityHint (ascending, alphabetical tiebreak) // - Request phase: validate (parallel) then mutate (sequential) // - Response phase: mutate (sequential) then validate (parallel) -// - Call interceptor/invoke via CallCustom for each entry +// - Call interceptor/invoke via the MCP SDK custom-method API for each entry // - For mutators: pass mutated payload from previous to next // - Handle abort, timeout, fail-open func (c *Chain) Execute(ctx context.Context, params *ExecutionParams) (*ExecutionResult, error) { @@ -443,9 +449,13 @@ func (c *Chain) callInvoke( } next := func(ctx context.Context, p *interceptors.InvokeParams) (interceptors.InvokeResult, error) { - var result interceptors.InvokeResult - err := entry.Server.CallCustom(ctx, interceptors.MethodInvoke, p, &result) - return result, err + result, err := mcp.CallCustomMethod[*interceptors.InvokeParams, *interceptors.InvokeResult]( + ctx, entry.Server, interceptors.MethodInvoke, p, + ) + if result == nil { + return interceptors.InvokeResult{}, err + } + return *result, err } if c.handler != nil { diff --git a/go/sdk/interceptors/chain/chain_test.go b/go/sdk/interceptors/chain/chain_test.go index f6c8a97..51e759b 100644 --- a/go/sdk/interceptors/chain/chain_test.go +++ b/go/sdk/interceptors/chain/chain_test.go @@ -17,6 +17,7 @@ import ( "github.com/modelcontextprotocol/ext-interceptors/go/sdk/interceptors" "github.com/modelcontextprotocol/ext-interceptors/go/sdk/interceptors/chain" + "github.com/modelcontextprotocol/ext-interceptors/go/sdk/interceptors/extension" ) // setupChainWithInterceptors creates an MCP server with the given @@ -34,7 +35,7 @@ func setupChainWithOpts(t *testing.T, opts []chain.ChainOption, is ...intercepto Version: "0.1.0", }, nil) - registerInterceptorMethods(mcpServer, is) + registerInterceptorMethods(t, mcpServer, is) serverTransport, clientTransport := mcp.NewInMemoryTransports() @@ -46,6 +47,7 @@ func setupChainWithOpts(t *testing.T, opts []chain.ChainOption, is ...intercepto Name: "chain-test-client", Version: "0.1.0", }, nil) + require.NoError(t, extension.RegisterSendingMethods(client)) cs, err := client.Connect(context.Background(), clientTransport, nil) require.NoError(t, err) t.Cleanup(func() { cs.Close() }) @@ -60,12 +62,13 @@ func setupChainWithOpts(t *testing.T, opts []chain.ChainOption, is ...intercepto // registerInterceptorMethods adds interceptors/list and interceptor/invoke // custom methods to the server, backed by the given interceptor list. -func registerInterceptorMethods(server *mcp.Server, is []interceptors.Interceptor) { - mcp.AddReceivingCustomMethod(server, interceptors.MethodList, - func(_ context.Context, req *mcp.ServerRequest[*interceptors.ListParams]) (*interceptors.ListResult, error) { +func registerInterceptorMethods(t *testing.T, server *mcp.Server, is []interceptors.Interceptor) { + t.Helper() + require.NoError(t, mcp.AddReceivingCustomMethod(server, interceptors.MethodList, + func(_ context.Context, _ *mcp.ServerSession, params *interceptors.ListParams) (*interceptors.ListResult, error) { var event string - if req.Params != nil { - event = req.Params.Event + if params != nil { + event = params.Event } infos := make([]interceptors.InterceptorInfo, 0, len(is)) for _, i := range is { @@ -87,14 +90,13 @@ func registerInterceptorMethods(server *mcp.Server, is []interceptors.Intercepto } return &interceptors.ListResult{Interceptors: infos}, nil }, - ) + )) - mcp.AddReceivingCustomMethod(server, interceptors.MethodInvoke, - func(ctx context.Context, req *mcp.ServerRequest[*interceptors.InvokeParams]) (*interceptors.InvokeResult, error) { - if req.Params == nil { + require.NoError(t, mcp.AddReceivingCustomMethod(server, interceptors.MethodInvoke, + func(ctx context.Context, _ *mcp.ServerSession, params *interceptors.InvokeParams) (*interceptors.InvokeResult, error) { + if params == nil { return nil, fmt.Errorf("params required") } - params := req.Params var target interceptors.Interceptor for _, i := range is { if i.GetMetadata().Name == params.Name { @@ -137,7 +139,7 @@ func registerInterceptorMethods(server *mcp.Server, is []interceptors.Intercepto } return result, nil }, - ) + )) } func TestChain_ExecutionHandler(t *testing.T) { diff --git a/go/sdk/interceptors/chain/doc.go b/go/sdk/interceptors/chain/doc.go index e228bc9..bb63425 100644 --- a/go/sdk/interceptors/chain/doc.go +++ b/go/sdk/interceptors/chain/doc.go @@ -26,6 +26,14 @@ // A [Chain] is created with [NewChain] and populated by adding MCP // servers via [Chain.AddMCPServer]: // +// client := mcp.NewClient(clientImpl, nil) +// if err := extension.RegisterSendingMethods(client); err != nil { +// return err +// } +// clientSession, err := client.Connect(ctx, transport, nil) +// if err != nil { +// return err +// } // chain := chain.NewChain() // chain.AddMCPServer(ctx, clientSession) // mcpServer.AddReceivingMiddleware( diff --git a/go/sdk/interceptors/doc.go b/go/sdk/interceptors/doc.go index 205848e..f2dea71 100644 --- a/go/sdk/interceptors/doc.go +++ b/go/sdk/interceptors/doc.go @@ -22,7 +22,9 @@ // ext := extension.New() // ext.AddInterceptor(myValidator) // ext.AddInterceptor(myMutator) -// ext.Install(mcpServer) +// if err := ext.Install(mcpServer); err != nil { +// return err +// } // // chain, err := ext.LocalChain(ctx, mcpServer) // mcpServer.AddReceivingMiddleware( @@ -64,8 +66,8 @@ // // A [Mutator] transforms the payload. Mutators run sequentially in // priority order (see [Priority]). Each mutator receives the payload -// as [json.RawMessage], unmarshals it, modifies it, and sets the -// updated JSON back on inv.Payload. If any mutator fails (and is not +// as [json.RawMessage], unmarshals it, modifies it, and returns the +// updated JSON in [MutationResult.Payload]. If any mutator fails (and is not // configured with FailOpen), the chain aborts. FailOpen mutators // record an [InvokeResult] (with the error captured) for // observability but do not block. diff --git a/go/sdk/interceptors/extension/client.go b/go/sdk/interceptors/extension/client.go new file mode 100644 index 0000000..763845f --- /dev/null +++ b/go/sdk/interceptors/extension/client.go @@ -0,0 +1,24 @@ +// Copyright 2025 The MCP Interceptors Authors. All rights reserved. +// Use of this source code is governed by an Apache-2.0 +// license that can be found in the LICENSE file. + +package extension + +import ( + "github.com/modelcontextprotocol/go-sdk/mcp" + + "github.com/modelcontextprotocol/ext-interceptors/go/sdk/interceptors" +) + +// RegisterSendingMethods registers the interceptor custom RPC methods on a +// client before it connects to interceptor-capable servers. +func RegisterSendingMethods(client *mcp.Client) error { + if err := mcp.AddSendingCustomMethod[*interceptors.ListParams, *interceptors.ListResult]( + client, interceptors.MethodList, + ); err != nil { + return err + } + return mcp.AddSendingCustomMethod[*interceptors.InvokeParams, *interceptors.InvokeResult]( + client, interceptors.MethodInvoke, + ) +} diff --git a/go/sdk/interceptors/extension/doc.go b/go/sdk/interceptors/extension/doc.go index 6bcc80c..01068aa 100644 --- a/go/sdk/interceptors/extension/doc.go +++ b/go/sdk/interceptors/extension/doc.go @@ -16,7 +16,9 @@ // ext := extension.New(extension.WithLogger(logger)) // ext.AddInterceptor(myValidator) // ext.AddInterceptor(myMutator) -// ext.Install(mcpServer) +// if err := ext.Install(mcpServer); err != nil { +// return err +// } // // At this point any connected MCP client can call interceptors/list // and interceptor/invoke. diff --git a/go/sdk/interceptors/extension/rpc.go b/go/sdk/interceptors/extension/rpc.go index 97a3c8f..7015d28 100644 --- a/go/sdk/interceptors/extension/rpc.go +++ b/go/sdk/interceptors/extension/rpc.go @@ -18,10 +18,10 @@ import ( // handleList implements the "interceptors/list" JSON-RPC method. // It returns all registered interceptors, optionally filtered by event. -func (e *Extension) handleList(_ context.Context, req *mcp.ServerRequest[*interceptors.ListParams]) (*interceptors.ListResult, error) { +func (e *Extension) handleList(_ context.Context, _ *mcp.ServerSession, params *interceptors.ListParams) (*interceptors.ListResult, error) { var event string - if req.Params != nil { - event = req.Params.Event + if params != nil { + event = params.Event } all := e.getInterceptors() @@ -38,14 +38,13 @@ func (e *Extension) handleList(_ context.Context, req *mcp.ServerRequest[*interc // handleInvoke implements the "interceptor/invoke" JSON-RPC method. // It invokes a single interceptor by name and returns its result. -func (e *Extension) handleInvoke(ctx context.Context, req *mcp.ServerRequest[*interceptors.InvokeParams]) (*interceptors.InvokeResult, error) { - if req.Params == nil || req.Params.Name == "" { +func (e *Extension) handleInvoke(ctx context.Context, _ *mcp.ServerSession, params *interceptors.InvokeParams) (*interceptors.InvokeResult, error) { + if params == nil || params.Name == "" { return nil, &jsonrpc.Error{ Code: jsonrpc.CodeInvalidParams, Message: "name is required", } } - params := req.Params // Look up the interceptor by name. i := e.findByName(params.Name) diff --git a/go/sdk/interceptors/extension/rpc_test.go b/go/sdk/interceptors/extension/rpc_test.go index 5a2911a..8721f5e 100644 --- a/go/sdk/interceptors/extension/rpc_test.go +++ b/go/sdk/interceptors/extension/rpc_test.go @@ -7,6 +7,7 @@ import ( "testing" "time" + "github.com/modelcontextprotocol/go-sdk/mcp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -22,8 +23,9 @@ func TestListInterceptors(t *testing.T) { blockToolValidator("dangerous"), ) - var result interceptors.ListResult - err := cs.CallCustom(context.Background(), interceptors.MethodList, nil, &result) + result, err := mcp.CallCustomMethod[*interceptors.ListParams, *interceptors.ListResult]( + context.Background(), cs, interceptors.MethodList, nil, + ) require.NoError(t, err) assert.Len(t, result.Interceptors, 2) @@ -56,25 +58,28 @@ func TestListWithEventFilter(t *testing.T) { cs := setupRPCServer(t, toolsValidator, promptsValidator) // Filter for tools/call — should only return tools-v - var result interceptors.ListResult - err := cs.CallCustom(context.Background(), interceptors.MethodList, - &interceptors.ListParams{Event: interceptors.EventToolsCall}, &result) + result, err := mcp.CallCustomMethod[*interceptors.ListParams, *interceptors.ListResult]( + context.Background(), cs, interceptors.MethodList, + &interceptors.ListParams{Event: interceptors.EventToolsCall}, + ) require.NoError(t, err) assert.Len(t, result.Interceptors, 1) assert.Equal(t, "tools-v", result.Interceptors[0].Name) // Filter for prompts/get — should only return prompts-v - var result2 interceptors.ListResult - err = cs.CallCustom(context.Background(), interceptors.MethodList, - &interceptors.ListParams{Event: interceptors.EventPromptsGet}, &result2) + result2, err := mcp.CallCustomMethod[*interceptors.ListParams, *interceptors.ListResult]( + context.Background(), cs, interceptors.MethodList, + &interceptors.ListParams{Event: interceptors.EventPromptsGet}, + ) require.NoError(t, err) assert.Len(t, result2.Interceptors, 1) assert.Equal(t, "prompts-v", result2.Interceptors[0].Name) // Filter for non-existent event — empty - var result3 interceptors.ListResult - err = cs.CallCustom(context.Background(), interceptors.MethodList, - &interceptors.ListParams{Event: "nonexistent/method"}, &result3) + result3, err := mcp.CallCustomMethod[*interceptors.ListParams, *interceptors.ListResult]( + context.Background(), cs, interceptors.MethodList, + &interceptors.ListParams{Event: "nonexistent/method"}, + ) require.NoError(t, err) assert.Empty(t, result3.Interceptors) } @@ -87,14 +92,15 @@ func TestInvokeValidator(t *testing.T) { cs := setupRPCServer(t, allowAllValidator("v1")) payload, _ := json.Marshal(map[string]any{"name": "echo", "arguments": map[string]any{"text": "hello"}}) - var result interceptors.InvokeResult - err := cs.CallCustom(context.Background(), interceptors.MethodInvoke, + result, err := mcp.CallCustomMethod[*interceptors.InvokeParams, *interceptors.InvokeResult]( + context.Background(), cs, interceptors.MethodInvoke, &interceptors.InvokeParams{ Name: "v1", Event: interceptors.EventToolsCall, Phase: interceptors.PhaseRequest, Payload: payload, - }, &result) + }, + ) require.NoError(t, err) assert.Equal(t, "v1", result.Interceptor) @@ -131,14 +137,15 @@ func TestInvokeValidatorRejects(t *testing.T) { cs := setupRPCServer(t, rejectAll) payload, _ := json.Marshal(map[string]any{"name": "echo"}) - var result interceptors.InvokeResult - err := cs.CallCustom(context.Background(), interceptors.MethodInvoke, + result, err := mcp.CallCustomMethod[*interceptors.InvokeParams, *interceptors.InvokeResult]( + context.Background(), cs, interceptors.MethodInvoke, &interceptors.InvokeParams{ Name: "reject-all", Event: interceptors.EventToolsCall, Phase: interceptors.PhaseRequest, Payload: payload, - }, &result) + }, + ) require.NoError(t, err) assert.Equal(t, "reject-all", result.Interceptor) @@ -182,14 +189,15 @@ func TestInvokeMutator(t *testing.T) { cs := setupRPCServer(t, mutator) payload, _ := json.Marshal(map[string]any{"name": "echo"}) - var result interceptors.InvokeResult - err := cs.CallCustom(context.Background(), interceptors.MethodInvoke, + result, err := mcp.CallCustomMethod[*interceptors.InvokeParams, *interceptors.InvokeResult]( + context.Background(), cs, interceptors.MethodInvoke, &interceptors.InvokeParams{ Name: "add-field", Event: interceptors.EventToolsCall, Phase: interceptors.PhaseRequest, Payload: payload, - }, &result) + }, + ) require.NoError(t, err) assert.Equal(t, "add-field", result.Interceptor) @@ -212,14 +220,15 @@ func TestInvokeUnknownName(t *testing.T) { cs := setupRPCServer(t, allowAllValidator("v1")) payload, _ := json.Marshal(map[string]any{}) - var result interceptors.InvokeResult - err := cs.CallCustom(context.Background(), interceptors.MethodInvoke, + _, err := mcp.CallCustomMethod[*interceptors.InvokeParams, *interceptors.InvokeResult]( + context.Background(), cs, interceptors.MethodInvoke, &interceptors.InvokeParams{ Name: "nonexistent", Event: interceptors.EventToolsCall, Phase: interceptors.PhaseRequest, Payload: payload, - }, &result) + }, + ) require.Error(t, err) assert.Contains(t, err.Error(), "nonexistent") @@ -250,15 +259,16 @@ func TestInvokeTimeout(t *testing.T) { cs := setupRPCServer(t, slowValidator) payload, _ := json.Marshal(map[string]any{}) - var result interceptors.InvokeResult - err := cs.CallCustom(context.Background(), interceptors.MethodInvoke, + _, err := mcp.CallCustomMethod[*interceptors.InvokeParams, *interceptors.InvokeResult]( + context.Background(), cs, interceptors.MethodInvoke, &interceptors.InvokeParams{ Name: "slow-v", Event: interceptors.EventToolsCall, Phase: interceptors.PhaseRequest, Payload: payload, TimeoutMs: 50, - }, &result) + }, + ) require.Error(t, err) } diff --git a/go/sdk/interceptors/extension/server.go b/go/sdk/interceptors/extension/server.go index 0aa975b..3e26bc9 100644 --- a/go/sdk/interceptors/extension/server.go +++ b/go/sdk/interceptors/extension/server.go @@ -6,6 +6,7 @@ package extension import ( "context" + "fmt" "log/slog" "sync" @@ -30,9 +31,9 @@ func WithLogger(l *slog.Logger) Option { } // Extension manages interceptors and can install them on one or more -// *mcp.Server instances. Interceptors are registered as first-class -// MCP resources discoverable via the "interceptors/list" JSON-RPC -// method and invocable via "interceptor/invoke". +// *mcp.Server instances. Interceptors are exposed as custom MCP methods: +// discoverable via the "interceptors/list" JSON-RPC method and invocable +// via "interceptor/invoke". // // Extension is a pure interceptor container — it does not hold a // reference to any particular server. Call [Extension.Install] to @@ -59,11 +60,16 @@ func New(opts ...Option) *Extension { // JSON-RPC methods and installs a receiving middleware to enrich the // initialize response with interceptor capabilities on the given // server. It can be called on multiple servers. -func (e *Extension) Install(server *mcp.Server) { +func (e *Extension) Install(server *mcp.Server) error { // Register JSON-RPC methods for interceptor discovery and invocation. - mcp.AddReceivingCustomMethod(server, interceptors.MethodList, e.handleList) - mcp.AddReceivingCustomMethod(server, interceptors.MethodInvoke, e.handleInvoke) + if err := mcp.AddReceivingCustomMethod(server, interceptors.MethodList, e.handleList); err != nil { + return fmt.Errorf("interceptors: register %q: %w", interceptors.MethodList, err) + } + if err := mcp.AddReceivingCustomMethod(server, interceptors.MethodInvoke, e.handleInvoke); err != nil { + return fmt.Errorf("interceptors: register %q: %w", interceptors.MethodInvoke, err) + } server.AddReceivingMiddleware(e.initMiddleware()) + return nil } // AddInterceptor registers an interceptor. It panics if the interceptor @@ -128,6 +134,10 @@ func (e *Extension) LocalChain(ctx context.Context, server *mcp.Server) (*chain. Name: "interceptor-chain-client", Version: "internal", }, nil) + if err := RegisterSendingMethods(client); err != nil { + ss.Close() + return nil, err + } cs, err := client.Connect(ctx, clientTransport, nil) if err != nil { ss.Close() diff --git a/go/sdk/interceptors/extension/server_integration_test.go b/go/sdk/interceptors/extension/server_integration_test.go index 85e8dab..732d1cd 100644 --- a/go/sdk/interceptors/extension/server_integration_test.go +++ b/go/sdk/interceptors/extension/server_integration_test.go @@ -637,20 +637,23 @@ func TestCustomMethodsFlowThroughMiddleware(t *testing.T) { require.NoError(t, err) assert.Greater(t, count.Swap(0), int64(0), "middleware must fire for tools/call") - var listResult interceptors.ListResult - err = cs.CallCustom(context.Background(), interceptors.MethodList, nil, &listResult) + listResult, err := mcp.CallCustomMethod[*interceptors.ListParams, *interceptors.ListResult]( + context.Background(), cs, interceptors.MethodList, nil, + ) require.NoError(t, err) assert.Len(t, listResult.Interceptors, 1) assert.Greater(t, count.Swap(0), int64(0), "middleware must fire for interceptors/list") payload, _ := json.Marshal(map[string]any{"name": "echo", "arguments": map[string]any{}}) - var invokeResult interceptors.InvokeResult - err = cs.CallCustom(context.Background(), interceptors.MethodInvoke, &interceptors.InvokeParams{ - Name: "v1", - Event: interceptors.EventToolsCall, - Phase: interceptors.PhaseRequest, - Payload: payload, - }, &invokeResult) + _, err = mcp.CallCustomMethod[*interceptors.InvokeParams, *interceptors.InvokeResult]( + context.Background(), cs, interceptors.MethodInvoke, + &interceptors.InvokeParams{ + Name: "v1", + Event: interceptors.EventToolsCall, + Phase: interceptors.PhaseRequest, + Payload: payload, + }, + ) require.NoError(t, err) assert.Greater(t, count.Swap(0), int64(0), "middleware must fire for interceptor/invoke") } @@ -676,8 +679,9 @@ func TestMiddlewareCanRejectCustomMethods(t *testing.T) { mcpServer.AddReceivingMiddleware(blockingMiddleware) cs := connectHTTPClient(t, mcpServer) - var listResult interceptors.ListResult - err := cs.CallCustom(context.Background(), interceptors.MethodList, nil, &listResult) + _, err := mcp.CallCustomMethod[*interceptors.ListParams, *interceptors.ListResult]( + context.Background(), cs, interceptors.MethodList, nil, + ) assert.Error(t, err, "blockingMiddleware should reject interceptors/list") assert.True(t, rejected.Load()) } diff --git a/go/sdk/interceptors/extension/testharness_test.go b/go/sdk/interceptors/extension/testharness_test.go index b562ca8..19aa582 100644 --- a/go/sdk/interceptors/extension/testharness_test.go +++ b/go/sdk/interceptors/extension/testharness_test.go @@ -47,7 +47,7 @@ func setupWithTools(t *testing.T, tools []testTool, is ...interceptors.Intercept for _, i := range is { ext.AddInterceptor(i) } - ext.Install(mcpServer) + require.NoError(t, ext.Install(mcpServer)) // Create a chain via LocalChain (in-memory transport). chain, err := ext.LocalChain(context.Background(), mcpServer) @@ -64,6 +64,7 @@ func setupWithTools(t *testing.T, tools []testTool, is ...interceptors.Intercept t.Cleanup(httpServer.Close) client := mcp.NewClient(&mcp.Implementation{Name: "test-client", Version: "0.1.0"}, nil) + require.NoError(t, extension.RegisterSendingMethods(client)) cs, err := client.Connect(context.Background(), &mcp.StreamableClientTransport{ Endpoint: httpServer.URL, }, nil) @@ -148,7 +149,7 @@ func buildServer(t *testing.T, is ...interceptors.Interceptor) *mcp.Server { for _, i := range is { ext.AddInterceptor(i) } - ext.Install(mcpServer) + require.NoError(t, ext.Install(mcpServer)) return mcpServer } @@ -164,6 +165,7 @@ func connectHTTPClient(t *testing.T, srv *mcp.Server) *mcp.ClientSession { httpServer := httptest.NewServer(handler) t.Cleanup(httpServer.Close) client := mcp.NewClient(&mcp.Implementation{Name: "test-client", Version: "0.1.0"}, nil) + require.NoError(t, extension.RegisterSendingMethods(client)) cs, err := client.Connect(context.Background(), &mcp.StreamableClientTransport{ Endpoint: httpServer.URL, }, nil) diff --git a/go/sdk/interceptors/integrations/gomiddleware/doc.go b/go/sdk/interceptors/integrations/gomiddleware/doc.go index 3ca8990..258f328 100644 --- a/go/sdk/interceptors/integrations/gomiddleware/doc.go +++ b/go/sdk/interceptors/integrations/gomiddleware/doc.go @@ -16,11 +16,13 @@ // // # Usage // -// // Create interceptor extension (registers interceptors as resources) +// // Create interceptor extension (exposes interceptors as custom methods) // ext := extension.New() // ext.AddInterceptor(myValidator) // ext.AddInterceptor(myMutator) -// ext.Install(mcpServer) +// if err := ext.Install(mcpServer); err != nil { +// return err +// } // // // Create chain via in-memory transport // chain, err := ext.LocalChain(ctx, mcpServer) diff --git a/go/sdk/interceptors/integrations/gomiddleware/middleware.go b/go/sdk/interceptors/integrations/gomiddleware/middleware.go index 0086023..e30495d 100644 --- a/go/sdk/interceptors/integrations/gomiddleware/middleware.go +++ b/go/sdk/interceptors/integrations/gomiddleware/middleware.go @@ -66,7 +66,7 @@ var skipMethods = map[string]bool{ // interceptor/invoke RPCs. Install it on an [mcp.Server] via // [mcp.Server.AddReceivingMiddleware]: // -// chain, _ := srv.LocalChain(ctx) +// chain, _ := ext.LocalChain(ctx, mcpServer) // mcpServer.AddReceivingMiddleware( // gomiddleware.Middleware(chain, gomiddleware.WithLogger(logger)), // ) diff --git a/go/sdk/interceptors/integrations/gomiddleware/middleware_test.go b/go/sdk/interceptors/integrations/gomiddleware/middleware_test.go index 66d15dc..457fd32 100644 --- a/go/sdk/interceptors/integrations/gomiddleware/middleware_test.go +++ b/go/sdk/interceptors/integrations/gomiddleware/middleware_test.go @@ -41,7 +41,7 @@ func setup(t *testing.T, is ...interceptors.Interceptor) *mcp.ClientSession { for _, i := range is { ext.AddInterceptor(i) } - ext.Install(mcpServer) + require.NoError(t, ext.Install(mcpServer)) // Create chain via LocalChain (in-memory transport). chain, err := ext.LocalChain(context.Background(), mcpServer) @@ -267,7 +267,7 @@ func TestMiddlewareWithContextProvider(t *testing.T) { ext := extension.New() ext.AddInterceptor(principalCheck) - ext.Install(mcpServer) + require.NoError(t, ext.Install(mcpServer)) chain, err := ext.LocalChain(context.Background(), mcpServer) require.NoError(t, err) diff --git a/go/sdk/vendor/github.com/davecgh/go-spew/LICENSE b/go/sdk/vendor/github.com/davecgh/go-spew/LICENSE deleted file mode 100644 index bc52e96..0000000 --- a/go/sdk/vendor/github.com/davecgh/go-spew/LICENSE +++ /dev/null @@ -1,15 +0,0 @@ -ISC License - -Copyright (c) 2012-2016 Dave Collins - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/go/sdk/vendor/github.com/davecgh/go-spew/spew/bypass.go b/go/sdk/vendor/github.com/davecgh/go-spew/spew/bypass.go deleted file mode 100644 index 70ddeaa..0000000 --- a/go/sdk/vendor/github.com/davecgh/go-spew/spew/bypass.go +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (c) 2015-2016 Dave Collins -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -// NOTE: Due to the following build constraints, this file will only be compiled -// when the code is not running on Google App Engine, compiled by GopherJS, and -// "-tags safe" is not added to the go build command line. The "disableunsafe" -// tag is deprecated and thus should not be used. -// Go versions prior to 1.4 are disabled because they use a different layout -// for interfaces which make the implementation of unsafeReflectValue more complex. -//go:build !js && !appengine && !safe && !disableunsafe && go1.4 -// +build !js,!appengine,!safe,!disableunsafe,go1.4 - -package spew - -import ( - "reflect" - "unsafe" -) - -const ( - // UnsafeDisabled is a build-time constant which specifies whether or - // not access to the unsafe package is available. - UnsafeDisabled = false - - // ptrSize is the size of a pointer on the current arch. - ptrSize = unsafe.Sizeof((*byte)(nil)) -) - -type flag uintptr - -var ( - // flagRO indicates whether the value field of a reflect.Value - // is read-only. - flagRO flag - - // flagAddr indicates whether the address of the reflect.Value's - // value may be taken. - flagAddr flag -) - -// flagKindMask holds the bits that make up the kind -// part of the flags field. In all the supported versions, -// it is in the lower 5 bits. -const flagKindMask = flag(0x1f) - -// Different versions of Go have used different -// bit layouts for the flags type. This table -// records the known combinations. -var okFlags = []struct { - ro, addr flag -}{{ - // From Go 1.4 to 1.5 - ro: 1 << 5, - addr: 1 << 7, -}, { - // Up to Go tip. - ro: 1<<5 | 1<<6, - addr: 1 << 8, -}} - -var flagValOffset = func() uintptr { - field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") - if !ok { - panic("reflect.Value has no flag field") - } - return field.Offset -}() - -// flagField returns a pointer to the flag field of a reflect.Value. -func flagField(v *reflect.Value) *flag { - return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset)) -} - -// unsafeReflectValue converts the passed reflect.Value into a one that bypasses -// the typical safety restrictions preventing access to unaddressable and -// unexported data. It works by digging the raw pointer to the underlying -// value out of the protected value and generating a new unprotected (unsafe) -// reflect.Value to it. -// -// This allows us to check for implementations of the Stringer and error -// interfaces to be used for pretty printing ordinarily unaddressable and -// inaccessible values such as unexported struct fields. -func unsafeReflectValue(v reflect.Value) reflect.Value { - if !v.IsValid() || (v.CanInterface() && v.CanAddr()) { - return v - } - flagFieldPtr := flagField(&v) - *flagFieldPtr &^= flagRO - *flagFieldPtr |= flagAddr - return v -} - -// Sanity checks against future reflect package changes -// to the type or semantics of the Value.flag field. -func init() { - field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") - if !ok { - panic("reflect.Value has no flag field") - } - if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() { - panic("reflect.Value flag field has changed kind") - } - type t0 int - var t struct { - A t0 - // t0 will have flagEmbedRO set. - t0 - // a will have flagStickyRO set - a t0 - } - vA := reflect.ValueOf(t).FieldByName("A") - va := reflect.ValueOf(t).FieldByName("a") - vt0 := reflect.ValueOf(t).FieldByName("t0") - - // Infer flagRO from the difference between the flags - // for the (otherwise identical) fields in t. - flagPublic := *flagField(&vA) - flagWithRO := *flagField(&va) | *flagField(&vt0) - flagRO = flagPublic ^ flagWithRO - - // Infer flagAddr from the difference between a value - // taken from a pointer and not. - vPtrA := reflect.ValueOf(&t).Elem().FieldByName("A") - flagNoPtr := *flagField(&vA) - flagPtr := *flagField(&vPtrA) - flagAddr = flagNoPtr ^ flagPtr - - // Check that the inferred flags tally with one of the known versions. - for _, f := range okFlags { - if flagRO == f.ro && flagAddr == f.addr { - return - } - } - panic("reflect.Value read-only flag has changed semantics") -} diff --git a/go/sdk/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go b/go/sdk/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go deleted file mode 100644 index 5e2d890..0000000 --- a/go/sdk/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2015-2016 Dave Collins -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -// NOTE: Due to the following build constraints, this file will only be compiled -// when the code is running on Google App Engine, compiled by GopherJS, or -// "-tags safe" is added to the go build command line. The "disableunsafe" -// tag is deprecated and thus should not be used. -//go:build js || appengine || safe || disableunsafe || !go1.4 -// +build js appengine safe disableunsafe !go1.4 - -package spew - -import "reflect" - -const ( - // UnsafeDisabled is a build-time constant which specifies whether or - // not access to the unsafe package is available. - UnsafeDisabled = true -) - -// unsafeReflectValue typically converts the passed reflect.Value into a one -// that bypasses the typical safety restrictions preventing access to -// unaddressable and unexported data. However, doing this relies on access to -// the unsafe package. This is a stub version which simply returns the passed -// reflect.Value when the unsafe package is not available. -func unsafeReflectValue(v reflect.Value) reflect.Value { - return v -} diff --git a/go/sdk/vendor/github.com/davecgh/go-spew/spew/common.go b/go/sdk/vendor/github.com/davecgh/go-spew/spew/common.go deleted file mode 100644 index 1be8ce9..0000000 --- a/go/sdk/vendor/github.com/davecgh/go-spew/spew/common.go +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package spew - -import ( - "bytes" - "fmt" - "io" - "reflect" - "sort" - "strconv" -) - -// Some constants in the form of bytes to avoid string overhead. This mirrors -// the technique used in the fmt package. -var ( - panicBytes = []byte("(PANIC=") - plusBytes = []byte("+") - iBytes = []byte("i") - trueBytes = []byte("true") - falseBytes = []byte("false") - interfaceBytes = []byte("(interface {})") - commaNewlineBytes = []byte(",\n") - newlineBytes = []byte("\n") - openBraceBytes = []byte("{") - openBraceNewlineBytes = []byte("{\n") - closeBraceBytes = []byte("}") - asteriskBytes = []byte("*") - colonBytes = []byte(":") - colonSpaceBytes = []byte(": ") - openParenBytes = []byte("(") - closeParenBytes = []byte(")") - spaceBytes = []byte(" ") - pointerChainBytes = []byte("->") - nilAngleBytes = []byte("") - maxNewlineBytes = []byte("\n") - maxShortBytes = []byte("") - circularBytes = []byte("") - circularShortBytes = []byte("") - invalidAngleBytes = []byte("") - openBracketBytes = []byte("[") - closeBracketBytes = []byte("]") - percentBytes = []byte("%") - precisionBytes = []byte(".") - openAngleBytes = []byte("<") - closeAngleBytes = []byte(">") - openMapBytes = []byte("map[") - closeMapBytes = []byte("]") - lenEqualsBytes = []byte("len=") - capEqualsBytes = []byte("cap=") -) - -// hexDigits is used to map a decimal value to a hex digit. -var hexDigits = "0123456789abcdef" - -// catchPanic handles any panics that might occur during the handleMethods -// calls. -func catchPanic(w io.Writer, v reflect.Value) { - if err := recover(); err != nil { - w.Write(panicBytes) - fmt.Fprintf(w, "%v", err) - w.Write(closeParenBytes) - } -} - -// handleMethods attempts to call the Error and String methods on the underlying -// type the passed reflect.Value represents and outputes the result to Writer w. -// -// It handles panics in any called methods by catching and displaying the error -// as the formatted value. -func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) { - // We need an interface to check if the type implements the error or - // Stringer interface. However, the reflect package won't give us an - // interface on certain things like unexported struct fields in order - // to enforce visibility rules. We use unsafe, when it's available, - // to bypass these restrictions since this package does not mutate the - // values. - if !v.CanInterface() { - if UnsafeDisabled { - return false - } - - v = unsafeReflectValue(v) - } - - // Choose whether or not to do error and Stringer interface lookups against - // the base type or a pointer to the base type depending on settings. - // Technically calling one of these methods with a pointer receiver can - // mutate the value, however, types which choose to satisify an error or - // Stringer interface with a pointer receiver should not be mutating their - // state inside these interface methods. - if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() { - v = unsafeReflectValue(v) - } - if v.CanAddr() { - v = v.Addr() - } - - // Is it an error or Stringer? - switch iface := v.Interface().(type) { - case error: - defer catchPanic(w, v) - if cs.ContinueOnMethod { - w.Write(openParenBytes) - w.Write([]byte(iface.Error())) - w.Write(closeParenBytes) - w.Write(spaceBytes) - return false - } - - w.Write([]byte(iface.Error())) - return true - - case fmt.Stringer: - defer catchPanic(w, v) - if cs.ContinueOnMethod { - w.Write(openParenBytes) - w.Write([]byte(iface.String())) - w.Write(closeParenBytes) - w.Write(spaceBytes) - return false - } - w.Write([]byte(iface.String())) - return true - } - return false -} - -// printBool outputs a boolean value as true or false to Writer w. -func printBool(w io.Writer, val bool) { - if val { - w.Write(trueBytes) - } else { - w.Write(falseBytes) - } -} - -// printInt outputs a signed integer value to Writer w. -func printInt(w io.Writer, val int64, base int) { - w.Write([]byte(strconv.FormatInt(val, base))) -} - -// printUint outputs an unsigned integer value to Writer w. -func printUint(w io.Writer, val uint64, base int) { - w.Write([]byte(strconv.FormatUint(val, base))) -} - -// printFloat outputs a floating point value using the specified precision, -// which is expected to be 32 or 64bit, to Writer w. -func printFloat(w io.Writer, val float64, precision int) { - w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision))) -} - -// printComplex outputs a complex value using the specified float precision -// for the real and imaginary parts to Writer w. -func printComplex(w io.Writer, c complex128, floatPrecision int) { - r := real(c) - w.Write(openParenBytes) - w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision))) - i := imag(c) - if i >= 0 { - w.Write(plusBytes) - } - w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision))) - w.Write(iBytes) - w.Write(closeParenBytes) -} - -// printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x' -// prefix to Writer w. -func printHexPtr(w io.Writer, p uintptr) { - // Null pointer. - num := uint64(p) - if num == 0 { - w.Write(nilAngleBytes) - return - } - - // Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix - buf := make([]byte, 18) - - // It's simpler to construct the hex string right to left. - base := uint64(16) - i := len(buf) - 1 - for num >= base { - buf[i] = hexDigits[num%base] - num /= base - i-- - } - buf[i] = hexDigits[num] - - // Add '0x' prefix. - i-- - buf[i] = 'x' - i-- - buf[i] = '0' - - // Strip unused leading bytes. - buf = buf[i:] - w.Write(buf) -} - -// valuesSorter implements sort.Interface to allow a slice of reflect.Value -// elements to be sorted. -type valuesSorter struct { - values []reflect.Value - strings []string // either nil or same len and values - cs *ConfigState -} - -// newValuesSorter initializes a valuesSorter instance, which holds a set of -// surrogate keys on which the data should be sorted. It uses flags in -// ConfigState to decide if and how to populate those surrogate keys. -func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface { - vs := &valuesSorter{values: values, cs: cs} - if canSortSimply(vs.values[0].Kind()) { - return vs - } - if !cs.DisableMethods { - vs.strings = make([]string, len(values)) - for i := range vs.values { - b := bytes.Buffer{} - if !handleMethods(cs, &b, vs.values[i]) { - vs.strings = nil - break - } - vs.strings[i] = b.String() - } - } - if vs.strings == nil && cs.SpewKeys { - vs.strings = make([]string, len(values)) - for i := range vs.values { - vs.strings[i] = Sprintf("%#v", vs.values[i].Interface()) - } - } - return vs -} - -// canSortSimply tests whether a reflect.Kind is a primitive that can be sorted -// directly, or whether it should be considered for sorting by surrogate keys -// (if the ConfigState allows it). -func canSortSimply(kind reflect.Kind) bool { - // This switch parallels valueSortLess, except for the default case. - switch kind { - case reflect.Bool: - return true - case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: - return true - case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: - return true - case reflect.Float32, reflect.Float64: - return true - case reflect.String: - return true - case reflect.Uintptr: - return true - case reflect.Array: - return true - } - return false -} - -// Len returns the number of values in the slice. It is part of the -// sort.Interface implementation. -func (s *valuesSorter) Len() int { - return len(s.values) -} - -// Swap swaps the values at the passed indices. It is part of the -// sort.Interface implementation. -func (s *valuesSorter) Swap(i, j int) { - s.values[i], s.values[j] = s.values[j], s.values[i] - if s.strings != nil { - s.strings[i], s.strings[j] = s.strings[j], s.strings[i] - } -} - -// valueSortLess returns whether the first value should sort before the second -// value. It is used by valueSorter.Less as part of the sort.Interface -// implementation. -func valueSortLess(a, b reflect.Value) bool { - switch a.Kind() { - case reflect.Bool: - return !a.Bool() && b.Bool() - case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: - return a.Int() < b.Int() - case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: - return a.Uint() < b.Uint() - case reflect.Float32, reflect.Float64: - return a.Float() < b.Float() - case reflect.String: - return a.String() < b.String() - case reflect.Uintptr: - return a.Uint() < b.Uint() - case reflect.Array: - // Compare the contents of both arrays. - l := a.Len() - for i := 0; i < l; i++ { - av := a.Index(i) - bv := b.Index(i) - if av.Interface() == bv.Interface() { - continue - } - return valueSortLess(av, bv) - } - } - return a.String() < b.String() -} - -// Less returns whether the value at index i should sort before the -// value at index j. It is part of the sort.Interface implementation. -func (s *valuesSorter) Less(i, j int) bool { - if s.strings == nil { - return valueSortLess(s.values[i], s.values[j]) - } - return s.strings[i] < s.strings[j] -} - -// sortValues is a sort function that handles both native types and any type that -// can be converted to error or Stringer. Other inputs are sorted according to -// their Value.String() value to ensure display stability. -func sortValues(values []reflect.Value, cs *ConfigState) { - if len(values) == 0 { - return - } - sort.Sort(newValuesSorter(values, cs)) -} diff --git a/go/sdk/vendor/github.com/davecgh/go-spew/spew/config.go b/go/sdk/vendor/github.com/davecgh/go-spew/spew/config.go deleted file mode 100644 index 161895f..0000000 --- a/go/sdk/vendor/github.com/davecgh/go-spew/spew/config.go +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package spew - -import ( - "bytes" - "fmt" - "io" - "os" -) - -// ConfigState houses the configuration options used by spew to format and -// display values. There is a global instance, Config, that is used to control -// all top-level Formatter and Dump functionality. Each ConfigState instance -// provides methods equivalent to the top-level functions. -// -// The zero value for ConfigState provides no indentation. You would typically -// want to set it to a space or a tab. -// -// Alternatively, you can use NewDefaultConfig to get a ConfigState instance -// with default settings. See the documentation of NewDefaultConfig for default -// values. -type ConfigState struct { - // Indent specifies the string to use for each indentation level. The - // global config instance that all top-level functions use set this to a - // single space by default. If you would like more indentation, you might - // set this to a tab with "\t" or perhaps two spaces with " ". - Indent string - - // MaxDepth controls the maximum number of levels to descend into nested - // data structures. The default, 0, means there is no limit. - // - // NOTE: Circular data structures are properly detected, so it is not - // necessary to set this value unless you specifically want to limit deeply - // nested data structures. - MaxDepth int - - // DisableMethods specifies whether or not error and Stringer interfaces are - // invoked for types that implement them. - DisableMethods bool - - // DisablePointerMethods specifies whether or not to check for and invoke - // error and Stringer interfaces on types which only accept a pointer - // receiver when the current type is not a pointer. - // - // NOTE: This might be an unsafe action since calling one of these methods - // with a pointer receiver could technically mutate the value, however, - // in practice, types which choose to satisify an error or Stringer - // interface with a pointer receiver should not be mutating their state - // inside these interface methods. As a result, this option relies on - // access to the unsafe package, so it will not have any effect when - // running in environments without access to the unsafe package such as - // Google App Engine or with the "safe" build tag specified. - DisablePointerMethods bool - - // DisablePointerAddresses specifies whether to disable the printing of - // pointer addresses. This is useful when diffing data structures in tests. - DisablePointerAddresses bool - - // DisableCapacities specifies whether to disable the printing of capacities - // for arrays, slices, maps and channels. This is useful when diffing - // data structures in tests. - DisableCapacities bool - - // ContinueOnMethod specifies whether or not recursion should continue once - // a custom error or Stringer interface is invoked. The default, false, - // means it will print the results of invoking the custom error or Stringer - // interface and return immediately instead of continuing to recurse into - // the internals of the data type. - // - // NOTE: This flag does not have any effect if method invocation is disabled - // via the DisableMethods or DisablePointerMethods options. - ContinueOnMethod bool - - // SortKeys specifies map keys should be sorted before being printed. Use - // this to have a more deterministic, diffable output. Note that only - // native types (bool, int, uint, floats, uintptr and string) and types - // that support the error or Stringer interfaces (if methods are - // enabled) are supported, with other types sorted according to the - // reflect.Value.String() output which guarantees display stability. - SortKeys bool - - // SpewKeys specifies that, as a last resort attempt, map keys should - // be spewed to strings and sorted by those strings. This is only - // considered if SortKeys is true. - SpewKeys bool -} - -// Config is the active configuration of the top-level functions. -// The configuration can be changed by modifying the contents of spew.Config. -var Config = ConfigState{Indent: " "} - -// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the formatted string as a value that satisfies error. See NewFormatter -// for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) { - return fmt.Errorf(format, c.convertArgs(a)...) -} - -// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) { - return fmt.Fprint(w, c.convertArgs(a)...) -} - -// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { - return fmt.Fprintf(w, format, c.convertArgs(a)...) -} - -// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it -// passed with a Formatter interface returned by c.NewFormatter. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { - return fmt.Fprintln(w, c.convertArgs(a)...) -} - -// Print is a wrapper for fmt.Print that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Print(c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Print(a ...interface{}) (n int, err error) { - return fmt.Print(c.convertArgs(a)...) -} - -// Printf is a wrapper for fmt.Printf that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) { - return fmt.Printf(format, c.convertArgs(a)...) -} - -// Println is a wrapper for fmt.Println that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Println(c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Println(a ...interface{}) (n int, err error) { - return fmt.Println(c.convertArgs(a)...) -} - -// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the resulting string. See NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Sprint(a ...interface{}) string { - return fmt.Sprint(c.convertArgs(a)...) -} - -// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the resulting string. See NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Sprintf(format string, a ...interface{}) string { - return fmt.Sprintf(format, c.convertArgs(a)...) -} - -// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it -// were passed with a Formatter interface returned by c.NewFormatter. It -// returns the resulting string. See NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Sprintln(a ...interface{}) string { - return fmt.Sprintln(c.convertArgs(a)...) -} - -/* -NewFormatter returns a custom formatter that satisfies the fmt.Formatter -interface. As a result, it integrates cleanly with standard fmt package -printing functions. The formatter is useful for inline printing of smaller data -types similar to the standard %v format specifier. - -The custom formatter only responds to the %v (most compact), %+v (adds pointer -addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb -combinations. Any other verbs such as %x and %q will be sent to the the -standard fmt package for formatting. In addition, the custom formatter ignores -the width and precision arguments (however they will still work on the format -specifiers not handled by the custom formatter). - -Typically this function shouldn't be called directly. It is much easier to make -use of the custom formatter by calling one of the convenience functions such as -c.Printf, c.Println, or c.Printf. -*/ -func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter { - return newFormatter(c, v) -} - -// Fdump formats and displays the passed arguments to io.Writer w. It formats -// exactly the same as Dump. -func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) { - fdump(c, w, a...) -} - -/* -Dump displays the passed parameters to standard out with newlines, customizable -indentation, and additional debug information such as complete types and all -pointer addresses used to indirect to the final value. It provides the -following features over the built-in printing facilities provided by the fmt -package: - - - Pointers are dereferenced and followed - - Circular data structures are detected and handled properly - - Custom Stringer/error interfaces are optionally invoked, including - on unexported types - - Custom types which only implement the Stringer/error interfaces via - a pointer receiver are optionally invoked when passing non-pointer - variables - - Byte arrays and slices are dumped like the hexdump -C command which - includes offsets, byte values in hex, and ASCII output - -The configuration options are controlled by modifying the public members -of c. See ConfigState for options documentation. - -See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to -get the formatted result as a string. -*/ -func (c *ConfigState) Dump(a ...interface{}) { - fdump(c, os.Stdout, a...) -} - -// Sdump returns a string with the passed arguments formatted exactly the same -// as Dump. -func (c *ConfigState) Sdump(a ...interface{}) string { - var buf bytes.Buffer - fdump(c, &buf, a...) - return buf.String() -} - -// convertArgs accepts a slice of arguments and returns a slice of the same -// length with each argument converted to a spew Formatter interface using -// the ConfigState associated with s. -func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) { - formatters = make([]interface{}, len(args)) - for index, arg := range args { - formatters[index] = newFormatter(c, arg) - } - return formatters -} - -// NewDefaultConfig returns a ConfigState with the following default settings. -// -// Indent: " " -// MaxDepth: 0 -// DisableMethods: false -// DisablePointerMethods: false -// ContinueOnMethod: false -// SortKeys: false -func NewDefaultConfig() *ConfigState { - return &ConfigState{Indent: " "} -} diff --git a/go/sdk/vendor/github.com/davecgh/go-spew/spew/doc.go b/go/sdk/vendor/github.com/davecgh/go-spew/spew/doc.go deleted file mode 100644 index 722e9aa..0000000 --- a/go/sdk/vendor/github.com/davecgh/go-spew/spew/doc.go +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* -Package spew implements a deep pretty printer for Go data structures to aid in -debugging. - -A quick overview of the additional features spew provides over the built-in -printing facilities for Go data types are as follows: - - - Pointers are dereferenced and followed - - Circular data structures are detected and handled properly - - Custom Stringer/error interfaces are optionally invoked, including - on unexported types - - Custom types which only implement the Stringer/error interfaces via - a pointer receiver are optionally invoked when passing non-pointer - variables - - Byte arrays and slices are dumped like the hexdump -C command which - includes offsets, byte values in hex, and ASCII output (only when using - Dump style) - -There are two different approaches spew allows for dumping Go data structures: - - - Dump style which prints with newlines, customizable indentation, - and additional debug information such as types and all pointer addresses - used to indirect to the final value - - A custom Formatter interface that integrates cleanly with the standard fmt - package and replaces %v, %+v, %#v, and %#+v to provide inline printing - similar to the default %v while providing the additional functionality - outlined above and passing unsupported format verbs such as %x and %q - along to fmt - -# Quick Start - -This section demonstrates how to quickly get started with spew. See the -sections below for further details on formatting and configuration options. - -To dump a variable with full newlines, indentation, type, and pointer -information use Dump, Fdump, or Sdump: - - spew.Dump(myVar1, myVar2, ...) - spew.Fdump(someWriter, myVar1, myVar2, ...) - str := spew.Sdump(myVar1, myVar2, ...) - -Alternatively, if you would prefer to use format strings with a compacted inline -printing style, use the convenience wrappers Printf, Fprintf, etc with -%v (most compact), %+v (adds pointer addresses), %#v (adds types), or -%#+v (adds types and pointer addresses): - - spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) - spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) - spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) - spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) - -# Configuration Options - -Configuration of spew is handled by fields in the ConfigState type. For -convenience, all of the top-level functions use a global state available -via the spew.Config global. - -It is also possible to create a ConfigState instance that provides methods -equivalent to the top-level functions. This allows concurrent configuration -options. See the ConfigState documentation for more details. - -The following configuration options are available: - - - Indent - String to use for each indentation level for Dump functions. - It is a single space by default. A popular alternative is "\t". - - - MaxDepth - Maximum number of levels to descend into nested data structures. - There is no limit by default. - - - DisableMethods - Disables invocation of error and Stringer interface methods. - Method invocation is enabled by default. - - - DisablePointerMethods - Disables invocation of error and Stringer interface methods on types - which only accept pointer receivers from non-pointer variables. - Pointer method invocation is enabled by default. - - - DisablePointerAddresses - DisablePointerAddresses specifies whether to disable the printing of - pointer addresses. This is useful when diffing data structures in tests. - - - DisableCapacities - DisableCapacities specifies whether to disable the printing of - capacities for arrays, slices, maps and channels. This is useful when - diffing data structures in tests. - - - ContinueOnMethod - Enables recursion into types after invoking error and Stringer interface - methods. Recursion after method invocation is disabled by default. - - - SortKeys - Specifies map keys should be sorted before being printed. Use - this to have a more deterministic, diffable output. Note that - only native types (bool, int, uint, floats, uintptr and string) - and types which implement error or Stringer interfaces are - supported with other types sorted according to the - reflect.Value.String() output which guarantees display - stability. Natural map order is used by default. - - - SpewKeys - Specifies that, as a last resort attempt, map keys should be - spewed to strings and sorted by those strings. This is only - considered if SortKeys is true. - -# Dump Usage - -Simply call spew.Dump with a list of variables you want to dump: - - spew.Dump(myVar1, myVar2, ...) - -You may also call spew.Fdump if you would prefer to output to an arbitrary -io.Writer. For example, to dump to standard error: - - spew.Fdump(os.Stderr, myVar1, myVar2, ...) - -A third option is to call spew.Sdump to get the formatted output as a string: - - str := spew.Sdump(myVar1, myVar2, ...) - -# Sample Dump Output - -See the Dump example for details on the setup of the types and variables being -shown here. - - (main.Foo) { - unexportedField: (*main.Bar)(0xf84002e210)({ - flag: (main.Flag) flagTwo, - data: (uintptr) - }), - ExportedField: (map[interface {}]interface {}) (len=1) { - (string) (len=3) "one": (bool) true - } - } - -Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C -command as shown. - - ([]uint8) (len=32 cap=32) { - 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... | - 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0| - 00000020 31 32 |12| - } - -# Custom Formatter - -Spew provides a custom formatter that implements the fmt.Formatter interface -so that it integrates cleanly with standard fmt package printing functions. The -formatter is useful for inline printing of smaller data types similar to the -standard %v format specifier. - -The custom formatter only responds to the %v (most compact), %+v (adds pointer -addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb -combinations. Any other verbs such as %x and %q will be sent to the the -standard fmt package for formatting. In addition, the custom formatter ignores -the width and precision arguments (however they will still work on the format -specifiers not handled by the custom formatter). - -# Custom Formatter Usage - -The simplest way to make use of the spew custom formatter is to call one of the -convenience functions such as spew.Printf, spew.Println, or spew.Printf. The -functions have syntax you are most likely already familiar with: - - spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) - spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) - spew.Println(myVar, myVar2) - spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) - spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) - -See the Index for the full list convenience functions. - -# Sample Formatter Output - -Double pointer to a uint8: - - %v: <**>5 - %+v: <**>(0xf8400420d0->0xf8400420c8)5 - %#v: (**uint8)5 - %#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5 - -Pointer to circular struct with a uint8 field and a pointer to itself: - - %v: <*>{1 <*>} - %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)} - %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)} - %#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)} - -See the Printf example for details on the setup of variables being shown -here. - -# Errors - -Since it is possible for custom Stringer/error interfaces to panic, spew -detects them and handles them internally by printing the panic information -inline with the output. Since spew is intended to provide deep pretty printing -capabilities on structures, it intentionally does not return any errors. -*/ -package spew diff --git a/go/sdk/vendor/github.com/davecgh/go-spew/spew/dump.go b/go/sdk/vendor/github.com/davecgh/go-spew/spew/dump.go deleted file mode 100644 index 8323041..0000000 --- a/go/sdk/vendor/github.com/davecgh/go-spew/spew/dump.go +++ /dev/null @@ -1,509 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package spew - -import ( - "bytes" - "encoding/hex" - "fmt" - "io" - "os" - "reflect" - "regexp" - "strconv" - "strings" -) - -var ( - // uint8Type is a reflect.Type representing a uint8. It is used to - // convert cgo types to uint8 slices for hexdumping. - uint8Type = reflect.TypeOf(uint8(0)) - - // cCharRE is a regular expression that matches a cgo char. - // It is used to detect character arrays to hexdump them. - cCharRE = regexp.MustCompile(`^.*\._Ctype_char$`) - - // cUnsignedCharRE is a regular expression that matches a cgo unsigned - // char. It is used to detect unsigned character arrays to hexdump - // them. - cUnsignedCharRE = regexp.MustCompile(`^.*\._Ctype_unsignedchar$`) - - // cUint8tCharRE is a regular expression that matches a cgo uint8_t. - // It is used to detect uint8_t arrays to hexdump them. - cUint8tCharRE = regexp.MustCompile(`^.*\._Ctype_uint8_t$`) -) - -// dumpState contains information about the state of a dump operation. -type dumpState struct { - w io.Writer - depth int - pointers map[uintptr]int - ignoreNextType bool - ignoreNextIndent bool - cs *ConfigState -} - -// indent performs indentation according to the depth level and cs.Indent -// option. -func (d *dumpState) indent() { - if d.ignoreNextIndent { - d.ignoreNextIndent = false - return - } - d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth)) -} - -// unpackValue returns values inside of non-nil interfaces when possible. -// This is useful for data types like structs, arrays, slices, and maps which -// can contain varying types packed inside an interface. -func (d *dumpState) unpackValue(v reflect.Value) reflect.Value { - if v.Kind() == reflect.Interface && !v.IsNil() { - v = v.Elem() - } - return v -} - -// dumpPtr handles formatting of pointers by indirecting them as necessary. -func (d *dumpState) dumpPtr(v reflect.Value) { - // Remove pointers at or below the current depth from map used to detect - // circular refs. - for k, depth := range d.pointers { - if depth >= d.depth { - delete(d.pointers, k) - } - } - - // Keep list of all dereferenced pointers to show later. - pointerChain := make([]uintptr, 0) - - // Figure out how many levels of indirection there are by dereferencing - // pointers and unpacking interfaces down the chain while detecting circular - // references. - nilFound := false - cycleFound := false - indirects := 0 - ve := v - for ve.Kind() == reflect.Ptr { - if ve.IsNil() { - nilFound = true - break - } - indirects++ - addr := ve.Pointer() - pointerChain = append(pointerChain, addr) - if pd, ok := d.pointers[addr]; ok && pd < d.depth { - cycleFound = true - indirects-- - break - } - d.pointers[addr] = d.depth - - ve = ve.Elem() - if ve.Kind() == reflect.Interface { - if ve.IsNil() { - nilFound = true - break - } - ve = ve.Elem() - } - } - - // Display type information. - d.w.Write(openParenBytes) - d.w.Write(bytes.Repeat(asteriskBytes, indirects)) - d.w.Write([]byte(ve.Type().String())) - d.w.Write(closeParenBytes) - - // Display pointer information. - if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 { - d.w.Write(openParenBytes) - for i, addr := range pointerChain { - if i > 0 { - d.w.Write(pointerChainBytes) - } - printHexPtr(d.w, addr) - } - d.w.Write(closeParenBytes) - } - - // Display dereferenced value. - d.w.Write(openParenBytes) - switch { - case nilFound: - d.w.Write(nilAngleBytes) - - case cycleFound: - d.w.Write(circularBytes) - - default: - d.ignoreNextType = true - d.dump(ve) - } - d.w.Write(closeParenBytes) -} - -// dumpSlice handles formatting of arrays and slices. Byte (uint8 under -// reflection) arrays and slices are dumped in hexdump -C fashion. -func (d *dumpState) dumpSlice(v reflect.Value) { - // Determine whether this type should be hex dumped or not. Also, - // for types which should be hexdumped, try to use the underlying data - // first, then fall back to trying to convert them to a uint8 slice. - var buf []uint8 - doConvert := false - doHexDump := false - numEntries := v.Len() - if numEntries > 0 { - vt := v.Index(0).Type() - vts := vt.String() - switch { - // C types that need to be converted. - case cCharRE.MatchString(vts): - fallthrough - case cUnsignedCharRE.MatchString(vts): - fallthrough - case cUint8tCharRE.MatchString(vts): - doConvert = true - - // Try to use existing uint8 slices and fall back to converting - // and copying if that fails. - case vt.Kind() == reflect.Uint8: - // We need an addressable interface to convert the type - // to a byte slice. However, the reflect package won't - // give us an interface on certain things like - // unexported struct fields in order to enforce - // visibility rules. We use unsafe, when available, to - // bypass these restrictions since this package does not - // mutate the values. - vs := v - if !vs.CanInterface() || !vs.CanAddr() { - vs = unsafeReflectValue(vs) - } - if !UnsafeDisabled { - vs = vs.Slice(0, numEntries) - - // Use the existing uint8 slice if it can be - // type asserted. - iface := vs.Interface() - if slice, ok := iface.([]uint8); ok { - buf = slice - doHexDump = true - break - } - } - - // The underlying data needs to be converted if it can't - // be type asserted to a uint8 slice. - doConvert = true - } - - // Copy and convert the underlying type if needed. - if doConvert && vt.ConvertibleTo(uint8Type) { - // Convert and copy each element into a uint8 byte - // slice. - buf = make([]uint8, numEntries) - for i := 0; i < numEntries; i++ { - vv := v.Index(i) - buf[i] = uint8(vv.Convert(uint8Type).Uint()) - } - doHexDump = true - } - } - - // Hexdump the entire slice as needed. - if doHexDump { - indent := strings.Repeat(d.cs.Indent, d.depth) - str := indent + hex.Dump(buf) - str = strings.Replace(str, "\n", "\n"+indent, -1) - str = strings.TrimRight(str, d.cs.Indent) - d.w.Write([]byte(str)) - return - } - - // Recursively call dump for each item. - for i := 0; i < numEntries; i++ { - d.dump(d.unpackValue(v.Index(i))) - if i < (numEntries - 1) { - d.w.Write(commaNewlineBytes) - } else { - d.w.Write(newlineBytes) - } - } -} - -// dump is the main workhorse for dumping a value. It uses the passed reflect -// value to figure out what kind of object we are dealing with and formats it -// appropriately. It is a recursive function, however circular data structures -// are detected and handled properly. -func (d *dumpState) dump(v reflect.Value) { - // Handle invalid reflect values immediately. - kind := v.Kind() - if kind == reflect.Invalid { - d.w.Write(invalidAngleBytes) - return - } - - // Handle pointers specially. - if kind == reflect.Ptr { - d.indent() - d.dumpPtr(v) - return - } - - // Print type information unless already handled elsewhere. - if !d.ignoreNextType { - d.indent() - d.w.Write(openParenBytes) - d.w.Write([]byte(v.Type().String())) - d.w.Write(closeParenBytes) - d.w.Write(spaceBytes) - } - d.ignoreNextType = false - - // Display length and capacity if the built-in len and cap functions - // work with the value's kind and the len/cap itself is non-zero. - valueLen, valueCap := 0, 0 - switch v.Kind() { - case reflect.Array, reflect.Slice, reflect.Chan: - valueLen, valueCap = v.Len(), v.Cap() - case reflect.Map, reflect.String: - valueLen = v.Len() - } - if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 { - d.w.Write(openParenBytes) - if valueLen != 0 { - d.w.Write(lenEqualsBytes) - printInt(d.w, int64(valueLen), 10) - } - if !d.cs.DisableCapacities && valueCap != 0 { - if valueLen != 0 { - d.w.Write(spaceBytes) - } - d.w.Write(capEqualsBytes) - printInt(d.w, int64(valueCap), 10) - } - d.w.Write(closeParenBytes) - d.w.Write(spaceBytes) - } - - // Call Stringer/error interfaces if they exist and the handle methods flag - // is enabled - if !d.cs.DisableMethods { - if (kind != reflect.Invalid) && (kind != reflect.Interface) { - if handled := handleMethods(d.cs, d.w, v); handled { - return - } - } - } - - switch kind { - case reflect.Invalid: - // Do nothing. We should never get here since invalid has already - // been handled above. - - case reflect.Bool: - printBool(d.w, v.Bool()) - - case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: - printInt(d.w, v.Int(), 10) - - case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: - printUint(d.w, v.Uint(), 10) - - case reflect.Float32: - printFloat(d.w, v.Float(), 32) - - case reflect.Float64: - printFloat(d.w, v.Float(), 64) - - case reflect.Complex64: - printComplex(d.w, v.Complex(), 32) - - case reflect.Complex128: - printComplex(d.w, v.Complex(), 64) - - case reflect.Slice: - if v.IsNil() { - d.w.Write(nilAngleBytes) - break - } - fallthrough - - case reflect.Array: - d.w.Write(openBraceNewlineBytes) - d.depth++ - if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { - d.indent() - d.w.Write(maxNewlineBytes) - } else { - d.dumpSlice(v) - } - d.depth-- - d.indent() - d.w.Write(closeBraceBytes) - - case reflect.String: - d.w.Write([]byte(strconv.Quote(v.String()))) - - case reflect.Interface: - // The only time we should get here is for nil interfaces due to - // unpackValue calls. - if v.IsNil() { - d.w.Write(nilAngleBytes) - } - - case reflect.Ptr: - // Do nothing. We should never get here since pointers have already - // been handled above. - - case reflect.Map: - // nil maps should be indicated as different than empty maps - if v.IsNil() { - d.w.Write(nilAngleBytes) - break - } - - d.w.Write(openBraceNewlineBytes) - d.depth++ - if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { - d.indent() - d.w.Write(maxNewlineBytes) - } else { - numEntries := v.Len() - keys := v.MapKeys() - if d.cs.SortKeys { - sortValues(keys, d.cs) - } - for i, key := range keys { - d.dump(d.unpackValue(key)) - d.w.Write(colonSpaceBytes) - d.ignoreNextIndent = true - d.dump(d.unpackValue(v.MapIndex(key))) - if i < (numEntries - 1) { - d.w.Write(commaNewlineBytes) - } else { - d.w.Write(newlineBytes) - } - } - } - d.depth-- - d.indent() - d.w.Write(closeBraceBytes) - - case reflect.Struct: - d.w.Write(openBraceNewlineBytes) - d.depth++ - if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { - d.indent() - d.w.Write(maxNewlineBytes) - } else { - vt := v.Type() - numFields := v.NumField() - for i := 0; i < numFields; i++ { - d.indent() - vtf := vt.Field(i) - d.w.Write([]byte(vtf.Name)) - d.w.Write(colonSpaceBytes) - d.ignoreNextIndent = true - d.dump(d.unpackValue(v.Field(i))) - if i < (numFields - 1) { - d.w.Write(commaNewlineBytes) - } else { - d.w.Write(newlineBytes) - } - } - } - d.depth-- - d.indent() - d.w.Write(closeBraceBytes) - - case reflect.Uintptr: - printHexPtr(d.w, uintptr(v.Uint())) - - case reflect.UnsafePointer, reflect.Chan, reflect.Func: - printHexPtr(d.w, v.Pointer()) - - // There were not any other types at the time this code was written, but - // fall back to letting the default fmt package handle it in case any new - // types are added. - default: - if v.CanInterface() { - fmt.Fprintf(d.w, "%v", v.Interface()) - } else { - fmt.Fprintf(d.w, "%v", v.String()) - } - } -} - -// fdump is a helper function to consolidate the logic from the various public -// methods which take varying writers and config states. -func fdump(cs *ConfigState, w io.Writer, a ...interface{}) { - for _, arg := range a { - if arg == nil { - w.Write(interfaceBytes) - w.Write(spaceBytes) - w.Write(nilAngleBytes) - w.Write(newlineBytes) - continue - } - - d := dumpState{w: w, cs: cs} - d.pointers = make(map[uintptr]int) - d.dump(reflect.ValueOf(arg)) - d.w.Write(newlineBytes) - } -} - -// Fdump formats and displays the passed arguments to io.Writer w. It formats -// exactly the same as Dump. -func Fdump(w io.Writer, a ...interface{}) { - fdump(&Config, w, a...) -} - -// Sdump returns a string with the passed arguments formatted exactly the same -// as Dump. -func Sdump(a ...interface{}) string { - var buf bytes.Buffer - fdump(&Config, &buf, a...) - return buf.String() -} - -/* -Dump displays the passed parameters to standard out with newlines, customizable -indentation, and additional debug information such as complete types and all -pointer addresses used to indirect to the final value. It provides the -following features over the built-in printing facilities provided by the fmt -package: - - - Pointers are dereferenced and followed - - Circular data structures are detected and handled properly - - Custom Stringer/error interfaces are optionally invoked, including - on unexported types - - Custom types which only implement the Stringer/error interfaces via - a pointer receiver are optionally invoked when passing non-pointer - variables - - Byte arrays and slices are dumped like the hexdump -C command which - includes offsets, byte values in hex, and ASCII output - -The configuration options are controlled by an exported package global, -spew.Config. See ConfigState for options documentation. - -See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to -get the formatted result as a string. -*/ -func Dump(a ...interface{}) { - fdump(&Config, os.Stdout, a...) -} diff --git a/go/sdk/vendor/github.com/davecgh/go-spew/spew/format.go b/go/sdk/vendor/github.com/davecgh/go-spew/spew/format.go deleted file mode 100644 index b04edb7..0000000 --- a/go/sdk/vendor/github.com/davecgh/go-spew/spew/format.go +++ /dev/null @@ -1,419 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package spew - -import ( - "bytes" - "fmt" - "reflect" - "strconv" - "strings" -) - -// supportedFlags is a list of all the character flags supported by fmt package. -const supportedFlags = "0-+# " - -// formatState implements the fmt.Formatter interface and contains information -// about the state of a formatting operation. The NewFormatter function can -// be used to get a new Formatter which can be used directly as arguments -// in standard fmt package printing calls. -type formatState struct { - value interface{} - fs fmt.State - depth int - pointers map[uintptr]int - ignoreNextType bool - cs *ConfigState -} - -// buildDefaultFormat recreates the original format string without precision -// and width information to pass in to fmt.Sprintf in the case of an -// unrecognized type. Unless new types are added to the language, this -// function won't ever be called. -func (f *formatState) buildDefaultFormat() (format string) { - buf := bytes.NewBuffer(percentBytes) - - for _, flag := range supportedFlags { - if f.fs.Flag(int(flag)) { - buf.WriteRune(flag) - } - } - - buf.WriteRune('v') - - format = buf.String() - return format -} - -// constructOrigFormat recreates the original format string including precision -// and width information to pass along to the standard fmt package. This allows -// automatic deferral of all format strings this package doesn't support. -func (f *formatState) constructOrigFormat(verb rune) (format string) { - buf := bytes.NewBuffer(percentBytes) - - for _, flag := range supportedFlags { - if f.fs.Flag(int(flag)) { - buf.WriteRune(flag) - } - } - - if width, ok := f.fs.Width(); ok { - buf.WriteString(strconv.Itoa(width)) - } - - if precision, ok := f.fs.Precision(); ok { - buf.Write(precisionBytes) - buf.WriteString(strconv.Itoa(precision)) - } - - buf.WriteRune(verb) - - format = buf.String() - return format -} - -// unpackValue returns values inside of non-nil interfaces when possible and -// ensures that types for values which have been unpacked from an interface -// are displayed when the show types flag is also set. -// This is useful for data types like structs, arrays, slices, and maps which -// can contain varying types packed inside an interface. -func (f *formatState) unpackValue(v reflect.Value) reflect.Value { - if v.Kind() == reflect.Interface { - f.ignoreNextType = false - if !v.IsNil() { - v = v.Elem() - } - } - return v -} - -// formatPtr handles formatting of pointers by indirecting them as necessary. -func (f *formatState) formatPtr(v reflect.Value) { - // Display nil if top level pointer is nil. - showTypes := f.fs.Flag('#') - if v.IsNil() && (!showTypes || f.ignoreNextType) { - f.fs.Write(nilAngleBytes) - return - } - - // Remove pointers at or below the current depth from map used to detect - // circular refs. - for k, depth := range f.pointers { - if depth >= f.depth { - delete(f.pointers, k) - } - } - - // Keep list of all dereferenced pointers to possibly show later. - pointerChain := make([]uintptr, 0) - - // Figure out how many levels of indirection there are by derferencing - // pointers and unpacking interfaces down the chain while detecting circular - // references. - nilFound := false - cycleFound := false - indirects := 0 - ve := v - for ve.Kind() == reflect.Ptr { - if ve.IsNil() { - nilFound = true - break - } - indirects++ - addr := ve.Pointer() - pointerChain = append(pointerChain, addr) - if pd, ok := f.pointers[addr]; ok && pd < f.depth { - cycleFound = true - indirects-- - break - } - f.pointers[addr] = f.depth - - ve = ve.Elem() - if ve.Kind() == reflect.Interface { - if ve.IsNil() { - nilFound = true - break - } - ve = ve.Elem() - } - } - - // Display type or indirection level depending on flags. - if showTypes && !f.ignoreNextType { - f.fs.Write(openParenBytes) - f.fs.Write(bytes.Repeat(asteriskBytes, indirects)) - f.fs.Write([]byte(ve.Type().String())) - f.fs.Write(closeParenBytes) - } else { - if nilFound || cycleFound { - indirects += strings.Count(ve.Type().String(), "*") - } - f.fs.Write(openAngleBytes) - f.fs.Write([]byte(strings.Repeat("*", indirects))) - f.fs.Write(closeAngleBytes) - } - - // Display pointer information depending on flags. - if f.fs.Flag('+') && (len(pointerChain) > 0) { - f.fs.Write(openParenBytes) - for i, addr := range pointerChain { - if i > 0 { - f.fs.Write(pointerChainBytes) - } - printHexPtr(f.fs, addr) - } - f.fs.Write(closeParenBytes) - } - - // Display dereferenced value. - switch { - case nilFound: - f.fs.Write(nilAngleBytes) - - case cycleFound: - f.fs.Write(circularShortBytes) - - default: - f.ignoreNextType = true - f.format(ve) - } -} - -// format is the main workhorse for providing the Formatter interface. It -// uses the passed reflect value to figure out what kind of object we are -// dealing with and formats it appropriately. It is a recursive function, -// however circular data structures are detected and handled properly. -func (f *formatState) format(v reflect.Value) { - // Handle invalid reflect values immediately. - kind := v.Kind() - if kind == reflect.Invalid { - f.fs.Write(invalidAngleBytes) - return - } - - // Handle pointers specially. - if kind == reflect.Ptr { - f.formatPtr(v) - return - } - - // Print type information unless already handled elsewhere. - if !f.ignoreNextType && f.fs.Flag('#') { - f.fs.Write(openParenBytes) - f.fs.Write([]byte(v.Type().String())) - f.fs.Write(closeParenBytes) - } - f.ignoreNextType = false - - // Call Stringer/error interfaces if they exist and the handle methods - // flag is enabled. - if !f.cs.DisableMethods { - if (kind != reflect.Invalid) && (kind != reflect.Interface) { - if handled := handleMethods(f.cs, f.fs, v); handled { - return - } - } - } - - switch kind { - case reflect.Invalid: - // Do nothing. We should never get here since invalid has already - // been handled above. - - case reflect.Bool: - printBool(f.fs, v.Bool()) - - case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: - printInt(f.fs, v.Int(), 10) - - case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: - printUint(f.fs, v.Uint(), 10) - - case reflect.Float32: - printFloat(f.fs, v.Float(), 32) - - case reflect.Float64: - printFloat(f.fs, v.Float(), 64) - - case reflect.Complex64: - printComplex(f.fs, v.Complex(), 32) - - case reflect.Complex128: - printComplex(f.fs, v.Complex(), 64) - - case reflect.Slice: - if v.IsNil() { - f.fs.Write(nilAngleBytes) - break - } - fallthrough - - case reflect.Array: - f.fs.Write(openBracketBytes) - f.depth++ - if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { - f.fs.Write(maxShortBytes) - } else { - numEntries := v.Len() - for i := 0; i < numEntries; i++ { - if i > 0 { - f.fs.Write(spaceBytes) - } - f.ignoreNextType = true - f.format(f.unpackValue(v.Index(i))) - } - } - f.depth-- - f.fs.Write(closeBracketBytes) - - case reflect.String: - f.fs.Write([]byte(v.String())) - - case reflect.Interface: - // The only time we should get here is for nil interfaces due to - // unpackValue calls. - if v.IsNil() { - f.fs.Write(nilAngleBytes) - } - - case reflect.Ptr: - // Do nothing. We should never get here since pointers have already - // been handled above. - - case reflect.Map: - // nil maps should be indicated as different than empty maps - if v.IsNil() { - f.fs.Write(nilAngleBytes) - break - } - - f.fs.Write(openMapBytes) - f.depth++ - if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { - f.fs.Write(maxShortBytes) - } else { - keys := v.MapKeys() - if f.cs.SortKeys { - sortValues(keys, f.cs) - } - for i, key := range keys { - if i > 0 { - f.fs.Write(spaceBytes) - } - f.ignoreNextType = true - f.format(f.unpackValue(key)) - f.fs.Write(colonBytes) - f.ignoreNextType = true - f.format(f.unpackValue(v.MapIndex(key))) - } - } - f.depth-- - f.fs.Write(closeMapBytes) - - case reflect.Struct: - numFields := v.NumField() - f.fs.Write(openBraceBytes) - f.depth++ - if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { - f.fs.Write(maxShortBytes) - } else { - vt := v.Type() - for i := 0; i < numFields; i++ { - if i > 0 { - f.fs.Write(spaceBytes) - } - vtf := vt.Field(i) - if f.fs.Flag('+') || f.fs.Flag('#') { - f.fs.Write([]byte(vtf.Name)) - f.fs.Write(colonBytes) - } - f.format(f.unpackValue(v.Field(i))) - } - } - f.depth-- - f.fs.Write(closeBraceBytes) - - case reflect.Uintptr: - printHexPtr(f.fs, uintptr(v.Uint())) - - case reflect.UnsafePointer, reflect.Chan, reflect.Func: - printHexPtr(f.fs, v.Pointer()) - - // There were not any other types at the time this code was written, but - // fall back to letting the default fmt package handle it if any get added. - default: - format := f.buildDefaultFormat() - if v.CanInterface() { - fmt.Fprintf(f.fs, format, v.Interface()) - } else { - fmt.Fprintf(f.fs, format, v.String()) - } - } -} - -// Format satisfies the fmt.Formatter interface. See NewFormatter for usage -// details. -func (f *formatState) Format(fs fmt.State, verb rune) { - f.fs = fs - - // Use standard formatting for verbs that are not v. - if verb != 'v' { - format := f.constructOrigFormat(verb) - fmt.Fprintf(fs, format, f.value) - return - } - - if f.value == nil { - if fs.Flag('#') { - fs.Write(interfaceBytes) - } - fs.Write(nilAngleBytes) - return - } - - f.format(reflect.ValueOf(f.value)) -} - -// newFormatter is a helper function to consolidate the logic from the various -// public methods which take varying config states. -func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter { - fs := &formatState{value: v, cs: cs} - fs.pointers = make(map[uintptr]int) - return fs -} - -/* -NewFormatter returns a custom formatter that satisfies the fmt.Formatter -interface. As a result, it integrates cleanly with standard fmt package -printing functions. The formatter is useful for inline printing of smaller data -types similar to the standard %v format specifier. - -The custom formatter only responds to the %v (most compact), %+v (adds pointer -addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb -combinations. Any other verbs such as %x and %q will be sent to the the -standard fmt package for formatting. In addition, the custom formatter ignores -the width and precision arguments (however they will still work on the format -specifiers not handled by the custom formatter). - -Typically this function shouldn't be called directly. It is much easier to make -use of the custom formatter by calling one of the convenience functions such as -Printf, Println, or Fprintf. -*/ -func NewFormatter(v interface{}) fmt.Formatter { - return newFormatter(&Config, v) -} diff --git a/go/sdk/vendor/github.com/davecgh/go-spew/spew/spew.go b/go/sdk/vendor/github.com/davecgh/go-spew/spew/spew.go deleted file mode 100644 index 32c0e33..0000000 --- a/go/sdk/vendor/github.com/davecgh/go-spew/spew/spew.go +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package spew - -import ( - "fmt" - "io" -) - -// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the formatted string as a value that satisfies error. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b)) -func Errorf(format string, a ...interface{}) (err error) { - return fmt.Errorf(format, convertArgs(a)...) -} - -// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b)) -func Fprint(w io.Writer, a ...interface{}) (n int, err error) { - return fmt.Fprint(w, convertArgs(a)...) -} - -// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b)) -func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { - return fmt.Fprintf(w, format, convertArgs(a)...) -} - -// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it -// passed with a default Formatter interface returned by NewFormatter. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b)) -func Fprintln(w io.Writer, a ...interface{}) (n int, err error) { - return fmt.Fprintln(w, convertArgs(a)...) -} - -// Print is a wrapper for fmt.Print that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b)) -func Print(a ...interface{}) (n int, err error) { - return fmt.Print(convertArgs(a)...) -} - -// Printf is a wrapper for fmt.Printf that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b)) -func Printf(format string, a ...interface{}) (n int, err error) { - return fmt.Printf(format, convertArgs(a)...) -} - -// Println is a wrapper for fmt.Println that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b)) -func Println(a ...interface{}) (n int, err error) { - return fmt.Println(convertArgs(a)...) -} - -// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the resulting string. See NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b)) -func Sprint(a ...interface{}) string { - return fmt.Sprint(convertArgs(a)...) -} - -// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the resulting string. See NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b)) -func Sprintf(format string, a ...interface{}) string { - return fmt.Sprintf(format, convertArgs(a)...) -} - -// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it -// were passed with a default Formatter interface returned by NewFormatter. It -// returns the resulting string. See NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b)) -func Sprintln(a ...interface{}) string { - return fmt.Sprintln(convertArgs(a)...) -} - -// convertArgs accepts a slice of arguments and returns a slice of the same -// length with each argument converted to a default spew Formatter interface. -func convertArgs(args []interface{}) (formatters []interface{}) { - formatters = make([]interface{}, len(args)) - for index, arg := range args { - formatters[index] = NewFormatter(arg) - } - return formatters -} diff --git a/go/sdk/vendor/github.com/google/jsonschema-go/LICENSE b/go/sdk/vendor/github.com/google/jsonschema-go/LICENSE deleted file mode 100644 index 1cb53e9..0000000 --- a/go/sdk/vendor/github.com/google/jsonschema-go/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2025 JSON Schema Go Project Authors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/annotations.go b/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/annotations.go deleted file mode 100644 index d4dd643..0000000 --- a/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/annotations.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2025 The JSON Schema Go Project Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package jsonschema - -import "maps" - -// An annotations tracks certain properties computed by keywords that are used by validation. -// ("Annotation" is the spec's term.) -// In particular, the unevaluatedItems and unevaluatedProperties keywords need to know which -// items and properties were evaluated (validated successfully). -type annotations struct { - allItems bool // all items were evaluated - endIndex int // 1+largest index evaluated by prefixItems - evaluatedIndexes map[int]bool // set of indexes evaluated by contains - allProperties bool // all properties were evaluated - evaluatedProperties map[string]bool // set of properties evaluated by various keywords -} - -// noteIndex marks i as evaluated. -func (a *annotations) noteIndex(i int) { - if a.evaluatedIndexes == nil { - a.evaluatedIndexes = map[int]bool{} - } - a.evaluatedIndexes[i] = true -} - -// noteEndIndex marks items with index less than end as evaluated. -func (a *annotations) noteEndIndex(end int) { - if end > a.endIndex { - a.endIndex = end - } -} - -// noteProperty marks prop as evaluated. -func (a *annotations) noteProperty(prop string) { - if a.evaluatedProperties == nil { - a.evaluatedProperties = map[string]bool{} - } - a.evaluatedProperties[prop] = true -} - -// noteProperties marks all the properties in props as evaluated. -func (a *annotations) noteProperties(props map[string]bool) { - a.evaluatedProperties = merge(a.evaluatedProperties, props) -} - -// merge adds b's annotations to a. -// a must not be nil. -func (a *annotations) merge(b *annotations) { - if b == nil { - return - } - if b.allItems { - a.allItems = true - } - if b.endIndex > a.endIndex { - a.endIndex = b.endIndex - } - a.evaluatedIndexes = merge(a.evaluatedIndexes, b.evaluatedIndexes) - if b.allProperties { - a.allProperties = true - } - a.evaluatedProperties = merge(a.evaluatedProperties, b.evaluatedProperties) -} - -// merge adds t's keys to s and returns s. -// If s is nil, it returns a copy of t. -func merge[K comparable](s, t map[K]bool) map[K]bool { - if s == nil { - return maps.Clone(t) - } - maps.Copy(s, t) - return s -} diff --git a/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/doc.go b/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/doc.go deleted file mode 100644 index eade338..0000000 --- a/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/doc.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2025 The JSON Schema Go Project Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -/* -Package jsonschema is an implementation of the [JSON Schema specification], -a JSON-based format for describing the structure of JSON data. -The package can be used to read schemas for code generation, and to validate -data using the draft 2020-12 and draft-07 specifications. Validation with -other drafts or custom meta-schemas is not supported. - -Construct a [Schema] as you would any Go struct (for example, by writing -a struct literal), or unmarshal a JSON schema into a [Schema] in the usual -way (with [encoding/json], for instance). It can then be used for code -generation or other purposes without further processing. -You can also infer a schema from a Go struct. - -# Resolution - -A Schema can refer to other schemas, both inside and outside itself. These -references must be resolved before a schema can be used for validation. -Call [Schema.Resolve] to obtain a resolved schema (called a [Resolved]). -If the schema has external references, pass a [ResolveOptions] with a [Loader] -to load them. To validate default values in a schema, set -[ResolveOptions.ValidateDefaults] to true. - -# Validation - -Call [Resolved.Validate] to validate a JSON value. The value must be a -Go value that looks like the result of unmarshaling a JSON value into an -[any] or a struct. For example, the JSON value - - {"name": "Al", "scores": [90, 80, 100]} - -could be represented as the Go value - - map[string]any{ - "name": "Al", - "scores": []any{90, 80, 100}, - } - -or as a value of this type: - - type Player struct { - Name string `json:"name"` - Scores []int `json:"scores"` - } - -# Inference - -The [For] function returns a [Schema] describing the given Go type. -Each field in the struct becomes a property of the schema. -The values of "json" tags are respected: the field's property name is taken -from the tag, and fields omitted from the JSON are omitted from the schema as -well. -For example, `jsonschema.For[Player]()` returns this schema: - - { - "properties": { - "name": { - "type": "string" - }, - "scores": { - "type": "array", - "items": {"type": "integer"} - } - "required": ["name", "scores"], - "additionalProperties": {"not": {}} - } - } - -Use the "jsonschema" struct tag to provide a description for the property: - - type Player struct { - Name string `json:"name" jsonschema:"player name"` - Scores []int `json:"scores" jsonschema:"scores of player's games"` - } - -# Deviations from the specification - -Regular expressions are processed with Go's regexp package, which differs -from ECMA 262, most significantly in not supporting back-references. -See [this table of differences] for more. - -The "format" keyword described in [section 7 of the validation spec] is recorded -in the Schema, but is ignored during validation. -It does not even produce [annotations]. -Use the "pattern" keyword instead: it will work more reliably across JSON Schema -implementations. See [learnjsonschema.com] for more recommendations about "format". - -The content keywords described in [section 8 of the validation spec] -are recorded in the schema, but ignored during validation. - -# Controlling behavior changes - -Minor and patch releases of this package may introduce behavior changes as part -of bug fixes or correctness improvements. To help manage the impact of such -changes, the package allows you to access previous behaviors using the -`JSONSCHEMAGODEBUG` environment variable. The available settings are listed -below; additional options may be introduced in future releases. - -- **typeschemasnull**: When set to `"1"`, the inferred schema for slices will -*not* include the `null` type alongside the array type. It will also avoid -adding `null` to non-native pointer types (such as `time.Time`). This restores -the behavior from versions prior to v0.3.0. The default behavior is to include -`null` in these cases. - -[JSON Schema specification]: https://json-schema.org -[section 7 of the validation spec]: https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-00#rfc.section.7 -[section 8 of the validation spec]: https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-00#rfc.section.8 -[learnjsonschema.com]: https://www.learnjsonschema.com/2020-12/format-annotation/format/ -[this table of differences]: https://github.com/dlclark/regexp2?tab=readme-ov-file#compare-regexp-and-regexp2 -[annotations]: https://json-schema.org/draft/2020-12/json-schema-core#name-annotations -*/ -package jsonschema diff --git a/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/infer.go b/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/infer.go deleted file mode 100644 index 9c195f5..0000000 --- a/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/infer.go +++ /dev/null @@ -1,400 +0,0 @@ -// Copyright 2025 The JSON Schema Go Project Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// This file contains functions that infer a schema from a Go type. - -package jsonschema - -import ( - "fmt" - "log/slog" - "maps" - "math" - "math/big" - "os" - "reflect" - "regexp" - "slices" - "time" -) - -const debugEnv = "JSONSCHEMAGODEBUG" - -// ForOptions are options for the [For] and [ForType] functions. -type ForOptions struct { - // If IgnoreInvalidTypes is true, fields that can't be represented as a JSON - // Schema are ignored instead of causing an error. - // This allows callers to adjust the resulting schema using custom knowledge. - // For example, an interface type where all the possible implementations are - // known can be described with "oneof". - IgnoreInvalidTypes bool - - // TypeSchemas maps types to their schemas. - // If [For] encounters a type that is a key in this map, the - // corresponding value is used as the resulting schema (after cloning to - // ensure uniqueness). - // Types in this map override the default translations, as described - // in [For]'s documentation. - // PropertyOrder defined in these schemas will not be used in [For] or [ForType]. - TypeSchemas map[reflect.Type]*Schema -} - -// For constructs a JSON schema object for the given type argument. -// If non-nil, the provided options configure certain aspects of this contruction, -// described below. - -// It translates Go types into compatible JSON schema types, as follows. -// These defaults can be overridden by [ForOptions.TypeSchemas]. -// -// - Strings have schema type "string". -// - Bools have schema type "boolean". -// - Signed and unsigned integer types have schema type "integer". -// - Floating point types have schema type "number". -// - Slices and arrays have schema type "array", and a corresponding schema -// for items. -// - Maps with string key have schema type "object", and corresponding -// schema for additionalProperties. -// - Structs have schema type "object", and disallow additionalProperties. -// Their properties are derived from exported struct fields, using the -// struct field JSON name. Fields that are marked "omitempty" or "omitzero" are -// considered optional; all other fields become required properties. -// For structs, the PropertyOrder will be set to the field order. -// - Some types in the standard library that implement json.Marshaler -// translate to schemas that match the values to which they marshal. -// For example, [time.Time] translates to the schema for strings. -// -// For will return an error if there is a cycle in the types. -// -// By default, For returns an error if t contains (possibly recursively) any of the -// following Go types, as they are incompatible with the JSON schema spec. -// If [ForOptions.IgnoreInvalidTypes] is true, then these types are ignored instead. -// - maps with key other than 'string' -// - function types -// - channel types -// - complex numbers -// - unsafe pointers -// -// This function recognizes struct field tags named "jsonschema". -// A jsonschema tag on a field is used as the description for the corresponding property. -// For future compatibility, descriptions must not start with "WORD=", where WORD is a -// sequence of non-whitespace characters. -func For[T any](opts *ForOptions) (*Schema, error) { - if opts == nil { - opts = &ForOptions{} - } - schemas := maps.Clone(initialSchemaMap) - // Add types from the options. They override the default ones. - maps.Copy(schemas, opts.TypeSchemas) - s, err := forType(reflect.TypeFor[T](), map[reflect.Type]bool{}, opts.IgnoreInvalidTypes, schemas) - if err != nil { - var z T - return nil, fmt.Errorf("For[%T](): %w", z, err) - } - return s, nil -} - -// ForType is like [For], but takes a [reflect.Type] -func ForType(t reflect.Type, opts *ForOptions) (*Schema, error) { - if opts == nil { - opts = &ForOptions{} - } - schemas := maps.Clone(initialSchemaMap) - // Add types from the options. They override the default ones. - maps.Copy(schemas, opts.TypeSchemas) - s, err := forType(t, map[reflect.Type]bool{}, opts.IgnoreInvalidTypes, schemas) - if err != nil { - return nil, fmt.Errorf("ForType(%s): %w", t, err) - } - return s, nil -} - -// Helper to create a *float64 pointer from a value -func f64Ptr(f float64) *float64 { - return &f -} - -func forType(t reflect.Type, seen map[reflect.Type]bool, ignore bool, schemas map[reflect.Type]*Schema) (*Schema, error) { - // Follow pointers: the schema for *T is almost the same as for T, except that - // an explicit JSON "null" is allowed for the pointer. - allowNull := false - for t.Kind() == reflect.Pointer { - allowNull = true - t = t.Elem() - } - - // Check for cycles - // User defined types have a name, so we can skip those that are natively defined - if t.Name() != "" { - if seen[t] { - return nil, fmt.Errorf("cycle detected for type %v", t) - } - seen[t] = true - defer delete(seen, t) - } - - if s := schemas[t]; s != nil { - cloned := s.CloneSchemas() - if os.Getenv(debugEnv) != "typeschemasnull=1" && allowNull { - if cloned.Type != "" { - cloned.Types = []string{"null", cloned.Type} - cloned.Type = "" - } else if !slices.Contains(cloned.Types, "null") { - cloned.Types = append([]string{"null"}, cloned.Types...) - } - } - return cloned, nil - } - - var ( - s = new(Schema) - err error - ) - - switch t.Kind() { - case reflect.Bool: - s.Type = "boolean" - - case reflect.Int, reflect.Int64: - s.Type = "integer" - - case reflect.Uint, reflect.Uint64, reflect.Uintptr: - s.Type = "integer" - s.Minimum = f64Ptr(0) - - case reflect.Int8: - s.Type = "integer" - s.Minimum = f64Ptr(math.MinInt8) - s.Maximum = f64Ptr(math.MaxInt8) - - case reflect.Uint8: - s.Type = "integer" - s.Minimum = f64Ptr(0) - s.Maximum = f64Ptr(math.MaxUint8) - - case reflect.Int16: - s.Type = "integer" - s.Minimum = f64Ptr(math.MinInt16) - s.Maximum = f64Ptr(math.MaxInt16) - - case reflect.Uint16: - s.Type = "integer" - s.Minimum = f64Ptr(0) - s.Maximum = f64Ptr(math.MaxUint16) - - case reflect.Int32: - s.Type = "integer" - s.Minimum = f64Ptr(math.MinInt32) - s.Maximum = f64Ptr(math.MaxInt32) - - case reflect.Uint32: - s.Type = "integer" - s.Minimum = f64Ptr(0) - s.Maximum = f64Ptr(math.MaxUint32) - - case reflect.Float32, reflect.Float64: - s.Type = "number" - - case reflect.Interface: - // Unrestricted - - case reflect.Map: - if t.Key().Kind() != reflect.String { - if ignore { - return nil, nil // ignore - } - return nil, fmt.Errorf("unsupported map key type %v", t.Key().Kind()) - } - if t.Key().Kind() != reflect.String { - } - s.Type = "object" - s.AdditionalProperties, err = forType(t.Elem(), seen, ignore, schemas) - if err != nil { - return nil, fmt.Errorf("computing map value schema: %v", err) - } - if ignore && s.AdditionalProperties == nil { - // Ignore if the element type is invalid. - return nil, nil - } - - case reflect.Slice, reflect.Array: - if os.Getenv(debugEnv) != "typeschemasnull=1" && t.Kind() == reflect.Slice { - s.Types = []string{"null", "array"} - } else { - s.Type = "array" - } - itemsSchema, err := forType(t.Elem(), seen, ignore, schemas) - if err != nil { - return nil, fmt.Errorf("computing element schema: %v", err) - } - if itemsSchema == nil { - return nil, nil - } - s.Items = itemsSchema - if ignore && s.Items == nil { - // Ignore if the element type is invalid. - return nil, nil - } - if t.Kind() == reflect.Array { - s.MinItems = Ptr(t.Len()) - s.MaxItems = Ptr(t.Len()) - } - - case reflect.String: - s.Type = "string" - - case reflect.Struct: - s.Type = "object" - // no additional properties are allowed - s.AdditionalProperties = falseSchema() - - // If skipPath is non-nil, it is path to an anonymous field whose - // schema has been replaced by a known schema. - var skipPath []int - for _, field := range reflect.VisibleFields(t) { - if s.Properties == nil { - s.Properties = make(map[string]*Schema) - } - if field.Anonymous { - override := schemas[field.Type] - if override != nil { - // Type must be object, and only properties can be set. - if override.Type != "object" { - return nil, fmt.Errorf(`custom schema for embedded struct must have type "object", got %q`, - override.Type) - } - // Check that all keywords relevant for objects are absent, except properties. - ov := reflect.ValueOf(override).Elem() - for _, sfi := range schemaFieldInfos { - if sfi.sf.Name == "Type" || sfi.sf.Name == "Properties" { - continue - } - fv := ov.FieldByIndex(sfi.sf.Index) - if !fv.IsZero() { - return nil, fmt.Errorf(`overrides for embedded fields can have only "Type" and "Properties"; this has %q`, sfi.sf.Name) - } - } - - skipPath = field.Index - keys := make([]string, 0, len(override.Properties)) - for k := range override.Properties { - keys = append(keys, k) - } - slices.Sort(keys) - for _, name := range keys { - if _, ok := s.Properties[name]; !ok { - s.Properties[name] = override.Properties[name].CloneSchemas() - s.PropertyOrder = append(s.PropertyOrder, name) - } - } - } - continue - } - - // Check to see if this field has been promoted from a replaced anonymous - // type. - if skipPath != nil { - skip := false - if len(field.Index) >= len(skipPath) { - skip = true - for i, index := range skipPath { - if field.Index[i] != index { - // If we're no longer in a subfield. - skip = false - break - } - } - } - if skip { - continue - } else { - // Anonymous fields are followed immediately by their promoted fields. - // Once we encounter a field that *isn't* promoted, we can stop - // checking. - skipPath = nil - } - } - - info := fieldJSONInfo(field) - if info.omit { - continue - } - fs, err := forType(field.Type, seen, ignore, schemas) - if err != nil { - return nil, err - } - if ignore && fs == nil { - // Skip fields of invalid type. - continue - } - if tag, ok := field.Tag.Lookup("jsonschema"); ok { - if tag == "" { - return nil, fmt.Errorf("empty jsonschema tag on struct field %s.%s", t, field.Name) - } - if disallowedPrefixRegexp.MatchString(tag) { - return nil, fmt.Errorf("tag must not begin with 'WORD=': %q", tag) - } - fs.Description = tag - } - s.Properties[info.name] = fs - - s.PropertyOrder = append(s.PropertyOrder, info.name) - - if !info.settings["omitempty"] && !info.settings["omitzero"] { - s.Required = append(s.Required, info.name) - } - } - - // Remove PropertyOrder duplicates, keeping the last occurrence - if len(s.PropertyOrder) > 1 { - seen := make(map[string]bool) - // Create a slice to hold the cleaned order (capacity = current length) - cleaned := make([]string, 0, len(s.PropertyOrder)) - - // Iterate backwards - for i := len(s.PropertyOrder) - 1; i >= 0; i-- { - name := s.PropertyOrder[i] - if !seen[name] { - cleaned = append(cleaned, name) - seen[name] = true - } - } - - // Since we collected them backwards, we need to reverse the result - // to restore the correct order. - slices.Reverse(cleaned) - s.PropertyOrder = cleaned - } - - default: - if ignore { - // Ignore. - return nil, nil - } - return nil, fmt.Errorf("type %v is unsupported by jsonschema", t) - } - if allowNull && s.Type != "" { - s.Types = []string{"null", s.Type} - s.Type = "" - } - return s, nil -} - -// initialSchemaMap holds types from the standard library that have MarshalJSON methods. -var initialSchemaMap = make(map[reflect.Type]*Schema) - -func init() { - ss := &Schema{Type: "string"} - initialSchemaMap[reflect.TypeFor[time.Time]()] = ss - initialSchemaMap[reflect.TypeFor[slog.Level]()] = ss - if os.Getenv(debugEnv) == "typeschemasnull=1" { - initialSchemaMap[reflect.TypeFor[big.Int]()] = &Schema{Types: []string{"null", "string"}} - } else { - initialSchemaMap[reflect.TypeFor[big.Int]()] = ss - } - initialSchemaMap[reflect.TypeFor[big.Rat]()] = ss - initialSchemaMap[reflect.TypeFor[big.Float]()] = ss -} - -// Disallow jsonschema tag values beginning "WORD=", for future expansion. -var disallowedPrefixRegexp = regexp.MustCompile("^[^ \t\n]*=") diff --git a/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/json_pointer.go b/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/json_pointer.go deleted file mode 100644 index 4a9db2e..0000000 --- a/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/json_pointer.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2025 The JSON Schema Go Project Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// This file implements JSON Pointers. -// A JSON Pointer is a path that refers to one JSON value within another. -// If the path is empty, it refers to the root value. -// Otherwise, it is a sequence of slash-prefixed strings, like "/points/1/x", -// selecting successive properties (for JSON objects) or items (for JSON arrays). -// For example, when applied to this JSON value: -// { -// "points": [ -// {"x": 1, "y": 2}, -// {"x": 3, "y": 4} -// ] -// } -// -// the JSON Pointer "/points/1/x" refers to the number 3. -// See the spec at https://datatracker.ietf.org/doc/html/rfc6901. - -package jsonschema - -import ( - "errors" - "fmt" - "reflect" - "strconv" - "strings" -) - -var ( - jsonPointerEscaper = strings.NewReplacer("~", "~0", "/", "~1") - jsonPointerUnescaper = strings.NewReplacer("~0", "~", "~1", "/") -) - -func escapeJSONPointerSegment(s string) string { - return jsonPointerEscaper.Replace(s) -} - -func unescapeJSONPointerSegment(s string) string { - return jsonPointerUnescaper.Replace(s) -} - -// parseJSONPointer splits a JSON Pointer into a sequence of segments. It doesn't -// convert strings to numbers, because that depends on the traversal: a segment -// is treated as a number when applied to an array, but a string when applied to -// an object. See section 4 of the spec. -func parseJSONPointer(ptr string) (segments []string, err error) { - if ptr == "" { - return nil, nil - } - if ptr[0] != '/' { - return nil, fmt.Errorf("JSON Pointer %q does not begin with '/'", ptr) - } - // Unlike file paths, consecutive slashes are not coalesced. - // Split is nicer than Cut here, because it gets a final "/" right. - segments = strings.Split(ptr[1:], "/") - if strings.Contains(ptr, "~") { - // Undo the simple escaping rules that allow one to include a slash in a segment. - for i := range segments { - segments[i] = unescapeJSONPointerSegment(segments[i]) - } - } - return segments, nil -} - -// dereferenceJSONPointer returns the Schema that sptr points to within s, -// or an error if none. -// This implementation suffices for JSON Schema: pointers are applied only to Schemas, -// and refer only to Schemas. -func dereferenceJSONPointer(s *Schema, sptr string) (_ *Schema, err error) { - defer wrapf(&err, "JSON Pointer %q", sptr) - - segments, err := parseJSONPointer(sptr) - if err != nil { - return nil, err - } - v := reflect.ValueOf(s) - for _, seg := range segments { - switch v.Kind() { - case reflect.Pointer: - v = v.Elem() - if !v.IsValid() { - return nil, errors.New("navigated to nil reference") - } - fallthrough // if valid, can only be a pointer to a Schema - - case reflect.Struct: - // The segment must refer to a field in a Schema. - if v.Type() != reflect.TypeFor[Schema]() { - return nil, fmt.Errorf("navigated to non-Schema %s", v.Type()) - } - v = lookupSchemaField(v, seg) - if !v.IsValid() { - return nil, fmt.Errorf("no schema field %q", seg) - } - case reflect.Slice, reflect.Array: - // The segment must be an integer without leading zeroes that refers to an item in the - // slice or array. - if seg == "-" { - return nil, errors.New("the JSON Pointer array segment '-' is not supported") - } - if len(seg) > 1 && seg[0] == '0' { - return nil, fmt.Errorf("segment %q has leading zeroes", seg) - } - n, err := strconv.Atoi(seg) - if err != nil { - return nil, fmt.Errorf("invalid int: %q", seg) - } - if n < 0 || n >= v.Len() { - return nil, fmt.Errorf("index %d is out of bounds for array of length %d", n, v.Len()) - } - v = v.Index(n) - // Cannot be invalid. - case reflect.Map: - // The segment must be a key in the map. - v = v.MapIndex(reflect.ValueOf(seg)) - if !v.IsValid() { - return nil, fmt.Errorf("no key %q in map", seg) - } - default: - return nil, fmt.Errorf("value %s (%s) is not a schema, slice or map", v, v.Type()) - } - } - if s, ok := v.Interface().(*Schema); ok { - return s, nil - } - return nil, fmt.Errorf("does not refer to a schema, but to a %s", v.Type()) -} - -// lookupSchemaField returns the value of the field with the given name in v, -// or the zero value if there is no such field or it is not of type Schema or *Schema. -func lookupSchemaField(v reflect.Value, name string) reflect.Value { - if name == "type" { - // The "type" keyword may refer to Type or Types. - // At most one will be non-zero. - if t := v.FieldByName("Type"); !t.IsZero() { - return t - } - return v.FieldByName("Types") - } - if name == "items" { - // The "items" keyword refers to the "union type" that is either a schema or a schema array. - // Implemented using the Items representing the schema and ItemsArray for the schema array. - if items := v.FieldByName("Items"); items.IsValid() && !items.IsNil() { - return items - } - return v.FieldByName("ItemsArray") - } - if name == "dependencies" { - // The "dependencies" keyword refers to both DependencyStrings and DependencySchemas maps. - // The value on schemaFieldMap is not garanteed to be DependencySchemas which we want - // for pointer dereference. So we use FieldByName to get the DependencySchemas map. - return v.FieldByName("DependencySchemas") - } - if sf, ok := schemaFieldMap[name]; ok { - return v.FieldByIndex(sf.Index) - } - return reflect.Value{} -} diff --git a/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/resolve.go b/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/resolve.go deleted file mode 100644 index d63115b..0000000 --- a/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/resolve.go +++ /dev/null @@ -1,589 +0,0 @@ -// Copyright 2025 The JSON Schema Go Project Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// This file deals with preparing a schema for validation, including various checks, -// optimizations, and the resolution of cross-schema references. - -package jsonschema - -import ( - "errors" - "fmt" - "net/url" - "reflect" - "regexp" - "strings" -) - -// A Resolved consists of a [Schema] along with associated information needed to -// validate documents against it. -// A Resolved has been validated against its meta-schema, and all its references -// (the $ref and $dynamicRef keywords) have been resolved to their referenced Schemas. -// Call [Schema.Resolve] to obtain a Resolved from a Schema. -type Resolved struct { - root *Schema - draft draft - // map from $ids to their schemas - resolvedURIs map[string]*Schema - // map from schemas to additional info computed during resolution - resolvedInfos map[*Schema]*resolvedInfo -} - -type draft int - -const ( - draft7 = iota - draft2020 -) - -func newResolved(s *Schema) *Resolved { - return &Resolved{ - root: s, - draft: detectDraft(s), - resolvedURIs: map[string]*Schema{}, - resolvedInfos: map[*Schema]*resolvedInfo{}, - } -} - -// detectDraft inspects the raw JSON to determine the schema version. -func detectDraft(s *Schema) draft { - // Check explicit $schema declaration - switch s.Schema { - case draft7SchemaVersion, draft7SecSchemaVersion: - return draft7 - case draft202012SchemaVersion: - return draft2020 - default: - // If nothing matches default to the latest supported version. - return draft2020 - } -} - -// resolvedInfo holds information specific to a schema that is computed by [Schema.Resolve]. -type resolvedInfo struct { - s *Schema - // The JSON Pointer path from the root schema to here. - // Used in errors. - path string - // The schema's base schema. - // If the schema is the root or has an ID, its base is itself. - // Otherwise, its base is the innermost enclosing schema whose base - // is itself. - // Intuitively, a base schema is one that can be referred to with a - // fragmentless URI. - base *Schema - // The URI for the schema, if it is the root or has an ID. - // Otherwise nil. - // Invariants: - // s.base.uri != nil. - // s.base == s <=> s.uri != nil - uri *url.URL - // The schema to which Ref refers. - resolvedRef *Schema - - // If the schema has a dynamic ref, exactly one of the next two fields - // will be non-zero after successful resolution. - // The schema to which the dynamic ref refers when it acts lexically. - resolvedDynamicRef *Schema - // The anchor to look up on the stack when the dynamic ref acts dynamically. - dynamicRefAnchor string - - // The following fields are independent of arguments to Schema.Resolved, - // so they could live on the Schema. We put them here for simplicity. - - // The set of required properties. - isRequired map[string]bool - - // Compiled regexps. - pattern *regexp.Regexp - patternProperties map[*regexp.Regexp]*Schema - - // Map from anchors to subschemas. - anchors map[string]anchorInfo -} - -// Schema returns the schema that was resolved. -// It must not be modified. -func (r *Resolved) Schema() *Schema { return r.root } - -// schemaString returns a short string describing the schema. -func (r *Resolved) schemaString(s *Schema) string { - if s.ID != "" { - return s.ID - } - info := r.resolvedInfos[s] - if info.path != "" { - return info.path - } - return "" -} - -// A Loader reads and unmarshals the schema at uri, if any. -type Loader func(uri *url.URL) (*Schema, error) - -// ResolveOptions are options for [Schema.Resolve]. -type ResolveOptions struct { - // BaseURI is the URI relative to which the root schema should be resolved. - // If non-empty, must be an absolute URI (one that starts with a scheme). - // It is resolved (in the URI sense; see [url.ResolveReference]) with root's - // $id property. - // If the resulting URI is not absolute, then the schema cannot contain - // relative URI references. - BaseURI string - // Loader loads schemas that are referred to by a $ref but are not under the - // root schema (remote references). - // If nil, resolving a remote reference will return an error. - Loader Loader - // ValidateDefaults determines whether to validate values of "default" keywords - // against their schemas. - // The [JSON Schema specification] does not require this, but it is recommended - // if defaults will be used. - // - // [JSON Schema specification]: https://json-schema.org/understanding-json-schema/reference/annotations - ValidateDefaults bool -} - -// Resolve resolves all references within the schema and performs other tasks that -// prepare the schema for validation. -// If opts is nil, the default values are used. -// The schema must not be changed after Resolve is called. -// The same schema may be resolved multiple times. -func (root *Schema) Resolve(opts *ResolveOptions) (*Resolved, error) { - // There are up to five steps required to prepare a schema to validate. - // 1. Load: read the schema from somewhere and unmarshal it. - // This schema (root) may have been loaded or created in memory, but other schemas that - // come into the picture in step 4 will be loaded by the given loader. - // 2. Check: validate the schema against a meta-schema, and perform other well-formedness checks. - // Precompute some values along the way. - // 3. Resolve URIs: determine the base URI of the root and all its subschemas, and - // resolve (in the URI sense) all identifiers and anchors with their bases. This step results - // in a map from URIs to schemas within root. - // 4. Resolve references: all refs in the schemas are replaced with the schema they refer to. - // 5. (Optional.) If opts.ValidateDefaults is true, validate the defaults. - r := &resolver{loaded: map[string]*Resolved{}} - if opts != nil { - r.opts = *opts - } - var base *url.URL - if r.opts.BaseURI == "" { - base = &url.URL{} // so we can call ResolveReference on it - } else { - var err error - base, err = url.Parse(r.opts.BaseURI) - if err != nil { - return nil, fmt.Errorf("parsing base URI: %w", err) - } - } - - if r.opts.Loader == nil { - r.opts.Loader = func(uri *url.URL) (*Schema, error) { - return nil, errors.New("cannot resolve remote schemas: no loader passed to Schema.Resolve") - } - } - - resolved, err := r.resolve(root, base) - if err != nil { - return nil, err - } - if r.opts.ValidateDefaults { - if err := resolved.validateDefaults(); err != nil { - return nil, err - } - } - // TODO: before we return, throw away anything we don't need for validation. - return resolved, nil -} - -// A resolver holds the state for resolution. -type resolver struct { - opts ResolveOptions - // A cache of loaded and partly resolved schemas. (They may not have had their - // refs resolved.) The cache ensures that the loader will never be called more - // than once with the same URI, and that reference cycles are handled properly. - loaded map[string]*Resolved -} - -func (r *resolver) resolve(s *Schema, baseURI *url.URL) (*Resolved, error) { - if baseURI.Fragment != "" { - return nil, fmt.Errorf("base URI %s must not have a fragment", baseURI) - } - rs := newResolved(s) - - if err := s.check(rs.resolvedInfos); err != nil { - return nil, err - } - - if err := resolveURIs(rs, baseURI); err != nil { - return nil, err - } - - // Remember the schema by both the URI we loaded it from and its canonical name, - // which may differ if the schema has an $id. - // We must set the map before calling resolveRefs, or ref cycles will cause unbounded recursion. - r.loaded[baseURI.String()] = rs - r.loaded[rs.resolvedInfos[s].uri.String()] = rs - - if err := r.resolveRefs(rs); err != nil { - return nil, err - } - return rs, nil -} - -func (root *Schema) check(infos map[*Schema]*resolvedInfo) error { - // Check for structural validity. Do this first and fail fast: - // bad structure will cause other code to panic. - if err := root.checkStructure(infos); err != nil { - return err - } - - var errs []error - report := func(err error) { errs = append(errs, err) } - - for ss := range root.all() { - ss.checkLocal(report, infos) - } - return errors.Join(errs...) -} - -// checkStructure verifies that root and its subschemas form a tree. -// It also assigns each schema a unique path, to improve error messages. -func (root *Schema) checkStructure(infos map[*Schema]*resolvedInfo) error { - assert(len(infos) == 0, "non-empty infos") - - var check func(reflect.Value, []byte) error - check = func(v reflect.Value, path []byte) error { - // For the purpose of error messages, the root schema has path "root" - // and other schemas' paths are their JSON Pointer from the root. - p := "root" - if len(path) > 0 { - p = string(path) - } - s := v.Interface().(*Schema) - if s == nil { - return fmt.Errorf("jsonschema: schema at %s is nil", p) - } - if info, ok := infos[s]; ok { - // We've seen s before. - // The schema graph at root is not a tree, but it needs to - // be because a schema's base must be unique. - // A cycle would also put Schema.all into an infinite recursion. - return fmt.Errorf("jsonschema: schemas at %s do not form a tree; %s appears more than once (also at %s)", - root, info.path, p) - } - infos[s] = &resolvedInfo{s: s, path: p} - - for _, info := range schemaFieldInfos { - fv := v.Elem().FieldByIndex(info.sf.Index) - switch info.sf.Type { - case schemaType: - // A field that contains an individual schema. - // A nil is valid: it just means the field isn't present. - if !fv.IsNil() { - if err := check(fv, fmt.Appendf(path, "/%s", info.jsonName)); err != nil { - return err - } - } - - case schemaSliceType: - for i := range fv.Len() { - if err := check(fv.Index(i), fmt.Appendf(path, "/%s/%d", info.jsonName, i)); err != nil { - return err - } - } - - case schemaMapType: - iter := fv.MapRange() - for iter.Next() { - key := escapeJSONPointerSegment(iter.Key().String()) - if err := check(iter.Value(), fmt.Appendf(path, "/%s/%s", info.jsonName, key)); err != nil { - return err - } - } - } - - } - return nil - } - - return check(reflect.ValueOf(root), make([]byte, 0, 256)) -} - -// checkLocal checks s for validity, independently of other schemas it may refer to. -// Since checking a regexp involves compiling it, checkLocal saves those compiled regexps -// in the schema for later use. -// It appends the errors it finds to errs. -func (s *Schema) checkLocal(report func(error), infos map[*Schema]*resolvedInfo) { - addf := func(format string, args ...any) { - msg := fmt.Sprintf(format, args...) - report(fmt.Errorf("jsonschema.Schema: %s: %s", s, msg)) - } - - if s == nil { - addf("nil subschema") - return - } - if err := s.basicChecks(); err != nil { - report(err) - return - } - - // TODO: validate the schema's properties, - // ideally by jsonschema-validating it against the meta-schema. - - // Some properties are present so that Schemas can round-trip, but we do not - // validate them. - // Currently, it's just the $vocabulary property. - // As a special case, we can validate the 2020-12 meta-schema. - if s.Vocabulary != nil && s.Schema != draft202012SchemaVersion { - addf("cannot validate a schema with $vocabulary") - } - - info := infos[s] - - // Check and compile regexps. - if s.Pattern != "" { - re, err := regexp.Compile(s.Pattern) - if err != nil { - addf("pattern: %v", err) - } else { - info.pattern = re - } - } - if len(s.PatternProperties) > 0 { - info.patternProperties = map[*regexp.Regexp]*Schema{} - for reString, subschema := range s.PatternProperties { - re, err := regexp.Compile(reString) - if err != nil { - addf("patternProperties[%q]: %v", reString, err) - continue - } - info.patternProperties[re] = subschema - } - } - - // Build a set of required properties, to avoid quadratic behavior when validating - // a struct. - if len(s.Required) > 0 { - info.isRequired = map[string]bool{} - for _, r := range s.Required { - info.isRequired[r] = true - } - } -} - -// resolveURIs resolves the ids and anchors in all the schemas of root, relative -// to baseURI. -// See https://json-schema.org/draft/2020-12/json-schema-core#section-8.2, section -// 8.2.1. -// -// Every schema has a base URI and a parent base URI. -// -// The parent base URI is the base URI of the lexically enclosing schema, or for -// a root schema, the URI it was loaded from or the one supplied to [Schema.Resolve]. -// -// If the schema has no $id property, the base URI of a schema is that of its parent. -// If the schema does have an $id, it must be a URI, possibly relative. The schema's -// base URI is the $id resolved (in the sense of [url.URL.ResolveReference]) against -// the parent base. -// -// As an example, consider this schema loaded from http://a.com/root.json (quotes omitted): -// -// { -// allOf: [ -// {$id: "sub1.json", minLength: 5}, -// {$id: "http://b.com", minimum: 10}, -// {not: {maximum: 20}} -// ] -// } -// -// The base URIs are as follows. Schema locations are expressed in the JSON Pointer notation. -// -// schema base URI -// root http://a.com/root.json -// allOf/0 http://a.com/sub1.json -// allOf/1 http://b.com (absolute $id; doesn't matter that it's not under the loaded URI) -// allOf/2 http://a.com/root.json (inherited from parent) -// allOf/2/not http://a.com/root.json (inherited from parent) -func resolveURIs(rs *Resolved, baseURI *url.URL) error { - // Anchors and dynamic anchors are URI fragments that are scoped to their base. - // We treat them as keys in a map stored within the schema. - setAnchor := func(s *Schema, baseInfo *resolvedInfo, anchor string, dynamic bool) error { - if anchor != "" { - if _, ok := baseInfo.anchors[anchor]; ok { - return fmt.Errorf("duplicate anchor %q in %s", anchor, baseInfo.uri) - } - if baseInfo.anchors == nil { - baseInfo.anchors = map[string]anchorInfo{} - } - baseInfo.anchors[anchor] = anchorInfo{s, dynamic} - } - return nil - } - - var resolve func(s, base *Schema) error - resolve = func(s, base *Schema) error { - info := rs.resolvedInfos[s] - baseInfo := rs.resolvedInfos[base] - - // ids are scoped to the root. - if s.ID != "" { - // draft-7 specific - // https://json-schema.org/draft-07/draft-handrews-json-schema-01#rfc.section.8.3 - // "All other properties in a "$ref" object MUST be ignored." - ignore := rs.draft == draft7 && s.Ref != "" - if !ignore { - // A non-empty ID establishes a new base. - idURI, err := url.Parse(s.ID) - if err != nil { - return err - } - if rs.draft == draft2020 && idURI.Fragment != "" { - return fmt.Errorf("$id %s must not have a fragment", s.ID) - } - if rs.draft == draft7 && idURI.Fragment != "" { - // anchor did not exist in draft 7, id was used for base uri and document navigation - // https://json-schema.org/draft-07/draft-handrews-json-schema-01#id-keyword - anchorName := strings.TrimPrefix(s.ID, "#") - setAnchor(s, baseInfo, anchorName, false) - } else { - // The base URI for this schema is its $id resolved against the parent base. - info.uri = baseInfo.uri.ResolveReference(idURI) - if !info.uri.IsAbs() { - return fmt.Errorf("$id %s does not resolve to an absolute URI (base is %q)", s.ID, baseInfo.uri) - } - rs.resolvedURIs[info.uri.String()] = s - base = s // needed for anchors - baseInfo = rs.resolvedInfos[base] - } - } - } - info.base = base - if rs.draft == draft2020 { - setAnchor(s, baseInfo, s.Anchor, false) - setAnchor(s, baseInfo, s.DynamicAnchor, true) - } - - for c := range s.children() { - if err := resolve(c, base); err != nil { - return err - } - } - return nil - } - - // Set the root URI to the base for now. If the root has an $id, this will change. - rs.resolvedInfos[rs.root].uri = baseURI - // The original base, even if changed, is still a valid way to refer to the root. - rs.resolvedURIs[baseURI.String()] = rs.root - - return resolve(rs.root, rs.root) -} - -// resolveRefs replaces every ref in the schemas with the schema it refers to. -// A reference that doesn't resolve within the schema may refer to some other schema -// that needs to be loaded. -func (r *resolver) resolveRefs(rs *Resolved) error { - for s := range rs.root.all() { - info := rs.resolvedInfos[s] - if s.Ref != "" { - refSchema, _, err := r.resolveRef(rs, s, s.Ref) - if err != nil { - return err - } - // Whether or not the anchor referred to by $ref fragment is dynamic, - // the ref still treats it lexically. - info.resolvedRef = refSchema - } - if s.DynamicRef != "" { - refSchema, frag, err := r.resolveRef(rs, s, s.DynamicRef) - if err != nil { - return err - } - if frag != "" { - // The dynamic ref's fragment points to a dynamic anchor. - // We must resolve the fragment at validation time. - info.dynamicRefAnchor = frag - } else { - // There is no dynamic anchor in the lexically referenced schema, - // so the dynamic ref behaves like a lexical ref. - info.resolvedDynamicRef = refSchema - } - } - } - return nil -} - -// resolveRef resolves the reference ref, which is either s.Ref or s.DynamicRef. -func (r *resolver) resolveRef(rs *Resolved, s *Schema, ref string) (_ *Schema, dynamicFragment string, err error) { - refURI, err := url.Parse(ref) - if err != nil { - return nil, "", err - } - // URI-resolve the ref against the current base URI to get a complete URI. - base := rs.resolvedInfos[s].base - refURI = rs.resolvedInfos[base].uri.ResolveReference(refURI) - // The non-fragment part of a ref URI refers to the base URI of some schema. - // This part is the same for dynamic refs too: their non-fragment part resolves - // lexically. - u := *refURI - u.Fragment = "" - fraglessRefURI := &u - // Look it up locally. - referencedSchema := rs.resolvedURIs[fraglessRefURI.String()] - if referencedSchema == nil { - // The schema is remote. Maybe we've already loaded it. - // We assume that the non-fragment part of refURI refers to a top-level schema - // document. That is, we don't support the case exemplified by - // http://foo.com/bar.json/baz, where the document is in bar.json and - // the reference points to a subschema within it. - // TODO: support that case. - if lrs := r.loaded[fraglessRefURI.String()]; lrs != nil { - referencedSchema = lrs.root - } else { - // Try to load the schema. - ls, err := r.opts.Loader(fraglessRefURI) - if err != nil { - return nil, "", fmt.Errorf("loading %s: %w", fraglessRefURI, err) - } - // Check if referenced schema has $schema defined. If not it should inherit the resolved - if ls.Schema == "" { - ls.Schema = s.Schema - } - lrs, err := r.resolve(ls, fraglessRefURI) - if err != nil { - return nil, "", err - } - referencedSchema = lrs.root - assert(referencedSchema != nil, "nil referenced schema") - // Copy the resolvedInfos from lrs into rs, without overwriting - // (hence we can't use maps.Insert). - for s, i := range lrs.resolvedInfos { - if rs.resolvedInfos[s] == nil { - rs.resolvedInfos[s] = i - } - } - } - } - - frag := refURI.Fragment - // Look up frag in refSchema. - // frag is either a JSON Pointer or the name of an anchor. - // A JSON Pointer is either the empty string or begins with a '/', - // whereas anchors are always non-empty strings that don't contain slashes. - if frag != "" && !strings.HasPrefix(frag, "/") { - resInfo := rs.resolvedInfos[referencedSchema] - info, found := resInfo.anchors[frag] - - if !found { - return nil, "", fmt.Errorf("no anchor %q in %s", frag, s) - } - if info.dynamic { - dynamicFragment = frag - } - return info.schema, dynamicFragment, nil - } - // frag is a JSON Pointer. - s, err = dereferenceJSONPointer(referencedSchema, frag) - return s, "", err -} diff --git a/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/schema.go b/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/schema.go deleted file mode 100644 index 243048a..0000000 --- a/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/schema.go +++ /dev/null @@ -1,642 +0,0 @@ -// Copyright 2025 The JSON Schema Go Project Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package jsonschema - -import ( - "bytes" - "cmp" - "encoding/json" - "errors" - "fmt" - "iter" - "maps" - "math" - "reflect" - "slices" -) - -// A Schema is a JSON schema object. -// It supports both draft-07 and the 2020-12 draft specifications: -// - Draft-07: https://json-schema.org/draft-07/draft-handrews-json-schema-01 -// and https://json-schema.org/draft-07/draft-handrews-json-schema-validation-01 -// - Draft 2020-12: https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-01 -// and https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-01 -// -// A Schema value may have non-zero values for more than one field: -// all relevant non-zero fields are used for validation. -// There is one exception to provide more Go type-safety: the Type and Types fields -// are mutually exclusive. -// -// Since this struct is a Go representation of a JSON value, it inherits JSON's -// distinction between nil and empty. Nil slices and maps are considered absent, -// but empty ones are present and affect validation. For example, -// -// Schema{Enum: nil} -// -// is equivalent to an empty schema, so it validates every instance. But -// -// Schema{Enum: []any{}} -// -// requires equality to some slice element, so it vacuously rejects every instance. -type Schema struct { - // core - ID string `json:"$id,omitempty"` - Schema string `json:"$schema,omitempty"` - Ref string `json:"$ref,omitempty"` - Comment string `json:"$comment,omitempty"` - Defs map[string]*Schema `json:"$defs,omitempty"` - Definitions map[string]*Schema `json:"definitions,omitempty"` - - // split draft 7 Dependencies into DependencySchemas and DependencyStrings - DependencySchemas map[string]*Schema `json:"-"` - DependencyStrings map[string][]string `json:"-"` - - Anchor string `json:"$anchor,omitempty"` - DynamicAnchor string `json:"$dynamicAnchor,omitempty"` - DynamicRef string `json:"$dynamicRef,omitempty"` - Vocabulary map[string]bool `json:"$vocabulary,omitempty"` - - // metadata - Title string `json:"title,omitempty"` - Description string `json:"description,omitempty"` - Default json.RawMessage `json:"default,omitempty"` - Deprecated bool `json:"deprecated,omitempty"` - ReadOnly bool `json:"readOnly,omitempty"` - WriteOnly bool `json:"writeOnly,omitempty"` - Examples []any `json:"examples,omitempty"` - - // validation - // Use Type for a single type, or Types for multiple types; never both. - Type string `json:"-"` - Types []string `json:"-"` - Enum []any `json:"enum,omitempty"` - // Const is *any because a JSON null (Go nil) is a valid value. - Const *any `json:"const,omitempty"` - MultipleOf *float64 `json:"multipleOf,omitempty"` - Minimum *float64 `json:"minimum,omitempty"` - Maximum *float64 `json:"maximum,omitempty"` - ExclusiveMinimum *float64 `json:"exclusiveMinimum,omitempty"` - ExclusiveMaximum *float64 `json:"exclusiveMaximum,omitempty"` - MinLength *int `json:"minLength,omitempty"` - MaxLength *int `json:"maxLength,omitempty"` - Pattern string `json:"pattern,omitempty"` - - // arrays - PrefixItems []*Schema `json:"prefixItems,omitempty"` - Items *Schema `json:"-"` - ItemsArray []*Schema `json:"-"` - MinItems *int `json:"minItems,omitempty"` - MaxItems *int `json:"maxItems,omitempty"` - AdditionalItems *Schema `json:"additionalItems,omitempty"` - UniqueItems bool `json:"uniqueItems,omitempty"` - Contains *Schema `json:"contains,omitempty"` - MinContains *int `json:"minContains,omitempty"` // *int, not int: default is 1, not 0 - MaxContains *int `json:"maxContains,omitempty"` - UnevaluatedItems *Schema `json:"unevaluatedItems,omitempty"` - - // objects - MinProperties *int `json:"minProperties,omitempty"` - MaxProperties *int `json:"maxProperties,omitempty"` - Required []string `json:"required,omitempty"` - DependentRequired map[string][]string `json:"dependentRequired,omitempty"` - Properties map[string]*Schema `json:"properties,omitempty"` - PatternProperties map[string]*Schema `json:"patternProperties,omitempty"` - AdditionalProperties *Schema `json:"additionalProperties,omitempty"` - PropertyNames *Schema `json:"propertyNames,omitempty"` - UnevaluatedProperties *Schema `json:"unevaluatedProperties,omitempty"` - - // logic - AllOf []*Schema `json:"allOf,omitempty"` - AnyOf []*Schema `json:"anyOf,omitempty"` - OneOf []*Schema `json:"oneOf,omitempty"` - Not *Schema `json:"not,omitempty"` - - // conditional - If *Schema `json:"if,omitempty"` - Then *Schema `json:"then,omitempty"` - Else *Schema `json:"else,omitempty"` - DependentSchemas map[string]*Schema `json:"dependentSchemas,omitempty"` - - // other - // https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-00#rfc.section.8 - ContentEncoding string `json:"contentEncoding,omitempty"` - ContentMediaType string `json:"contentMediaType,omitempty"` - ContentSchema *Schema `json:"contentSchema,omitempty"` - - // https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-00#rfc.section.7 - Format string `json:"format,omitempty"` - - // Extra allows for additional keywords beyond those specified. - Extra map[string]any `json:"-"` - - // PropertyOrder records the ordering of properties for JSON rendering. - // - // During [For], PropertyOrder is set to the field order, - // if the type used for inference is a struct. - // - // If PropertyOrder is set, it controls the relative ordering of properties in [Schema.MarshalJSON]. - // The rendered JSON first lists any properties that appear in the PropertyOrder slice in the order - // they appear, followed by all other properties that do not appear in the PropertyOrder slice in an - // undefined but deterministic order. - PropertyOrder []string `json:"-"` -} - -// falseSchema returns a new Schema tree that fails to validate any value. -func falseSchema() *Schema { - return &Schema{Not: &Schema{}} -} - -// anchorInfo records the subschema to which an anchor refers, and whether -// the anchor keyword is $anchor or $dynamicAnchor. -type anchorInfo struct { - schema *Schema - dynamic bool -} - -// String returns a short description of the schema. -func (s *Schema) String() string { - if s.ID != "" { - return s.ID - } - if a := cmp.Or(s.Anchor, s.DynamicAnchor); a != "" { - return fmt.Sprintf("anchor %s", a) - } - return "" -} - -// CloneSchemas returns a copy of s. -// The copy is shallow except for sub-schemas, which are themelves copied with CloneSchemas. -// This allows both s and s.CloneSchemas() to appear as sub-schemas of the same parent. -func (s *Schema) CloneSchemas() *Schema { - if s == nil { - return nil - } - s2 := *s - v := reflect.ValueOf(&s2) - for _, info := range schemaFieldInfos { - fv := v.Elem().FieldByIndex(info.sf.Index) - switch info.sf.Type { - case schemaType: - sscss := fv.Interface().(*Schema) - fv.Set(reflect.ValueOf(sscss.CloneSchemas())) - - case schemaSliceType: - slice := fv.Interface().([]*Schema) - slice = slices.Clone(slice) - for i, ss := range slice { - slice[i] = ss.CloneSchemas() - } - fv.Set(reflect.ValueOf(slice)) - - case schemaMapType: - m := fv.Interface().(map[string]*Schema) - m = maps.Clone(m) - for k, ss := range m { - m[k] = ss.CloneSchemas() - } - fv.Set(reflect.ValueOf(m)) - - } - } - return &s2 -} - -func (s *Schema) basicChecks() error { - if s.Type != "" && s.Types != nil { - return errors.New("both Type and Types are set; at most one should be") - } - if s.Defs != nil && s.Definitions != nil { - return errors.New("both Defs and Definitions are set; at most one should be") - } - if s.Items != nil && s.ItemsArray != nil { - return errors.New("both Items and ItemsArray are set; at most one should be") - } - propertyOrderSeen := make(map[string]bool) - for _, val := range s.PropertyOrder { - if _, ok := propertyOrderSeen[val]; ok { - // Duplicate found - return fmt.Errorf("property order slice cannot contain duplicate entries, found duplicate %q", val) - } - propertyOrderSeen[val] = true - } - - for key := range s.DependencySchemas { - // Check if the key exists in the dependency strings map - if _, exists := s.DependencyStrings[key]; exists { - return fmt.Errorf("dependency key %q cannot be defined as both a schema and a string array", key) - } - } - return nil -} - -type schemaWithoutMethods Schema // doesn't implement json.{Unm,M}arshaler - -func (s Schema) MarshalJSON() ([]byte, error) { - // NOTE: Use a value receiver here to avoid the encoding/json bugs - // described in golang/go#22967, golang/go#33993, and golang/go#55890. - // With a pointer receiver, MarshalJSON is only called for Schema in - // some cases (for example when the field value is addressable, or not - // stored as a map value), which leads to inconsistent JSON encoding. - // A value receiver makes Schema itself implement json.Marshaler and - // ensures that encoding/json always calls this method. - if err := s.basicChecks(); err != nil { - return nil, err - } - // Marshal either Type or Types as "type". - var typ any - switch { - case s.Type != "": - typ = s.Type - case s.Types != nil: - typ = s.Types - } - - var items any - switch { - case s.Items != nil: - items = s.Items - case s.ItemsArray != nil: - items = s.ItemsArray - } - - var dep map[string]any - size := len(s.DependencySchemas) + len(s.DependencyStrings) - if size > 0 { - dep = make(map[string]any, size) - for k, v := range s.DependencySchemas { - dep[k] = v - } - for k, v := range s.DependencyStrings { - dep[k] = v - } - } - - ms := struct { - Type any `json:"type,omitempty"` - Properties json.Marshaler `json:"properties,omitempty"` - Dependencies map[string]any `json:"dependencies,omitempty"` - Items any `json:"items,omitempty"` - *schemaWithoutMethods - }{ - Type: typ, - Dependencies: dep, - Items: items, - schemaWithoutMethods: (*schemaWithoutMethods)(&s), - } - // Marshal properties, even if the empty map (but not nil). - if s.Properties != nil { - ms.Properties = orderedProperties{ - props: s.Properties, - order: s.PropertyOrder, - } - } - - bs, err := marshalStructWithMap(&ms, "Extra") - if err != nil { - return nil, err - } - // Marshal {} as true and {"not": {}} as false. - // It is wasteful to do this here instead of earlier, but much easier. - switch { - case bytes.Equal(bs, []byte(`{}`)): - bs = []byte("true") - case bytes.Equal(bs, []byte(`{"not":true}`)): - bs = []byte("false") - } - return bs, nil -} - -// orderedProperties is a helper to marshal the properties map in a specific order. -type orderedProperties struct { - props map[string]*Schema - order []string -} - -func (op orderedProperties) MarshalJSON() ([]byte, error) { - var buf bytes.Buffer - buf.WriteByte('{') - - first := true - processed := make(map[string]bool, len(op.props)) - - // Helper closure to write "key": value - writeEntry := func(key string, val *Schema) error { - if !first { - buf.WriteByte(',') - } - first = false - - // Marshal the Key - keyBytes, err := json.Marshal(key) - if err != nil { - return err - } - buf.Write(keyBytes) - - buf.WriteByte(':') - - // Marshal the Value - valBytes, err := json.Marshal(val) - if err != nil { - return err - } - buf.Write(valBytes) - return nil - } - - // Write keys explicitly listed in PropertyOrder - for _, name := range op.order { - if prop, ok := op.props[name]; ok { - if err := writeEntry(name, prop); err != nil { - return nil, err - } - processed[name] = true - } - } - - // Write any remaining keys - var remaining []string - for name := range op.props { - if !processed[name] { - remaining = append(remaining, name) - } - } - - // Sort the slice alphabetically - slices.Sort(remaining) - - for _, name := range remaining { - if err := writeEntry(name, op.props[name]); err != nil { - return nil, err - } - } - - buf.WriteByte('}') - return buf.Bytes(), nil -} - -func (s *Schema) UnmarshalJSON(data []byte) error { - // A JSON boolean is a valid schema. - var b bool - if err := json.Unmarshal(data, &b); err == nil { - if b { - // true is the empty schema, which validates everything. - *s = Schema{} - } else { - // false is the schema that validates nothing. - *s = *falseSchema() - } - return nil - } - - ms := struct { - Type json.RawMessage `json:"type,omitempty"` - Dependencies map[string]json.RawMessage `json:"dependencies,omitempty"` - Items json.RawMessage `json:"items,omitempty"` - Const json.RawMessage `json:"const,omitempty"` - MinLength *integer `json:"minLength,omitempty"` - MaxLength *integer `json:"maxLength,omitempty"` - MinItems *integer `json:"minItems,omitempty"` - MaxItems *integer `json:"maxItems,omitempty"` - MinProperties *integer `json:"minProperties,omitempty"` - MaxProperties *integer `json:"maxProperties,omitempty"` - MinContains *integer `json:"minContains,omitempty"` - MaxContains *integer `json:"maxContains,omitempty"` - - *schemaWithoutMethods - }{ - schemaWithoutMethods: (*schemaWithoutMethods)(s), - } - if err := unmarshalStructWithMap(data, &ms, "Extra"); err != nil { - return err - } - // Unmarshal "type" as either Type or Types. - var err error - if len(ms.Type) > 0 { - switch ms.Type[0] { - case '"': - err = json.Unmarshal(ms.Type, &s.Type) - case '[': - err = json.Unmarshal(ms.Type, &s.Types) - default: - err = fmt.Errorf(`invalid value for "type": %q`, ms.Type) - } - } - if err != nil { - return err - } - - // Unmarshal "items" as either Items or ItemsArray. - if len(ms.Items) > 0 { - switch ms.Items[0] { - case '[': - var schemas []*Schema - err = json.Unmarshal(ms.Items, &schemas) - s.ItemsArray = schemas - default: - var schema Schema - err = json.Unmarshal(ms.Items, &schema) - s.Items = &schema - } - } - if err != nil { - return err - } - - // Unmarshal "Dependencies" values as either string arrays or schemas - // and assign them to specific map DependencySchemas or DependencyStrings. - for k, v := range ms.Dependencies { - if len(v) > 0 { - switch v[0] { - case '[': - var dstrings []string - err = json.Unmarshal(v, &dstrings) - if s.DependencyStrings == nil { - s.DependencyStrings = make(map[string][]string) - } - s.DependencyStrings[k] = dstrings - default: - var dschema Schema - err = json.Unmarshal(v, &dschema) - if s.DependencySchemas == nil { - s.DependencySchemas = make(map[string]*Schema) - } - s.DependencySchemas[k] = &dschema - } - } - if err != nil { - return err - } - } - - unmarshalAnyPtr := func(p **any, raw json.RawMessage) error { - if len(raw) == 0 { - return nil - } - if bytes.Equal(raw, []byte("null")) { - *p = new(any) - return nil - } - return json.Unmarshal(raw, p) - } - - // Setting Const to a pointer to null will marshal properly, but won't - // unmarshal: the *any is set to nil, not a pointer to nil. - if err := unmarshalAnyPtr(&s.Const, ms.Const); err != nil { - return err - } - - set := func(dst **int, src *integer) { - if src != nil { - *dst = Ptr(int(*src)) - } - } - - set(&s.MinLength, ms.MinLength) - set(&s.MaxLength, ms.MaxLength) - set(&s.MinItems, ms.MinItems) - set(&s.MaxItems, ms.MaxItems) - set(&s.MinProperties, ms.MinProperties) - set(&s.MaxProperties, ms.MaxProperties) - set(&s.MinContains, ms.MinContains) - set(&s.MaxContains, ms.MaxContains) - - return nil -} - -type integer int32 // for the integer-valued fields of Schema - -func (ip *integer) UnmarshalJSON(data []byte) error { - if len(data) == 0 { - // nothing to do - return nil - } - // If there is a decimal point, src is a floating-point number. - var i int64 - if bytes.ContainsRune(data, '.') { - var f float64 - if err := json.Unmarshal(data, &f); err != nil { - return errors.New("not a number") - } - i = int64(f) - if float64(i) != f { - return errors.New("not an integer value") - } - } else { - if err := json.Unmarshal(data, &i); err != nil { - return errors.New("cannot be unmarshaled into an int") - } - } - // Ensure behavior is the same on both 32-bit and 64-bit systems. - if i < math.MinInt32 || i > math.MaxInt32 { - return errors.New("integer is out of range") - } - *ip = integer(i) - return nil -} - -// Ptr returns a pointer to a new variable whose value is x. -func Ptr[T any](x T) *T { return &x } - -// every applies f preorder to every schema under s including s. -// The second argument to f is the path to the schema appended to the argument path. -// It stops when f returns false. -func (s *Schema) every(f func(*Schema) bool) bool { - return f(s) && s.everyChild(func(s *Schema) bool { return s.every(f) }) -} - -// everyChild reports whether f is true for every immediate child schema of s. -func (s *Schema) everyChild(f func(*Schema) bool) bool { - v := reflect.ValueOf(s) - for _, info := range schemaFieldInfos { - fv := v.Elem().FieldByIndex(info.sf.Index) - switch info.sf.Type { - case schemaType: - // A field that contains an individual schema. A nil is valid: it just means the field isn't present. - c := fv.Interface().(*Schema) - if c != nil && !f(c) { - return false - } - - case schemaSliceType: - slice := fv.Interface().([]*Schema) - for _, c := range slice { - if !f(c) { - return false - } - } - - case schemaMapType: - // Sort keys for determinism. - m := fv.Interface().(map[string]*Schema) - for _, k := range slices.Sorted(maps.Keys(m)) { - if !f(m[k]) { - return false - } - } - } - } - - return true -} - -// all wraps every in an iterator. -func (s *Schema) all() iter.Seq[*Schema] { - return func(yield func(*Schema) bool) { s.every(yield) } -} - -// children wraps everyChild in an iterator. -func (s *Schema) children() iter.Seq[*Schema] { - return func(yield func(*Schema) bool) { s.everyChild(yield) } -} - -var ( - schemaType = reflect.TypeFor[*Schema]() - schemaSliceType = reflect.TypeFor[[]*Schema]() - schemaMapType = reflect.TypeFor[map[string]*Schema]() -) - -type structFieldInfo struct { - sf reflect.StructField - jsonName string -} - -var ( - // the visible fields of Schema that have a JSON name, sorted by that name - schemaFieldInfos []structFieldInfo - // map from JSON name to field - schemaFieldMap = map[string]reflect.StructField{} -) - -func init() { - t := reflect.VisibleFields(reflect.TypeFor[Schema]()) - for _, sf := range t { - info := fieldJSONInfo(sf) - if !info.omit { - schemaFieldInfos = append(schemaFieldInfos, structFieldInfo{sf, info.name}) - } else { - // jsoninfo.name is used to build the info paths. The items and dependencies are ommited, - // since the original fields are separated to handle the union types supported in json and - // these fields have custom marshalling and unmarshalling logic. - // we still need these fields in schemaFieldInfos for creating schema trees and calculating paths and refs. - // so we manually create them and assign the jsonName to the original field json name. - switch sf.Name { - case "Items", "ItemsArray": - schemaFieldInfos = append(schemaFieldInfos, structFieldInfo{sf, "items"}) - case "DependencySchemas", "DependencyStrings": - schemaFieldInfos = append(schemaFieldInfos, structFieldInfo{sf, "dependencies"}) - } - } - } - // The value of "dependencies" this sort of schemaFieldInfos. - // This sort is unstable and is comparing the json.names of DependencyStrings and DependencySchemas which are both "dependencies". - // Since the sort is unstable it cannot be guarantied that "dependencies" has the DependencySchemas value. - slices.SortFunc(schemaFieldInfos, func(i1, i2 structFieldInfo) int { - return cmp.Compare(i1.jsonName, i2.jsonName) - }) - for _, info := range schemaFieldInfos { - schemaFieldMap[info.jsonName] = info.sf - } -} diff --git a/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/util.go b/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/util.go deleted file mode 100644 index 5cfa27d..0000000 --- a/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/util.go +++ /dev/null @@ -1,463 +0,0 @@ -// Copyright 2025 The JSON Schema Go Project Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package jsonschema - -import ( - "bytes" - "cmp" - "encoding/binary" - "encoding/json" - "fmt" - "hash/maphash" - "math" - "math/big" - "reflect" - "slices" - "strings" - "sync" -) - -// Equal reports whether two Go values representing JSON values are equal according -// to the JSON Schema spec. -// The values must not contain cycles. -// See https://json-schema.org/draft/2020-12/json-schema-core#section-4.2.2. -// It behaves like reflect.DeepEqual, except that numbers are compared according -// to mathematical equality. -func Equal(x, y any) bool { - return equalValue(reflect.ValueOf(x), reflect.ValueOf(y)) -} - -func equalValue(x, y reflect.Value) bool { - // Copied from src/reflect/deepequal.go, omitting the visited check (because JSON - // values are trees). - if !x.IsValid() || !y.IsValid() { - return x.IsValid() == y.IsValid() - } - - // Treat numbers specially. - rx, ok1 := jsonNumber(x) - ry, ok2 := jsonNumber(y) - if ok1 && ok2 { - return rx.Cmp(ry) == 0 - } - if x.Kind() != y.Kind() { - return false - } - switch x.Kind() { - case reflect.Array: - if x.Len() != y.Len() { - return false - } - for i := range x.Len() { - if !equalValue(x.Index(i), y.Index(i)) { - return false - } - } - return true - case reflect.Slice: - if x.IsNil() != y.IsNil() { - return false - } - if x.Len() != y.Len() { - return false - } - if x.UnsafePointer() == y.UnsafePointer() { - return true - } - // Special case for []byte, which is common. - if x.Type().Elem().Kind() == reflect.Uint8 && x.Type() == y.Type() { - return bytes.Equal(x.Bytes(), y.Bytes()) - } - for i := range x.Len() { - if !equalValue(x.Index(i), y.Index(i)) { - return false - } - } - return true - case reflect.Interface: - if x.IsNil() || y.IsNil() { - return x.IsNil() == y.IsNil() - } - return equalValue(x.Elem(), y.Elem()) - case reflect.Pointer: - if x.UnsafePointer() == y.UnsafePointer() { - return true - } - return equalValue(x.Elem(), y.Elem()) - case reflect.Struct: - t := x.Type() - if t != y.Type() { - return false - } - for i := range t.NumField() { - sf := t.Field(i) - if !sf.IsExported() { - continue - } - if !equalValue(x.FieldByIndex(sf.Index), y.FieldByIndex(sf.Index)) { - return false - } - } - return true - case reflect.Map: - if x.IsNil() != y.IsNil() { - return false - } - if x.Len() != y.Len() { - return false - } - if x.UnsafePointer() == y.UnsafePointer() { - return true - } - iter := x.MapRange() - for iter.Next() { - vx := iter.Value() - vy := y.MapIndex(iter.Key()) - if !vy.IsValid() || !equalValue(vx, vy) { - return false - } - } - return true - case reflect.Func: - if x.Type() != y.Type() { - return false - } - if x.IsNil() && y.IsNil() { - return true - } - panic("cannot compare functions") - case reflect.String: - return x.String() == y.String() - case reflect.Bool: - return x.Bool() == y.Bool() - // Ints, uints and floats handled in jsonNumber, at top of function. - default: - panic(fmt.Sprintf("unsupported kind: %s", x.Kind())) - } -} - -// hashValue adds v to the data hashed by h. v must not have cycles. -// hashValue panics if the value contains functions or channels, or maps whose -// key type is not string. -// It ignores unexported fields of structs. -// Calls to hashValue with the equal values (in the sense -// of [Equal]) result in the same sequence of values written to the hash. -func hashValue(h *maphash.Hash, v reflect.Value) { - // TODO: replace writes of basic types with WriteComparable in 1.24. - - writeUint := func(u uint64) { - var buf [8]byte - binary.BigEndian.PutUint64(buf[:], u) - h.Write(buf[:]) - } - - var write func(reflect.Value) - write = func(v reflect.Value) { - if r, ok := jsonNumber(v); ok { - // We want 1.0 and 1 to hash the same. - // big.Rats are always normalized, so they will be. - // We could do this more efficiently by handling the int and float cases - // separately, but that's premature. - writeUint(uint64(r.Sign() + 1)) - h.Write(r.Num().Bytes()) - h.Write(r.Denom().Bytes()) - return - } - switch v.Kind() { - case reflect.Invalid: - h.WriteByte(0) - case reflect.String: - h.WriteString(v.String()) - case reflect.Bool: - if v.Bool() { - h.WriteByte(1) - } else { - h.WriteByte(0) - } - case reflect.Complex64, reflect.Complex128: - c := v.Complex() - writeUint(math.Float64bits(real(c))) - writeUint(math.Float64bits(imag(c))) - case reflect.Array, reflect.Slice: - // Although we could treat []byte more efficiently, - // JSON values are unlikely to contain them. - writeUint(uint64(v.Len())) - for i := range v.Len() { - write(v.Index(i)) - } - case reflect.Interface, reflect.Pointer: - write(v.Elem()) - case reflect.Struct: - t := v.Type() - for i := range t.NumField() { - if sf := t.Field(i); sf.IsExported() { - write(v.FieldByIndex(sf.Index)) - } - } - case reflect.Map: - if v.Type().Key().Kind() != reflect.String { - panic("map with non-string key") - } - // Sort the keys so the hash is deterministic. - keys := v.MapKeys() - // Write the length. That distinguishes between, say, two consecutive - // maps with disjoint keys from one map that has the items of both. - writeUint(uint64(len(keys))) - slices.SortFunc(keys, func(x, y reflect.Value) int { return cmp.Compare(x.String(), y.String()) }) - for _, k := range keys { - write(k) - write(v.MapIndex(k)) - } - // Ints, uints and floats handled in jsonNumber, at top of function. - default: - panic(fmt.Sprintf("unsupported kind: %s", v.Kind())) - } - } - - write(v) -} - -// jsonNumber converts a numeric value or a json.Number to a [big.Rat]. -// If v is not a number, it returns nil, false. -func jsonNumber(v reflect.Value) (*big.Rat, bool) { - r := new(big.Rat) - switch { - case !v.IsValid(): - return nil, false - case v.CanInt(): - r.SetInt64(v.Int()) - case v.CanUint(): - r.SetUint64(v.Uint()) - case v.CanFloat(): - r.SetFloat64(v.Float()) - default: - jn, ok := v.Interface().(json.Number) - if !ok { - return nil, false - } - if _, ok := r.SetString(jn.String()); !ok { - // This can fail in rare cases; for example, "1e9999999". - // That is a valid JSON number, since the spec puts no limit on the size - // of the exponent. - return nil, false - } - } - return r, true -} - -// jsonType returns a string describing the type of the JSON value, -// as described in the JSON Schema specification: -// https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-01#section-6.1.1. -// It returns "", false if the value is not valid JSON. -func jsonType(v reflect.Value) (string, bool) { - if !v.IsValid() { - // Not v.IsNil(): a nil []any is still a JSON array. - return "null", true - } - if v.CanInt() || v.CanUint() { - return "integer", true - } - if v.CanFloat() { - if _, f := math.Modf(v.Float()); f == 0 { - return "integer", true - } - return "number", true - } - switch v.Kind() { - case reflect.Bool: - return "boolean", true - case reflect.String: - return "string", true - case reflect.Slice, reflect.Array: - return "array", true - case reflect.Map, reflect.Struct: - return "object", true - default: - return "", false - } -} - -func assert(cond bool, msg string) { - if !cond { - panic("assertion failed: " + msg) - } -} - -// marshalStructWithMap marshals its first argument to JSON, treating the field named -// mapField as an embedded map. The first argument must be a pointer to -// a struct. The underlying type of mapField must be a map[string]any, and it must have -// a "-" json tag, meaning it will not be marshaled. -// -// For example, given this struct: -// -// type S struct { -// A int -// Extra map[string] any `json:"-"` -// } -// -// and this value: -// -// s := S{A: 1, Extra: map[string]any{"B": 2}} -// -// the call marshalJSONWithMap(s, "Extra") would return -// -// {"A": 1, "B": 2} -// -// It is an error if the map contains the same key as another struct field's -// JSON name. -// -// marshalStructWithMap calls json.Marshal on a value of type T, so T must not -// have a MarshalJSON method that calls this function, on pain of infinite regress. -// -// Note that there is a similar function in mcp/util.go, but they are not the same. -// Here the function requires `-` json tag, does not clear the mapField map, -// and handles embedded struct due to the implementation of jsonNames in this package. -// -// TODO: avoid this restriction on T by forcing it to marshal in a default way. -// See https://go.dev/play/p/EgXKJHxEx_R. -func marshalStructWithMap[T any](s *T, mapField string) ([]byte, error) { - // Marshal the struct and the map separately, and concatenate the bytes. - // This strategy is dramatically less complicated than - // constructing a synthetic struct or map with the combined keys. - if s == nil { - return []byte("null"), nil - } - s2 := *s - vMapField := reflect.ValueOf(&s2).Elem().FieldByName(mapField) - mapVal := vMapField.Interface().(map[string]any) - - // Check for duplicates. - names := jsonNames(reflect.TypeFor[T]()) - for key := range mapVal { - if names[key] { - return nil, fmt.Errorf("map key %q duplicates struct field", key) - } - } - - structBytes, err := json.Marshal(s2) - if err != nil { - return nil, fmt.Errorf("marshalStructWithMap(%+v): %w", s, err) - } - if len(mapVal) == 0 { - return structBytes, nil - } - mapBytes, err := json.Marshal(mapVal) - if err != nil { - return nil, err - } - if len(structBytes) == 2 { // must be "{}" - return mapBytes, nil - } - // "{X}" + "{Y}" => "{X,Y}" - res := append(structBytes[:len(structBytes)-1], ',') - res = append(res, mapBytes[1:]...) - return res, nil -} - -// unmarshalStructWithMap is the inverse of marshalStructWithMap. -// T has the same restrictions as in that function. -// -// Note that there is a similar function in mcp/util.go, but they are not the same. -// Here jsonNames also returns fields from embedded structs, hence this function -// handles embedded structs as well. -func unmarshalStructWithMap[T any](data []byte, v *T, mapField string) error { - // Unmarshal into the struct, ignoring unknown fields. - if err := json.Unmarshal(data, v); err != nil { - return err - } - // Unmarshal into the map. - m := map[string]any{} - if err := json.Unmarshal(data, &m); err != nil { - return err - } - // Delete from the map the fields of the struct. - for n := range jsonNames(reflect.TypeFor[T]()) { - delete(m, n) - } - if len(m) != 0 { - reflect.ValueOf(v).Elem().FieldByName(mapField).Set(reflect.ValueOf(m)) - } - return nil -} - -var jsonNamesMap sync.Map // from reflect.Type to map[string]bool - -// jsonNames returns the set of JSON object keys that t will marshal into, -// including fields from embedded structs in t. -// t must be a struct type. -// -// Note that there is a similar function in mcp/util.go, but they are not the same -// Here the function recurses over embedded structs and includes fields from them. -func jsonNames(t reflect.Type) map[string]bool { - // Lock not necessary: at worst we'll duplicate work. - if val, ok := jsonNamesMap.Load(t); ok { - return val.(map[string]bool) - } - m := map[string]bool{} - for i := range t.NumField() { - field := t.Field(i) - // handle embedded structs - if field.Anonymous { - fieldType := field.Type - if fieldType.Kind() == reflect.Ptr { - fieldType = fieldType.Elem() - } - for n := range jsonNames(fieldType) { - m[n] = true - } - continue - } - info := fieldJSONInfo(field) - if !info.omit { - m[info.name] = true - } - } - jsonNamesMap.Store(t, m) - return m -} - -type jsonInfo struct { - omit bool // unexported or first tag element is "-" - name string // Go field name or first tag element. Empty if omit is true. - settings map[string]bool // "omitempty", "omitzero", etc. -} - -// fieldJSONInfo reports information about how encoding/json -// handles the given struct field. -// If the field is unexported, jsonInfo.omit is true and no other jsonInfo field -// is populated. -// If the field is exported and has no tag, then name is the field's name and all -// other fields are false. -// Otherwise, the information is obtained from the tag. -func fieldJSONInfo(f reflect.StructField) jsonInfo { - if !f.IsExported() { - return jsonInfo{omit: true} - } - info := jsonInfo{name: f.Name} - if tag, ok := f.Tag.Lookup("json"); ok { - name, rest, found := strings.Cut(tag, ",") - // "-" means omit, but "-," means the name is "-" - if name == "-" && !found { - return jsonInfo{omit: true} - } - if name != "" { - info.name = name - } - if len(rest) > 0 { - info.settings = map[string]bool{} - for _, s := range strings.Split(rest, ",") { - info.settings[s] = true - } - } - } - return info -} - -// wrapf wraps *errp with the given formatted message if *errp is not nil. -func wrapf(errp *error, format string, args ...any) { - if *errp != nil { - *errp = fmt.Errorf("%s: %w", fmt.Sprintf(format, args...), *errp) - } -} diff --git a/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/validate.go b/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/validate.go deleted file mode 100644 index bbef590..0000000 --- a/go/sdk/vendor/github.com/google/jsonschema-go/jsonschema/validate.go +++ /dev/null @@ -1,905 +0,0 @@ -// Copyright 2025 The JSON Schema Go Project Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package jsonschema - -import ( - "encoding/json" - "errors" - "fmt" - "hash/maphash" - "iter" - "math" - "math/big" - "reflect" - "slices" - "strings" - "sync" - "unicode/utf8" -) - -// The values of the "$schema" keyword for the versions that we can validate. -const ( - draft7SchemaVersion = "http://json-schema.org/draft-07/schema#" - draft7SecSchemaVersion = "https://json-schema.org/draft-07/schema#" - draft202012SchemaVersion = "https://json-schema.org/draft/2020-12/schema" -) - -// isValidSchemaVersion checks if the given schema version is supported -func isValidSchemaVersion(version string) bool { - return version == "" || version == draft7SchemaVersion || version == draft7SecSchemaVersion || version == draft202012SchemaVersion -} - -// Validate validates the instance, which must be a JSON value, against the schema. -// It returns nil if validation is successful or an error if it is not. -// If the schema type is "object", instance should be a map[string]any. -func (rs *Resolved) Validate(instance any) error { - if s := rs.root.Schema; !isValidSchemaVersion(s) { - return fmt.Errorf("cannot validate version %s, supported versions: draft-07 and draft 2020-12", s) - } - st := &state{rs: rs} - return st.validate(reflect.ValueOf(instance), st.rs.root, nil) -} - -// validateDefaults walks the schema tree. If it finds a default, it validates it -// against the schema containing it. -// -// TODO(jba): account for dynamic refs. This algorithm simple-mindedly -// treats each schema with a default as its own root. -func (rs *Resolved) validateDefaults() error { - if s := rs.root.Schema; !isValidSchemaVersion(s) { - return fmt.Errorf("cannot validate version %s, supported versions: draft-07 and draft 2020-12", s) - } - st := &state{rs: rs} - for s := range rs.root.all() { - // We checked for nil schemas in [Schema.Resolve]. - assert(s != nil, "nil schema") - if s.DynamicRef != "" { - return fmt.Errorf("jsonschema: %s: validateDefaults does not support dynamic refs", rs.schemaString(s)) - } - if s.Default != nil { - var d any - if err := json.Unmarshal(s.Default, &d); err != nil { - return fmt.Errorf("unmarshaling default value of schema %s: %w", rs.schemaString(s), err) - } - if err := st.validate(reflect.ValueOf(d), s, nil); err != nil { - return err - } - } - } - return nil -} - -// state is the state of single call to ResolvedSchema.Validate. -type state struct { - rs *Resolved - // stack holds the schemas from recursive calls to validate. - // These are the "dynamic scopes" used to resolve dynamic references. - // https://json-schema.org/draft/2020-12/json-schema-core#scopes - stack []*Schema -} - -// validate validates the reflected value of the instance. -func (st *state) validate(instance reflect.Value, schema *Schema, callerAnns *annotations) (err error) { - defer wrapf(&err, "validating %s", st.rs.schemaString(schema)) - - // Maintain a stack for dynamic schema resolution. - st.stack = append(st.stack, schema) // push - defer func() { - st.stack = st.stack[:len(st.stack)-1] // pop - }() - - // We checked for nil schemas in [Schema.Resolve]. - assert(schema != nil, "nil schema") - - // Step through interfaces and pointers. - for instance.Kind() == reflect.Pointer || instance.Kind() == reflect.Interface { - instance = instance.Elem() - } - - schemaInfo := st.rs.resolvedInfos[schema] - - var anns annotations // all the annotations for this call and child calls - // $ref: https://json-schema.org/draft/2020-12/json-schema-core#section-8.2.3.1 - if schema.Ref != "" { - if err := st.validate(instance, schemaInfo.resolvedRef, &anns); err != nil { - return err - } - // https://json-schema.org/draft-07/draft-handrews-json-schema-01#rfc.section.8.3 - // "All other properties in a "$ref" object MUST be ignored." - if st.rs.draft == draft7 { - return nil - } - } - - // type: https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-01#section-6.1.1 - if schema.Type != "" || schema.Types != nil { - gotType, ok := jsonType(instance) - if !ok { - return fmt.Errorf("type: %v of type %[1]T is not a valid JSON value", instance) - } - if schema.Type != "" { - // "number" subsumes integers - if !(gotType == schema.Type || - gotType == "integer" && schema.Type == "number") { - return fmt.Errorf("type: %v has type %q, want %q", instance, gotType, schema.Type) - } - } else { - if !(slices.Contains(schema.Types, gotType) || (gotType == "integer" && slices.Contains(schema.Types, "number"))) { - return fmt.Errorf("type: %v has type %q, want one of %q", - instance, gotType, strings.Join(schema.Types, ", ")) - } - } - } - // enum: https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-01#section-6.1.2 - if schema.Enum != nil { - ok := false - for _, e := range schema.Enum { - if equalValue(reflect.ValueOf(e), instance) { - ok = true - break - } - } - if !ok { - return fmt.Errorf("enum: %v does not equal any of: %v", instance, schema.Enum) - } - } - - // const: https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-01#section-6.1.3 - if schema.Const != nil { - if !equalValue(reflect.ValueOf(*schema.Const), instance) { - return fmt.Errorf("const: %v does not equal %v", instance, *schema.Const) - } - } - - // numbers: https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-01#section-6.2 - if schema.MultipleOf != nil || schema.Minimum != nil || schema.Maximum != nil || schema.ExclusiveMinimum != nil || schema.ExclusiveMaximum != nil { - n, ok := jsonNumber(instance) - if ok { // these keywords don't apply to non-numbers - if schema.MultipleOf != nil { - // TODO: validate MultipleOf as non-zero. - // The test suite assumes floats. - nf, _ := n.Float64() // don't care if it's exact or not - if _, f := math.Modf(nf / *schema.MultipleOf); f != 0 { - return fmt.Errorf("multipleOf: %s is not a multiple of %f", n, *schema.MultipleOf) - } - } - - m := new(big.Rat) // reuse for all of the following - cmp := func(f float64) int { return n.Cmp(m.SetFloat64(f)) } - - if schema.Minimum != nil && cmp(*schema.Minimum) < 0 { - return fmt.Errorf("minimum: %s is less than %f", n, *schema.Minimum) - } - if schema.Maximum != nil && cmp(*schema.Maximum) > 0 { - return fmt.Errorf("maximum: %s is greater than %f", n, *schema.Maximum) - } - if schema.ExclusiveMinimum != nil && cmp(*schema.ExclusiveMinimum) <= 0 { - return fmt.Errorf("exclusiveMinimum: %s is less than or equal to %f", n, *schema.ExclusiveMinimum) - } - if schema.ExclusiveMaximum != nil && cmp(*schema.ExclusiveMaximum) >= 0 { - return fmt.Errorf("exclusiveMaximum: %s is greater than or equal to %f", n, *schema.ExclusiveMaximum) - } - } - } - - // strings: https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-01#section-6.3 - if instance.Kind() == reflect.String && (schema.MinLength != nil || schema.MaxLength != nil || schema.Pattern != "") { - str := instance.String() - n := utf8.RuneCountInString(str) - if schema.MinLength != nil { - if m := *schema.MinLength; n < m { - return fmt.Errorf("minLength: %q contains %d Unicode code points, fewer than %d", str, n, m) - } - } - if schema.MaxLength != nil { - if m := *schema.MaxLength; n > m { - return fmt.Errorf("maxLength: %q contains %d Unicode code points, more than %d", str, n, m) - } - } - - if schema.Pattern != "" && !schemaInfo.pattern.MatchString(str) { - return fmt.Errorf("pattern: %q does not match regular expression %q", str, schema.Pattern) - } - } - - // $dynamicRef: https://json-schema.org/draft/2020-12/json-schema-core#section-8.2.3.2 - if schema.DynamicRef != "" { - // The ref behaves lexically or dynamically, but not both. - assert((schemaInfo.resolvedDynamicRef == nil) != (schemaInfo.dynamicRefAnchor == ""), - "DynamicRef not resolved properly") - if schemaInfo.resolvedDynamicRef != nil { - // Same as $ref. - if err := st.validate(instance, schemaInfo.resolvedDynamicRef, &anns); err != nil { - return err - } - } else { - // Dynamic behavior. - // Look for the base of the outermost schema on the stack with this dynamic - // anchor. (Yes, outermost: the one farthest from here. This the opposite - // of how ordinary dynamic variables behave.) - // Why the base of the schema being validated and not the schema itself? - // Because the base is the scope for anchors. In fact it's possible to - // refer to a schema that is not on the stack, but a child of some base - // on the stack. - // For an example, search for "detached" in testdata/draft2020-12/dynamicRef.json. - var dynamicSchema *Schema - for _, s := range st.stack { - base := st.rs.resolvedInfos[s].base - info, ok := st.rs.resolvedInfos[base].anchors[schemaInfo.dynamicRefAnchor] - if ok && info.dynamic { - dynamicSchema = info.schema - break - } - } - if dynamicSchema == nil { - return fmt.Errorf("missing dynamic anchor %q", schemaInfo.dynamicRefAnchor) - } - if err := st.validate(instance, dynamicSchema, &anns); err != nil { - return err - } - } - } - - // logic - // https://json-schema.org/draft/2020-12/json-schema-core#section-10.2 - // These must happen before arrays and objects because if they evaluate an item or property, - // then the unevaluatedItems/Properties schemas don't apply to it. - // See https://json-schema.org/draft/2020-12/json-schema-core#section-11.2, paragraph 4. - // - // If any of these fail, then validation fails, even if there is an unevaluatedXXX - // keyword in the schema. The spec is unclear about this, but that is the intention. - - valid := func(s *Schema, anns *annotations) bool { return st.validate(instance, s, anns) == nil } - - if schema.AllOf != nil { - for _, ss := range schema.AllOf { - if err := st.validate(instance, ss, &anns); err != nil { - return err - } - } - } - if schema.AnyOf != nil { - // We must visit them all, to collect annotations. - ok := false - for _, ss := range schema.AnyOf { - if valid(ss, &anns) { - ok = true - } - } - if !ok { - return fmt.Errorf("anyOf: did not validate against any of %v", schema.AnyOf) - } - } - if schema.OneOf != nil { - // Exactly one. - var okSchema *Schema - for _, ss := range schema.OneOf { - if valid(ss, &anns) { - if okSchema != nil { - return fmt.Errorf("oneOf: validated against both %v and %v", okSchema, ss) - } - okSchema = ss - } - } - if okSchema == nil { - return fmt.Errorf("oneOf: did not validate against any of %v", schema.OneOf) - } - } - if schema.Not != nil { - // Ignore annotations from "not". - if valid(schema.Not, nil) { - return fmt.Errorf("not: validated against %v", schema.Not) - } - } - if schema.If != nil { - var ss *Schema - if valid(schema.If, &anns) { - ss = schema.Then - } else { - ss = schema.Else - } - if ss != nil { - if err := st.validate(instance, ss, &anns); err != nil { - return err - } - } - } - - // arrays - if instance.Kind() == reflect.Array || instance.Kind() == reflect.Slice { - // Handle both draft-07 and draft 2020-12 - // https://json-schema.org/draft/2020-12/json-schema-core#section-10.3.1 - // This validate call doesn't collect annotations for the items of the instance; they are separate - // instances in their own right. - // TODO(jba): if the test suite doesn't cover this case, add a test. For example, nested arrays. - if st.rs.draft == draft7 { - // For draft-07: additionalItems applies to remaining items after items array. - // If items is a Schema or if items is not set, additionalItems should be ignored - if schema.ItemsArray != nil { - for i, ischema := range schema.ItemsArray { - if i >= instance.Len() { - break // shorter is OK - } - if err := st.validate(instance.Index(i), ischema, nil); err != nil { - return err - } - } - anns.noteEndIndex(min(len(schema.ItemsArray), instance.Len())) - if schema.AdditionalItems != nil { - for i := len(schema.ItemsArray); i < instance.Len(); i++ { - if err := st.validate(instance.Index(i), schema.AdditionalItems, nil); err != nil { - return err - } - } - anns.allItems = true - } - } else if schema.Items != nil { - for i := 0; i < instance.Len(); i++ { - if err := st.validate(instance.Index(i), schema.Items, nil); err != nil { - return err - } - } - // Note that all the items in this array have been validated. - anns.allItems = true - } - } else if st.rs.draft == draft2020 { - // For draft 2020-12: items applies to remaining items after prefixItems - for i, ischema := range schema.PrefixItems { - if i >= instance.Len() { - break // shorter is OK - } - if err := st.validate(instance.Index(i), ischema, nil); err != nil { - return err - } - } - anns.noteEndIndex(min(len(schema.PrefixItems), instance.Len())) - if schema.Items != nil { - for i := len(schema.PrefixItems); i < instance.Len(); i++ { - if err := st.validate(instance.Index(i), schema.Items, nil); err != nil { - return err - } - } - // Note that all the items in this array have been validated. - anns.allItems = true - } - } - nContains := 0 - if schema.Contains != nil { - for i := range instance.Len() { - if err := st.validate(instance.Index(i), schema.Contains, nil); err == nil { - nContains++ - anns.noteIndex(i) - } - } - if nContains == 0 && (schema.MinContains == nil || *schema.MinContains > 0) { - return fmt.Errorf("contains: %s does not have an item matching %s", instance, schema.Contains) - } - } - - // https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-01#section-6.4 - // TODO(jba): check that these next four keywords' values are integers. - if schema.MinContains != nil && schema.Contains != nil { - if m := *schema.MinContains; nContains < m { - return fmt.Errorf("minContains: contains validated %d items, less than %d", nContains, m) - } - } - if schema.MaxContains != nil && schema.Contains != nil { - if m := *schema.MaxContains; nContains > m { - return fmt.Errorf("maxContains: contains validated %d items, greater than %d", nContains, m) - } - } - if schema.MinItems != nil { - if m := *schema.MinItems; instance.Len() < m { - return fmt.Errorf("minItems: array length %d is less than %d", instance.Len(), m) - } - } - if schema.MaxItems != nil { - if m := *schema.MaxItems; instance.Len() > m { - return fmt.Errorf("maxItems: array length %d is greater than %d", instance.Len(), m) - } - } - if schema.UniqueItems { - if instance.Len() > 1 { - // Hash each item and compare the hashes. - // If two hashes differ, the items differ. - // If two hashes are the same, compare the collisions for equality. - // (The same logic as hash table lookup.) - // TODO(jba): Use container/hash.Map when it becomes available (https://go.dev/issue/69559), - hashes := map[uint64][]int{} // from hash to indices - seed := maphash.MakeSeed() - for i := range instance.Len() { - item := instance.Index(i) - var h maphash.Hash - h.SetSeed(seed) - hashValue(&h, item) - hv := h.Sum64() - if sames := hashes[hv]; len(sames) > 0 { - for _, j := range sames { - if equalValue(item, instance.Index(j)) { - return fmt.Errorf("uniqueItems: array items %d and %d are equal", i, j) - } - } - } - hashes[hv] = append(hashes[hv], i) - } - } - } - - // https://json-schema.org/draft/2020-12/json-schema-core#section-11.2 - if schema.UnevaluatedItems != nil && !anns.allItems { - // Apply this subschema to all items in the array that haven't been successfully validated. - // That includes validations by subschemas on the same instance, like allOf. - for i := anns.endIndex; i < instance.Len(); i++ { - if !anns.evaluatedIndexes[i] { - if err := st.validate(instance.Index(i), schema.UnevaluatedItems, nil); err != nil { - return err - } - } - } - anns.allItems = true - } - } - - // objects - // https://json-schema.org/draft/2020-12/json-schema-core#section-10.3.2 - // Validating structs is problematic. See https://github.com/google/jsonschema-go/issues/23. - if instance.Kind() == reflect.Struct { - return errors.New("cannot validate against a struct; see https://github.com/google/jsonschema-go/issues/23 for details") - } - if instance.Kind() == reflect.Map { - if kt := instance.Type().Key(); kt.Kind() != reflect.String { - return fmt.Errorf("map key type %s is not a string", kt) - } - // Track the evaluated properties for just this schema, to support additionalProperties. - // If we used anns here, then we'd be including properties evaluated in subschemas - // from allOf, etc., which additionalProperties shouldn't observe. - evalProps := map[string]bool{} - for prop, subschema := range schema.Properties { - val := property(instance, prop) - if !val.IsValid() { - // It's OK if the instance doesn't have the property. - continue - } - // If the instance is a struct and an optional property has the zero - // value, then we could interpret it as present or missing. Be generous: - // assume it's missing, and thus always validates successfully. - if instance.Kind() == reflect.Struct && val.IsZero() && !schemaInfo.isRequired[prop] { - continue - } - if err := st.validate(val, subschema, nil); err != nil { - return err - } - evalProps[prop] = true - } - if len(schema.PatternProperties) > 0 { - for prop, val := range properties(instance) { - // Check every matching pattern. - for re, schema := range schemaInfo.patternProperties { - if re.MatchString(prop) { - if err := st.validate(val, schema, nil); err != nil { - return err - } - evalProps[prop] = true - } - } - } - } - if schema.AdditionalProperties != nil { - // Special case for a better error message when additional properties is - // 'falsy' - // - // If additionalProperties is {"not":{}} (which is how we - // unmarshal "false"), we can produce a better error message that - // summarizes all the extra properties. Otherwise, we fall back to the - // default validation. - // - // Note: this is much faster than comparing with falseSchema using Equal. - isFalsy := schema.AdditionalProperties.Not != nil && reflect.ValueOf(*schema.AdditionalProperties.Not).IsZero() - if isFalsy { - var disallowed []string - for prop := range properties(instance) { - if !evalProps[prop] { - disallowed = append(disallowed, prop) - } - } - if len(disallowed) > 0 { - return fmt.Errorf("unexpected additional properties %q", disallowed) - } - } else { - // Apply to all properties not handled above. - for prop, val := range properties(instance) { - if !evalProps[prop] { - if err := st.validate(val, schema.AdditionalProperties, nil); err != nil { - return err - } - evalProps[prop] = true - } - } - } - } - anns.noteProperties(evalProps) - if schema.PropertyNames != nil { - // Note: properties unnecessarily fetches each value. We could define a propertyNames function - // if performance ever matters. - for prop := range properties(instance) { - if err := st.validate(reflect.ValueOf(prop), schema.PropertyNames, nil); err != nil { - return err - } - } - } - - // https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-01#section-6.5 - var min, max int - if schema.MinProperties != nil || schema.MaxProperties != nil { - min, max = numPropertiesBounds(instance, schemaInfo.isRequired) - } - if schema.MinProperties != nil { - if n, m := max, *schema.MinProperties; n < m { - return fmt.Errorf("minProperties: object has %d properties, less than %d", n, m) - } - } - if schema.MaxProperties != nil { - if n, m := min, *schema.MaxProperties; n > m { - return fmt.Errorf("maxProperties: object has %d properties, greater than %d", n, m) - } - } - - hasProperty := func(prop string) bool { - return property(instance, prop).IsValid() - } - - missingProperties := func(props []string) []string { - var missing []string - for _, p := range props { - if !hasProperty(p) { - missing = append(missing, p) - } - } - return missing - } - - if schema.Required != nil { - if m := missingProperties(schema.Required); len(m) > 0 { - return fmt.Errorf("required: missing properties: %q", m) - } - } - - if st.rs.draft == draft7 { - if schema.DependencyStrings != nil { - for dprop, dstrings := range schema.DependencyStrings { - if hasProperty(dprop) { - if m := missingProperties(dstrings); len(m) > 0 { - return fmt.Errorf("dependentRequired[%q]: missing properties %q", dprop, m) - } - } - } - } - if schema.DependencySchemas != nil { - for dprop, dschema := range schema.DependencySchemas { - if hasProperty(dprop) { - err := st.validate(instance, dschema, &anns) - if err != nil { - return err - } - } - } - } - } else if st.rs.draft == draft2020 { - if schema.DependentRequired != nil { - // "Validation succeeds if, for each name that appears in both the instance - // and as a name within this keyword's value, every item in the corresponding - // array is also the name of a property in the instance." §6.5.4 - for dprop, reqs := range schema.DependentRequired { - if hasProperty(dprop) { - if m := missingProperties(reqs); len(m) > 0 { - return fmt.Errorf("dependentRequired[%q]: missing properties %q", dprop, m) - } - } - } - } - - // https://json-schema.org/draft/2020-12/json-schema-core#section-10.2.2.4 - if schema.DependentSchemas != nil { - // This does not collect annotations, although it seems like it should. - for dprop, ss := range schema.DependentSchemas { - if hasProperty(dprop) { - // TODO: include dependentSchemas[dprop] in the errors. - err := st.validate(instance, ss, &anns) - if err != nil { - return err - } - } - } - } - } - - if schema.UnevaluatedProperties != nil && !anns.allProperties { - // This looks a lot like AdditionalProperties, but depends on in-place keywords like allOf - // in addition to sibling keywords. - for prop, val := range properties(instance) { - if !anns.evaluatedProperties[prop] { - if err := st.validate(val, schema.UnevaluatedProperties, nil); err != nil { - return err - } - } - } - // The spec says the annotation should be the set of evaluated properties, but we can optimize - // by setting a single boolean, since after this succeeds all properties will be validated. - // See https://json-schema.slack.com/archives/CT7FF623C/p1745592564381459. - anns.allProperties = true - } - } - - if callerAnns != nil { - // Our caller wants to know what we've validated. - callerAnns.merge(&anns) - } - return nil -} - -// resolveDynamicRef returns the schema referred to by the argument schema's -// $dynamicRef value. -// It returns an error if the dynamic reference has no referent. -// If there is no $dynamicRef, resolveDynamicRef returns nil, nil. -// See https://json-schema.org/draft/2020-12/json-schema-core#section-8.2.3.2. -func (st *state) resolveDynamicRef(schema *Schema) (*Schema, error) { - if schema.DynamicRef == "" { - return nil, nil - } - info := st.rs.resolvedInfos[schema] - // The ref behaves lexically or dynamically, but not both. - assert((info.resolvedDynamicRef == nil) != (info.dynamicRefAnchor == ""), - "DynamicRef not statically resolved properly") - if r := info.resolvedDynamicRef; r != nil { - // Same as $ref. - return r, nil - } - // Dynamic behavior. - // Look for the base of the outermost schema on the stack with this dynamic - // anchor. (Yes, outermost: the one farthest from here. This the opposite - // of how ordinary dynamic variables behave.) - // Why the base of the schema being validated and not the schema itself? - // Because the base is the scope for anchors. In fact it's possible to - // refer to a schema that is not on the stack, but a child of some base - // on the stack. - // For an example, search for "detached" in testdata/draft2020-12/dynamicRef.json. - for _, s := range st.stack { - base := st.rs.resolvedInfos[s].base - info, ok := st.rs.resolvedInfos[base].anchors[info.dynamicRefAnchor] - if ok && info.dynamic { - return info.schema, nil - } - } - return nil, fmt.Errorf("missing dynamic anchor %q", info.dynamicRefAnchor) -} - -// ApplyDefaults modifies an instance by applying the schema's defaults to it. If -// a schema or sub-schema has a default, then a corresponding missing instance value -// is set to the default. -// -// The JSON Schema specification does not describe how defaults should be interpreted. -// This method honors defaults only on properties, and only those that are not required. -// If the instance is a map and the property is missing, the property is added to -// the map with the default. -// ApplyDefaults does not support structs, because it cannot know whether a field -// is missing in the JSON, or was explicitly set to its zero value. -// -// ApplyDefaults can panic if a default cannot be assigned to a field. -// -// The argument must be a pointer to the instance. -// (In case we decide that top-level defaults are meaningful.) -// -// It is recommended to first call Resolve with a ValidateDefaults option of true, -// then call this method, and lastly call Validate. -func (rs *Resolved) ApplyDefaults(instancep any) error { - // TODO(jba): consider what defaults on top-level or array instances might mean. - // TODO(jba): follow $ref and $dynamicRef - st := &state{rs: rs} - return st.applyDefaults(reflect.ValueOf(instancep), rs.root) -} - -// Recursive helper used by ApplyDefaults. Applies defaults on sub-schemas -// of object properties recursively. -func (st *state) applyDefaults(instancep reflect.Value, schema *Schema) (err error) { - defer wrapf(&err, "applyDefaults: schema %s, instance %v", st.rs.schemaString(schema), instancep) - - schemaInfo := st.rs.resolvedInfos[schema] - instance := instancep.Elem() - if instance.Kind() == reflect.Interface && instance.IsValid() { - // If we unmarshalled into 'any', the default object unmarshalling will be map[string]any. - instance = instance.Elem() - } - if instance.Kind() == reflect.Map || instance.Kind() == reflect.Struct { - if instance.Kind() == reflect.Map { - if kt := instance.Type().Key(); kt.Kind() != reflect.String { - return fmt.Errorf("map key type %s is not a string", kt) - } - } - for prop, subschema := range schema.Properties { - // Ignore defaults on required properties. (A required property shouldn't have a default.) - if schemaInfo.isRequired[prop] { - continue - } - val := property(instance, prop) - switch instance.Kind() { - case reflect.Map: - // If there is a default for this property, and the map key is missing, - // set the map value to the default. - if subschema.Default != nil && !val.IsValid() { - // Create an lvalue, since map values aren't addressable. - lvalue := reflect.New(instance.Type().Elem()) - if err := json.Unmarshal(subschema.Default, lvalue.Interface()); err != nil { - return err - } - // Recurse unconditionally; applyDefaults will only act on object-like values. - if err := st.applyDefaults(lvalue, subschema); err != nil { - return err - } - instance.SetMapIndex(reflect.ValueOf(prop), lvalue.Elem()) - } else if val.IsValid() { - // Recurse into an existing sub-instance. - // MapIndex returns a non-addressable value; copy into an addressable lvalue, recurse, then set back. - lvalue := reflect.New(instance.Type().Elem()) - // Initialize the lvalue with current value. - lvalue.Elem().Set(val) - if err := st.applyDefaults(lvalue, subschema); err != nil { - return err - } - instance.SetMapIndex(reflect.ValueOf(prop), lvalue.Elem()) - } else if schemaHasDefaultsInProperties(subschema) { - // Property is missing, but descendants still have some defaults - // Create an empty container and recurse to populate - elemType := instance.Type().Elem() - var child reflect.Value - switch elemType.Kind() { - case reflect.Interface: - child = reflect.ValueOf(map[string]any{}) - case reflect.Map: - child = reflect.MakeMap(elemType) - case reflect.Struct: - child = reflect.New(elemType).Elem() - } - if child.IsValid() { - lvalue := reflect.New(elemType) - lvalue.Elem().Set(child) - if err := st.applyDefaults(lvalue, subschema); err != nil { - return err - } - instance.SetMapIndex(reflect.ValueOf(prop), lvalue.Elem()) - } - } - case reflect.Struct: - return errors.New("cannot apply defaults to a struct") - default: - panic(fmt.Sprintf("applyDefaults: property %s: bad value %s of kind %s", - prop, instance, instance.Kind())) - } - } - } - return nil -} - -// schemaHasDefaultsInProperties reports whether s or any descendant schema under -// its Properties contains a default. Only walks Properties to match ApplyDefaults semantics. -func schemaHasDefaultsInProperties(s *Schema) bool { - if s == nil { - return false - } - if s.Default != nil { - return true - } - if s.Properties != nil { - for _, ss := range s.Properties { - if schemaHasDefaultsInProperties(ss) { - return true - } - } - } - return false -} - -// property returns the value of the property of v with the given name, or the invalid -// reflect.Value if there is none. -// If v is a map, the property is the value of the map whose key is name. -// If v is a struct, the property is the value of the field with the given name according -// to the encoding/json package (see [jsonName]). -// If v is anything else, property panics. -func property(v reflect.Value, name string) reflect.Value { - switch v.Kind() { - case reflect.Map: - return v.MapIndex(reflect.ValueOf(name)) - case reflect.Struct: - props := structPropertiesOf(v.Type()) - // Ignore nonexistent properties. - if sf, ok := props[name]; ok { - return v.FieldByIndex(sf.Index) - } - return reflect.Value{} - default: - panic(fmt.Sprintf("property(%q): bad value %s of kind %s", name, v, v.Kind())) - } -} - -// properties returns an iterator over the names and values of all properties -// in v, which must be a map or a struct. -// If a struct, zero-valued properties that are marked omitempty or omitzero -// are excluded. -func properties(v reflect.Value) iter.Seq2[string, reflect.Value] { - return func(yield func(string, reflect.Value) bool) { - switch v.Kind() { - case reflect.Map: - for k, e := range v.Seq2() { - if !yield(k.String(), e) { - return - } - } - case reflect.Struct: - for name, sf := range structPropertiesOf(v.Type()) { - val := v.FieldByIndex(sf.Index) - if val.IsZero() { - info := fieldJSONInfo(sf) - if info.settings["omitempty"] || info.settings["omitzero"] { - continue - } - } - if !yield(name, val) { - return - } - } - default: - panic(fmt.Sprintf("bad value %s of kind %s", v, v.Kind())) - } - } -} - -// numPropertiesBounds returns bounds on the number of v's properties. -// v must be a map or a struct. -// If v is a map, both bounds are the map's size. -// If v is a struct, the max is the number of struct properties. -// But since we don't know whether a zero value indicates a missing optional property -// or not, be generous and use the number of non-zero properties as the min. -func numPropertiesBounds(v reflect.Value, isRequired map[string]bool) (int, int) { - switch v.Kind() { - case reflect.Map: - return v.Len(), v.Len() - case reflect.Struct: - sp := structPropertiesOf(v.Type()) - min := 0 - for prop, sf := range sp { - if !v.FieldByIndex(sf.Index).IsZero() || isRequired[prop] { - min++ - } - } - return min, len(sp) - default: - panic(fmt.Sprintf("properties: bad value: %s of kind %s", v, v.Kind())) - } -} - -// A propertyMap is a map from property name to struct field index. -type propertyMap = map[string]reflect.StructField - -var structProperties sync.Map // from reflect.Type to propertyMap - -// structPropertiesOf returns the JSON Schema properties for the struct type t. -// The caller must not mutate the result. -func structPropertiesOf(t reflect.Type) propertyMap { - // Mutex not necessary: at worst we'll recompute the same value. - if props, ok := structProperties.Load(t); ok { - return props.(propertyMap) - } - props := map[string]reflect.StructField{} - for _, sf := range reflect.VisibleFields(t) { - if sf.Anonymous { - continue - } - info := fieldJSONInfo(sf) - if !info.omit { - props[info.name] = sf - } - } - structProperties.Store(t, props) - return props -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/LICENSE b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/LICENSE deleted file mode 100644 index 5791499..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/LICENSE +++ /dev/null @@ -1,216 +0,0 @@ -The MCP project is undergoing a licensing transition from the MIT License to the Apache License, Version 2.0 ("Apache-2.0"). All new code and specification contributions to the project are licensed under Apache-2.0. Documentation contributions (excluding specifications) are licensed under CC-BY-4.0. - -Contributions for which relicensing consent has been obtained are licensed under Apache-2.0. Contributions made by authors who originally licensed their work under the MIT License and who have not yet granted explicit permission to relicense remain licensed under the MIT License. - -No rights beyond those granted by the applicable original license are conveyed for such contributions. - ---- - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright - owner or by an individual or Legal Entity authorized to submit on behalf - of the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - ---- - -MIT License - -Copyright (c) 2024-2025 Model Context Protocol a Series of LF Projects, LLC. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ---- - -Creative Commons Attribution 4.0 International (CC-BY-4.0) - -Documentation in this project (excluding specifications) is licensed under -CC-BY-4.0. See https://creativecommons.org/licenses/by/4.0/legalcode for -the full license text. diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/auth/auth.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/auth/auth.go deleted file mode 100644 index 36ff259..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/auth/auth.go +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package auth - -import ( - "context" - "encoding/json" - "errors" - "net/http" - "slices" - "strings" - "time" - - "github.com/modelcontextprotocol/go-sdk/oauthex" -) - -// TokenInfo holds information from a bearer token. -type TokenInfo struct { - Scopes []string - Expiration time.Time - // UserID is an optional identifier for the authenticated user. - // If set by a TokenVerifier, it can be used by transports to prevent - // session hijacking by ensuring that all requests for a given session - // come from the same user. - UserID string - Extra map[string]any -} - -// The error that a TokenVerifier should return if the token cannot be verified. -var ErrInvalidToken = errors.New("invalid token") - -// The error that a TokenVerifier should return for OAuth-specific protocol errors. -var ErrOAuth = errors.New("oauth error") - -// A TokenVerifier checks the validity of a bearer token, and extracts information -// from it. If verification fails, it should return an error that unwraps to ErrInvalidToken. -// The HTTP request is provided in case verifying the token involves checking it. -type TokenVerifier func(ctx context.Context, token string, req *http.Request) (*TokenInfo, error) - -// RequireBearerTokenOptions are options for [RequireBearerToken]. -type RequireBearerTokenOptions struct { - // The URL for the resource server metadata OAuth flow, to be returned as part - // of the WWW-Authenticate header. - ResourceMetadataURL string - // The required scopes. - Scopes []string -} - -type tokenInfoKey struct{} - -// TokenInfoFromContext returns the [TokenInfo] stored in ctx, or nil if none. -func TokenInfoFromContext(ctx context.Context) *TokenInfo { - ti := ctx.Value(tokenInfoKey{}) - if ti == nil { - return nil - } - return ti.(*TokenInfo) -} - -// RequireBearerToken returns a piece of middleware that verifies a bearer token using the verifier. -// If verification succeeds, the [TokenInfo] is added to the request's context and the request proceeds. -// If verification fails, the request fails with a 401 Unauthenticated, and the WWW-Authenticate header -// is populated to enable [protected resource metadata]. -// -// [protected resource metadata]: https://datatracker.ietf.org/doc/rfc9728 -func RequireBearerToken(verifier TokenVerifier, opts *RequireBearerTokenOptions) func(http.Handler) http.Handler { - // Based on typescript-sdk/src/server/auth/middleware/bearerAuth.ts. - - return func(handler http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - tokenInfo, errmsg, code := verify(r, verifier, opts) - if code != 0 { - if code == http.StatusUnauthorized || code == http.StatusForbidden { - if opts != nil && opts.ResourceMetadataURL != "" { - w.Header().Add("WWW-Authenticate", "Bearer resource_metadata="+opts.ResourceMetadataURL) - } - } - http.Error(w, errmsg, code) - return - } - r = r.WithContext(context.WithValue(r.Context(), tokenInfoKey{}, tokenInfo)) - handler.ServeHTTP(w, r) - }) - } -} - -func verify(req *http.Request, verifier TokenVerifier, opts *RequireBearerTokenOptions) (_ *TokenInfo, errmsg string, code int) { - // Extract bearer token. - authHeader := req.Header.Get("Authorization") - fields := strings.Fields(authHeader) - if len(fields) != 2 || strings.ToLower(fields[0]) != "bearer" { - return nil, "no bearer token", http.StatusUnauthorized - } - - // Verify the token and get information from it. - tokenInfo, err := verifier(req.Context(), fields[1], req) - if err != nil { - if errors.Is(err, ErrInvalidToken) { - return nil, err.Error(), http.StatusUnauthorized - } - if errors.Is(err, ErrOAuth) { - return nil, err.Error(), http.StatusBadRequest - } - return nil, err.Error(), http.StatusInternalServerError - } - if tokenInfo == nil { - return nil, "token validation failed", http.StatusInternalServerError - } - - // Check scopes. All must be present. - if opts != nil { - // Note: quadratic, but N is small. - for _, s := range opts.Scopes { - if !slices.Contains(tokenInfo.Scopes, s) { - return nil, "insufficient scope", http.StatusForbidden - } - } - } - - // Check expiration. - if tokenInfo.Expiration.IsZero() { - return nil, "token missing expiration", http.StatusUnauthorized - } - if tokenInfo.Expiration.Before(time.Now()) { - return nil, "token expired", http.StatusUnauthorized - } - return tokenInfo, "", 0 -} - -// ProtectedResourceMetadataHandler returns an http.Handler that serves OAuth 2.0 -// protected resource metadata (RFC 9728) with CORS support. -// -// This handler allows cross-origin requests from any origin (Access-Control-Allow-Origin: *) -// because OAuth metadata is public information intended for client discovery (RFC 9728 §3.1). -// The metadata contains only non-sensitive configuration data about authorization servers -// and supported scopes. -// -// No validation of metadata fields is performed; ensure metadata accuracy at configuration time. -// -// For more sophisticated CORS policies or to restrict origins, wrap this handler with a -// CORS middleware like github.com/rs/cors or github.com/jub0bs/cors. -func ProtectedResourceMetadataHandler(metadata *oauthex.ProtectedResourceMetadata) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // Set CORS headers for cross-origin client discovery. - // OAuth metadata is public information, so allowing any origin is safe. - w.Header().Set("Access-Control-Allow-Origin", "*") - w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS") - w.Header().Set("Access-Control-Allow-Headers", "Content-Type") - - // Handle CORS preflight requests - if r.Method == http.MethodOptions { - w.WriteHeader(http.StatusNoContent) - return - } - - // Only GET allowed for metadata retrieval - if r.Method != http.MethodGet { - http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) - return - } - - w.Header().Set("Content-Type", "application/json") - if err := json.NewEncoder(w).Encode(metadata); err != nil { - http.Error(w, "Failed to encode metadata", http.StatusInternalServerError) - return - } - }) -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/auth/authorization_code.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/auth/authorization_code.go deleted file mode 100644 index 2a6ed32..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/auth/authorization_code.go +++ /dev/null @@ -1,548 +0,0 @@ -// Copyright 2026 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by the license -// that can be found in the LICENSE file. - -//go:build mcp_go_client_oauth - -package auth - -import ( - "context" - "crypto/rand" - "errors" - "fmt" - "net/http" - "net/url" - "slices" - "strings" - - "github.com/modelcontextprotocol/go-sdk/oauthex" - "golang.org/x/oauth2" -) - -// ClientSecretAuthConfig is used to configure client authentication using client_secret. -// Authentication method will be selected based on the authorization server's supported methods, -// according to the following preference order: -// 1. client_secret_post -// 2. client_secret_basic -type ClientSecretAuthConfig struct { - // ClientID is the client ID to be used for client authentication. - ClientID string - // ClientSecret is the client secret to be used for client authentication. - ClientSecret string -} - -// ClientIDMetadataDocumentConfig is used to configure the Client ID Metadata Document -// based client registration per -// https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#client-id-metadata-documents. -// See https://client.dev/ for more information. -type ClientIDMetadataDocumentConfig struct { - // URL is the client identifier URL as per - // https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-00#section-3. - URL string -} - -// PreregisteredClientConfig is used to configure a pre-registered client per -// https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#preregistration. -// Currently only "client_secret_basic" and "client_secret_post" authentication methods are supported. -type PreregisteredClientConfig struct { - // ClientSecretAuthConfig is the client_secret based configuration to be used for client authentication. - ClientSecretAuthConfig *ClientSecretAuthConfig -} - -// DynamicClientRegistrationConfig is used to configure dynamic client registration per -// https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#dynamic-client-registration. -type DynamicClientRegistrationConfig struct { - // Metadata to be used in dynamic client registration request as per - // https://datatracker.ietf.org/doc/html/rfc7591#section-2. - Metadata *oauthex.ClientRegistrationMetadata -} - -// AuthorizationResult is the result of an authorization flow. -// It is returned by [AuthorizationCodeHandler].AuthorizationCodeFetcher implementations. -type AuthorizationResult struct { - // Code is the authorization code obtained from the authorization server. - Code string - // State string returned by the authorization server. - State string -} - -// AuthorizationArgs is the input to [AuthorizationCodeHandlerConfig].AuthorizationCodeFetcher. -type AuthorizationArgs struct { - // Authorization URL to be opened in a browser for the user to start the authorization process. - URL string -} - -// AuthorizationCodeHandlerConfig is the configuration for [AuthorizationCodeHandler]. -type AuthorizationCodeHandlerConfig struct { - // Client registration configuration. - // It is attempted in the following order: - // 1. Client ID Metadata Document - // 2. Preregistration - // 3. Dynamic Client Registration - // At least one method must be configured. - ClientIDMetadataDocumentConfig *ClientIDMetadataDocumentConfig - PreregisteredClientConfig *PreregisteredClientConfig - DynamicClientRegistrationConfig *DynamicClientRegistrationConfig - - // RedirectURL is a required URL to redirect to after authorization. - // The caller is responsible for handling the redirect out of band. - // - // If Dynamic Client Registration is used: - // - this field is permitted to be empty, in which case it will be set - // to the first redirect URI from - // DynamicClientRegistrationConfig.Metadata.RedirectURIs. - // - if the field is not empty, it must be one of the redirect URIs in - // DynamicClientRegistrationConfig.Metadata.RedirectURIs. - RedirectURL string - - // AuthorizationCodeFetcher is a required function called to initiate the authorization flow. - // It is responsible for opening the URL in a browser for the user to start the authorization process. - // It should return the authorization code and state once the Authorization Server - // redirects back to the RedirectURL. - AuthorizationCodeFetcher func(ctx context.Context, args *AuthorizationArgs) (*AuthorizationResult, error) -} - -// AuthorizationCodeHandler is an implementation of [OAuthHandler] that uses -// the authorization code flow to obtain access tokens. -type AuthorizationCodeHandler struct { - config *AuthorizationCodeHandlerConfig - - // tokenSource is the token source to use for authorization. - tokenSource oauth2.TokenSource -} - -var _ OAuthHandler = (*AuthorizationCodeHandler)(nil) - -func (h *AuthorizationCodeHandler) isOAuthHandler() {} - -func (h *AuthorizationCodeHandler) TokenSource(ctx context.Context) (oauth2.TokenSource, error) { - return h.tokenSource, nil -} - -// NewAuthorizationCodeHandler creates a new AuthorizationCodeHandler. -// It performs validation of the configuration and returns an error if it is invalid. -// The passed config is consumed by the handler and should not be modified after. -func NewAuthorizationCodeHandler(config *AuthorizationCodeHandlerConfig) (*AuthorizationCodeHandler, error) { - if config == nil { - return nil, errors.New("config must be provided") - } - if config.ClientIDMetadataDocumentConfig == nil && - config.PreregisteredClientConfig == nil && - config.DynamicClientRegistrationConfig == nil { - return nil, errors.New("at least one client registration configuration must be provided") - } - if config.AuthorizationCodeFetcher == nil { - return nil, errors.New("AuthorizationCodeFetcher is required") - } - if config.ClientIDMetadataDocumentConfig != nil && !isNonRootHTTPSURL(config.ClientIDMetadataDocumentConfig.URL) { - return nil, fmt.Errorf("client ID metadata document URL must be a non-root HTTPS URL") - } - preCfg := config.PreregisteredClientConfig - if preCfg != nil { - if preCfg.ClientSecretAuthConfig == nil { - return nil, errors.New("ClientSecretAuthConfig is required for pre-registered client") - } - if preCfg.ClientSecretAuthConfig.ClientID == "" || preCfg.ClientSecretAuthConfig.ClientSecret == "" { - return nil, fmt.Errorf("pre-registered client ID or secret is empty") - } - } - dCfg := config.DynamicClientRegistrationConfig - if dCfg != nil { - if dCfg.Metadata == nil { - return nil, errors.New("Metadata is required for dynamic client registration") - } - if len(dCfg.Metadata.RedirectURIs) == 0 { - return nil, errors.New("Metadata.RedirectURIs is required for dynamic client registration") - } - if config.RedirectURL == "" { - config.RedirectURL = dCfg.Metadata.RedirectURIs[0] - } else if !slices.Contains(dCfg.Metadata.RedirectURIs, config.RedirectURL) { - return nil, fmt.Errorf("RedirectURL %q is not in the list of allowed redirect URIs for dynamic client registration", config.RedirectURL) - } - } - if config.RedirectURL == "" { - // If the RedirectURL was supposed to be set by the dynamic client registration, - // it should have been set by now. Otherwise, it is required. - return nil, errors.New("RedirectURL is required") - } - return &AuthorizationCodeHandler{config: config}, nil -} - -func isNonRootHTTPSURL(u string) bool { - pu, err := url.Parse(u) - if err != nil { - return false - } - return pu.Scheme == "https" && pu.Path != "" -} - -// Authorize performs the authorization flow. -// It is designed to perform the whole Authorization Code Grant flow. -// On success, [AuthorizationCodeHandler.TokenSource] will return a token source with the fetched token. -func (h *AuthorizationCodeHandler) Authorize(ctx context.Context, req *http.Request, resp *http.Response) error { - defer resp.Body.Close() - - wwwChallenges, err := oauthex.ParseWWWAuthenticate(resp.Header[http.CanonicalHeaderKey("WWW-Authenticate")]) - if err != nil { - return fmt.Errorf("failed to parse WWW-Authenticate header: %v", err) - } - - if resp.StatusCode == http.StatusForbidden && errorFromChallenges(wwwChallenges) != "insufficient_scope" { - // We only want to perform step-up authorization for insufficient_scope errors. - // Returning nil, so that the call is retried immediately and the response - // is handled appropriately by the connection. - // Step-up authorization is defined at - // https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#step-up-authorization-flow - return nil - } - - prm, err := h.getProtectedResourceMetadata(ctx, wwwChallenges, req.URL.String()) - if err != nil { - return err - } - - asm, err := h.getAuthServerMetadata(ctx, prm) - if err != nil { - return err - } - - resolvedClientConfig, err := h.handleRegistration(ctx, asm) - if err != nil { - return err - } - - scps := scopesFromChallenges(wwwChallenges) - if len(scps) == 0 && len(prm.ScopesSupported) > 0 { - scps = prm.ScopesSupported - } - - cfg := &oauth2.Config{ - ClientID: resolvedClientConfig.clientID, - ClientSecret: resolvedClientConfig.clientSecret, - - Endpoint: oauth2.Endpoint{ - AuthURL: asm.AuthorizationEndpoint, - TokenURL: asm.TokenEndpoint, - AuthStyle: resolvedClientConfig.authStyle, - }, - RedirectURL: h.config.RedirectURL, - Scopes: scps, - } - - authRes, err := h.getAuthorizationCode(ctx, cfg, req.URL.String()) - if err != nil { - // Purposefully leaving the error unwrappable so it can be handled by the caller. - return err - } - - return h.exchangeAuthorizationCode(ctx, cfg, authRes, prm.Resource) -} - -// resourceMetadataURLFromChallenges returns a resource metadata URL from the given "WWW-Authenticate" header challenges, -// or the empty string if there is none. -func resourceMetadataURLFromChallenges(cs []oauthex.Challenge) string { - for _, c := range cs { - if u := c.Params["resource_metadata"]; u != "" { - return u - } - } - return "" -} - -// scopesFromChallenges returns the scopes from the given "WWW-Authenticate" header challenges. -// It only looks at challenges with the "Bearer" scheme. -func scopesFromChallenges(cs []oauthex.Challenge) []string { - for _, c := range cs { - if c.Scheme == "bearer" && c.Params["scope"] != "" { - return strings.Fields(c.Params["scope"]) - } - } - return nil -} - -// errorFromChallenges returns the error from the given "WWW-Authenticate" header challenges. -// It only looks at challenges with the "Bearer" scheme. -func errorFromChallenges(cs []oauthex.Challenge) string { - for _, c := range cs { - if c.Scheme == "bearer" && c.Params["error"] != "" { - return c.Params["error"] - } - } - return "" -} - -// getProtectedResourceMetadata returns the protected resource metadata. -// If no metadata was found or the fetched metadata fails security checks, -// it returns an error. -func (h *AuthorizationCodeHandler) getProtectedResourceMetadata(ctx context.Context, wwwChallenges []oauthex.Challenge, mcpServerURL string) (*oauthex.ProtectedResourceMetadata, error) { - var errs []error - // Use MCP server URL as the resource URI per - // https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#canonical-server-uri. - for _, url := range protectedResourceMetadataURLs(resourceMetadataURLFromChallenges(wwwChallenges), mcpServerURL) { - prm, err := oauthex.GetProtectedResourceMetadata(ctx, url.URL, url.Resource, http.DefaultClient) - if err != nil { - errs = append(errs, err) - continue - } - if prm == nil { - errs = append(errs, fmt.Errorf("protected resource metadata is nil")) - continue - } - return prm, nil - } - return nil, fmt.Errorf("failed to get protected resource metadata: %v", errors.Join(errs...)) -} - -type prmURL struct { - // URL represents a URL where Protected Resource Metadata may be retrieved. - URL string - // Resource represents the corresponding resource URL for [URL]. - // It is required to perform validation described in RFC 9728, section 3.3. - Resource string -} - -// protectedResourceMetadataURLs returns a list of URLs to try when looking for -// protected resource metadata as mandated by the MCP specification: -// https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#protected-resource-metadata-discovery-requirements -func protectedResourceMetadataURLs(metadataURL, resourceURL string) []prmURL { - var urls []prmURL - if metadataURL != "" { - urls = append(urls, prmURL{ - URL: metadataURL, - Resource: resourceURL, - }) - } - ru, err := url.Parse(resourceURL) - if err != nil { - return urls - } - mu := *ru - // "At the path of the server's MCP endpoint". - mu.Path = "/.well-known/oauth-protected-resource/" + strings.TrimLeft(ru.Path, "/") - urls = append(urls, prmURL{ - URL: mu.String(), - Resource: resourceURL, - }) - // "At the root". - mu.Path = "/.well-known/oauth-protected-resource" - ru.Path = "" - urls = append(urls, prmURL{ - URL: mu.String(), - Resource: ru.String(), - }) - return urls -} - -// getAuthServerMetadata returns the authorization server metadata. -// The provided Protected Resource Metadata must not be nil. -// It returns an error if the metadata request fails with non-4xx HTTP status code -// or the fetched metadata fails security checks. -// If no metadata was found, it returns a minimal set of endpoints -// as a fallback to 2025-03-26 spec. -func (h *AuthorizationCodeHandler) getAuthServerMetadata(ctx context.Context, prm *oauthex.ProtectedResourceMetadata) (*oauthex.AuthServerMeta, error) { - var authServerURL string - if len(prm.AuthorizationServers) > 0 { - // Use the first authorization server, similarly to other SDKs. - authServerURL = prm.AuthorizationServers[0] - } else { - // Fallback to 2025-03-26 spec: MCP server base URL acts as Authorization Server. - authURL, err := url.Parse(prm.Resource) - if err != nil { - return nil, fmt.Errorf("failed to parse resource URL: %v", err) - } - authURL.Path = "" - authServerURL = authURL.String() - } - - for _, u := range authorizationServerMetadataURLs(authServerURL) { - asm, err := oauthex.GetAuthServerMeta(ctx, u, authServerURL, http.DefaultClient) - if err != nil { - return nil, fmt.Errorf("failed to get authorization server metadata: %w", err) - } - if asm != nil { - return asm, nil - } - } - - // Fallback to 2025-03-26 spec: predefined endpoints. - // https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization#fallbacks-for-servers-without-metadata-discovery - asm := &oauthex.AuthServerMeta{ - Issuer: authServerURL, - AuthorizationEndpoint: authServerURL + "/authorize", - TokenEndpoint: authServerURL + "/token", - RegistrationEndpoint: authServerURL + "/register", - } - return asm, nil -} - -// authorizationServerMetadataURLs returns a list of URLs to try when looking for -// authorization server metadata as mandated by the MCP specification: -// https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#authorization-server-metadata-discovery. -func authorizationServerMetadataURLs(issuerURL string) []string { - var urls []string - - baseURL, err := url.Parse(issuerURL) - if err != nil { - return nil - } - - if baseURL.Path == "" { - // "OAuth 2.0 Authorization Server Metadata". - baseURL.Path = "/.well-known/oauth-authorization-server" - urls = append(urls, baseURL.String()) - // "OpenID Connect Discovery 1.0". - baseURL.Path = "/.well-known/openid-configuration" - urls = append(urls, baseURL.String()) - return urls - } - - originalPath := baseURL.Path - // "OAuth 2.0 Authorization Server Metadata with path insertion". - baseURL.Path = "/.well-known/oauth-authorization-server/" + strings.TrimLeft(originalPath, "/") - urls = append(urls, baseURL.String()) - // "OpenID Connect Discovery 1.0 with path insertion". - baseURL.Path = "/.well-known/openid-configuration/" + strings.TrimLeft(originalPath, "/") - urls = append(urls, baseURL.String()) - // "OpenID Connect Discovery 1.0 with path appending". - baseURL.Path = "/" + strings.Trim(originalPath, "/") + "/.well-known/openid-configuration" - urls = append(urls, baseURL.String()) - return urls -} - -type registrationType int - -const ( - registrationTypeClientIDMetadataDocument registrationType = iota - registrationTypePreregistered - registrationTypeDynamic -) - -type resolvedClientConfig struct { - registrationType registrationType - clientID string - clientSecret string - authStyle oauth2.AuthStyle -} - -func selectTokenAuthMethod(supported []string) oauth2.AuthStyle { - prefOrder := []string{ - // Preferred in OAuth 2.1 draft: https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-14.html#name-client-secret. - "client_secret_post", - "client_secret_basic", - } - for _, method := range prefOrder { - if slices.Contains(supported, method) { - return authMethodToStyle(method) - } - } - return oauth2.AuthStyleAutoDetect -} - -func authMethodToStyle(method string) oauth2.AuthStyle { - switch method { - case "client_secret_post": - return oauth2.AuthStyleInParams - case "client_secret_basic": - return oauth2.AuthStyleInHeader - case "none": - // "none" is equivalent to "client_secret_post" but without sending client secret. - return oauth2.AuthStyleInParams - default: - // "client_secret_basic" is the default per https://datatracker.ietf.org/doc/html/rfc7591#section-2. - return oauth2.AuthStyleInHeader - } -} - -// handleRegistration handles client registration. -// The provided authorization server metadata must be non-nil. -// Support for different registration methods is defined as follows: -// - Client ID Metadata Document: metadata must have -// `ClientIDMetadataDocumentSupported` set to true. -// - Pre-registered client: assumed to be supported. -// - Dynamic client registration: metadata must have -// `RegistrationEndpoint` set to a non-empty value. -func (h *AuthorizationCodeHandler) handleRegistration(ctx context.Context, asm *oauthex.AuthServerMeta) (*resolvedClientConfig, error) { - // 1. Attempt to use Client ID Metadata Document (SEP-991). - cimdCfg := h.config.ClientIDMetadataDocumentConfig - if cimdCfg != nil && asm.ClientIDMetadataDocumentSupported { - return &resolvedClientConfig{ - registrationType: registrationTypeClientIDMetadataDocument, - clientID: cimdCfg.URL, - }, nil - } - // 2. Attempt to use pre-registered client configuration. - pCfg := h.config.PreregisteredClientConfig - if pCfg != nil { - authStyle := selectTokenAuthMethod(asm.TokenEndpointAuthMethodsSupported) - return &resolvedClientConfig{ - registrationType: registrationTypePreregistered, - clientID: pCfg.ClientSecretAuthConfig.ClientID, - clientSecret: pCfg.ClientSecretAuthConfig.ClientSecret, - authStyle: authStyle, - }, nil - } - // 3. Attempt to use dynamic client registration. - dcrCfg := h.config.DynamicClientRegistrationConfig - if dcrCfg != nil && asm.RegistrationEndpoint != "" { - regResp, err := oauthex.RegisterClient(ctx, asm.RegistrationEndpoint, dcrCfg.Metadata, http.DefaultClient) - if err != nil { - return nil, fmt.Errorf("failed to register client: %w", err) - } - cfg := &resolvedClientConfig{ - registrationType: registrationTypeDynamic, - clientID: regResp.ClientID, - clientSecret: regResp.ClientSecret, - authStyle: authMethodToStyle(regResp.TokenEndpointAuthMethod), - } - return cfg, nil - } - return nil, fmt.Errorf("no configured client registration methods are supported by the authorization server") -} - -type authResult struct { - *AuthorizationResult - // usedCodeVerifier is the PKCE code verifier used to obtain the authorization code. - // It is preserved for the token exchange step. - usedCodeVerifier string -} - -// getAuthorizationCode uses the [AuthorizationCodeHandler.AuthorizationCodeFetcher] -// to obtain an authorization code. -func (h *AuthorizationCodeHandler) getAuthorizationCode(ctx context.Context, cfg *oauth2.Config, resourceURL string) (*authResult, error) { - codeVerifier := oauth2.GenerateVerifier() - state := rand.Text() - - authURL := cfg.AuthCodeURL(state, - oauth2.S256ChallengeOption(codeVerifier), - oauth2.SetAuthURLParam("resource", resourceURL), - ) - - authRes, err := h.config.AuthorizationCodeFetcher(ctx, &AuthorizationArgs{URL: authURL}) - if err != nil { - // Purposefully leaving the error unwrappable so it can be handled by the caller. - return nil, err - } - if authRes.State != state { - return nil, fmt.Errorf("state mismatch") - } - return &authResult{ - AuthorizationResult: authRes, - usedCodeVerifier: codeVerifier, - }, nil -} - -// exchangeAuthorizationCode exchanges the authorization code for a token -// and stores it in a token source. -func (h *AuthorizationCodeHandler) exchangeAuthorizationCode(ctx context.Context, cfg *oauth2.Config, authResult *authResult, resourceURL string) error { - opts := []oauth2.AuthCodeOption{ - oauth2.VerifierOption(authResult.usedCodeVerifier), - oauth2.SetAuthURLParam("resource", resourceURL), - } - token, err := cfg.Exchange(ctx, authResult.Code, opts...) - if err != nil { - return fmt.Errorf("token exchange failed: %w", err) - } - h.tokenSource = cfg.TokenSource(ctx, token) - return nil -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/auth/client.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/auth/client.go deleted file mode 100644 index 0af6963..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/auth/client.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package auth - -import ( - "context" - "net/http" - - "golang.org/x/oauth2" -) - -// OAuthHandler is an interface for handling OAuth flows. -// -// If a transport wishes to support OAuth 2 authorization, it should support -// being configured with an OAuthHandler. It should call the handler's -// TokenSource method whenever it sends an HTTP request to set the -// Authorization header. If a request fails with a 401 or 403, it should call -// Authorize, and if that returns nil, it should retry the request. It should -// not call Authorize after the second failure. See -// [github.com/modelcontextprotocol/go-sdk/mcp.StreamableClientTransport] -// for an example. -type OAuthHandler interface { - isOAuthHandler() - - // TokenSource returns a token source to be used for outgoing requests. - // Returned token source might be nil. In that case, the transport will not - // add any authorization headers to the request. - TokenSource(context.Context) (oauth2.TokenSource, error) - - // Authorize is called when an HTTP request results in an error that may - // be addressed by the authorization flow (currently 401 Unauthorized and 403 Forbidden). - // It is responsible for performing the OAuth flow to obtain an access token. - // The arguments are the request that failed and the response that was received for it. - // The headers of the request are available, but the body will have already been consumed - // when Authorize is called. - // If the returned error is nil, TokenSource is expected to return a non-nil token source. - // After a successful call to Authorize, the HTTP request will be retried by the transport. - // The function is responsible for closing the response body. - Authorize(context.Context, *http.Request, *http.Response) error -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/auth/client_private.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/auth/client_private.go deleted file mode 100644 index 767c59e..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/auth/client_private.go +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -//go:build mcp_go_client_oauth - -package auth - -import ( - "bytes" - "errors" - "io" - "net/http" - "sync" - - "golang.org/x/oauth2" -) - -// An OAuthHandlerLegacy conducts an OAuth flow and returns a [oauth2.TokenSource] if the authorization -// is approved, or an error if not. -// The handler receives the HTTP request and response that triggered the authentication flow. -// To obtain the protected resource metadata, call [oauthex.GetProtectedResourceMetadataFromHeader]. -// -// Deprecated: Please use the new [OAuthHandler] abstraction that is built -// into the streamable transport. This struct will be removed in v1.5.0. -type OAuthHandlerLegacy func(req *http.Request, res *http.Response) (oauth2.TokenSource, error) - -// HTTPTransport is an [http.RoundTripper] that follows the MCP -// OAuth protocol when it encounters a 401 Unauthorized response. -// -// Deprecated: Please use the new [OAuthHandler] abstraction that is built -// into the streamable transport. This struct will be removed in v1.5.0. -type HTTPTransport struct { - handler OAuthHandlerLegacy - mu sync.Mutex // protects opts.Base - opts HTTPTransportOptions -} - -// NewHTTPTransport returns a new [*HTTPTransport]. -// The handler is invoked when an HTTP request results in a 401 Unauthorized status. -// It is called only once per transport. Once a TokenSource is obtained, it is used -// for the lifetime of the transport; subsequent 401s are not processed. -// -// Deprecated: Please use the new [OAuthHandler] abstraction that is built -// into the streamable transport. This struct will be removed in v1.5.0. -func NewHTTPTransport(handler OAuthHandlerLegacy, opts *HTTPTransportOptions) (*HTTPTransport, error) { - if handler == nil { - return nil, errors.New("handler cannot be nil") - } - t := &HTTPTransport{ - handler: handler, - } - if opts != nil { - t.opts = *opts - } - if t.opts.Base == nil { - t.opts.Base = http.DefaultTransport - } - return t, nil -} - -// HTTPTransportOptions are options to [NewHTTPTransport]. -// -// Deprecated: Please use the new [OAuthHandler] abstraction that is built -// into the streamable transport. This struct will be removed in v1.5.0. -type HTTPTransportOptions struct { - // Base is the [http.RoundTripper] to use. - // If nil, [http.DefaultTransport] is used. - Base http.RoundTripper -} - -func (t *HTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) { - t.mu.Lock() - base := t.opts.Base - t.mu.Unlock() - - var ( - // If haveBody is set, the request has a nontrivial body, and we need avoid - // reading (or closing) it multiple times. In that case, bodyBytes is its - // content. - haveBody bool - bodyBytes []byte - ) - if req.Body != nil && req.Body != http.NoBody { - // if we're setting Body, we must mutate first. - req = req.Clone(req.Context()) - haveBody = true - var err error - bodyBytes, err = io.ReadAll(req.Body) - if err != nil { - return nil, err - } - // Now that we've read the request body, http.RoundTripper requires that we - // close it. - req.Body.Close() // ignore error - req.Body = io.NopCloser(bytes.NewReader(bodyBytes)) - } - - resp, err := base.RoundTrip(req) - if err != nil { - return nil, err - } - if resp.StatusCode != http.StatusUnauthorized { - return resp, nil - } - if _, ok := base.(*oauth2.Transport); ok { - // We failed to authorize even with a token source; give up. - return resp, nil - } - - resp.Body.Close() - // Try to authorize. - t.mu.Lock() - defer t.mu.Unlock() - // If we don't have a token source, get one by following the OAuth flow. - // (We may have obtained one while t.mu was not held above.) - // TODO: We hold the lock for the entire OAuth flow. This could be a long - // time. Is there a better way? - if _, ok := t.opts.Base.(*oauth2.Transport); !ok { - ts, err := t.handler(req, resp) - if err != nil { - return nil, err - } - t.opts.Base = &oauth2.Transport{Base: t.opts.Base, Source: ts} - } - - // If we don't have a body, the request is reusable, though it will be cloned - // by the base. However, if we've had to read the body, we must clone. - if haveBody { - req = req.Clone(req.Context()) - req.Body = io.NopCloser(bytes.NewReader(bodyBytes)) - } - - return t.opts.Base.RoundTrip(req) -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/json/json.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/json/json.go deleted file mode 100644 index 1148770..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/json/json.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by the license -// that can be found in the LICENSE file. - -// Package json provides internal JSON utilities. - -package json - -import ( - "bytes" - - "github.com/segmentio/encoding/json" -) - -func Unmarshal(data []byte, v any) error { - dec := json.NewDecoder(bytes.NewReader(data)) - dec.DontMatchCaseInsensitiveStructFields() - return dec.Decode(v) -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2/conn.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2/conn.go deleted file mode 100644 index 571df63..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2/conn.go +++ /dev/null @@ -1,842 +0,0 @@ -// Copyright 2018 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package jsonrpc2 - -import ( - "context" - "errors" - "fmt" - "io" - "sync" - "sync/atomic" - "time" - - "github.com/modelcontextprotocol/go-sdk/internal/json" -) - -// Binder builds a connection configuration. -// This may be used in servers to generate a new configuration per connection. -// ConnectionOptions itself implements Binder returning itself unmodified, to -// allow for the simple cases where no per connection information is needed. -type Binder interface { - // Bind returns the ConnectionOptions to use when establishing the passed-in - // Connection. - // - // The connection is not ready to use when Bind is called, - // but Bind may close it without reading or writing to it. - Bind(context.Context, *Connection) ConnectionOptions -} - -// A BinderFunc implements the Binder interface for a standalone Bind function. -type BinderFunc func(context.Context, *Connection) ConnectionOptions - -func (f BinderFunc) Bind(ctx context.Context, c *Connection) ConnectionOptions { - return f(ctx, c) -} - -var _ Binder = BinderFunc(nil) - -// ConnectionOptions holds the options for new connections. -type ConnectionOptions struct { - // Framer allows control over the message framing and encoding. - // If nil, HeaderFramer will be used. - Framer Framer - // Preempter allows registration of a pre-queue message handler. - // If nil, no messages will be preempted. - Preempter Preempter - // Handler is used as the queued message handler for inbound messages. - // If nil, all responses will be ErrNotHandled. - Handler Handler - // OnInternalError, if non-nil, is called with any internal errors that occur - // while serving the connection, such as protocol errors or invariant - // violations. (If nil, internal errors result in panics.) - OnInternalError func(error) -} - -// Connection manages the jsonrpc2 protocol, connecting responses back to their -// calls. Connection is bidirectional; it does not have a designated server or -// client end. -// -// Note that the word 'Connection' is overloaded: the mcp.Connection represents -// the bidirectional stream of messages between client an server. The -// jsonrpc2.Connection layers RPC logic on top of that stream, dispatching RPC -// handlers, and correlating requests with responses from the peer. -// -// Some of the complexity of the Connection type is grown out of its usage in -// gopls: it could probably be simplified based on our usage in MCP. -type Connection struct { - seq int64 // must only be accessed using atomic operations - - stateMu sync.Mutex - state inFlightState // accessed only in updateInFlight - done chan struct{} // closed (under stateMu) when state.closed is true and all goroutines have completed - - writer Writer - handler Handler - - onInternalError func(error) - onDone func() -} - -// inFlightState records the state of the incoming and outgoing calls on a -// Connection. -type inFlightState struct { - connClosing bool // true when the Connection's Close method has been called - reading bool // true while the readIncoming goroutine is running - readErr error // non-nil when the readIncoming goroutine exits (typically io.EOF) - writeErr error // non-nil if a call to the Writer has failed with a non-canceled Context - - // closer shuts down and cleans up the Reader and Writer state, ideally - // interrupting any Read or Write call that is currently blocked. It is closed - // when the state is idle and one of: connClosing is true, readErr is non-nil, - // or writeErr is non-nil. - // - // After the closer has been invoked, the closer field is set to nil - // and the closeErr field is simultaneously set to its result. - closer io.Closer - closeErr error // error returned from closer.Close - - outgoingCalls map[ID]*AsyncCall // calls only - outgoingNotifications int // # of notifications awaiting "write" - - // incoming stores the total number of incoming calls and notifications - // that have not yet written or processed a result. - incoming int - - incomingByID map[ID]*incomingRequest // calls only - - // handlerQueue stores the backlog of calls and notifications that were not - // already handled by a preempter. - // The queue does not include the request currently being handled (if any). - handlerQueue []*incomingRequest - handlerRunning bool -} - -// updateInFlight locks the state of the connection's in-flight requests, allows -// f to mutate that state, and closes the connection if it is idle and either -// is closing or has a read or write error. -func (c *Connection) updateInFlight(f func(*inFlightState)) { - c.stateMu.Lock() - defer c.stateMu.Unlock() - - s := &c.state - - f(s) - - select { - case <-c.done: - // The connection was already completely done at the start of this call to - // updateInFlight, so it must remain so. (The call to f should have noticed - // that and avoided making any updates that would cause the state to be - // non-idle.) - if !s.idle() { - panic("jsonrpc2: updateInFlight transitioned to non-idle when already done") - } - return - default: - } - - if s.idle() && s.shuttingDown(ErrUnknown) != nil { - if s.closer != nil { - s.closeErr = s.closer.Close() - s.closer = nil // prevent duplicate Close calls - } - if s.reading { - // The readIncoming goroutine is still running. Our call to Close should - // cause it to exit soon, at which point it will make another call to - // updateInFlight, set s.reading to false, and mark the Connection done. - } else { - // The readIncoming goroutine has exited, or never started to begin with. - // Since everything else is idle, we're completely done. - if c.onDone != nil { - c.onDone() - } - close(c.done) - } - } -} - -// idle reports whether the connection is in a state with no pending calls or -// notifications. -// -// If idle returns true, the readIncoming goroutine may still be running, -// but no other goroutines are doing work on behalf of the connection. -func (s *inFlightState) idle() bool { - return len(s.outgoingCalls) == 0 && s.outgoingNotifications == 0 && s.incoming == 0 && !s.handlerRunning -} - -// shuttingDown reports whether the connection is in a state that should -// disallow new (incoming and outgoing) calls. It returns either nil or -// an error that is or wraps the provided errClosing. -func (s *inFlightState) shuttingDown(errClosing error) error { - if s.connClosing { - // If Close has been called explicitly, it doesn't matter what state the - // Reader and Writer are in: we shouldn't be starting new work because the - // caller told us not to start new work. - return errClosing - } - if s.readErr != nil { - // If the read side of the connection is broken, we cannot read new call - // requests, and cannot read responses to our outgoing calls. - return fmt.Errorf("%w: %v", errClosing, s.readErr) - } - if s.writeErr != nil { - // If the write side of the connection is broken, we cannot write responses - // for incoming calls, and cannot write requests for outgoing calls. - return fmt.Errorf("%w: %v", errClosing, s.writeErr) - } - return nil -} - -// incomingRequest is used to track an incoming request as it is being handled -type incomingRequest struct { - *Request // the request being processed - ctx context.Context - cancel context.CancelFunc -} - -// Bind returns the options unmodified. -func (o ConnectionOptions) Bind(context.Context, *Connection) ConnectionOptions { - return o -} - -// A ConnectionConfig configures a bidirectional jsonrpc2 connection. -type ConnectionConfig struct { - Reader Reader // required - Writer Writer // required - Closer io.Closer // required - Preempter Preempter // optional - Bind func(*Connection) Handler // required - OnDone func() // optional - OnInternalError func(error) // optional -} - -// NewConnection creates a new [Connection] object and starts processing -// incoming messages. -func NewConnection(ctx context.Context, cfg ConnectionConfig) *Connection { - ctx = notDone{ctx} - - c := &Connection{ - state: inFlightState{closer: cfg.Closer}, - done: make(chan struct{}), - writer: cfg.Writer, - onDone: cfg.OnDone, - onInternalError: cfg.OnInternalError, - } - c.handler = cfg.Bind(c) - c.start(ctx, cfg.Reader, cfg.Preempter) - return c -} - -// bindConnection creates a new connection and runs it. -// -// This is used by the Dial and Serve functions to build the actual connection. -// -// The connection is closed automatically (and its resources cleaned up) when -// the last request has completed after the underlying ReadWriteCloser breaks, -// but it may be stopped earlier by calling Close (for a clean shutdown). -func bindConnection(bindCtx context.Context, rwc io.ReadWriteCloser, binder Binder, onDone func()) *Connection { - // TODO: Should we create a new event span here? - // This will propagate cancellation from ctx; should it? - ctx := notDone{bindCtx} - - c := &Connection{ - state: inFlightState{closer: rwc}, - done: make(chan struct{}), - onDone: onDone, - } - // It's tempting to set a finalizer on c to verify that the state has gone - // idle when the connection becomes unreachable. Unfortunately, the Binder - // interface makes that unsafe: it allows the Handler to close over the - // Connection, which could create a reference cycle that would cause the - // Connection to become uncollectable. - - options := binder.Bind(bindCtx, c) - framer := options.Framer - if framer == nil { - framer = HeaderFramer() - } - c.handler = options.Handler - if c.handler == nil { - c.handler = defaultHandler{} - } - c.onInternalError = options.OnInternalError - - c.writer = framer.Writer(rwc) - reader := framer.Reader(rwc) - c.start(ctx, reader, options.Preempter) - return c -} - -func (c *Connection) start(ctx context.Context, reader Reader, preempter Preempter) { - c.updateInFlight(func(s *inFlightState) { - select { - case <-c.done: - // Bind already closed the connection; don't start a goroutine to read it. - return - default: - } - - // The goroutine started here will continue until the underlying stream is closed. - // - // (If the Binder closed the Connection already, this should error out and - // return almost immediately.) - s.reading = true - go c.readIncoming(ctx, reader, preempter) - }) -} - -// Notify invokes the target method but does not wait for a response. -// The params will be marshaled to JSON before sending over the wire, and will -// be handed to the method invoked. -func (c *Connection) Notify(ctx context.Context, method string, params any) (err error) { - attempted := false - - defer func() { - if attempted { - c.updateInFlight(func(s *inFlightState) { - s.outgoingNotifications-- - }) - } - }() - - c.updateInFlight(func(s *inFlightState) { - // If the connection is shutting down, allow outgoing notifications only if - // there is at least one call still in flight. The number of calls in flight - // cannot increase once shutdown begins, and allowing outgoing notifications - // may permit notifications that will cancel in-flight calls. - if len(s.outgoingCalls) == 0 && len(s.incomingByID) == 0 { - err = s.shuttingDown(ErrClientClosing) - if err != nil { - return - } - } - s.outgoingNotifications++ - attempted = true - }) - if err != nil { - return err - } - - notify, err := NewNotification(method, params) - if err != nil { - return fmt.Errorf("marshaling notify parameters: %v", err) - } - - return c.write(ctx, notify) -} - -// Call invokes the target method and returns an object that can be used to await the response. -// The params will be marshaled to JSON before sending over the wire, and will -// be handed to the method invoked. -// You do not have to wait for the response, it can just be ignored if not needed. -// If sending the call failed, the response will be ready and have the error in it. -func (c *Connection) Call(ctx context.Context, method string, params any) *AsyncCall { - // Generate a new request identifier. - id := Int64ID(atomic.AddInt64(&c.seq, 1)) - - ac := &AsyncCall{ - id: id, - ready: make(chan struct{}), - } - // When this method returns, either ac is retired, or the request has been - // written successfully and the call is awaiting a response (to be provided by - // the readIncoming goroutine). - - call, err := NewCall(ac.id, method, params) - if err != nil { - ac.retire(&Response{ID: id, Error: fmt.Errorf("marshaling call parameters: %w", err)}) - return ac - } - - c.updateInFlight(func(s *inFlightState) { - err = s.shuttingDown(ErrClientClosing) - if err != nil { - return - } - if s.outgoingCalls == nil { - s.outgoingCalls = make(map[ID]*AsyncCall) - } - s.outgoingCalls[ac.id] = ac - }) - if err != nil { - ac.retire(&Response{ID: id, Error: err}) - return ac - } - - if err := c.write(ctx, call); err != nil { - // Sending failed. We will never get a response, so deliver a fake one if it - // wasn't already retired by the connection breaking. - c.Retire(ac, err) - } - return ac -} - -// Retire stops tracking the call, and reports err as its terminal error. -// -// Retire is safe to call multiple times: if the call is already no longer -// tracked, Retire is a no op. -func (c *Connection) Retire(ac *AsyncCall, err error) { - c.updateInFlight(func(s *inFlightState) { - if s.outgoingCalls[ac.id] == ac { - delete(s.outgoingCalls, ac.id) - ac.retire(&Response{ID: ac.id, Error: err}) - } else { - // ac was already retired elsewhere. - } - }) -} - -// Async, signals that the current jsonrpc2 request may be handled -// asynchronously to subsequent requests, when ctx is the request context. -// -// Async must be called at most once on each request's context (and its -// descendants). -func Async(ctx context.Context) { - if r, ok := ctx.Value(asyncKey).(*releaser); ok { - r.release(false) - } -} - -type asyncKeyType struct{} - -var asyncKey = asyncKeyType{} - -// A releaser implements concurrency safe 'releasing' of async requests. (A -// request is released when it is allowed to run concurrent with other -// requests, via a call to [Async].) -type releaser struct { - mu sync.Mutex - ch chan struct{} - released bool -} - -// release closes the associated channel. If soft is set, multiple calls to -// release are allowed. -func (r *releaser) release(soft bool) { - r.mu.Lock() - defer r.mu.Unlock() - - if r.released { - if !soft { - panic("jsonrpc2.Async called multiple times") - } - } else { - close(r.ch) - r.released = true - } -} - -type AsyncCall struct { - id ID - ready chan struct{} // closed after response has been set - response *Response -} - -// ID used for this call. -// This can be used to cancel the call if needed. -func (ac *AsyncCall) ID() ID { return ac.id } - -// IsReady can be used to check if the result is already prepared. -// This is guaranteed to return true on a result for which Await has already -// returned, or a call that failed to send in the first place. -func (ac *AsyncCall) IsReady() bool { - select { - case <-ac.ready: - return true - default: - return false - } -} - -// retire processes the response to the call. -// -// It is an error to call retire more than once: retire is guarded by the -// connection's outgoingCalls map. -func (ac *AsyncCall) retire(response *Response) { - select { - case <-ac.ready: - panic(fmt.Sprintf("jsonrpc2: retire called twice for ID %v", ac.id)) - default: - } - - ac.response = response - close(ac.ready) -} - -// Await waits for (and decodes) the results of a Call. -// The response will be unmarshaled from JSON into the result. -// -// If the call is cancelled due to context cancellation, the result is -// ctx.Err(). -func (ac *AsyncCall) Await(ctx context.Context, result any) error { - select { - case <-ctx.Done(): - return ctx.Err() - case <-ac.ready: - } - if ac.response.Error != nil { - return ac.response.Error - } - if result == nil { - return nil - } - return json.Unmarshal(ac.response.Result, result) -} - -// Cancel cancels the Context passed to the Handle call for the inbound message -// with the given ID. -// -// Cancel will not complain if the ID is not a currently active message, and it -// will not cause any messages that have not arrived yet with that ID to be -// cancelled. -func (c *Connection) Cancel(id ID) { - var req *incomingRequest - c.updateInFlight(func(s *inFlightState) { - req = s.incomingByID[id] - }) - if req != nil { - req.cancel() - } -} - -// Wait blocks until the connection is fully closed, but does not close it. -func (c *Connection) Wait() error { - return c.wait(true) -} - -// wait for the connection to close, and aggregates the most cause of its -// termination, if abnormal. -// -// The fromWait argument allows this logic to be shared with Close, where we -// only want to expose the closeErr. -// -// (Previously, Wait also only returned the closeErr, which was misleading if -// the connection was broken for another reason). -func (c *Connection) wait(fromWait bool) error { - var err error - <-c.done - c.updateInFlight(func(s *inFlightState) { - if fromWait { - if !errors.Is(s.readErr, io.EOF) { - err = s.readErr - } - if err == nil && !errors.Is(s.writeErr, io.EOF) { - err = s.writeErr - } - } - if err == nil { - err = s.closeErr - } - }) - return err -} - -// Close stops accepting new requests, waits for in-flight requests and enqueued -// Handle calls to complete, and then closes the underlying stream. -// -// After the start of a Close, notification requests (that lack IDs and do not -// receive responses) will continue to be passed to the Preempter, but calls -// with IDs will receive immediate responses with ErrServerClosing, and no new -// requests (not even notifications!) will be enqueued to the Handler. -func (c *Connection) Close() error { - // Stop handling new requests, and interrupt the reader (by closing the - // connection) as soon as the active requests finish. - c.updateInFlight(func(s *inFlightState) { s.connClosing = true }) - return c.wait(false) -} - -// readIncoming collects inbound messages from the reader and delivers them, either responding -// to outgoing calls or feeding requests to the queue. -func (c *Connection) readIncoming(ctx context.Context, reader Reader, preempter Preempter) { - var err error - for { - var msg Message - msg, err = reader.Read(ctx) - if err != nil { - break - } - - switch msg := msg.(type) { - case *Request: - c.acceptRequest(ctx, msg, preempter) - - case *Response: - c.updateInFlight(func(s *inFlightState) { - if ac, ok := s.outgoingCalls[msg.ID]; ok { - delete(s.outgoingCalls, msg.ID) - ac.retire(msg) - } else { - // TODO: How should we report unexpected responses? - } - }) - - default: - c.internalErrorf("Read returned an unexpected message of type %T", msg) - } - } - - c.updateInFlight(func(s *inFlightState) { - s.reading = false - s.readErr = err - - // Retire any outgoing requests that were still in flight: with the Reader no - // longer being processed, they necessarily cannot receive a response. - for id, ac := range s.outgoingCalls { - ac.retire(&Response{ID: id, Error: err}) - } - s.outgoingCalls = nil - }) -} - -// acceptRequest either handles msg synchronously or enqueues it to be handled -// asynchronously. -func (c *Connection) acceptRequest(ctx context.Context, msg *Request, preempter Preempter) { - // In theory notifications cannot be cancelled, but we build them a cancel - // context anyway. - reqCtx, cancel := context.WithCancel(ctx) - req := &incomingRequest{ - Request: msg, - ctx: reqCtx, - cancel: cancel, - } - - // If the request is a call, add it to the incoming map so it can be - // cancelled (or responded) by ID. - var err error - c.updateInFlight(func(s *inFlightState) { - s.incoming++ - - if req.IsCall() { - if s.incomingByID[req.ID] != nil { - err = fmt.Errorf("%w: request ID %v already in use", ErrInvalidRequest, req.ID) - req.ID = ID{} // Don't misattribute this error to the existing request. - return - } - - if s.incomingByID == nil { - s.incomingByID = make(map[ID]*incomingRequest) - } - s.incomingByID[req.ID] = req - - // When shutting down, reject all new Call requests, even if they could - // theoretically be handled by the preempter. The preempter could return - // ErrAsyncResponse, which would increase the amount of work in flight - // when we're trying to ensure that it strictly decreases. - err = s.shuttingDown(ErrServerClosing) - } - }) - if err != nil { - c.processResult("acceptRequest", req, nil, err) - return - } - - if preempter != nil { - result, err := preempter.Preempt(req.ctx, req.Request) - - if !errors.Is(err, ErrNotHandled) { - c.processResult("Preempt", req, result, err) - return - } - } - - c.updateInFlight(func(s *inFlightState) { - // If the connection is shutting down, don't enqueue anything to the - // handler — not even notifications. That ensures that if the handler - // continues to make progress, it will eventually become idle and - // close the connection. - err = s.shuttingDown(ErrServerClosing) - if err != nil { - return - } - - // We enqueue requests that have not been preempted to an unbounded slice. - // Unfortunately, we cannot in general limit the size of the handler - // queue: we have to read every response that comes in on the wire - // (because it may be responding to a request issued by, say, an - // asynchronous handler), and in order to get to that response we have - // to read all of the requests that came in ahead of it. - s.handlerQueue = append(s.handlerQueue, req) - if !s.handlerRunning { - // We start the handleAsync goroutine when it has work to do, and let it - // exit when the queue empties. - // - // Otherwise, in order to synchronize the handler we would need some other - // goroutine (probably readIncoming?) to explicitly wait for handleAsync - // to finish, and that would complicate error reporting: either the error - // report from the goroutine would be blocked on the handler emptying its - // queue (which was tried, and introduced a deadlock detected by - // TestCloseCallRace), or the error would need to be reported separately - // from synchronizing completion. Allowing the handler goroutine to exit - // when idle seems simpler than trying to implement either of those - // alternatives correctly. - s.handlerRunning = true - go c.handleAsync() - } - }) - if err != nil { - c.processResult("acceptRequest", req, nil, err) - } -} - -// handleAsync invokes the handler on the requests in the handler queue -// sequentially until the queue is empty. -func (c *Connection) handleAsync() { - for { - var req *incomingRequest - c.updateInFlight(func(s *inFlightState) { - if len(s.handlerQueue) > 0 { - req, s.handlerQueue = s.handlerQueue[0], s.handlerQueue[1:] - } else { - s.handlerRunning = false - } - }) - if req == nil { - return - } - - // Only deliver to the Handler if not already canceled. - if err := req.ctx.Err(); err != nil { - c.updateInFlight(func(s *inFlightState) { - if s.writeErr != nil { - // Assume that req.ctx was canceled due to s.writeErr. - // TODO(#51365): use a Context API to plumb this through req.ctx. - err = fmt.Errorf("%w: %v", ErrServerClosing, s.writeErr) - } - }) - c.processResult("handleAsync", req, nil, err) - continue - } - - releaser := &releaser{ch: make(chan struct{})} - ctx := context.WithValue(req.ctx, asyncKey, releaser) - go func() { - defer releaser.release(true) - result, err := c.handler.Handle(ctx, req.Request) - c.processResult(c.handler, req, result, err) - }() - <-releaser.ch - } -} - -// processResult processes the result of a request and, if appropriate, sends a response. -func (c *Connection) processResult(from any, req *incomingRequest, result any, err error) error { - switch err { - case ErrNotHandled, ErrMethodNotFound: - // Add detail describing the unhandled method. - err = fmt.Errorf("%w: %q", ErrMethodNotFound, req.Method) - } - - if result != nil && err != nil { - c.internalErrorf("%#v returned a non-nil result with a non-nil error for %s:\n%v\n%#v", from, req.Method, err, result) - result = nil // Discard the spurious result and respond with err. - } - - if req.IsCall() { - if result == nil && err == nil { - err = c.internalErrorf("%#v returned a nil result and nil error for a %q Request that requires a Response", from, req.Method) - } - - response, respErr := NewResponse(req.ID, result, err) - - // The caller could theoretically reuse the request's ID as soon as we've - // sent the response, so ensure that it is removed from the incoming map - // before sending. - c.updateInFlight(func(s *inFlightState) { - delete(s.incomingByID, req.ID) - }) - if respErr == nil { - writeErr := c.write(notDone{req.ctx}, response) - if err == nil { - err = writeErr - } - } else { - err = c.internalErrorf("%#v returned a malformed result for %q: %w", from, req.Method, respErr) - } - } else { // req is a notification - if result != nil { - err = c.internalErrorf("%#v returned a non-nil result for a %q Request without an ID", from, req.Method) - } else if err != nil { - err = fmt.Errorf("%w: %q notification failed: %v", ErrInternal, req.Method, err) - } - } - if err != nil { - // TODO: can/should we do anything with this error beyond writing it to the event log? - // (Is this the right label to attach to the log?) - } - - // Cancel the request to free any associated resources. - req.cancel() - c.updateInFlight(func(s *inFlightState) { - if s.incoming == 0 { - panic("jsonrpc2: processResult called when incoming count is already zero") - } - s.incoming-- - }) - return nil -} - -// write is used by all things that write outgoing messages, including replies. -// it makes sure that writes are atomic -func (c *Connection) write(ctx context.Context, msg Message) error { - var err error - // Fail writes immediately if the connection is shutting down. - // - // TODO(rfindley): should we allow cancellation notifications through? It - // could be the case that writes can still succeed. - c.updateInFlight(func(s *inFlightState) { - err = s.shuttingDown(ErrServerClosing) - }) - if err == nil { - err = c.writer.Write(ctx, msg) - } - - // For cancelled or rejected requests, we don't set the writeErr (which would - // break the connection). They can just be returned to the caller. - if err != nil && ctx.Err() == nil && !errors.Is(err, ErrRejected) { - // The call to Write failed, and since ctx.Err() is nil we can't attribute - // the failure (even indirectly) to Context cancellation. The writer appears - // to be broken, and future writes are likely to also fail. - // - // If the read side of the connection is also broken, we might not even be - // able to receive cancellation notifications. Since we can't reliably write - // the results of incoming calls and can't receive explicit cancellations, - // cancel the calls now. - c.updateInFlight(func(s *inFlightState) { - if s.writeErr == nil { - s.writeErr = err - for _, r := range s.incomingByID { - r.cancel() - } - } - }) - } - - return err -} - -// internalErrorf reports an internal error. By default it panics, but if -// c.onInternalError is non-nil it instead calls that and returns an error -// wrapping ErrInternal. -func (c *Connection) internalErrorf(format string, args ...any) error { - err := fmt.Errorf(format, args...) - if c.onInternalError == nil { - panic("jsonrpc2: " + err.Error()) - } - c.onInternalError(err) - - return fmt.Errorf("%w: %v", ErrInternal, err) -} - -// notDone is a context.Context wrapper that returns a nil Done channel. -type notDone struct{ ctx context.Context } - -func (ic notDone) Value(key any) any { - return ic.ctx.Value(key) -} - -func (notDone) Done() <-chan struct{} { return nil } -func (notDone) Err() error { return nil } -func (notDone) Deadline() (time.Time, bool) { return time.Time{}, false } diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2/frame.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2/frame.go deleted file mode 100644 index 72527cb..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2/frame.go +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright 2018 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package jsonrpc2 - -import ( - "bufio" - "context" - "encoding/json" - "fmt" - "io" - "strconv" - "strings" - "sync" -) - -// Reader abstracts the transport mechanics from the JSON RPC protocol. -// A Conn reads messages from the reader it was provided on construction, -// and assumes that each call to Read fully transfers a single message, -// or returns an error. -// -// A reader is not safe for concurrent use, it is expected it will be used by -// a single Conn in a safe manner. -type Reader interface { - // Read gets the next message from the stream. - Read(context.Context) (Message, error) -} - -// Writer abstracts the transport mechanics from the JSON RPC protocol. -// A Conn writes messages using the writer it was provided on construction, -// and assumes that each call to Write fully transfers a single message, -// or returns an error. -// -// A writer must be safe for concurrent use, as writes may occur concurrently -// in practice: libraries may make calls or respond to requests asynchronously. -type Writer interface { - // Write sends a message to the stream. - Write(context.Context, Message) error -} - -// Framer wraps low level byte readers and writers into jsonrpc2 message -// readers and writers. -// It is responsible for the framing and encoding of messages into wire form. -// -// TODO(rfindley): rethink the framer interface, as with JSONRPC2 batching -// there is a need for Reader and Writer to be correlated, and while the -// implementation of framing here allows that, it is not made explicit by the -// interface. -// -// Perhaps a better interface would be -// -// Frame(io.ReadWriteCloser) (Reader, Writer). -type Framer interface { - // Reader wraps a byte reader into a message reader. - Reader(io.Reader) Reader - // Writer wraps a byte writer into a message writer. - Writer(io.Writer) Writer -} - -// RawFramer returns a new Framer. -// The messages are sent with no wrapping, and rely on json decode consistency -// to determine message boundaries. -func RawFramer() Framer { return rawFramer{} } - -type rawFramer struct{} -type rawReader struct{ in *json.Decoder } -type rawWriter struct { - mu sync.Mutex - out io.Writer -} - -func (rawFramer) Reader(rw io.Reader) Reader { - return &rawReader{in: json.NewDecoder(rw)} -} - -func (rawFramer) Writer(rw io.Writer) Writer { - return &rawWriter{out: rw} -} - -func (r *rawReader) Read(ctx context.Context) (Message, error) { - select { - case <-ctx.Done(): - return nil, ctx.Err() - default: - } - var raw json.RawMessage - if err := r.in.Decode(&raw); err != nil { - return nil, err - } - msg, err := DecodeMessage(raw) - return msg, err -} - -func (w *rawWriter) Write(ctx context.Context, msg Message) error { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - - data, err := EncodeMessage(msg) - if err != nil { - return fmt.Errorf("marshaling message: %v", err) - } - - w.mu.Lock() - defer w.mu.Unlock() - _, err = w.out.Write(data) - return err -} - -// HeaderFramer returns a new Framer. -// The messages are sent with HTTP content length and MIME type headers. -// This is the format used by LSP and others. -func HeaderFramer() Framer { return headerFramer{} } - -type headerFramer struct{} -type headerReader struct{ in *bufio.Reader } -type headerWriter struct { - mu sync.Mutex - out io.Writer -} - -func (headerFramer) Reader(rw io.Reader) Reader { - return &headerReader{in: bufio.NewReader(rw)} -} - -func (headerFramer) Writer(rw io.Writer) Writer { - return &headerWriter{out: rw} -} - -func (r *headerReader) Read(ctx context.Context) (Message, error) { - select { - case <-ctx.Done(): - return nil, ctx.Err() - default: - } - - firstRead := true // to detect a clean EOF below - var contentLength int64 - // read the header, stop on the first empty line - for { - line, err := r.in.ReadString('\n') - if err != nil { - if err == io.EOF { - if firstRead && line == "" { - return nil, io.EOF // clean EOF - } - err = io.ErrUnexpectedEOF - } - return nil, fmt.Errorf("failed reading header line: %w", err) - } - firstRead = false - - line = strings.TrimSpace(line) - // check we have a header line - if line == "" { - break - } - colon := strings.IndexRune(line, ':') - if colon < 0 { - return nil, fmt.Errorf("invalid header line %q", line) - } - name, value := line[:colon], strings.TrimSpace(line[colon+1:]) - switch { - case strings.EqualFold(name, "Content-Length"): - if contentLength, err = strconv.ParseInt(value, 10, 32); err != nil { - return nil, fmt.Errorf("failed parsing Content-Length: %v", value) - } - if contentLength <= 0 { - return nil, fmt.Errorf("invalid Content-Length: %v", contentLength) - } - default: - // ignoring unknown headers - } - } - if contentLength == 0 { - return nil, fmt.Errorf("missing Content-Length header") - } - data := make([]byte, contentLength) - _, err := io.ReadFull(r.in, data) - if err != nil { - return nil, err - } - msg, err := DecodeMessage(data) - return msg, err -} - -func (w *headerWriter) Write(ctx context.Context, msg Message) error { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - w.mu.Lock() - defer w.mu.Unlock() - - data, err := EncodeMessage(msg) - if err != nil { - return fmt.Errorf("marshaling message: %v", err) - } - _, err = fmt.Fprintf(w.out, "Content-Length: %v\r\n\r\n", len(data)) - if err == nil { - _, err = w.out.Write(data) - } - return err -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2/jsonrpc2.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2/jsonrpc2.go deleted file mode 100644 index 234e6ee..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2/jsonrpc2.go +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2018 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// Package jsonrpc2 is a minimal implementation of the JSON RPC 2 spec. -// https://www.jsonrpc.org/specification -// It is intended to be compatible with other implementations at the wire level. -package jsonrpc2 - -import ( - "context" - "errors" -) - -var ( - // ErrIdleTimeout is returned when serving timed out waiting for new connections. - ErrIdleTimeout = errors.New("timed out waiting for new connections") - - // ErrNotHandled is returned from a Handler or Preempter to indicate it did - // not handle the request. - // - // If a Handler returns ErrNotHandled, the server replies with - // ErrMethodNotFound. - ErrNotHandled = errors.New("JSON RPC not handled") -) - -// Preempter handles messages on a connection before they are queued to the main -// handler. -// Primarily this is used for cancel handlers or notifications for which out of -// order processing is not an issue. -type Preempter interface { - // Preempt is invoked for each incoming request before it is queued for handling. - // - // If Preempt returns ErrNotHandled, the request will be queued, - // and eventually passed to a Handle call. - // - // Otherwise, the result and error are processed as if returned by Handle. - // - // Preempt must not block. (The Context passed to it is for Values only.) - Preempt(ctx context.Context, req *Request) (result any, err error) -} - -// A PreempterFunc implements the Preempter interface for a standalone Preempt function. -type PreempterFunc func(ctx context.Context, req *Request) (any, error) - -func (f PreempterFunc) Preempt(ctx context.Context, req *Request) (any, error) { - return f(ctx, req) -} - -var _ Preempter = PreempterFunc(nil) - -// Handler handles messages on a connection. -type Handler interface { - // Handle is invoked sequentially for each incoming request that has not - // already been handled by a Preempter. - // - // If the Request has a nil ID, Handle must return a nil result, - // and any error may be logged but will not be reported to the caller. - // - // If the Request has a non-nil ID, Handle must return either a - // non-nil, JSON-marshalable result, or a non-nil error. - // - // The Context passed to Handle will be canceled if the - // connection is broken or the request is canceled or completed. - // (If Handle returns ErrAsyncResponse, ctx will remain uncanceled - // until either Cancel or Respond is called for the request's ID.) - Handle(ctx context.Context, req *Request) (result any, err error) -} - -type defaultHandler struct{} - -func (defaultHandler) Preempt(context.Context, *Request) (any, error) { - return nil, ErrNotHandled -} - -func (defaultHandler) Handle(context.Context, *Request) (any, error) { - return nil, ErrNotHandled -} - -// A HandlerFunc implements the Handler interface for a standalone Handle function. -type HandlerFunc func(ctx context.Context, req *Request) (any, error) - -func (f HandlerFunc) Handle(ctx context.Context, req *Request) (any, error) { - return f(ctx, req) -} - -var _ Handler = HandlerFunc(nil) - -// async is a small helper for operations with an asynchronous result that you -// can wait for. -type async struct { - ready chan struct{} // closed when done - firstErr chan error // 1-buffered; contains either nil or the first non-nil error -} - -func newAsync() *async { - var a async - a.ready = make(chan struct{}) - a.firstErr = make(chan error, 1) - a.firstErr <- nil - return &a -} - -func (a *async) done() { - close(a.ready) -} - -func (a *async) wait() error { - <-a.ready - err := <-a.firstErr - a.firstErr <- err - return err -} - -func (a *async) setError(err error) { - storedErr := <-a.firstErr - if storedErr == nil { - storedErr = err - } - a.firstErr <- storedErr -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2/messages.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2/messages.go deleted file mode 100644 index b424780..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2/messages.go +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright 2018 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package jsonrpc2 - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - - internaljson "github.com/modelcontextprotocol/go-sdk/internal/json" - - "github.com/modelcontextprotocol/go-sdk/internal/mcpgodebug" -) - -// ID is a Request identifier, which is defined by the spec to be a string, integer, or null. -// https://www.jsonrpc.org/specification#request_object -type ID struct { - value any -} - -// MakeID coerces the given Go value to an ID. The value should be the -// default JSON marshaling of a Request identifier: nil, float64, or string. -// -// Returns an error if the value type was not a valid Request ID type. -// -// TODO: ID can't be a json.Marshaler/Unmarshaler, because we want to omitzero. -// Simplify this package by making ID json serializable once we can rely on -// omitzero. -func MakeID(v any) (ID, error) { - switch v := v.(type) { - case nil: - return ID{}, nil - case float64: - return Int64ID(int64(v)), nil - case string: - return StringID(v), nil - } - return ID{}, fmt.Errorf("%w: invalid ID type %T", ErrParse, v) -} - -// Message is the interface to all jsonrpc2 message types. -// They share no common functionality, but are a closed set of concrete types -// that are allowed to implement this interface. The message types are *Request -// and *Response. -type Message interface { - // marshal builds the wire form from the API form. - // It is private, which makes the set of Message implementations closed. - marshal(to *wireCombined) -} - -// Request is a Message sent to a peer to request behavior. -// If it has an ID it is a call, otherwise it is a notification. -type Request struct { - // ID of this request, used to tie the Response back to the request. - // This will be nil for notifications. - ID ID - // Method is a string containing the method name to invoke. - Method string - // Params is either a struct or an array with the parameters of the method. - Params json.RawMessage - // Extra is additional information that does not appear on the wire. It can be - // used to pass information from the application to the underlying transport. - Extra any -} - -// Response is a Message used as a reply to a call Request. -// It will have the same ID as the call it is a response to. -type Response struct { - // result is the content of the response. - Result json.RawMessage - // err is set only if the call failed. - Error error - // id of the request this is a response to. - ID ID - // Extra is additional information that does not appear on the wire. It can be - // used to pass information from the underlying transport to the application. - Extra any -} - -// StringID creates a new string request identifier. -func StringID(s string) ID { return ID{value: s} } - -// Int64ID creates a new integer request identifier. -func Int64ID(i int64) ID { return ID{value: i} } - -// IsValid returns true if the ID is a valid identifier. -// The default value for ID will return false. -func (id ID) IsValid() bool { return id.value != nil } - -// Raw returns the underlying value of the ID. -func (id ID) Raw() any { return id.value } - -// NewNotification constructs a new Notification message for the supplied -// method and parameters. -func NewNotification(method string, params any) (*Request, error) { - p, merr := marshalToRaw(params) - return &Request{Method: method, Params: p}, merr -} - -// NewCall constructs a new Call message for the supplied ID, method and -// parameters. -func NewCall(id ID, method string, params any) (*Request, error) { - p, merr := marshalToRaw(params) - return &Request{ID: id, Method: method, Params: p}, merr -} - -func (msg *Request) IsCall() bool { return msg.ID.IsValid() } - -func (msg *Request) marshal(to *wireCombined) { - to.ID = msg.ID.value - to.Method = msg.Method - to.Params = msg.Params -} - -// NewResponse constructs a new Response message that is a reply to the -// supplied. If err is set result may be ignored. -func NewResponse(id ID, result any, rerr error) (*Response, error) { - r, merr := marshalToRaw(result) - return &Response{ID: id, Result: r, Error: rerr}, merr -} - -func (msg *Response) marshal(to *wireCombined) { - to.ID = msg.ID.value - to.Error = toWireError(msg.Error) - to.Result = msg.Result -} - -func toWireError(err error) *WireError { - if err == nil { - // no error, the response is complete - return nil - } - if err, ok := err.(*WireError); ok { - // already a wire error, just use it - return err - } - result := &WireError{Message: err.Error()} - var wrapped *WireError - if errors.As(err, &wrapped) { - // if we wrapped a wire error, keep the code from the wrapped error - // but the message from the outer error - result.Code = wrapped.Code - } - return result -} - -func EncodeMessage(msg Message) ([]byte, error) { - wire := wireCombined{VersionTag: wireVersion} - msg.marshal(&wire) - data, err := jsonMarshal(&wire) - if err != nil { - return nil, fmt.Errorf("marshaling jsonrpc message: %w", err) - } - return data, nil -} - -// EncodeIndent is like EncodeMessage, but honors indents. -// TODO(rfindley): refactor so that this concern is handled independently. -// Perhaps we should pass in a json.Encoder? -func EncodeIndent(msg Message, prefix, indent string) ([]byte, error) { - wire := wireCombined{VersionTag: wireVersion} - msg.marshal(&wire) - var buf bytes.Buffer - enc := json.NewEncoder(&buf) - enc.SetEscapeHTML(false) - enc.SetIndent(prefix, indent) - if err := enc.Encode(&wire); err != nil { - return nil, fmt.Errorf("marshaling jsonrpc message: %w", err) - } - return bytes.TrimRight(buf.Bytes(), "\n"), nil -} - -func DecodeMessage(data []byte) (Message, error) { - msg := wireCombined{} - if err := internaljson.Unmarshal(data, &msg); err != nil { - return nil, fmt.Errorf("unmarshaling jsonrpc message: %w", err) - } - if msg.VersionTag != wireVersion { - return nil, fmt.Errorf("invalid message version tag %q; expected %q", msg.VersionTag, wireVersion) - } - id, err := MakeID(msg.ID) - if err != nil { - return nil, err - } - if msg.Method != "" { - // has a method, must be a call - return &Request{ - Method: msg.Method, - ID: id, - Params: msg.Params, - }, nil - } - // no method, should be a response - if !id.IsValid() { - return nil, ErrInvalidRequest - } - resp := &Response{ - ID: id, - Result: msg.Result, - } - // we have to check if msg.Error is nil to avoid a typed error - if msg.Error != nil { - resp.Error = msg.Error - } - return resp, nil -} - -func marshalToRaw(obj any) (json.RawMessage, error) { - if obj == nil { - return nil, nil - } - data, err := jsonMarshal(obj) - if err != nil { - return nil, err - } - return json.RawMessage(data), nil -} - -// jsonescaping is a compatibility parameter that allows to restore -// JSON escaping in the JSON marshaling, which stopped being the default -// in the 1.4.0 version of the SDK. See the documentation for the -// mcpgodebug package for instructions how to enable it. -// The option will be removed in the 1.6.0 version of the SDK. -var jsonescaping = mcpgodebug.Value("jsonescaping") - -// jsonMarshal marshals obj to JSON like json.Marshal but without HTML escaping. -func jsonMarshal(obj any) ([]byte, error) { - if jsonescaping == "1" { - return json.Marshal(obj) - } - var buf bytes.Buffer - enc := json.NewEncoder(&buf) - enc.SetEscapeHTML(false) - if err := enc.Encode(obj); err != nil { - return nil, err - } - // json.Encoder.Encode adds a trailing newline. Trim it to be consistent with json.Marshal. - return bytes.TrimRight(buf.Bytes(), "\n"), nil -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2/net.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2/net.go deleted file mode 100644 index 05db062..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2/net.go +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright 2018 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package jsonrpc2 - -import ( - "context" - "io" - "net" - "os" -) - -// This file contains implementations of the transport primitives that use the standard network -// package. - -// NetListenOptions is the optional arguments to the NetListen function. -type NetListenOptions struct { - NetListenConfig net.ListenConfig - NetDialer net.Dialer -} - -// NetListener returns a new Listener that listens on a socket using the net package. -func NetListener(ctx context.Context, network, address string, options NetListenOptions) (Listener, error) { - ln, err := options.NetListenConfig.Listen(ctx, network, address) - if err != nil { - return nil, err - } - return &netListener{net: ln}, nil -} - -// netListener is the implementation of Listener for connections made using the net package. -type netListener struct { - net net.Listener -} - -// Accept blocks waiting for an incoming connection to the listener. -func (l *netListener) Accept(context.Context) (io.ReadWriteCloser, error) { - return l.net.Accept() -} - -// Close will cause the listener to stop listening. It will not close any connections that have -// already been accepted. -func (l *netListener) Close() error { - addr := l.net.Addr() - err := l.net.Close() - if addr.Network() == "unix" { - rerr := os.Remove(addr.String()) - if rerr != nil && err == nil { - err = rerr - } - } - return err -} - -// Dialer returns a dialer that can be used to connect to the listener. -func (l *netListener) Dialer() Dialer { - return NetDialer(l.net.Addr().Network(), l.net.Addr().String(), net.Dialer{}) -} - -// NetDialer returns a Dialer using the supplied standard network dialer. -func NetDialer(network, address string, nd net.Dialer) Dialer { - return &netDialer{ - network: network, - address: address, - dialer: nd, - } -} - -type netDialer struct { - network string - address string - dialer net.Dialer -} - -func (n *netDialer) Dial(ctx context.Context) (io.ReadWriteCloser, error) { - return n.dialer.DialContext(ctx, n.network, n.address) -} - -// NetPipeListener returns a new Listener that listens using net.Pipe. -// It is only possibly to connect to it using the Dialer returned by the -// Dialer method, each call to that method will generate a new pipe the other -// side of which will be returned from the Accept call. -func NetPipeListener(ctx context.Context) (Listener, error) { - return &netPiper{ - done: make(chan struct{}), - dialed: make(chan io.ReadWriteCloser), - }, nil -} - -// netPiper is the implementation of Listener build on top of net.Pipes. -type netPiper struct { - done chan struct{} - dialed chan io.ReadWriteCloser -} - -// Accept blocks waiting for an incoming connection to the listener. -func (l *netPiper) Accept(context.Context) (io.ReadWriteCloser, error) { - // Block until the pipe is dialed or the listener is closed, - // preferring the latter if already closed at the start of Accept. - select { - case <-l.done: - return nil, net.ErrClosed - default: - } - select { - case rwc := <-l.dialed: - return rwc, nil - case <-l.done: - return nil, net.ErrClosed - } -} - -// Close will cause the listener to stop listening. It will not close any connections that have -// already been accepted. -func (l *netPiper) Close() error { - // unblock any accept calls that are pending - close(l.done) - return nil -} - -func (l *netPiper) Dialer() Dialer { - return l -} - -func (l *netPiper) Dial(ctx context.Context) (io.ReadWriteCloser, error) { - client, server := net.Pipe() - - select { - case l.dialed <- server: - return client, nil - - case <-l.done: - client.Close() - server.Close() - return nil, net.ErrClosed - } -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2/serve.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2/serve.go deleted file mode 100644 index 424163a..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2/serve.go +++ /dev/null @@ -1,330 +0,0 @@ -// Copyright 2020 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package jsonrpc2 - -import ( - "context" - "fmt" - "io" - "runtime" - "sync" - "sync/atomic" - "time" -) - -// Listener is implemented by protocols to accept new inbound connections. -type Listener interface { - // Accept accepts an inbound connection to a server. - // It blocks until either an inbound connection is made, or the listener is closed. - Accept(context.Context) (io.ReadWriteCloser, error) - - // Close closes the listener. - // Any blocked Accept or Dial operations will unblock and return errors. - Close() error - - // Dialer returns a dialer that can be used to connect to this listener - // locally. - // If a listener does not implement this it will return nil. - Dialer() Dialer -} - -// Dialer is used by clients to dial a server. -type Dialer interface { - // Dial returns a new communication byte stream to a listening server. - Dial(ctx context.Context) (io.ReadWriteCloser, error) -} - -// Server is a running server that is accepting incoming connections. -type Server struct { - listener Listener - binder Binder - async *async - - shutdownOnce sync.Once - closing int32 // atomic: set to nonzero when Shutdown is called -} - -// Dial uses the dialer to make a new connection, wraps the returned -// reader and writer using the framer to make a stream, and then builds -// a connection on top of that stream using the binder. -// -// The returned Connection will operate independently using the Preempter and/or -// Handler provided by the Binder, and will release its own resources when the -// connection is broken, but the caller may Close it earlier to stop accepting -// (or sending) new requests. -// -// If non-nil, the onDone function is called when the connection is closed. -func Dial(ctx context.Context, dialer Dialer, binder Binder, onDone func()) (*Connection, error) { - // dial a server - rwc, err := dialer.Dial(ctx) - if err != nil { - return nil, err - } - return bindConnection(ctx, rwc, binder, onDone), nil -} - -// NewServer starts a new server listening for incoming connections and returns -// it. -// This returns a fully running and connected server, it does not block on -// the listener. -// You can call Wait to block on the server, or Shutdown to get the sever to -// terminate gracefully. -// To notice incoming connections, use an intercepting Binder. -func NewServer(ctx context.Context, listener Listener, binder Binder) *Server { - server := &Server{ - listener: listener, - binder: binder, - async: newAsync(), - } - go server.run(ctx) - return server -} - -// Wait returns only when the server has shut down. -func (s *Server) Wait() error { - return s.async.wait() -} - -// Shutdown informs the server to stop accepting new connections. -func (s *Server) Shutdown() { - s.shutdownOnce.Do(func() { - atomic.StoreInt32(&s.closing, 1) - s.listener.Close() - }) -} - -// run accepts incoming connections from the listener, -// If IdleTimeout is non-zero, run exits after there are no clients for this -// duration, otherwise it exits only on error. -func (s *Server) run(ctx context.Context) { - defer s.async.done() - - var activeConns sync.WaitGroup - for { - rwc, err := s.listener.Accept(ctx) - if err != nil { - // Only Shutdown closes the listener. If we get an error after Shutdown is - // called, assume that was the cause and don't report the error; - // otherwise, report the error in case it is unexpected. - if atomic.LoadInt32(&s.closing) == 0 { - s.async.setError(err) - } - // We are done generating new connections for good. - break - } - - // A new inbound connection. - activeConns.Add(1) - _ = bindConnection(ctx, rwc, s.binder, activeConns.Done) // unregisters itself when done - } - activeConns.Wait() -} - -// NewIdleListener wraps a listener with an idle timeout. -// -// When there are no active connections for at least the timeout duration, -// calls to Accept will fail with ErrIdleTimeout. -// -// A connection is considered inactive as soon as its Close method is called. -func NewIdleListener(timeout time.Duration, wrap Listener) Listener { - l := &idleListener{ - wrapped: wrap, - timeout: timeout, - active: make(chan int, 1), - timedOut: make(chan struct{}), - idleTimer: make(chan *time.Timer, 1), - } - l.idleTimer <- time.AfterFunc(l.timeout, l.timerExpired) - return l -} - -type idleListener struct { - wrapped Listener - timeout time.Duration - - // Only one of these channels is receivable at any given time. - active chan int // count of active connections; closed when Close is called if not timed out - timedOut chan struct{} // closed when the idle timer expires - idleTimer chan *time.Timer // holds the timer only when idle -} - -// Accept accepts an incoming connection. -// -// If an incoming connection is accepted concurrent to the listener being closed -// due to idleness, the new connection is immediately closed. -func (l *idleListener) Accept(ctx context.Context) (io.ReadWriteCloser, error) { - rwc, err := l.wrapped.Accept(ctx) - - select { - case n, ok := <-l.active: - if err != nil { - if ok { - l.active <- n - } - return nil, err - } - if ok { - l.active <- n + 1 - } else { - // l.wrapped.Close Close has been called, but Accept returned a - // connection. This race can occur with concurrent Accept and Close calls - // with any net.Listener, and it is benign: since the listener was closed - // explicitly, it can't have also timed out. - } - return l.newConn(rwc), nil - - case <-l.timedOut: - if err == nil { - // Keeping the connection open would leave the listener simultaneously - // active and closed due to idleness, which would be contradictory and - // confusing. Close the connection and pretend that it never happened. - rwc.Close() - } else { - // In theory the timeout could have raced with an unrelated error return - // from Accept. However, ErrIdleTimeout is arguably still valid (since we - // would have closed due to the timeout independent of the error), and the - // harm from returning a spurious ErrIdleTimeout is negligible anyway. - } - return nil, ErrIdleTimeout - - case timer := <-l.idleTimer: - if err != nil { - // The idle timer doesn't run until it receives itself from the idleTimer - // channel, so it can't have called l.wrapped.Close yet and thus err can't - // be ErrIdleTimeout. Leave the idle timer as it was and return whatever - // error we got. - l.idleTimer <- timer - return nil, err - } - - if !timer.Stop() { - // Failed to stop the timer — the timer goroutine is in the process of - // firing. Send the timer back to the timer goroutine so that it can - // safely close the timedOut channel, and then wait for the listener to - // actually be closed before we return ErrIdleTimeout. - l.idleTimer <- timer - rwc.Close() - <-l.timedOut - return nil, ErrIdleTimeout - } - - l.active <- 1 - return l.newConn(rwc), nil - } -} - -func (l *idleListener) Close() error { - select { - case _, ok := <-l.active: - if ok { - close(l.active) - } - - case <-l.timedOut: - // Already closed by the timer; take care not to double-close if the caller - // only explicitly invokes this Close method once, since the io.Closer - // interface explicitly leaves doubled Close calls undefined. - return ErrIdleTimeout - - case timer := <-l.idleTimer: - if !timer.Stop() { - // Couldn't stop the timer. It shouldn't take long to run, so just wait - // (so that the Listener is guaranteed to be closed before we return) - // and pretend that this call happened afterward. - // That way we won't leak any timers or goroutines when Close returns. - l.idleTimer <- timer - <-l.timedOut - return ErrIdleTimeout - } - close(l.active) - } - - return l.wrapped.Close() -} - -func (l *idleListener) Dialer() Dialer { - return l.wrapped.Dialer() -} - -func (l *idleListener) timerExpired() { - select { - case n, ok := <-l.active: - if ok { - panic(fmt.Sprintf("jsonrpc2: idleListener idle timer fired with %d connections still active", n)) - } else { - panic("jsonrpc2: Close finished with idle timer still running") - } - - case <-l.timedOut: - panic("jsonrpc2: idleListener idle timer fired more than once") - - case <-l.idleTimer: - // The timer for this very call! - } - - // Close the Listener with all channels still blocked to ensure that this call - // to l.wrapped.Close doesn't race with the one in l.Close. - defer close(l.timedOut) - l.wrapped.Close() -} - -func (l *idleListener) connClosed() { - select { - case n, ok := <-l.active: - if !ok { - // l is already closed, so it can't close due to idleness, - // and we don't need to track the number of active connections any more. - return - } - n-- - if n == 0 { - l.idleTimer <- time.AfterFunc(l.timeout, l.timerExpired) - } else { - l.active <- n - } - - case <-l.timedOut: - panic("jsonrpc2: idleListener idle timer fired before last active connection was closed") - - case <-l.idleTimer: - panic("jsonrpc2: idleListener idle timer active before last active connection was closed") - } -} - -type idleListenerConn struct { - wrapped io.ReadWriteCloser - l *idleListener - closeOnce sync.Once -} - -func (l *idleListener) newConn(rwc io.ReadWriteCloser) *idleListenerConn { - c := &idleListenerConn{ - wrapped: rwc, - l: l, - } - - // A caller that forgets to call Close may disrupt the idleListener's - // accounting, even though the file descriptor for the underlying connection - // may eventually be garbage-collected anyway. - // - // Set a (best-effort) finalizer to verify that a Close call always occurs. - // (We will clear the finalizer explicitly in Close.) - runtime.SetFinalizer(c, func(c *idleListenerConn) { - panic("jsonrpc2: IdleListener connection became unreachable without a call to Close") - }) - - return c -} - -func (c *idleListenerConn) Read(p []byte) (int, error) { return c.wrapped.Read(p) } -func (c *idleListenerConn) Write(p []byte) (int, error) { return c.wrapped.Write(p) } - -func (c *idleListenerConn) Close() error { - defer c.closeOnce.Do(func() { - c.l.connClosed() - runtime.SetFinalizer(c, nil) - }) - return c.wrapped.Close() -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2/wire.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2/wire.go deleted file mode 100644 index c0a41bf..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2/wire.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2018 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package jsonrpc2 - -import ( - "encoding/json" -) - -// This file contains the go forms of the wire specification. -// see http://www.jsonrpc.org/specification for details - -var ( - // ErrParse is used when invalid JSON was received by the server. - ErrParse = NewError(-32700, "parse error") - // ErrInvalidRequest is used when the JSON sent is not a valid Request object. - ErrInvalidRequest = NewError(-32600, "invalid request") - // ErrMethodNotFound should be returned by the handler when the method does - // not exist / is not available. - ErrMethodNotFound = NewError(-32601, "method not found") - // ErrInvalidParams should be returned by the handler when method - // parameter(s) were invalid. - ErrInvalidParams = NewError(-32602, "invalid params") - // ErrInternal indicates a failure to process a call correctly - ErrInternal = NewError(-32603, "internal error") - - // The following errors are not part of the json specification, but - // compliant extensions specific to this implementation. - - // ErrServerOverloaded is returned when a message was refused due to a - // server being temporarily unable to accept any new messages. - ErrServerOverloaded = NewError(-32000, "overloaded") - // ErrUnknown should be used for all non coded errors. - ErrUnknown = NewError(-32001, "unknown error") - // ErrServerClosing is returned for calls that arrive while the server is closing. - ErrServerClosing = NewError(-32004, "server is closing") - // ErrClientClosing is a dummy error returned for calls initiated while the client is closing. - ErrClientClosing = NewError(-32003, "client is closing") - - // The following errors have special semantics for MCP transports - - // ErrRejected may be wrapped to return errors from calls to Writer.Write - // that signal that the request was rejected by the transport layer as - // invalid. - // - // Such failures do not indicate that the connection is broken, but rather - // should be returned to the caller to indicate that the specific request is - // invalid in the current context. - ErrRejected = NewError(-32005, "rejected by transport") -) - -const wireVersion = "2.0" - -// wireCombined has all the fields of both Request and Response. -// We can decode this and then work out which it is. -type wireCombined struct { - VersionTag string `json:"jsonrpc"` - ID any `json:"id,omitempty"` - Method string `json:"method,omitempty"` - Params json.RawMessage `json:"params,omitempty"` - Result json.RawMessage `json:"result,omitempty"` - Error *WireError `json:"error,omitempty"` -} - -// WireError represents a structured error in a Response. -type WireError struct { - // Code is an error code indicating the type of failure. - Code int64 `json:"code"` - // Message is a short description of the error. - Message string `json:"message"` - // Data is optional structured data containing additional information about the error. - Data json.RawMessage `json:"data,omitempty"` -} - -// NewError returns an error that will encode on the wire correctly. -// The standard codes are made available from this package, this function should -// only be used to build errors for application specific codes as allowed by the -// specification. -func NewError(code int64, message string) error { - return &WireError{ - Code: code, - Message: message, - } -} - -func (err *WireError) Error() string { - return err.Message -} - -func (err *WireError) Is(other error) bool { - w, ok := other.(*WireError) - if !ok { - return false - } - return err.Code == w.Code -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/mcpgodebug/mcpgodebug.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/mcpgodebug/mcpgodebug.go deleted file mode 100644 index 7f8f7ca..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/mcpgodebug/mcpgodebug.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by the license -// that can be found in the LICENSE file. - -// Package mcpgodebug provides a mechanism to configure compatibility parameters -// via the MCPGODEBUG environment variable. -// -// The value of MCPGODEBUG is a comma-separated list of key=value pairs. -// For example: -// -// MCPGODEBUG=someoption=1,otheroption=value -package mcpgodebug - -import ( - "fmt" - "os" - "strings" -) - -const compatibilityEnvKey = "MCPGODEBUG" - -var compatibilityParams map[string]string - -func init() { - var err error - compatibilityParams, err = parseCompatibility(os.Getenv(compatibilityEnvKey)) - if err != nil { - panic(err) - } -} - -// Value returns the value of the compatibility parameter with the given key. -// It returns an empty string if the key is not set. -func Value(key string) string { - return compatibilityParams[key] -} - -func parseCompatibility(envValue string) (map[string]string, error) { - if envValue == "" { - return nil, nil - } - - params := make(map[string]string) - for part := range strings.SplitSeq(envValue, ",") { - k, v, ok := strings.Cut(part, "=") - if !ok { - return nil, fmt.Errorf("MCPGODEBUG: invalid format: %q", part) - } - params[strings.TrimSpace(k)] = strings.TrimSpace(v) - } - return params, nil -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/util/net.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/util/net.go deleted file mode 100644 index 6858614..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/util/net.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by the license -// that can be found in the LICENSE file. -package util - -import ( - "net" - "net/netip" - "strings" -) - -func IsLoopback(addr string) bool { - host, _, err := net.SplitHostPort(addr) - if err != nil { - // If SplitHostPort fails, it might be just a host without a port. - host = strings.Trim(addr, "[]") - } - if host == "localhost" { - return true - } - ip, err := netip.ParseAddr(host) - if err != nil { - return false - } - return ip.IsLoopback() -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/util/util.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/util/util.go deleted file mode 100644 index 4b5c325..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/util/util.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package util - -import ( - "cmp" - "fmt" - "iter" - "slices" -) - -// Helpers below are copied from gopls' moremaps package. - -// Sorted returns an iterator over the entries of m in key order. -func Sorted[M ~map[K]V, K cmp.Ordered, V any](m M) iter.Seq2[K, V] { - // TODO(adonovan): use maps.Sorted if proposal #68598 is accepted. - return func(yield func(K, V) bool) { - keys := KeySlice(m) - slices.Sort(keys) - for _, k := range keys { - if !yield(k, m[k]) { - break - } - } - } -} - -// KeySlice returns the keys of the map M, like slices.Collect(maps.Keys(m)). -func KeySlice[M ~map[K]V, K comparable, V any](m M) []K { - r := make([]K, 0, len(m)) - for k := range m { - r = append(r, k) - } - return r -} - -// Wrapf wraps *errp with the given formatted message if *errp is not nil. -func Wrapf(errp *error, format string, args ...any) { - if *errp != nil { - *errp = fmt.Errorf("%s: %w", fmt.Sprintf(format, args...), *errp) - } -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/xcontext/xcontext.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/xcontext/xcontext.go deleted file mode 100644 index 849060d..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/internal/xcontext/xcontext.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2019 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// Package xcontext is a package to offer the extra functionality we need -// from contexts that is not available from the standard context package. -package xcontext - -import ( - "context" - "time" -) - -// Detach returns a context that keeps all the values of its parent context -// but detaches from the cancellation and error handling. -func Detach(ctx context.Context) context.Context { return detachedContext{ctx} } - -type detachedContext struct{ parent context.Context } - -func (v detachedContext) Deadline() (time.Time, bool) { return time.Time{}, false } -func (v detachedContext) Done() <-chan struct{} { return nil } -func (v detachedContext) Err() error { return nil } -func (v detachedContext) Value(key any) any { return v.parent.Value(key) } diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/jsonrpc/jsonrpc.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/jsonrpc/jsonrpc.go deleted file mode 100644 index a9ea78f..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/jsonrpc/jsonrpc.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// Package jsonrpc exposes part of a JSON-RPC v2 implementation -// for use by mcp transport authors. -package jsonrpc - -import "github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2" - -type ( - // ID is a JSON-RPC request ID. - ID = jsonrpc2.ID - // Message is a JSON-RPC message. - Message = jsonrpc2.Message - // Request is a JSON-RPC request. - Request = jsonrpc2.Request - // Response is a JSON-RPC response. - Response = jsonrpc2.Response - // Error is a structured error in a JSON-RPC response. - Error = jsonrpc2.WireError -) - -// MakeID coerces the given Go value to an ID. The value should be the -// default JSON marshaling of a Request identifier: nil, float64, or string. -// -// Returns an error if the value type was not a valid Request ID type. -func MakeID(v any) (ID, error) { - return jsonrpc2.MakeID(v) -} - -// EncodeMessage serializes a JSON-RPC message to its wire format. -func EncodeMessage(msg Message) ([]byte, error) { - return jsonrpc2.EncodeMessage(msg) -} - -// DecodeMessage deserializes JSON-RPC wire format data into a Message. -// It returns either a Request or Response based on the message content. -func DecodeMessage(data []byte) (Message, error) { - return jsonrpc2.DecodeMessage(data) -} - -// Standard JSON-RPC 2.0 error codes. -// See https://www.jsonrpc.org/specification#error_object -const ( - // CodeParseError indicates invalid JSON was received by the server. - CodeParseError = -32700 - // CodeInvalidRequest indicates the JSON sent is not a valid Request object. - CodeInvalidRequest = -32600 - // CodeMethodNotFound indicates the method does not exist or is not available. - CodeMethodNotFound = -32601 - // CodeInvalidParams indicates invalid method parameter(s). - CodeInvalidParams = -32602 - // CodeInternalError indicates an internal JSON-RPC error. - CodeInternalError = -32603 -) diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/client.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/client.go deleted file mode 100644 index f3b4c2a..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/client.go +++ /dev/null @@ -1,1191 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package mcp - -import ( - "context" - "errors" - "fmt" - "iter" - "log/slog" - "slices" - "strings" - "sync" - "sync/atomic" - "time" - - "github.com/google/jsonschema-go/jsonschema" - "github.com/modelcontextprotocol/go-sdk/internal/json" - "github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2" - "github.com/modelcontextprotocol/go-sdk/jsonrpc" -) - -// A Client is an MCP client, which may be connected to an MCP server -// using the [Client.Connect] method. -type Client struct { - impl *Implementation - opts ClientOptions - mu sync.Mutex - roots *featureSet[*Root] - sessions []*ClientSession - sendingMethodHandler_ MethodHandler - receivingMethodHandler_ MethodHandler -} - -// NewClient creates a new [Client]. -// -// Use [Client.Connect] to connect it to an MCP server. -// -// The first argument must not be nil. -// -// If non-nil, the provided options configure the Client. -func NewClient(impl *Implementation, options *ClientOptions) *Client { - if impl == nil { - panic("nil Implementation") - } - var opts ClientOptions - if options != nil { - opts = *options - } - options = nil // prevent reuse - - if opts.CreateMessageHandler != nil && opts.CreateMessageWithToolsHandler != nil { - panic("cannot set both CreateMessageHandler and CreateMessageWithToolsHandler; use CreateMessageWithToolsHandler for tool support, or CreateMessageHandler for basic sampling") - } - if opts.Logger == nil { // ensure we have a logger - opts.Logger = ensureLogger(nil) - } - - return &Client{ - impl: impl, - opts: opts, - roots: newFeatureSet(func(r *Root) string { return r.URI }), - sendingMethodHandler_: defaultSendingMethodHandler, - receivingMethodHandler_: defaultReceivingMethodHandler[*ClientSession], - } -} - -// ClientOptions configures the behavior of the client. -type ClientOptions struct { - // Logger may be set to a non-nil value to enable logging of client activity. - Logger *slog.Logger - // CreateMessageHandler handles incoming requests for sampling/createMessage. - // - // Setting CreateMessageHandler to a non-nil value automatically causes the - // client to advertise the sampling capability, with default value - // &SamplingCapabilities{}. If [ClientOptions.Capabilities] is set and has a - // non nil value for [ClientCapabilities.Sampling], that value overrides the - // inferred capability. - CreateMessageHandler func(context.Context, *CreateMessageRequest) (*CreateMessageResult, error) - // CreateMessageWithToolsHandler handles incoming sampling/createMessage - // requests that may involve tool use. It returns - // [CreateMessageWithToolsResult], which supports array content for parallel - // tool calls. - // - // Setting this handler causes the client to advertise the sampling - // capability with tools support (sampling.tools). As with - // [CreateMessageHandler], [ClientOptions.Capabilities].Sampling overrides - // the inferred capability. - // - // It is a panic to set both CreateMessageHandler and - // CreateMessageWithToolsHandler. - CreateMessageWithToolsHandler func(context.Context, *CreateMessageWithToolsRequest) (*CreateMessageWithToolsResult, error) - // ElicitationHandler handles incoming requests for elicitation/create. - // - // Setting ElicitationHandler to a non-nil value automatically causes the - // client to advertise the elicitation capability, with default value - // &ElicitationCapabilities{}. If [ClientOptions.Capabilities] is set and has - // a non nil value for [ClientCapabilities.ELicitattion], that value - // overrides the inferred capability. - ElicitationHandler func(context.Context, *ElicitRequest) (*ElicitResult, error) - // Capabilities optionally configures the client's default capabilities, - // before any capabilities are inferred from other configuration. - // - // If Capabilities is nil, the default client capabilities are - // {"roots":{"listChanged":true}}, for historical reasons. Setting - // Capabilities to a non-nil value overrides this default. As a special case, - // to work around #607, Capabilities.Roots is ignored: set - // Capabilities.RootsV2 to configure the roots capability. This allows the - // "roots" capability to be disabled entirely. - // - // For example: - // - To disable the "roots" capability, use &ClientCapabilities{} - // - To configure "roots", but disable "listChanged" notifications, use - // &ClientCapabilities{RootsV2:&RootCapabilities{}}. - // - // # Interaction with capability inference - // - // Sampling and elicitation capabilities are automatically added when their - // corresponding handlers are set, with the default value described at - // [ClientOptions.CreateMessageHandler] and - // [ClientOptions.ElicitationHandler]. If the Sampling or Elicitation fields - // are set in the Capabilities field, their values override the inferred - // value. - // - // For example, to advertise sampling with tools and context support: - // - // Capabilities: &ClientCapabilities{ - // Sampling: &SamplingCapabilities{ - // Tools: &SamplingToolsCapabilities{}, - // Context: &SamplingContextCapabilities{}, - // }, - // } - // - // Or to configure elicitation modes: - // - // Capabilities: &ClientCapabilities{ - // Elicitation: &ElicitationCapabilities{ - // Form: &FormElicitationCapabilities{}, - // URL: &URLElicitationCapabilities{}, - // }, - // } - // - // Conversely, if Capabilities does not set a field (for example, if the - // Elicitation field is nil), the inferred capability will be used. - Capabilities *ClientCapabilities - // ElicitationCompleteHandler handles incoming notifications for notifications/elicitation/complete. - ElicitationCompleteHandler func(context.Context, *ElicitationCompleteNotificationRequest) - // Handlers for notifications from the server. - ToolListChangedHandler func(context.Context, *ToolListChangedRequest) - PromptListChangedHandler func(context.Context, *PromptListChangedRequest) - ResourceListChangedHandler func(context.Context, *ResourceListChangedRequest) - ResourceUpdatedHandler func(context.Context, *ResourceUpdatedNotificationRequest) - LoggingMessageHandler func(context.Context, *LoggingMessageRequest) - ProgressNotificationHandler func(context.Context, *ProgressNotificationClientRequest) - // If non-zero, defines an interval for regular "ping" requests. - // If the peer fails to respond to pings originating from the keepalive check, - // the session is automatically closed. - KeepAlive time.Duration -} - -// bind implements the binder[*ClientSession] interface, so that Clients can -// be connected using [connect]. -func (c *Client) bind(mcpConn Connection, conn *jsonrpc2.Connection, state *clientSessionState, onClose func()) *ClientSession { - assert(mcpConn != nil && conn != nil, "nil connection") - cs := &ClientSession{conn: conn, mcpConn: mcpConn, client: c, onClose: onClose} - if state != nil { - cs.state = *state - } - c.mu.Lock() - defer c.mu.Unlock() - c.sessions = append(c.sessions, cs) - return cs -} - -// disconnect implements the binder[*Client] interface, so that -// Clients can be connected using [connect]. -func (c *Client) disconnect(cs *ClientSession) { - c.mu.Lock() - defer c.mu.Unlock() - c.sessions = slices.DeleteFunc(c.sessions, func(cs2 *ClientSession) bool { - return cs2 == cs - }) -} - -// TODO: Consider exporting this type and its field. -type unsupportedProtocolVersionError struct { - version string -} - -func (e unsupportedProtocolVersionError) Error() string { - return fmt.Sprintf("unsupported protocol version: %q", e.version) -} - -// ClientSessionOptions is reserved for future use. -type ClientSessionOptions struct { - // protocolVersion overrides the protocol version sent in the initialize - // request, for testing. If empty, latestProtocolVersion is used. - protocolVersion string -} - -func (c *Client) capabilities(protocolVersion string) *ClientCapabilities { - // Start with user-provided capabilities as defaults, or use SDK defaults. - var caps *ClientCapabilities - if c.opts.Capabilities != nil { - // Deep copy the user-provided capabilities to avoid mutation. - caps = c.opts.Capabilities.clone() - } else { - // SDK defaults: roots with listChanged. - // (this was the default behavior at v1.0.0, and so cannot be changed) - caps = &ClientCapabilities{ - RootsV2: &RootCapabilities{ - ListChanged: true, - }, - } - } - - // Sync Roots from RootsV2 for backward compatibility (#607). - if caps.RootsV2 != nil { - caps.Roots = *caps.RootsV2 - } - - // Augment with sampling capability if a handler is set. - if c.opts.CreateMessageHandler != nil || c.opts.CreateMessageWithToolsHandler != nil { - if caps.Sampling == nil { - caps.Sampling = &SamplingCapabilities{} - if c.opts.CreateMessageWithToolsHandler != nil { - caps.Sampling.Tools = &SamplingToolsCapabilities{} - } - } - } - - // Augment with elicitation capability if handler is set. - if c.opts.ElicitationHandler != nil { - if caps.Elicitation == nil { - caps.Elicitation = &ElicitationCapabilities{} - // Form elicitation was added in 2025-11-25; for older versions, - // {} is treated the same as {"form":{}}. - if protocolVersion >= protocolVersion20251125 { - caps.Elicitation.Form = &FormElicitationCapabilities{} - } - } - } - return caps -} - -// Connect begins an MCP session by connecting to a server over the given -// transport. The resulting session is initialized, and ready to use. -// -// Typically, it is the responsibility of the client to close the connection -// when it is no longer needed. However, if the connection is closed by the -// server, calls or notifications will return an error wrapping -// [ErrConnectionClosed]. -func (c *Client) Connect(ctx context.Context, t Transport, opts *ClientSessionOptions) (cs *ClientSession, err error) { - cs, err = connect(ctx, t, c, (*clientSessionState)(nil), nil) - if err != nil { - return nil, err - } - - protocolVersion := latestProtocolVersion - if opts != nil && opts.protocolVersion != "" { - protocolVersion = opts.protocolVersion - } - params := &InitializeParams{ - ProtocolVersion: protocolVersion, - ClientInfo: c.impl, - Capabilities: c.capabilities(protocolVersion), - } - req := &InitializeRequest{Session: cs, Params: params} - res, err := handleSend[*InitializeResult](ctx, methodInitialize, req) - if err != nil { - _ = cs.Close() - return nil, err - } - if !slices.Contains(supportedProtocolVersions, res.ProtocolVersion) { - return nil, unsupportedProtocolVersionError{res.ProtocolVersion} - } - cs.state.InitializeResult = res - if hc, ok := cs.mcpConn.(clientConnection); ok { - hc.sessionUpdated(cs.state) - } - req2 := &initializedClientRequest{Session: cs, Params: &InitializedParams{}} - if err := handleNotify(ctx, notificationInitialized, req2); err != nil { - _ = cs.Close() - return nil, err - } - - if c.opts.KeepAlive > 0 { - cs.startKeepalive(c.opts.KeepAlive) - } - - return cs, nil -} - -// A ClientSession is a logical connection with an MCP server. Its -// methods can be used to send requests or notifications to the server. Create -// a session by calling [Client.Connect]. -// -// Call [ClientSession.Close] to close the connection, or await server -// termination with [ClientSession.Wait]. -type ClientSession struct { - // Ensure that onClose is called at most once. - // We defensively use an atomic CompareAndSwap rather than a sync.Once, in case the - // onClose callback triggers a re-entrant call to Close. - calledOnClose atomic.Bool - onClose func() - - conn *jsonrpc2.Connection - client *Client - keepaliveCancel context.CancelFunc - mcpConn Connection - - // No mutex is (currently) required to guard the session state, because it is - // only set synchronously during Client.Connect. - state clientSessionState - - // Pending URL elicitations waiting for completion notifications. - pendingElicitationsMu sync.Mutex - pendingElicitations map[string]chan struct{} -} - -type clientSessionState struct { - InitializeResult *InitializeResult -} - -func (cs *ClientSession) InitializeResult() *InitializeResult { return cs.state.InitializeResult } - -func (cs *ClientSession) ID() string { - if c, ok := cs.mcpConn.(hasSessionID); ok { - return c.SessionID() - } - return "" -} - -// Close performs a graceful close of the connection, preventing new requests -// from being handled, and waiting for ongoing requests to return. Close then -// terminates the connection. -// -// Close is idempotent and concurrency safe. -func (cs *ClientSession) Close() error { - // Note: keepaliveCancel access is safe without a mutex because: - // 1. keepaliveCancel is only written once during startKeepalive (happens-before all Close calls) - // 2. context.CancelFunc is safe to call multiple times and from multiple goroutines - // 3. The keepalive goroutine calls Close on ping failure, but this is safe since - // Close is idempotent and conn.Close() handles concurrent calls correctly - if cs.keepaliveCancel != nil { - cs.keepaliveCancel() - } - err := cs.conn.Close() - - if cs.onClose != nil && cs.calledOnClose.CompareAndSwap(false, true) { - cs.onClose() - } - - return err -} - -// Wait waits for the connection to be closed by the server. -// Generally, clients should be responsible for closing the connection. -func (cs *ClientSession) Wait() error { - return cs.conn.Wait() -} - -// registerElicitationWaiter registers a waiter for an elicitation complete -// notification with the given elicitation ID. It returns two functions: an await -// function that waits for the notification or context cancellation, and a cleanup -// function that must be called to unregister the waiter. This must be called before -// triggering the elicitation to avoid a race condition where the notification -// arrives before the waiter is registered. -// -// The cleanup function must be called even if the await function is never called, -// to prevent leaking the registration. -func (cs *ClientSession) registerElicitationWaiter(elicitationID string) (await func(context.Context) error, cleanup func()) { - // Create a channel for this elicitation. - ch := make(chan struct{}, 1) - - // Register the channel. - cs.pendingElicitationsMu.Lock() - if cs.pendingElicitations == nil { - cs.pendingElicitations = make(map[string]chan struct{}) - } - cs.pendingElicitations[elicitationID] = ch - cs.pendingElicitationsMu.Unlock() - - // Return await and cleanup functions. - await = func(ctx context.Context) error { - select { - case <-ctx.Done(): - return fmt.Errorf("context cancelled while waiting for elicitation completion: %w", ctx.Err()) - case <-ch: - return nil - } - } - - cleanup = func() { - cs.pendingElicitationsMu.Lock() - delete(cs.pendingElicitations, elicitationID) - cs.pendingElicitationsMu.Unlock() - } - - return await, cleanup -} - -// startKeepalive starts the keepalive mechanism for this client session. -func (cs *ClientSession) startKeepalive(interval time.Duration) { - startKeepalive(cs, interval, &cs.keepaliveCancel) -} - -// AddRoots adds the given roots to the client, -// replacing any with the same URIs, -// and notifies any connected servers. -func (c *Client) AddRoots(roots ...*Root) { - // Only notify if something could change. - if len(roots) == 0 { - return - } - changeAndNotify(c, notificationRootsListChanged, &RootsListChangedParams{}, - func() bool { c.roots.add(roots...); return true }) -} - -// RemoveRoots removes the roots with the given URIs, -// and notifies any connected servers if the list has changed. -// It is not an error to remove a nonexistent root. -func (c *Client) RemoveRoots(uris ...string) { - changeAndNotify(c, notificationRootsListChanged, &RootsListChangedParams{}, - func() bool { return c.roots.remove(uris...) }) -} - -// changeAndNotify is called when a feature is added or removed. -// It calls change, which should do the work and report whether a change actually occurred. -// If there was a change, it notifies a snapshot of the sessions. -func changeAndNotify[P Params](c *Client, notification string, params P, change func() bool) { - var sessions []*ClientSession - // Lock for the change, but not for the notification. - c.mu.Lock() - if change() { - // Check if listChanged is enabled for this notification type. - if c.shouldSendListChangedNotification(notification) { - sessions = slices.Clone(c.sessions) - } - } - c.mu.Unlock() - notifySessions(sessions, notification, params, c.opts.Logger) -} - -// shouldSendListChangedNotification checks if the client's capabilities allow -// sending the given list-changed notification. -func (c *Client) shouldSendListChangedNotification(notification string) bool { - // Get effective capabilities (considering user-provided defaults). - caps := c.opts.Capabilities - - switch notification { - case notificationRootsListChanged: - // If user didn't specify capabilities, default behavior sends notifications. - if caps == nil { - return true - } - // Check RootsV2 first (preferred), then fall back to Roots. - if caps.RootsV2 != nil { - return caps.RootsV2.ListChanged - } - return caps.Roots.ListChanged - default: - // Unknown notification, allow by default. - return true - } -} - -func (c *Client) listRoots(_ context.Context, req *ListRootsRequest) (*ListRootsResult, error) { - c.mu.Lock() - defer c.mu.Unlock() - roots := slices.Collect(c.roots.all()) - if roots == nil { - roots = []*Root{} // avoid JSON null - } - return &ListRootsResult{ - Roots: roots, - }, nil -} - -func (c *Client) createMessage(ctx context.Context, req *CreateMessageWithToolsRequest) (*CreateMessageWithToolsResult, error) { - if c.opts.CreateMessageWithToolsHandler != nil { - return c.opts.CreateMessageWithToolsHandler(ctx, req) - } - if c.opts.CreateMessageHandler != nil { - // Downconvert the request for the basic handler. - baseParams, err := req.Params.toBase() - if err != nil { - return nil, err - } - baseReq := &CreateMessageRequest{ - Session: req.Session, - Params: baseParams, - } - res, err := c.opts.CreateMessageHandler(ctx, baseReq) - if err != nil { - return nil, err - } - return res.toWithTools(), nil - } - return nil, &jsonrpc.Error{Code: codeUnsupportedMethod, Message: "client does not support CreateMessage"} -} - -// urlElicitationMiddleware returns middleware that automatically handles URL elicitation -// required errors by executing the elicitation handler, waiting for completion notifications, -// and retrying the operation. -// -// This middleware should be added to clients that want automatic URL elicitation handling: -// -// client := mcp.NewClient(impl, opts) -// client.AddSendingMiddleware(mcp.urlElicitationMiddleware()) -// -// TODO(rfindley): this isn't strictly necessary for the SEP, but may be -// useful. Propose exporting it. -func urlElicitationMiddleware() Middleware { - return func(next MethodHandler) MethodHandler { - return func(ctx context.Context, method string, req Request) (Result, error) { - // Call the underlying handler. - res, err := next(ctx, method, req) - if err == nil { - return res, nil - } - - // Check if this is a URL elicitation required error. - var rpcErr *jsonrpc.Error - if !errors.As(err, &rpcErr) || rpcErr.Code != CodeURLElicitationRequired { - return res, err - } - - // Notifications don't support retries. - if strings.HasPrefix(method, "notifications/") { - return res, err - } - - // Extract the client session. - cs, ok := req.GetSession().(*ClientSession) - if !ok { - return res, err - } - - // Check if the client has an elicitation handler. - if cs.client.opts.ElicitationHandler == nil { - return res, err - } - - // Parse the elicitations from the error data. - var errorData struct { - Elicitations []*ElicitParams `json:"elicitations"` - } - if rpcErr.Data != nil { - if err := json.Unmarshal(rpcErr.Data, &errorData); err != nil { - return nil, fmt.Errorf("failed to parse URL elicitation error data: %w", err) - } - } - - // Validate that all elicitations are URL mode. - for _, elicit := range errorData.Elicitations { - mode := elicit.Mode - if mode == "" { - mode = "form" // Default mode. - } - if mode != "url" { - return nil, fmt.Errorf("URLElicitationRequired error must only contain URL mode elicitations, got %q", mode) - } - } - - // Register waiters for all elicitations before executing handlers - // to avoid race condition where notification arrives before waiter is registered. - type waiter struct { - await func(context.Context) error - cleanup func() - } - waiters := make([]waiter, 0, len(errorData.Elicitations)) - for _, elicitParams := range errorData.Elicitations { - await, cleanup := cs.registerElicitationWaiter(elicitParams.ElicitationID) - waiters = append(waiters, waiter{await: await, cleanup: cleanup}) - } - - // Ensure cleanup happens even if we return early. - defer func() { - for _, w := range waiters { - w.cleanup() - } - }() - - // Execute the elicitation handler for each elicitation. - for _, elicitParams := range errorData.Elicitations { - elicitReq := newClientRequest(cs, elicitParams) - _, elicitErr := cs.client.elicit(ctx, elicitReq) - if elicitErr != nil { - return nil, fmt.Errorf("URL elicitation failed: %w", elicitErr) - } - } - - // Wait for all elicitations to complete. - for _, w := range waiters { - if err := w.await(ctx); err != nil { - return nil, err - } - } - - // All elicitations complete, retry the original operation. - return next(ctx, method, req) - } - } -} - -func (c *Client) elicit(ctx context.Context, req *ElicitRequest) (*ElicitResult, error) { - if c.opts.ElicitationHandler == nil { - return nil, &jsonrpc.Error{Code: jsonrpc.CodeInvalidParams, Message: "client does not support elicitation"} - } - - // Validate the elicitation parameters based on the mode. - mode := req.Params.Mode - if mode == "" { - mode = "form" - } - - switch mode { - case "form": - if req.Params.URL != "" { - return nil, &jsonrpc.Error{Code: jsonrpc.CodeInvalidParams, Message: "URL must not be set for form elicitation"} - } - schema, err := validateElicitSchema(req.Params.RequestedSchema) - if err != nil { - return nil, &jsonrpc.Error{Code: jsonrpc.CodeInvalidParams, Message: err.Error()} - } - res, err := c.opts.ElicitationHandler(ctx, req) - if err != nil { - return nil, err - } - // Validate elicitation result content against requested schema. - if res.Action == "accept" && schema != nil && res.Content != nil { - resolved, err := schema.Resolve(nil) - if err != nil { - return nil, &jsonrpc.Error{Code: jsonrpc.CodeInvalidParams, Message: fmt.Sprintf("failed to resolve requested schema: %v", err)} - } - if err := resolved.Validate(res.Content); err != nil { - return nil, &jsonrpc.Error{Code: jsonrpc.CodeInvalidParams, Message: fmt.Sprintf("elicitation result content does not match requested schema: %v", err)} - } - err = resolved.ApplyDefaults(&res.Content) - if err != nil { - return nil, &jsonrpc.Error{Code: jsonrpc.CodeInvalidParams, Message: fmt.Sprintf("failed to apply schema defalts to elicitation result: %v", err)} - } - } - return res, nil - case "url": - if req.Params.RequestedSchema != nil { - return nil, &jsonrpc.Error{Code: jsonrpc.CodeInvalidParams, Message: "requestedSchema must not be set for URL elicitation"} - } - if req.Params.URL == "" { - return nil, &jsonrpc.Error{Code: jsonrpc.CodeInvalidParams, Message: "URL must be set for URL elicitation"} - } - // No schema validation for URL mode, just pass through to handler. - return c.opts.ElicitationHandler(ctx, req) - default: - return nil, &jsonrpc.Error{Code: jsonrpc.CodeInvalidParams, Message: fmt.Sprintf("unsupported elicitation mode: %q", mode)} - } -} - -// validateElicitSchema validates that the schema conforms to MCP elicitation schema requirements. -// Per the MCP specification, elicitation schemas are limited to flat objects with primitive properties only. -func validateElicitSchema(wireSchema any) (*jsonschema.Schema, error) { - if wireSchema == nil { - return nil, nil // nil schema is allowed - } - - var schema *jsonschema.Schema - if err := remarshal(wireSchema, &schema); err != nil { - return nil, err - } - if schema == nil { - return nil, nil - } - - // The root schema must be of type "object" if specified - if schema.Type != "" && schema.Type != "object" { - return nil, fmt.Errorf("elicit schema must be of type 'object', got %q", schema.Type) - } - - // Check if the schema has properties - if schema.Properties != nil { - for propName, propSchema := range schema.Properties { - if propSchema == nil { - continue - } - - if err := validateElicitProperty(propName, propSchema); err != nil { - return nil, err - } - } - } - - return schema, nil -} - -// validateElicitProperty validates a single property in an elicitation schema. -func validateElicitProperty(propName string, propSchema *jsonschema.Schema) error { - // Check if this property has nested properties (not allowed) - if len(propSchema.Properties) > 0 { - return fmt.Errorf("elicit schema property %q contains nested properties, only primitive properties are allowed", propName) - } - // Validate based on the property type - only primitives are supported - switch propSchema.Type { - case "string": - return validateElicitStringProperty(propName, propSchema) - case "number", "integer": - return validateElicitNumberProperty(propName, propSchema) - case "boolean": - return validateElicitBooleanProperty(propName, propSchema) - case "array": - return validateElicitArrayProperty(propName, propSchema) - default: - return fmt.Errorf("elicit schema property %q has unsupported type %q, only string, number, integer, boolean, and array are allowed", propName, propSchema.Type) - } -} - -// validateElicitStringProperty validates string-type properties, including enums. -func validateElicitStringProperty(propName string, propSchema *jsonschema.Schema) error { - // Handle enum validation (enums are a special case of strings) - if len(propSchema.Enum) > 0 { - // Enums must be string type (or untyped which defaults to string) - if propSchema.Type != "" && propSchema.Type != "string" { - return fmt.Errorf("elicit schema property %q has enum values but type is %q, enums are only supported for string type", propName, propSchema.Type) - } - // Enum values themselves are validated by the JSON schema library - // Validate legacy enumNames if present - must match enum length. - if propSchema.Extra != nil { - if enumNamesRaw, exists := propSchema.Extra["enumNames"]; exists { - // Type check enumNames - should be a slice - if enumNamesSlice, ok := enumNamesRaw.([]any); ok { - if len(enumNamesSlice) != len(propSchema.Enum) { - return fmt.Errorf("elicit schema property %q has %d enum values but %d enumNames, they must match", propName, len(propSchema.Enum), len(enumNamesSlice)) - } - } else { - return fmt.Errorf("elicit schema property %q has invalid enumNames type, must be an array", propName) - } - } - } - return nil - } - // Handle new style of titled enums. - if propSchema.OneOf != nil { - for _, entry := range propSchema.OneOf { - if err := validateTitledEnumEntry(entry); err != nil { - return fmt.Errorf("elicit schema property %q oneOf has invalid entry: %v", propName, err) - } - } - return nil - } - - // Validate format if specified - only specific formats are allowed - if propSchema.Format != "" { - allowedFormats := map[string]bool{ - "email": true, - "uri": true, - "date": true, - "date-time": true, - } - if !allowedFormats[propSchema.Format] { - return fmt.Errorf("elicit schema property %q has unsupported format %q, only email, uri, date, and date-time are allowed", propName, propSchema.Format) - } - } - - // Validate minLength constraint if specified - if propSchema.MinLength != nil { - if *propSchema.MinLength < 0 { - return fmt.Errorf("elicit schema property %q has invalid minLength %d, must be non-negative", propName, *propSchema.MinLength) - } - } - - // Validate maxLength constraint if specified - if propSchema.MaxLength != nil { - if *propSchema.MaxLength < 0 { - return fmt.Errorf("elicit schema property %q has invalid maxLength %d, must be non-negative", propName, *propSchema.MaxLength) - } - // Check that maxLength >= minLength if both are specified - if propSchema.MinLength != nil && *propSchema.MaxLength < *propSchema.MinLength { - return fmt.Errorf("elicit schema property %q has maxLength %d less than minLength %d", propName, *propSchema.MaxLength, *propSchema.MinLength) - } - } - - return validateDefaultProperty[string](propName, propSchema) -} - -// validateElicitNumberProperty validates number and integer-type properties. -func validateElicitNumberProperty(propName string, propSchema *jsonschema.Schema) error { - if propSchema.Minimum != nil && propSchema.Maximum != nil { - if *propSchema.Maximum < *propSchema.Minimum { - return fmt.Errorf("elicit schema property %q has maximum %g less than minimum %g", propName, *propSchema.Maximum, *propSchema.Minimum) - } - } - - intDefaultError := validateDefaultProperty[int](propName, propSchema) - floatDefaultError := validateDefaultProperty[float64](propName, propSchema) - if intDefaultError != nil && floatDefaultError != nil { - return fmt.Errorf("elicit schema property %q has default value that cannot be interpreted as an int or float", propName) - } - - return nil -} - -// validateElicitArrayProperty validates multi-select enum properties. -func validateElicitArrayProperty(propName string, propSchema *jsonschema.Schema) error { - if propSchema.Items == nil { - return fmt.Errorf("elicit schema property %q is array but missing 'items' definition", propName) - } - - items := propSchema.Items - switch items.Type { - case "string": - // Untitled enums. - if items.Enum == nil { - return fmt.Errorf("elicit schema property %q items must specify enum for untitled enums", propName) - } - return nil - case "": - // Titled enums. - if len(items.AnyOf) == 0 { - return fmt.Errorf("elicit schema property %q items must specify anyOf for titled enums", propName) - } - for _, entry := range items.AnyOf { - if err := validateTitledEnumEntry(entry); err != nil { - return fmt.Errorf("elicit schema property %q items has invalid entry: %v", propName, err) - } - } - return nil - default: - return fmt.Errorf("elicit schema property %q items have unsupported type %q", propName, items.Type) - } -} - -func validateTitledEnumEntry(entry *jsonschema.Schema) error { - if entry.Const == nil { - return fmt.Errorf("const is required for titled enum entries") - } - constVal, ok := (*entry.Const).(string) - if !ok { - return fmt.Errorf("const must be a string for titled enum entries") - } - if constVal == "" { - return fmt.Errorf("const cannot be empty for titled enum entries") - } - if entry.Title == "" { - return fmt.Errorf("title is required for titled enum entries") - } - return nil -} - -// validateElicitBooleanProperty validates boolean-type properties. -func validateElicitBooleanProperty(propName string, propSchema *jsonschema.Schema) error { - return validateDefaultProperty[bool](propName, propSchema) -} - -func validateDefaultProperty[T any](propName string, propSchema *jsonschema.Schema) error { - // Validate default value if specified - must be a valid T - if propSchema.Default != nil { - var defaultValue T - if err := json.Unmarshal(propSchema.Default, &defaultValue); err != nil { - return fmt.Errorf("elicit schema property %q has invalid default value, must be a %T: %v", propName, defaultValue, err) - } - } - return nil -} - -// AddSendingMiddleware wraps the current sending method handler using the provided -// middleware. Middleware is applied from right to left, so that the first one is -// executed first. -// -// For example, AddSendingMiddleware(m1, m2, m3) augments the method handler as -// m1(m2(m3(handler))). -// -// Sending middleware is called when a request is sent. It is useful for tasks -// such as tracing, metrics, and adding progress tokens. -func (c *Client) AddSendingMiddleware(middleware ...Middleware) { - c.mu.Lock() - defer c.mu.Unlock() - addMiddleware(&c.sendingMethodHandler_, middleware) -} - -// AddReceivingMiddleware wraps the current receiving method handler using -// the provided middleware. Middleware is applied from right to left, so that the -// first one is executed first. -// -// For example, AddReceivingMiddleware(m1, m2, m3) augments the method handler as -// m1(m2(m3(handler))). -// -// Receiving middleware is called when a request is received. It is useful for tasks -// such as authentication, request logging and metrics. -func (c *Client) AddReceivingMiddleware(middleware ...Middleware) { - c.mu.Lock() - defer c.mu.Unlock() - addMiddleware(&c.receivingMethodHandler_, middleware) -} - -// clientMethodInfos maps from the RPC method name to serverMethodInfos. -// -// The 'allowMissingParams' values are extracted from the protocol schema. -// TODO(rfindley): actually load and validate the protocol schema, rather than -// curating these method flags. -var clientMethodInfos = map[string]methodInfo{ - methodComplete: newClientMethodInfo(clientSessionMethod((*ClientSession).Complete), 0), - methodPing: newClientMethodInfo(clientSessionMethod((*ClientSession).ping), missingParamsOK), - methodListRoots: newClientMethodInfo(clientMethod((*Client).listRoots), missingParamsOK), - methodCreateMessage: newClientMethodInfo(clientMethod((*Client).createMessage), 0), - methodElicit: newClientMethodInfo(clientMethod((*Client).elicit), missingParamsOK), - notificationCancelled: newClientMethodInfo(clientSessionMethod((*ClientSession).cancel), notification|missingParamsOK), - notificationToolListChanged: newClientMethodInfo(clientMethod((*Client).callToolChangedHandler), notification|missingParamsOK), - notificationPromptListChanged: newClientMethodInfo(clientMethod((*Client).callPromptChangedHandler), notification|missingParamsOK), - notificationResourceListChanged: newClientMethodInfo(clientMethod((*Client).callResourceChangedHandler), notification|missingParamsOK), - notificationResourceUpdated: newClientMethodInfo(clientMethod((*Client).callResourceUpdatedHandler), notification|missingParamsOK), - notificationLoggingMessage: newClientMethodInfo(clientMethod((*Client).callLoggingHandler), notification), - notificationProgress: newClientMethodInfo(clientSessionMethod((*ClientSession).callProgressNotificationHandler), notification), - notificationElicitationComplete: newClientMethodInfo(clientMethod((*Client).callElicitationCompleteHandler), notification|missingParamsOK), -} - -func (cs *ClientSession) sendingMethodInfos() map[string]methodInfo { - return serverMethodInfos -} - -func (cs *ClientSession) receivingMethodInfos() map[string]methodInfo { - return clientMethodInfos -} - -func (cs *ClientSession) handle(ctx context.Context, req *jsonrpc.Request) (any, error) { - if req.IsCall() { - jsonrpc2.Async(ctx) - } - return handleReceive(ctx, cs, req) -} - -func (cs *ClientSession) sendingMethodHandler() MethodHandler { - cs.client.mu.Lock() - defer cs.client.mu.Unlock() - return cs.client.sendingMethodHandler_ -} - -func (cs *ClientSession) receivingMethodHandler() MethodHandler { - cs.client.mu.Lock() - defer cs.client.mu.Unlock() - return cs.client.receivingMethodHandler_ -} - -// getConn implements [Session.getConn]. -func (cs *ClientSession) getConn() *jsonrpc2.Connection { return cs.conn } - -func (*ClientSession) ping(context.Context, *PingParams) (*emptyResult, error) { - return &emptyResult{}, nil -} - -// cancel is a placeholder: cancellation is handled the jsonrpc2 package. -// -// It should never be invoked in practice because cancellation is preempted, -// but having its signature here facilitates the construction of methodInfo -// that can be used to validate incoming cancellation notifications. -func (*ClientSession) cancel(context.Context, *CancelledParams) (Result, error) { - return nil, nil -} - -func newClientRequest[P Params](cs *ClientSession, params P) *ClientRequest[P] { - return &ClientRequest[P]{Session: cs, Params: params} -} - -// Ping makes an MCP "ping" request to the server. -func (cs *ClientSession) Ping(ctx context.Context, params *PingParams) error { - _, err := handleSend[*emptyResult](ctx, methodPing, newClientRequest(cs, orZero[Params](params))) - return err -} - -// ListPrompts lists prompts that are currently available on the server. -func (cs *ClientSession) ListPrompts(ctx context.Context, params *ListPromptsParams) (*ListPromptsResult, error) { - return handleSend[*ListPromptsResult](ctx, methodListPrompts, newClientRequest(cs, orZero[Params](params))) -} - -// GetPrompt gets a prompt from the server. -func (cs *ClientSession) GetPrompt(ctx context.Context, params *GetPromptParams) (*GetPromptResult, error) { - return handleSend[*GetPromptResult](ctx, methodGetPrompt, newClientRequest(cs, orZero[Params](params))) -} - -// ListTools lists tools that are currently available on the server. -func (cs *ClientSession) ListTools(ctx context.Context, params *ListToolsParams) (*ListToolsResult, error) { - return handleSend[*ListToolsResult](ctx, methodListTools, newClientRequest(cs, orZero[Params](params))) -} - -// CallTool calls the tool with the given parameters. -// -// The params.Arguments can be any value that marshals into a JSON object. -func (cs *ClientSession) CallTool(ctx context.Context, params *CallToolParams) (*CallToolResult, error) { - if params == nil { - params = new(CallToolParams) - } - if params.Arguments == nil { - // Avoid sending nil over the wire. - params.Arguments = map[string]any{} - } - return handleSend[*CallToolResult](ctx, methodCallTool, newClientRequest(cs, orZero[Params](params))) -} - -func (cs *ClientSession) SetLoggingLevel(ctx context.Context, params *SetLoggingLevelParams) error { - _, err := handleSend[*emptyResult](ctx, methodSetLevel, newClientRequest(cs, orZero[Params](params))) - return err -} - -// ListResources lists the resources that are currently available on the server. -func (cs *ClientSession) ListResources(ctx context.Context, params *ListResourcesParams) (*ListResourcesResult, error) { - return handleSend[*ListResourcesResult](ctx, methodListResources, newClientRequest(cs, orZero[Params](params))) -} - -// ListResourceTemplates lists the resource templates that are currently available on the server. -func (cs *ClientSession) ListResourceTemplates(ctx context.Context, params *ListResourceTemplatesParams) (*ListResourceTemplatesResult, error) { - return handleSend[*ListResourceTemplatesResult](ctx, methodListResourceTemplates, newClientRequest(cs, orZero[Params](params))) -} - -// ReadResource asks the server to read a resource and return its contents. -func (cs *ClientSession) ReadResource(ctx context.Context, params *ReadResourceParams) (*ReadResourceResult, error) { - return handleSend[*ReadResourceResult](ctx, methodReadResource, newClientRequest(cs, orZero[Params](params))) -} - -func (cs *ClientSession) Complete(ctx context.Context, params *CompleteParams) (*CompleteResult, error) { - return handleSend[*CompleteResult](ctx, methodComplete, newClientRequest(cs, orZero[Params](params))) -} - -// Subscribe sends a "resources/subscribe" request to the server, asking for -// notifications when the specified resource changes. -func (cs *ClientSession) Subscribe(ctx context.Context, params *SubscribeParams) error { - _, err := handleSend[*emptyResult](ctx, methodSubscribe, newClientRequest(cs, orZero[Params](params))) - return err -} - -// Unsubscribe sends a "resources/unsubscribe" request to the server, cancelling -// a previous subscription. -func (cs *ClientSession) Unsubscribe(ctx context.Context, params *UnsubscribeParams) error { - _, err := handleSend[*emptyResult](ctx, methodUnsubscribe, newClientRequest(cs, orZero[Params](params))) - return err -} - -func (c *Client) callToolChangedHandler(ctx context.Context, req *ToolListChangedRequest) (Result, error) { - if h := c.opts.ToolListChangedHandler; h != nil { - h(ctx, req) - } - return nil, nil -} - -func (c *Client) callPromptChangedHandler(ctx context.Context, req *PromptListChangedRequest) (Result, error) { - if h := c.opts.PromptListChangedHandler; h != nil { - h(ctx, req) - } - return nil, nil -} - -func (c *Client) callResourceChangedHandler(ctx context.Context, req *ResourceListChangedRequest) (Result, error) { - if h := c.opts.ResourceListChangedHandler; h != nil { - h(ctx, req) - } - return nil, nil -} - -func (c *Client) callResourceUpdatedHandler(ctx context.Context, req *ResourceUpdatedNotificationRequest) (Result, error) { - if h := c.opts.ResourceUpdatedHandler; h != nil { - h(ctx, req) - } - return nil, nil -} - -func (c *Client) callLoggingHandler(ctx context.Context, req *LoggingMessageRequest) (Result, error) { - if h := c.opts.LoggingMessageHandler; h != nil { - h(ctx, req) - } - return nil, nil -} - -func (cs *ClientSession) callProgressNotificationHandler(ctx context.Context, params *ProgressNotificationParams) (Result, error) { - if h := cs.client.opts.ProgressNotificationHandler; h != nil { - h(ctx, clientRequestFor(cs, params)) - } - return nil, nil -} - -func (c *Client) callElicitationCompleteHandler(ctx context.Context, req *ElicitationCompleteNotificationRequest) (Result, error) { - // Check if there's a pending elicitation waiting for this notification. - if cs, ok := req.GetSession().(*ClientSession); ok { - cs.pendingElicitationsMu.Lock() - if ch, exists := cs.pendingElicitations[req.Params.ElicitationID]; exists { - select { - case ch <- struct{}{}: - default: - // Channel already signaled. - } - } - cs.pendingElicitationsMu.Unlock() - } - - // Call the user's handler if provided. - if h := c.opts.ElicitationCompleteHandler; h != nil { - h(ctx, req) - } - return nil, nil -} - -// NotifyProgress sends a progress notification from the client to the server -// associated with this session. -// This can be used if the client is performing a long-running task that was -// initiated by the server. -func (cs *ClientSession) NotifyProgress(ctx context.Context, params *ProgressNotificationParams) error { - return handleNotify(ctx, notificationProgress, newClientRequest(cs, orZero[Params](params))) -} - -// Tools provides an iterator for all tools available on the server, -// automatically fetching pages and managing cursors. -// The params argument can set the initial cursor. -// Iteration stops at the first encountered error, which will be yielded. -func (cs *ClientSession) Tools(ctx context.Context, params *ListToolsParams) iter.Seq2[*Tool, error] { - if params == nil { - params = &ListToolsParams{} - } - return paginate(ctx, params, cs.ListTools, func(res *ListToolsResult) []*Tool { - return res.Tools - }) -} - -// Resources provides an iterator for all resources available on the server, -// automatically fetching pages and managing cursors. -// The params argument can set the initial cursor. -// Iteration stops at the first encountered error, which will be yielded. -func (cs *ClientSession) Resources(ctx context.Context, params *ListResourcesParams) iter.Seq2[*Resource, error] { - if params == nil { - params = &ListResourcesParams{} - } - return paginate(ctx, params, cs.ListResources, func(res *ListResourcesResult) []*Resource { - return res.Resources - }) -} - -// ResourceTemplates provides an iterator for all resource templates available on the server, -// automatically fetching pages and managing cursors. -// The params argument can set the initial cursor. -// Iteration stops at the first encountered error, which will be yielded. -func (cs *ClientSession) ResourceTemplates(ctx context.Context, params *ListResourceTemplatesParams) iter.Seq2[*ResourceTemplate, error] { - if params == nil { - params = &ListResourceTemplatesParams{} - } - return paginate(ctx, params, cs.ListResourceTemplates, func(res *ListResourceTemplatesResult) []*ResourceTemplate { - return res.ResourceTemplates - }) -} - -// Prompts provides an iterator for all prompts available on the server, -// automatically fetching pages and managing cursors. -// The params argument can set the initial cursor. -// Iteration stops at the first encountered error, which will be yielded. -func (cs *ClientSession) Prompts(ctx context.Context, params *ListPromptsParams) iter.Seq2[*Prompt, error] { - if params == nil { - params = &ListPromptsParams{} - } - return paginate(ctx, params, cs.ListPrompts, func(res *ListPromptsResult) []*Prompt { - return res.Prompts - }) -} - -// paginate is a generic helper function to provide a paginated iterator. -func paginate[P listParams, R listResult[T], T any](ctx context.Context, params P, listFunc func(context.Context, P) (R, error), items func(R) []*T) iter.Seq2[*T, error] { - return func(yield func(*T, error) bool) { - for { - res, err := listFunc(ctx, params) - if err != nil { - yield(nil, err) - return - } - for _, r := range items(res) { - if !yield(r, nil) { - return - } - } - nextCursorVal := res.nextCursorPtr() - if nextCursorVal == nil || *nextCursorVal == "" { - return - } - *params.cursorPtr() = *nextCursorVal - } - } -} - -// CallCustom sends a raw JSON-RPC call to the server for a custom method -// that is not part of the standard MCP protocol. The params value is -// marshaled to JSON and sent as the request params. The response is -// unmarshaled into the provided result pointer. -func (cs *ClientSession) CallCustom(ctx context.Context, method string, params any, result any) error { - call := cs.conn.Call(ctx, method, params) - return call.Await(ctx, result) -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/cmd.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/cmd.go deleted file mode 100644 index b531eaf..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/cmd.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package mcp - -import ( - "context" - "fmt" - "io" - "os/exec" - "syscall" - "time" -) - -var defaultTerminateDuration = 5 * time.Second // mutable for testing - -// A CommandTransport is a [Transport] that runs a command and communicates -// with it over stdin/stdout, using newline-delimited JSON. -type CommandTransport struct { - Command *exec.Cmd - // TerminateDuration controls how long Close waits after closing stdin - // for the process to exit before sending SIGTERM. - // If zero or negative, the default of 5s is used. - TerminateDuration time.Duration -} - -// Connect starts the command, and connects to it over stdin/stdout. -func (t *CommandTransport) Connect(ctx context.Context) (Connection, error) { - stdout, err := t.Command.StdoutPipe() - if err != nil { - return nil, err - } - stdout = io.NopCloser(stdout) // close the connection by closing stdin, not stdout - stdin, err := t.Command.StdinPipe() - if err != nil { - return nil, err - } - if err := t.Command.Start(); err != nil { - return nil, err - } - td := t.TerminateDuration - if td <= 0 { - td = defaultTerminateDuration - } - return newIOConn(&pipeRWC{t.Command, stdout, stdin, td}), nil -} - -// A pipeRWC is an io.ReadWriteCloser that communicates with a subprocess over -// stdin/stdout pipes. -type pipeRWC struct { - cmd *exec.Cmd - stdout io.ReadCloser - stdin io.WriteCloser - terminateDuration time.Duration -} - -func (s *pipeRWC) Read(p []byte) (n int, err error) { - return s.stdout.Read(p) -} - -func (s *pipeRWC) Write(p []byte) (n int, err error) { - return s.stdin.Write(p) -} - -// Close closes the input stream to the child process, and awaits normal -// termination of the command. If the command does not exit, it is signalled to -// terminate, and then eventually killed. -func (s *pipeRWC) Close() error { - // Spec: - // "For the stdio transport, the client SHOULD initiate shutdown by:... - - // "...First, closing the input stream to the child process (the server)" - if err := s.stdin.Close(); err != nil { - return fmt.Errorf("closing stdin: %v", err) - } - resChan := make(chan error, 1) - go func() { - resChan <- s.cmd.Wait() - }() - // "...Waiting for the server to exit, or sending SIGTERM if the server does not exit within a reasonable time" - wait := func() (error, bool) { - select { - case err := <-resChan: - return err, true - case <-time.After(s.terminateDuration): - } - return nil, false - } - if err, ok := wait(); ok { - return err - } - // Note the condition here: if sending SIGTERM fails, don't wait and just - // move on to SIGKILL. - if err := s.cmd.Process.Signal(syscall.SIGTERM); err == nil { - if err, ok := wait(); ok { - return err - } - } - // "...Sending SIGKILL if the server does not exit within a reasonable time after SIGTERM" - if err := s.cmd.Process.Kill(); err != nil { - return err - } - if err, ok := wait(); ok { - return err - } - return fmt.Errorf("unresponsive subprocess") -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/content.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/content.go deleted file mode 100644 index 95ea40d..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/content.go +++ /dev/null @@ -1,410 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// TODO(findleyr): update JSON marshalling of all content types to preserve required fields. -// (See [TextContent.MarshalJSON], which handles this for text content). - -package mcp - -import ( - "encoding/json" - "fmt" - - internaljson "github.com/modelcontextprotocol/go-sdk/internal/json" -) - -// A Content is a [TextContent], [ImageContent], [AudioContent], -// [ResourceLink], [EmbeddedResource], [ToolUseContent], or [ToolResultContent]. -// -// Note: [ToolUseContent] and [ToolResultContent] are only valid in sampling -// message contexts (CreateMessageParams/CreateMessageResult). -type Content interface { - MarshalJSON() ([]byte, error) - fromWire(*wireContent) -} - -// TextContent is a textual content. -type TextContent struct { - Text string - Meta Meta - Annotations *Annotations -} - -func (c *TextContent) MarshalJSON() ([]byte, error) { - // Custom wire format to ensure the required "text" field is always included, even when empty. - wire := struct { - Type string `json:"type"` - Text string `json:"text"` - Meta Meta `json:"_meta,omitempty"` - Annotations *Annotations `json:"annotations,omitempty"` - }{ - Type: "text", - Text: c.Text, - Meta: c.Meta, - Annotations: c.Annotations, - } - return json.Marshal(wire) -} - -func (c *TextContent) fromWire(wire *wireContent) { - c.Text = wire.Text - c.Meta = wire.Meta - c.Annotations = wire.Annotations -} - -// ImageContent contains base64-encoded image data. -type ImageContent struct { - Meta Meta - Annotations *Annotations - Data []byte // base64-encoded - MIMEType string -} - -func (c *ImageContent) MarshalJSON() ([]byte, error) { - // Custom wire format to ensure required fields are always included, even when empty. - data := c.Data - if data == nil { - data = []byte{} - } - wire := imageAudioWire{ - Type: "image", - MIMEType: c.MIMEType, - Data: data, - Meta: c.Meta, - Annotations: c.Annotations, - } - return json.Marshal(wire) -} - -func (c *ImageContent) fromWire(wire *wireContent) { - c.MIMEType = wire.MIMEType - c.Data = wire.Data - c.Meta = wire.Meta - c.Annotations = wire.Annotations -} - -// AudioContent contains base64-encoded audio data. -type AudioContent struct { - Data []byte - MIMEType string - Meta Meta - Annotations *Annotations -} - -func (c AudioContent) MarshalJSON() ([]byte, error) { - // Custom wire format to ensure required fields are always included, even when empty. - data := c.Data - if data == nil { - data = []byte{} - } - wire := imageAudioWire{ - Type: "audio", - MIMEType: c.MIMEType, - Data: data, - Meta: c.Meta, - Annotations: c.Annotations, - } - return json.Marshal(wire) -} - -func (c *AudioContent) fromWire(wire *wireContent) { - c.MIMEType = wire.MIMEType - c.Data = wire.Data - c.Meta = wire.Meta - c.Annotations = wire.Annotations -} - -// Custom wire format to ensure required fields are always included, even when empty. -type imageAudioWire struct { - Type string `json:"type"` - MIMEType string `json:"mimeType"` - Data []byte `json:"data"` - Meta Meta `json:"_meta,omitempty"` - Annotations *Annotations `json:"annotations,omitempty"` -} - -// ResourceLink is a link to a resource -type ResourceLink struct { - URI string - Name string - Title string - Description string - MIMEType string - Size *int64 - Meta Meta - Annotations *Annotations - // Icons for the resource link, if any. - Icons []Icon `json:"icons,omitempty"` -} - -func (c *ResourceLink) MarshalJSON() ([]byte, error) { - return json.Marshal(&wireContent{ - Type: "resource_link", - URI: c.URI, - Name: c.Name, - Title: c.Title, - Description: c.Description, - MIMEType: c.MIMEType, - Size: c.Size, - Meta: c.Meta, - Annotations: c.Annotations, - Icons: c.Icons, - }) -} - -func (c *ResourceLink) fromWire(wire *wireContent) { - c.URI = wire.URI - c.Name = wire.Name - c.Title = wire.Title - c.Description = wire.Description - c.MIMEType = wire.MIMEType - c.Size = wire.Size - c.Meta = wire.Meta - c.Annotations = wire.Annotations - c.Icons = wire.Icons -} - -// EmbeddedResource contains embedded resources. -type EmbeddedResource struct { - Resource *ResourceContents - Meta Meta - Annotations *Annotations -} - -func (c *EmbeddedResource) MarshalJSON() ([]byte, error) { - return json.Marshal(&wireContent{ - Type: "resource", - Resource: c.Resource, - Meta: c.Meta, - Annotations: c.Annotations, - }) -} - -func (c *EmbeddedResource) fromWire(wire *wireContent) { - c.Resource = wire.Resource - c.Meta = wire.Meta - c.Annotations = wire.Annotations -} - -// ToolUseContent represents a request from the assistant to invoke a tool. -// This content type is only valid in sampling messages. -type ToolUseContent struct { - // ID is a unique identifier for this tool use, used to match with ToolResultContent. - ID string - // Name is the name of the tool to invoke. - Name string - // Input contains the tool arguments as a JSON object. - Input map[string]any - Meta Meta -} - -func (c *ToolUseContent) MarshalJSON() ([]byte, error) { - input := c.Input - if input == nil { - input = map[string]any{} - } - wire := struct { - Type string `json:"type"` - ID string `json:"id"` - Name string `json:"name"` - Input map[string]any `json:"input"` - Meta Meta `json:"_meta,omitempty"` - }{ - Type: "tool_use", - ID: c.ID, - Name: c.Name, - Input: input, - Meta: c.Meta, - } - return json.Marshal(wire) -} - -func (c *ToolUseContent) fromWire(wire *wireContent) { - c.ID = wire.ID - c.Name = wire.Name - c.Input = wire.Input - c.Meta = wire.Meta -} - -// ToolResultContent represents the result of a tool invocation. -// This content type is only valid in sampling messages with role "user". -type ToolResultContent struct { - // ToolUseID references the ID from the corresponding ToolUseContent. - ToolUseID string - // Content holds the unstructured result of the tool call. - Content []Content - // StructuredContent holds an optional structured result as a JSON object. - StructuredContent any - // IsError indicates whether the tool call ended in an error. - IsError bool - Meta Meta -} - -func (c *ToolResultContent) MarshalJSON() ([]byte, error) { - // Marshal nested content - var contentWire []*wireContent - for _, content := range c.Content { - data, err := content.MarshalJSON() - if err != nil { - return nil, err - } - var w wireContent - if err := internaljson.Unmarshal(data, &w); err != nil { - return nil, err - } - contentWire = append(contentWire, &w) - } - if contentWire == nil { - contentWire = []*wireContent{} // avoid JSON null - } - - wire := struct { - Type string `json:"type"` - ToolUseID string `json:"toolUseId"` - Content []*wireContent `json:"content"` - StructuredContent any `json:"structuredContent,omitempty"` - IsError bool `json:"isError,omitempty"` - Meta Meta `json:"_meta,omitempty"` - }{ - Type: "tool_result", - ToolUseID: c.ToolUseID, - Content: contentWire, - StructuredContent: c.StructuredContent, - IsError: c.IsError, - Meta: c.Meta, - } - return json.Marshal(wire) -} - -func (c *ToolResultContent) fromWire(wire *wireContent) { - c.ToolUseID = wire.ToolUseID - c.StructuredContent = wire.StructuredContent - c.IsError = wire.IsError - c.Meta = wire.Meta - // Content is handled separately in contentFromWire due to nested content -} - -// ResourceContents contains the contents of a specific resource or -// sub-resource. -type ResourceContents struct { - URI string `json:"uri"` - MIMEType string `json:"mimeType,omitempty"` - Text string `json:"text,omitempty"` - Blob []byte `json:"blob,omitzero"` - Meta Meta `json:"_meta,omitempty"` -} - -// wireContent is the wire format for content. -// It represents the protocol types TextContent, ImageContent, AudioContent, -// ResourceLink, EmbeddedResource, ToolUseContent, and ToolResultContent. -// The Type field distinguishes them. In the protocol, each type has a constant -// value for the field. -type wireContent struct { - Type string `json:"type"` - Text string `json:"text,omitempty"` // TextContent - MIMEType string `json:"mimeType,omitempty"` // ImageContent, AudioContent, ResourceLink - Data []byte `json:"data,omitempty"` // ImageContent, AudioContent - Resource *ResourceContents `json:"resource,omitempty"` // EmbeddedResource - URI string `json:"uri,omitempty"` // ResourceLink - Name string `json:"name,omitempty"` // ResourceLink, ToolUseContent - Title string `json:"title,omitempty"` // ResourceLink - Description string `json:"description,omitempty"` // ResourceLink - Size *int64 `json:"size,omitempty"` // ResourceLink - Meta Meta `json:"_meta,omitempty"` // all types - Annotations *Annotations `json:"annotations,omitempty"` // all types except ToolUseContent, ToolResultContent - Icons []Icon `json:"icons,omitempty"` // ResourceLink - ID string `json:"id,omitempty"` // ToolUseContent - Input map[string]any `json:"input,omitempty"` // ToolUseContent - ToolUseID string `json:"toolUseId,omitempty"` // ToolResultContent - NestedContent []*wireContent `json:"content,omitempty"` // ToolResultContent - StructuredContent any `json:"structuredContent,omitempty"` // ToolResultContent - IsError bool `json:"isError,omitempty"` // ToolResultContent -} - -// unmarshalContent unmarshals JSON that is either a single content object or -// an array of content objects. A single object is wrapped in a one-element slice. -func unmarshalContent(raw json.RawMessage, allow map[string]bool) ([]Content, error) { - if len(raw) == 0 || string(raw) == "null" { - return nil, fmt.Errorf("nil content") - } - // Try array first, then fall back to single object. - var wires []*wireContent - if err := internaljson.Unmarshal(raw, &wires); err == nil { - return contentsFromWire(wires, allow) - } - var wire wireContent - if err := internaljson.Unmarshal(raw, &wire); err != nil { - return nil, err - } - c, err := contentFromWire(&wire, allow) - if err != nil { - return nil, err - } - return []Content{c}, nil -} - -func contentsFromWire(wires []*wireContent, allow map[string]bool) ([]Content, error) { - blocks := make([]Content, 0, len(wires)) - for _, wire := range wires { - block, err := contentFromWire(wire, allow) - if err != nil { - return nil, err - } - blocks = append(blocks, block) - } - return blocks, nil -} - -func contentFromWire(wire *wireContent, allow map[string]bool) (Content, error) { - if wire == nil { - return nil, fmt.Errorf("nil content") - } - if allow != nil && !allow[wire.Type] { - return nil, fmt.Errorf("invalid content type %q", wire.Type) - } - switch wire.Type { - case "text": - v := new(TextContent) - v.fromWire(wire) - return v, nil - case "image": - v := new(ImageContent) - v.fromWire(wire) - return v, nil - case "audio": - v := new(AudioContent) - v.fromWire(wire) - return v, nil - case "resource_link": - v := new(ResourceLink) - v.fromWire(wire) - return v, nil - case "resource": - v := new(EmbeddedResource) - v.fromWire(wire) - return v, nil - case "tool_use": - v := new(ToolUseContent) - v.fromWire(wire) - return v, nil - case "tool_result": - v := new(ToolResultContent) - v.fromWire(wire) - // Handle nested content - tool_result content can contain text, image, audio, - // resource_link, and resource (same as CallToolResult.content) - if wire.NestedContent != nil { - toolResultContentAllow := map[string]bool{ - "text": true, "image": true, "audio": true, - "resource_link": true, "resource": true, - } - nestedContent, err := contentsFromWire(wire.NestedContent, toolResultContentAllow) - if err != nil { - return nil, fmt.Errorf("tool_result nested content: %w", err) - } - v.Content = nestedContent - } - return v, nil - } - return nil, fmt.Errorf("unrecognized content type %q", wire.Type) -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/event.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/event.go deleted file mode 100644 index 62dd2ad..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/event.go +++ /dev/null @@ -1,436 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// This file is for SSE events. -// See https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events. - -package mcp - -import ( - "bufio" - "bytes" - "context" - "errors" - "fmt" - "io" - "iter" - "maps" - "net/http" - "slices" - "strings" - "sync" -) - -// If true, MemoryEventStore will do frequent validation to check invariants, slowing it down. -// Enable for debugging. -const validateMemoryEventStore = false - -// An Event is a server-sent event. -// See https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#fields. -type Event struct { - Name string // the "event" field - ID string // the "id" field - Data []byte // the "data" field - Retry string // the "retry" field -} - -// Empty reports whether the Event is empty. -func (e Event) Empty() bool { - return e.Name == "" && e.ID == "" && len(e.Data) == 0 && e.Retry == "" -} - -// writeEvent writes the event to w, and flushes. -func writeEvent(w io.Writer, evt Event) (int, error) { - var b bytes.Buffer - if evt.Name != "" { - fmt.Fprintf(&b, "event: %s\n", evt.Name) - } - if evt.ID != "" { - fmt.Fprintf(&b, "id: %s\n", evt.ID) - } - if evt.Retry != "" { - fmt.Fprintf(&b, "retry: %s\n", evt.Retry) - } - fmt.Fprintf(&b, "data: %s\n\n", string(evt.Data)) - n, err := w.Write(b.Bytes()) - if f, ok := w.(http.Flusher); ok { - f.Flush() - } - return n, err -} - -// scanEvents iterates SSE events in the given scanner. The iterated error is -// terminal: if encountered, the stream is corrupt or broken and should no -// longer be used. -// -// TODO(rfindley): consider a different API here that makes failure modes more -// apparent. -func scanEvents(r io.Reader) iter.Seq2[Event, error] { - reader := bufio.NewReader(r) - - // TODO: investigate proper behavior when events are out of order, or have - // non-standard names. - var ( - eventKey = []byte("event") - idKey = []byte("id") - dataKey = []byte("data") - retryKey = []byte("retry") - ) - - return func(yield func(Event, error) bool) { - // iterate event from the wire. - // https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#examples - // - // - `key: value` line records. - // - Consecutive `data: ...` fields are joined with newlines. - // - Unrecognized fields are ignored. Since we only care about 'event', 'id', and - // 'data', these are the only three we consider. - // - Lines starting with ":" are ignored. - // - Records are terminated with two consecutive newlines. - var ( - evt Event - dataBuf *bytes.Buffer // if non-nil, preceding field was also data - ) - yieldEvent := func() bool { - if dataBuf != nil { - evt.Data = dataBuf.Bytes() - dataBuf = nil - } - if evt.Empty() { - return true - } - if !yield(evt, nil) { - return false - } - evt = Event{} - return true - } - for { - line, err := reader.ReadBytes('\n') - if err != nil && !errors.Is(err, io.EOF) { - yield(Event{}, fmt.Errorf("error reading event: %v", err)) - return - } - line = bytes.TrimRight(line, "\r\n") - isEOF := errors.Is(err, io.EOF) - - if len(line) == 0 { - if !yieldEvent() { - return - } - if isEOF { - return - } - continue - } - before, after, found := bytes.Cut(line, []byte{':'}) - if !found { - yield(Event{}, fmt.Errorf("%w: malformed line in SSE stream: %q", errMalformedEvent, string(line))) - return - } - switch { - case bytes.Equal(before, eventKey): - evt.Name = strings.TrimSpace(string(after)) - case bytes.Equal(before, idKey): - evt.ID = strings.TrimSpace(string(after)) - case bytes.Equal(before, retryKey): - evt.Retry = strings.TrimSpace(string(after)) - case bytes.Equal(before, dataKey): - data := bytes.TrimSpace(after) - if dataBuf == nil { - dataBuf = new(bytes.Buffer) - } else { - dataBuf.WriteByte('\n') - } - dataBuf.Write(data) - } - - if isEOF { - yieldEvent() - return - } - } - } -} - -// An EventStore tracks data for SSE streams. -// A single EventStore suffices for all sessions, since session IDs are -// globally unique. So one EventStore can be created per process, for -// all Servers in the process. -// Such a store is able to bound resource usage for the entire process. -// -// All of an EventStore's methods must be safe for use by multiple goroutines. -type EventStore interface { - // Open is called when a new stream is created. It may be used to ensure that - // the underlying data structure for the stream is initialized, making it - // ready to store and replay event streams. - Open(_ context.Context, sessionID, streamID string) error - - // Append appends data for an outgoing event to given stream, which is part of the - // given session. - Append(_ context.Context, sessionID, streamID string, data []byte) error - - // After returns an iterator over the data for the given session and stream, beginning - // just after the given index. - // - // Once the iterator yields a non-nil error, it will stop. - // After's iterator must return an error immediately if any data after index was - // dropped; it must not return partial results. - // The stream must have been opened previously (see [EventStore.Open]). - After(_ context.Context, sessionID, streamID string, index int) iter.Seq2[[]byte, error] - - // SessionClosed informs the store that the given session is finished, along - // with all of its streams. - // - // A store cannot rely on this method being called for cleanup. It should institute - // additional mechanisms, such as timeouts, to reclaim storage. - SessionClosed(_ context.Context, sessionID string) error - - // There is no StreamClosed method. A server doesn't know when a stream is finished, because - // the client can always send a GET with a Last-Event-ID referring to the stream. -} - -// A dataList is a list of []byte. -// The zero dataList is ready to use. -type dataList struct { - size int // total size of data bytes - first int // the stream index of the first element in data - data [][]byte -} - -func (dl *dataList) appendData(d []byte) { - // Empty data consumes memory but doesn't increment size. However, it should - // be rare. - dl.data = append(dl.data, d) - dl.size += len(d) -} - -// removeFirst removes the first data item in dl, returning the size of the item. -// It panics if dl is empty. -func (dl *dataList) removeFirst() int { - if len(dl.data) == 0 { - panic("empty dataList") - } - r := len(dl.data[0]) - dl.size -= r - dl.data[0] = nil // help GC - dl.data = dl.data[1:] - dl.first++ - return r -} - -// A MemoryEventStore is an [EventStore] backed by memory. -type MemoryEventStore struct { - mu sync.Mutex - maxBytes int // max total size of all data - nBytes int // current total size of all data - store map[string]map[string]*dataList // session ID -> stream ID -> *dataList -} - -// MemoryEventStoreOptions are options for a [MemoryEventStore]. -type MemoryEventStoreOptions struct{} - -// MaxBytes returns the maximum number of bytes that the store will retain before -// purging data. -func (s *MemoryEventStore) MaxBytes() int { - s.mu.Lock() - defer s.mu.Unlock() - return s.maxBytes -} - -// SetMaxBytes sets the maximum number of bytes the store will retain before purging -// data. The argument must not be negative. If it is zero, a suitable default will be used. -// SetMaxBytes can be called at any time. The size of the store will be adjusted -// immediately. -func (s *MemoryEventStore) SetMaxBytes(n int) { - s.mu.Lock() - defer s.mu.Unlock() - switch { - case n < 0: - panic("negative argument") - case n == 0: - s.maxBytes = defaultMaxBytes - default: - s.maxBytes = n - } - s.purge() -} - -const defaultMaxBytes = 10 << 20 // 10 MiB - -// NewMemoryEventStore creates a [MemoryEventStore] with the default value -// for MaxBytes. -func NewMemoryEventStore(opts *MemoryEventStoreOptions) *MemoryEventStore { - return &MemoryEventStore{ - maxBytes: defaultMaxBytes, - store: make(map[string]map[string]*dataList), - } -} - -// Open implements [EventStore.Open]. It ensures that the underlying data -// structures for the given session are initialized and ready for use. -func (s *MemoryEventStore) Open(_ context.Context, sessionID, streamID string) error { - s.mu.Lock() - defer s.mu.Unlock() - s.init(sessionID, streamID) - return nil -} - -// init is an internal helper function that ensures the nested map structure for a -// given sessionID and streamID exists, creating it if necessary. It returns the -// dataList associated with the specified IDs. -// Requires s.mu. -func (s *MemoryEventStore) init(sessionID, streamID string) *dataList { - streamMap, ok := s.store[sessionID] - if !ok { - streamMap = make(map[string]*dataList) - s.store[sessionID] = streamMap - } - dl, ok := streamMap[streamID] - if !ok { - dl = &dataList{} - streamMap[streamID] = dl - } - return dl -} - -// Append implements [EventStore.Append] by recording data in memory. -func (s *MemoryEventStore) Append(_ context.Context, sessionID, streamID string, data []byte) error { - s.mu.Lock() - defer s.mu.Unlock() - dl := s.init(sessionID, streamID) - // Purge before adding, so at least the current data item will be present. - // (That could result in nBytes > maxBytes, but we'll live with that.) - s.purge() - dl.appendData(data) - s.nBytes += len(data) - return nil -} - -// ErrEventsPurged is the error that [EventStore.After] should return if the event just after the -// index is no longer available. -var ErrEventsPurged = errors.New("data purged") - -// errMalformedEvent is returned when an SSE event cannot be parsed due to format violations. -// This is a hard error indicating corrupted data or protocol violations, as opposed to -// transient I/O errors which may be retryable. -var errMalformedEvent = errors.New("malformed event") - -// After implements [EventStore.After]. -func (s *MemoryEventStore) After(_ context.Context, sessionID, streamID string, index int) iter.Seq2[[]byte, error] { - // Return the data items to yield. - // We must copy, because dataList.removeFirst nils out slice elements. - copyData := func() ([][]byte, error) { - s.mu.Lock() - defer s.mu.Unlock() - streamMap, ok := s.store[sessionID] - if !ok { - return nil, fmt.Errorf("MemoryEventStore.After: unknown session ID %q", sessionID) - } - dl, ok := streamMap[streamID] - if !ok { - return nil, fmt.Errorf("MemoryEventStore.After: unknown stream ID %v in session %q", streamID, sessionID) - } - start := index + 1 - if dl.first > start { - return nil, fmt.Errorf("MemoryEventStore.After: index %d, stream ID %v, session %q: %w", - index, streamID, sessionID, ErrEventsPurged) - } - return slices.Clone(dl.data[start-dl.first:]), nil - } - - return func(yield func([]byte, error) bool) { - ds, err := copyData() - if err != nil { - yield(nil, err) - return - } - for _, d := range ds { - if !yield(d, nil) { - return - } - } - } -} - -// SessionClosed implements [EventStore.SessionClosed]. -func (s *MemoryEventStore) SessionClosed(_ context.Context, sessionID string) error { - s.mu.Lock() - defer s.mu.Unlock() - for _, dl := range s.store[sessionID] { - s.nBytes -= dl.size - } - delete(s.store, sessionID) - s.validate() - return nil -} - -// purge removes data until no more than s.maxBytes bytes are in use. -// It must be called with s.mu held. -func (s *MemoryEventStore) purge() { - // Remove the first element of every dataList until below the max. - for s.nBytes > s.maxBytes { - changed := false - for _, sm := range s.store { - for _, dl := range sm { - if dl.size > 0 { - r := dl.removeFirst() - if r > 0 { - changed = true - s.nBytes -= r - } - } - } - } - if !changed { - panic("no progress during purge") - } - } - s.validate() -} - -// validate checks that the store's data structures are valid. -// It must be called with s.mu held. -func (s *MemoryEventStore) validate() { - if !validateMemoryEventStore { - return - } - // Check that we're accounting for the size correctly. - n := 0 - for _, sm := range s.store { - for _, dl := range sm { - for _, d := range dl.data { - n += len(d) - } - } - } - if n != s.nBytes { - panic("sizes don't add up") - } -} - -// debugString returns a string containing the state of s. -// Used in tests. -func (s *MemoryEventStore) debugString() string { - s.mu.Lock() - defer s.mu.Unlock() - var b strings.Builder - for i, sess := range slices.Sorted(maps.Keys(s.store)) { - if i > 0 { - fmt.Fprintf(&b, "; ") - } - sm := s.store[sess] - for i, sid := range slices.Sorted(maps.Keys(sm)) { - if i > 0 { - fmt.Fprintf(&b, "; ") - } - dl := sm[sid] - fmt.Fprintf(&b, "%s %s first=%d", sess, sid, dl.first) - for _, d := range dl.data { - fmt.Fprintf(&b, " %s", d) - } - } - } - return b.String() -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/features.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/features.go deleted file mode 100644 index 438370f..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/features.go +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package mcp - -import ( - "iter" - "maps" - "slices" -) - -// This file contains implementations that are common to all features. -// A feature is an item provided to a peer. In the 2025-03-26 spec, -// the features are prompt, tool, resource and root. - -// A featureSet is a collection of features of type T. -// Every feature has a unique ID, and the spec never mentions -// an ordering for the List calls, so what it calls a "list" is actually a set. -// -// An alternative implementation would use an ordered map, but that's probably -// not necessary as adds and removes are rare, and usually batched. -type featureSet[T any] struct { - uniqueID func(T) string - features map[string]T - sortedKeys []string // lazily computed; nil after add or remove -} - -// newFeatureSet creates a new featureSet for features of type T. -// The argument function should return the unique ID for a single feature. -func newFeatureSet[T any](uniqueIDFunc func(T) string) *featureSet[T] { - return &featureSet[T]{ - uniqueID: uniqueIDFunc, - features: make(map[string]T), - } -} - -// add adds each feature to the set if it is not present, -// or replaces an existing feature. -func (s *featureSet[T]) add(fs ...T) { - for _, f := range fs { - s.features[s.uniqueID(f)] = f - } - s.sortedKeys = nil -} - -// remove removes all features with the given uids from the set if present, -// and returns whether any were removed. -// It is not an error to remove a nonexistent feature. -func (s *featureSet[T]) remove(uids ...string) bool { - changed := false - for _, uid := range uids { - if _, ok := s.features[uid]; ok { - changed = true - delete(s.features, uid) - } - } - if changed { - s.sortedKeys = nil - } - return changed -} - -// get returns the feature with the given uid. -// If there is none, it returns zero, false. -func (s *featureSet[T]) get(uid string) (T, bool) { - t, ok := s.features[uid] - return t, ok -} - -// len returns the number of features in the set. -func (s *featureSet[T]) len() int { return len(s.features) } - -// all returns an iterator over of all the features in the set -// sorted by unique ID. -func (s *featureSet[T]) all() iter.Seq[T] { - s.sortKeys() - return func(yield func(T) bool) { - s.yieldFrom(0, yield) - } -} - -// above returns an iterator over features in the set whose unique IDs are -// greater than `uid`, in ascending ID order. -func (s *featureSet[T]) above(uid string) iter.Seq[T] { - s.sortKeys() - index, found := slices.BinarySearch(s.sortedKeys, uid) - if found { - index++ - } - return func(yield func(T) bool) { - s.yieldFrom(index, yield) - } -} - -// sortKeys is a helper that maintains a sorted list of feature IDs. It -// computes this list lazily upon its first call after a modification, or -// if it's nil. -func (s *featureSet[T]) sortKeys() { - if s.sortedKeys != nil { - return - } - s.sortedKeys = slices.Sorted(maps.Keys(s.features)) -} - -// yieldFrom is a helper that iterates over the features in the set, -// starting at the given index, and calls the yield function for each one. -func (s *featureSet[T]) yieldFrom(index int, yield func(T) bool) { - for i := index; i < len(s.sortedKeys); i++ { - if !yield(s.features[s.sortedKeys[i]]) { - return - } - } -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/logging.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/logging.go deleted file mode 100644 index b1bd82b..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/logging.go +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package mcp - -import ( - "bytes" - "cmp" - "context" - "encoding/json" - "log/slog" - "slices" - "sync" - "time" -) - -// Logging levels. -const ( - LevelDebug = slog.LevelDebug - LevelInfo = slog.LevelInfo - LevelNotice = (slog.LevelInfo + slog.LevelWarn) / 2 - LevelWarning = slog.LevelWarn - LevelError = slog.LevelError - LevelCritical = slog.LevelError + 4 - LevelAlert = slog.LevelError + 8 - LevelEmergency = slog.LevelError + 12 -) - -var slogToMCP = map[slog.Level]LoggingLevel{ - LevelDebug: "debug", - LevelInfo: "info", - LevelNotice: "notice", - LevelWarning: "warning", - LevelError: "error", - LevelCritical: "critical", - LevelAlert: "alert", - LevelEmergency: "emergency", -} - -var mcpToSlog = make(map[LoggingLevel]slog.Level) - -func init() { - for sl, ml := range slogToMCP { - mcpToSlog[ml] = sl - } -} - -func slogLevelToMCP(sl slog.Level) LoggingLevel { - if ml, ok := slogToMCP[sl]; ok { - return ml - } - return "debug" // for lack of a better idea -} - -func mcpLevelToSlog(ll LoggingLevel) slog.Level { - if sl, ok := mcpToSlog[ll]; ok { - return sl - } - // TODO: is there a better default? - return LevelDebug -} - -// compareLevels behaves like [cmp.Compare] for [LoggingLevel]s. -func compareLevels(l1, l2 LoggingLevel) int { - return cmp.Compare(mcpLevelToSlog(l1), mcpLevelToSlog(l2)) -} - -// LoggingHandlerOptions are options for a LoggingHandler. -type LoggingHandlerOptions struct { - // The value for the "logger" field of logging notifications. - LoggerName string - // Limits the rate at which log messages are sent. - // Excess messages are dropped. - // If zero, there is no rate limiting. - MinInterval time.Duration -} - -// A LoggingHandler is a [slog.Handler] for MCP. -type LoggingHandler struct { - opts LoggingHandlerOptions - ss *ServerSession - // Ensures that the buffer reset is atomic with the write (see Handle). - // A pointer so that clones share the mutex. See - // https://github.com/golang/example/blob/master/slog-handler-guide/README.md#getting-the-mutex-right. - mu *sync.Mutex - lastMessageSent time.Time // for rate-limiting - buf *bytes.Buffer - handler slog.Handler -} - -// ensureLogger returns l if non-nil, otherwise a discard logger. -func ensureLogger(l *slog.Logger) *slog.Logger { - if l != nil { - return l - } - return slog.New(slog.DiscardHandler) -} - -// NewLoggingHandler creates a [LoggingHandler] that logs to the given [ServerSession] using a -// [slog.JSONHandler]. -func NewLoggingHandler(ss *ServerSession, opts *LoggingHandlerOptions) *LoggingHandler { - var buf bytes.Buffer - jsonHandler := slog.NewJSONHandler(&buf, &slog.HandlerOptions{ - ReplaceAttr: func(_ []string, a slog.Attr) slog.Attr { - // Remove level: it appears in LoggingMessageParams. - if a.Key == slog.LevelKey { - return slog.Attr{} - } - return a - }, - }) - lh := &LoggingHandler{ - ss: ss, - mu: new(sync.Mutex), - buf: &buf, - handler: jsonHandler, - } - if opts != nil { - lh.opts = *opts - } - return lh -} - -// Enabled implements [slog.Handler.Enabled] by comparing level to the [ServerSession]'s level. -func (h *LoggingHandler) Enabled(ctx context.Context, level slog.Level) bool { - // This is also checked in ServerSession.LoggingMessage, so checking it here - // is just an optimization that skips building the JSON. - h.ss.mu.Lock() - mcpLevel := h.ss.state.LogLevel - h.ss.mu.Unlock() - return level >= mcpLevelToSlog(mcpLevel) -} - -// WithAttrs implements [slog.Handler.WithAttrs]. -func (h *LoggingHandler) WithAttrs(as []slog.Attr) slog.Handler { - h2 := *h - h2.handler = h.handler.WithAttrs(as) - return &h2 -} - -// WithGroup implements [slog.Handler.WithGroup]. -func (h *LoggingHandler) WithGroup(name string) slog.Handler { - h2 := *h - h2.handler = h.handler.WithGroup(name) - return &h2 -} - -// Handle implements [slog.Handler.Handle] by writing the Record to a JSONHandler, -// then calling [ServerSession.LoggingMessage] with the result. -func (h *LoggingHandler) Handle(ctx context.Context, r slog.Record) error { - err := h.handle(ctx, r) - // TODO(jba): find a way to surface the error. - // The return value will probably be ignored. - return err -} - -func (h *LoggingHandler) handle(ctx context.Context, r slog.Record) error { - // Observe the rate limit. - // TODO(jba): use golang.org/x/time/rate. - h.mu.Lock() - skip := time.Since(h.lastMessageSent) < h.opts.MinInterval - h.mu.Unlock() - if skip { - return nil - } - - var err error - var data json.RawMessage - // Make the buffer reset atomic with the record write. - // We are careful here in the unlikely event that the handler panics. - // We don't want to hold the lock for the entire function, because Notify is - // an I/O operation. - // This can result in out-of-order delivery. - func() { - h.mu.Lock() - defer h.mu.Unlock() - h.buf.Reset() - err = h.handler.Handle(ctx, r) - // Clone the buffer as Bytes() references the internal buffer. - data = json.RawMessage(slices.Clone(h.buf.Bytes())) - }() - if err != nil { - return err - } - - h.mu.Lock() - h.lastMessageSent = time.Now() - h.mu.Unlock() - - params := &LoggingMessageParams{ - Logger: h.opts.LoggerName, - Level: slogLevelToMCP(r.Level), - Data: data, - } - // We pass the argument context to Notify, even though slog.Handler.Handle's - // documentation says not to. - // In this case logging is a service to clients, not a means for debugging the - // server, so we want to cancel the log message. - return h.ss.Log(ctx, params) -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/mcp.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/mcp.go deleted file mode 100644 index 56e950b..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/mcp.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// The mcp package provides an SDK for writing model context protocol clients -// and servers. -// -// To get started, create either a [Client] or [Server], add features to it -// using `AddXXX` functions, and connect it to a peer using a [Transport]. -// -// For example, to run a simple server on the [StdioTransport]: -// -// server := mcp.NewServer(&mcp.Implementation{Name: "greeter"}, nil) -// -// // Using the generic AddTool automatically populates the the input and output -// // schema of the tool. -// type args struct { -// Name string `json:"name" jsonschema:"the person to greet"` -// } -// mcp.AddTool(server, &mcp.Tool{ -// Name: "greet", -// Description: "say hi", -// }, func(ctx context.Context, req *mcp.CallToolRequest, args args) (*mcp.CallToolResult, any, error) { -// return &mcp.CallToolResult{ -// Content: []mcp.Content{ -// &mcp.TextContent{Text: "Hi " + args.Name}, -// }, -// }, nil, nil -// }) -// -// // Run the server on the stdio transport. -// if err := server.Run(context.Background(), &mcp.StdioTransport{}); err != nil { -// log.Printf("Server failed: %v", err) -// } -// -// To connect to this server, use the [CommandTransport]: -// -// client := mcp.NewClient(&mcp.Implementation{Name: "mcp-client", Version: "v1.0.0"}, nil) -// transport := &mcp.CommandTransport{Command: exec.Command("myserver")} -// session, err := client.Connect(ctx, transport, nil) -// if err != nil { -// log.Fatal(err) -// } -// defer session.Close() -// -// params := &mcp.CallToolParams{ -// Name: "greet", -// Arguments: map[string]any{"name": "you"}, -// } -// res, err := session.CallTool(ctx, params) -// if err != nil { -// log.Fatalf("CallTool failed: %v", err) -// } -// -// # Clients, servers, and sessions -// -// In this SDK, both a [Client] and [Server] may handle many concurrent -// connections. Each time a client or server is connected to a peer using a -// [Transport], it creates a new session (either a [ClientSession] or -// [ServerSession]): -// -// Client Server -// ⇅ (jsonrpc2) ⇅ -// ClientSession ⇄ Client Transport ⇄ Server Transport ⇄ ServerSession -// -// The session types expose an API to interact with its peer. For example, -// [ClientSession.CallTool] or [ServerSession.ListRoots]. -// -// # Adding features -// -// Add MCP servers to your Client or Server using AddXXX methods (for example -// [Client.AddRoot] or [Server.AddPrompt]). If any peers are connected when -// AddXXX is called, they will receive a corresponding change notification -// (for example notifications/roots/list_changed). -// -// Adding tools is special: tools may be bound to ordinary Go functions by -// using the top-level generic [AddTool] function, which allows specifying an -// input and output type. When AddTool is used, the tool's input schema and -// output schema are automatically populated, and inputs are automatically -// validated. As a special case, if the output type is 'any', no output schema -// is generated. -// -// func double(_ context.Context, _ *mcp.CallToolRequest, in In) (*mcp.CallToolResult, Out, error) { -// return nil, Out{Answer: 2*in.Number}, nil -// } -// ... -// mcp.AddTool(server, &mcp.Tool{Name: "double"}, double) -package mcp diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/prompt.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/prompt.go deleted file mode 100644 index 62f38a3..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/prompt.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package mcp - -import ( - "context" -) - -// A PromptHandler handles a call to prompts/get. -type PromptHandler func(context.Context, *GetPromptRequest) (*GetPromptResult, error) - -type serverPrompt struct { - prompt *Prompt - handler PromptHandler -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/protocol.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/protocol.go deleted file mode 100644 index 837ce78..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/protocol.go +++ /dev/null @@ -1,1622 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package mcp - -// Protocol types for version 2025-06-18. -// To see the schema changes from the previous version, run: -// -// prefix=https://raw.githubusercontent.com/modelcontextprotocol/modelcontextprotocol/refs/heads/main/schema -// sdiff -l <(curl $prefix/2025-03-26/schema.ts) <(curl $prefix/2025/06-18/schema.ts) - -import ( - "encoding/json" - "fmt" - "maps" - - internaljson "github.com/modelcontextprotocol/go-sdk/internal/json" -) - -// Optional annotations for the client. The client can use annotations to inform -// how objects are used or displayed. -type Annotations struct { - // Describes who the intended customer of this object or data is. - // - // It can include multiple entries to indicate content useful for multiple - // audiences (e.g., []Role{"user", "assistant"}). - Audience []Role `json:"audience,omitempty"` - // The moment the resource was last modified, as an ISO 8601 formatted string. - // - // Should be an ISO 8601 formatted string (e.g., "2025-01-12T15:00:58Z"). - // - // Examples: last activity timestamp in an open file, timestamp when the - // resource was attached, etc. - LastModified string `json:"lastModified,omitempty"` - // Describes how important this data is for operating the server. - // - // A value of 1 means "most important," and indicates that the data is - // effectively required, while 0 means "least important," and indicates that the - // data is entirely optional. - Priority float64 `json:"priority,omitempty"` -} - -// CallToolParams is used by clients to call a tool. -type CallToolParams struct { - // Meta is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // Name is the name of the tool to call. - Name string `json:"name"` - // Arguments holds the tool arguments. It can hold any value that can be - // marshaled to JSON. - Arguments any `json:"arguments,omitempty"` -} - -// CallToolParamsRaw is passed to tool handlers on the server. Its arguments -// are not yet unmarshaled (hence "raw"), so that the handlers can perform -// unmarshaling themselves. -type CallToolParamsRaw struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // Name is the name of the tool being called. - Name string `json:"name"` - // Arguments is the raw arguments received over the wire from the client. It - // is the responsibility of the tool handler to unmarshal and validate the - // Arguments (see [AddTool]). - Arguments json.RawMessage `json:"arguments,omitempty"` -} - -// A CallToolResult is the server's response to a tool call. -// -// The [ToolHandler] and [ToolHandlerFor] handler functions return this result, -// though [ToolHandlerFor] populates much of it automatically as documented at -// each field. -type CallToolResult struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - - // A list of content objects that represent the unstructured result of the tool - // call. - // - // When using a [ToolHandlerFor] with structured output, if Content is unset - // it will be populated with JSON text content corresponding to the - // structured output value. - Content []Content `json:"content"` - - // StructuredContent is an optional value that represents the structured - // result of the tool call. It must marshal to a JSON object. - // - // When using a [ToolHandlerFor] with structured output, you should not - // populate this field. It will be automatically populated with the typed Out - // value. - StructuredContent any `json:"structuredContent,omitempty"` - - // IsError reports whether the tool call ended in an error. - // - // If not set, this is assumed to be false (the call was successful). - // - // Any errors that originate from the tool should be reported inside the - // Content field, with IsError set to true, not as an MCP protocol-level - // error response. Otherwise, the LLM would not be able to see that an error - // occurred and self-correct. - // - // However, any errors in finding the tool, an error indicating that the - // server does not support tool calls, or any other exceptional conditions, - // should be reported as an MCP error response. - // - // When using a [ToolHandlerFor], this field is automatically set when the - // tool handler returns an error, and the error string is included as text in - // the Content field. - IsError bool `json:"isError,omitempty"` - - // The error passed to setError, if any. - // It is not marshaled, and therefore it is only visible on the server. - // Its only use is in server sending middleware, where it can be accessed - // with getError. - err error -} - -// SetError sets the error for the tool result and populates the Content field -// with the error text. It also sets IsError to true. -func (r *CallToolResult) SetError(err error) { - r.Content = []Content{&TextContent{Text: err.Error()}} - r.IsError = true - r.err = err -} - -// GetError returns the error set with SetError, or nil if none. -// This function always returns nil on clients. -func (r *CallToolResult) GetError() error { - return r.err -} - -func (*CallToolResult) isResult() {} - -// UnmarshalJSON handles the unmarshalling of content into the Content -// interface. -func (x *CallToolResult) UnmarshalJSON(data []byte) error { - type res CallToolResult // avoid recursion - var wire struct { - res - Content []*wireContent `json:"content"` - } - if err := internaljson.Unmarshal(data, &wire); err != nil { - return err - } - var err error - if wire.res.Content, err = contentsFromWire(wire.Content, nil); err != nil { - return err - } - *x = CallToolResult(wire.res) - return nil -} - -func (x *CallToolParams) isParams() {} -func (x *CallToolParams) GetProgressToken() any { return getProgressToken(x) } -func (x *CallToolParams) SetProgressToken(t any) { setProgressToken(x, t) } - -func (x *CallToolParamsRaw) isParams() {} -func (x *CallToolParamsRaw) GetProgressToken() any { return getProgressToken(x) } -func (x *CallToolParamsRaw) SetProgressToken(t any) { setProgressToken(x, t) } - -type CancelledParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // An optional string describing the reason for the cancellation. This may be - // logged or presented to the user. - Reason string `json:"reason,omitempty"` - // The ID of the request to cancel. - // - // This must correspond to the ID of a request previously issued in the same - // direction. - RequestID any `json:"requestId"` -} - -func (x *CancelledParams) isParams() {} -func (x *CancelledParams) GetProgressToken() any { return getProgressToken(x) } -func (x *CancelledParams) SetProgressToken(t any) { setProgressToken(x, t) } - -// RootCapabilities describes a client's support for roots. -type RootCapabilities struct { - // ListChanged reports whether the client supports notifications for - // changes to the roots list. - ListChanged bool `json:"listChanged,omitempty"` -} - -// Capabilities a client may support. Known capabilities are defined here, in -// this schema, but this is not a closed set: any client can define its own, -// additional capabilities. -type ClientCapabilities struct { - // NOTE: any addition to ClientCapabilities must also be reflected in - // [ClientCapabilities.clone]. - - // Experimental reports non-standard capabilities that the client supports. - // The caller should not modify the map after assigning it. - Experimental map[string]any `json:"experimental,omitempty"` - // Extensions reports extensions that the client supports. - // Keys are extension identifiers in "{vendor-prefix}/{extension-name}" format. - // Values are per-extension settings objects; use [ClientCapabilities.AddExtension] - // to ensure nil settings are normalized to empty objects. - // The caller should not modify the map or its values after assigning it. - Extensions map[string]any `json:"extensions,omitempty"` - // Roots describes the client's support for roots. - // - // Deprecated: use RootsV2. As described in #607, Roots should have been a - // pointer to a RootCapabilities value. Roots will be continue to be - // populated, but any new fields will only be added in the RootsV2 field. - Roots struct { - // ListChanged reports whether the client supports notifications for - // changes to the roots list. - ListChanged bool `json:"listChanged,omitempty"` - } `json:"roots,omitempty"` - // RootsV2 is present if the client supports roots. When capabilities are explicitly configured via [ClientOptions.Capabilities] - RootsV2 *RootCapabilities `json:"-"` - // Sampling is present if the client supports sampling from an LLM. - Sampling *SamplingCapabilities `json:"sampling,omitempty"` - // Elicitation is present if the client supports elicitation from the server. - Elicitation *ElicitationCapabilities `json:"elicitation,omitempty"` -} - -// AddExtension adds an extension with the given name and settings. -// If settings is nil, an empty map is used to ensure valid JSON serialization -// (the spec requires an object, not null). -// The settings map should not be modified after the call. -func (c *ClientCapabilities) AddExtension(name string, settings map[string]any) { - if c.Extensions == nil { - c.Extensions = make(map[string]any) - } - if settings == nil { - settings = map[string]any{} - } - c.Extensions[name] = settings -} - -// clone returns a copy of the ClientCapabilities. -// Values in the Extensions and Experimental maps are shallow-copied. -func (c *ClientCapabilities) clone() *ClientCapabilities { - cp := *c - cp.Experimental = maps.Clone(c.Experimental) - cp.Extensions = maps.Clone(c.Extensions) - cp.RootsV2 = shallowClone(c.RootsV2) - if c.Sampling != nil { - x := *c.Sampling - x.Tools = shallowClone(c.Sampling.Tools) - x.Context = shallowClone(c.Sampling.Context) - cp.Sampling = &x - } - if c.Elicitation != nil { - x := *c.Elicitation - x.Form = shallowClone(c.Elicitation.Form) - x.URL = shallowClone(c.Elicitation.URL) - cp.Elicitation = &x - } - return &cp -} - -// shallowClone returns a shallow clone of *p, or nil if p is nil. -func shallowClone[T any](p *T) *T { - if p == nil { - return nil - } - x := *p - return &x -} - -func (c *ClientCapabilities) toV2() *clientCapabilitiesV2 { - return &clientCapabilitiesV2{ - ClientCapabilities: *c, - Roots: c.RootsV2, - } -} - -// clientCapabilitiesV2 is a version of ClientCapabilities that fixes the bug -// described in #607: Roots should have been a pointer to value type -// RootCapabilities. -type clientCapabilitiesV2 struct { - ClientCapabilities - Roots *RootCapabilities `json:"roots,omitempty"` -} - -func (c *clientCapabilitiesV2) toV1() *ClientCapabilities { - caps := c.ClientCapabilities - caps.RootsV2 = c.Roots - // Sync Roots from RootsV2 for backward compatibility (#607). - if caps.RootsV2 != nil { - caps.Roots = *caps.RootsV2 - } - return &caps -} - -type CompleteParamsArgument struct { - // The name of the argument - Name string `json:"name"` - // The value of the argument to use for completion matching. - Value string `json:"value"` -} - -// CompleteContext represents additional, optional context for completions. -type CompleteContext struct { - // Previously-resolved variables in a URI template or prompt. - Arguments map[string]string `json:"arguments,omitempty"` -} - -// CompleteReference represents a completion reference type (ref/prompt ref/resource). -// The Type field determines which other fields are relevant. -type CompleteReference struct { - Type string `json:"type"` - // Name is relevant when Type is "ref/prompt". - Name string `json:"name,omitempty"` - // URI is relevant when Type is "ref/resource". - URI string `json:"uri,omitempty"` -} - -func (r *CompleteReference) UnmarshalJSON(data []byte) error { - type wireCompleteReference CompleteReference // for naive unmarshaling - var r2 wireCompleteReference - if err := internaljson.Unmarshal(data, &r2); err != nil { - return err - } - switch r2.Type { - case "ref/prompt", "ref/resource": - if r2.Type == "ref/prompt" && r2.URI != "" { - return fmt.Errorf("reference of type %q must not have a URI set", r2.Type) - } - if r2.Type == "ref/resource" && r2.Name != "" { - return fmt.Errorf("reference of type %q must not have a Name set", r2.Type) - } - default: - return fmt.Errorf("unrecognized content type %q", r2.Type) - } - *r = CompleteReference(r2) - return nil -} - -func (r *CompleteReference) MarshalJSON() ([]byte, error) { - // Validation for marshalling: ensure consistency before converting to JSON. - switch r.Type { - case "ref/prompt": - if r.URI != "" { - return nil, fmt.Errorf("reference of type %q must not have a URI set for marshalling", r.Type) - } - case "ref/resource": - if r.Name != "" { - return nil, fmt.Errorf("reference of type %q must not have a Name set for marshalling", r.Type) - } - default: - return nil, fmt.Errorf("unrecognized reference type %q for marshalling", r.Type) - } - - type wireReference CompleteReference - return json.Marshal(wireReference(*r)) -} - -type CompleteParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // The argument's information - Argument CompleteParamsArgument `json:"argument"` - Context *CompleteContext `json:"context,omitempty"` - Ref *CompleteReference `json:"ref"` -} - -func (*CompleteParams) isParams() {} - -type CompletionResultDetails struct { - HasMore bool `json:"hasMore,omitempty"` - Total int `json:"total,omitempty"` - Values []string `json:"values"` -} - -// The server's response to a completion/complete request -type CompleteResult struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - Completion CompletionResultDetails `json:"completion"` -} - -func (*CompleteResult) isResult() {} - -type CreateMessageParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // A request to include context from one or more MCP servers (including the - // caller), to be attached to the prompt. The client may ignore this request. - // - // The default is "none". Values "thisServer" and - // "allServers" are soft-deprecated. Servers SHOULD only use these values if - // the client declares ClientCapabilities.sampling.context. These values may - // be removed in future spec releases. - IncludeContext string `json:"includeContext,omitempty"` - // The maximum number of tokens to sample, as requested by the server. The - // client may choose to sample fewer tokens than requested. - MaxTokens int64 `json:"maxTokens"` - Messages []*SamplingMessage `json:"messages"` - // Optional metadata to pass through to the LLM provider. The format of this - // metadata is provider-specific. - Metadata any `json:"metadata,omitempty"` - // The server's preferences for which model to select. The client may ignore - // these preferences. - ModelPreferences *ModelPreferences `json:"modelPreferences,omitempty"` - StopSequences []string `json:"stopSequences,omitempty"` - // An optional system prompt the server wants to use for sampling. The client - // may modify or omit this prompt. - SystemPrompt string `json:"systemPrompt,omitempty"` - Temperature float64 `json:"temperature,omitempty"` -} - -func (x *CreateMessageParams) isParams() {} -func (x *CreateMessageParams) GetProgressToken() any { return getProgressToken(x) } -func (x *CreateMessageParams) SetProgressToken(t any) { setProgressToken(x, t) } - -// CreateMessageWithToolsParams is a sampling request that includes tools. -// It extends the basic [CreateMessageParams] fields with tools, tool choice, -// and messages that support array content (for parallel tool calls). -// -// Use with [ServerSession.CreateMessageWithTools]. -type CreateMessageWithToolsParams struct { - Meta `json:"_meta,omitempty"` - IncludeContext string `json:"includeContext,omitempty"` - MaxTokens int64 `json:"maxTokens"` - // Messages supports array content for tool_use and tool_result blocks. - Messages []*SamplingMessageV2 `json:"messages"` - Metadata any `json:"metadata,omitempty"` - ModelPreferences *ModelPreferences `json:"modelPreferences,omitempty"` - StopSequences []string `json:"stopSequences,omitempty"` - SystemPrompt string `json:"systemPrompt,omitempty"` - Temperature float64 `json:"temperature,omitempty"` - // Tools is the list of tools available for the model to use. - Tools []*Tool `json:"tools,omitempty"` - // ToolChoice controls how the model should use tools. - ToolChoice *ToolChoice `json:"toolChoice,omitempty"` -} - -func (x *CreateMessageWithToolsParams) isParams() {} -func (x *CreateMessageWithToolsParams) GetProgressToken() any { return getProgressToken(x) } -func (x *CreateMessageWithToolsParams) SetProgressToken(t any) { setProgressToken(x, t) } - -// toBase converts to CreateMessageParams by taking the content block from each -// message. Tools and ToolChoice are dropped. Returns an error if any message -// has multiple content blocks, since SamplingMessage only supports one. -func (p *CreateMessageWithToolsParams) toBase() (*CreateMessageParams, error) { - var msgs []*SamplingMessage - for _, m := range p.Messages { - if len(m.Content) > 1 { - return nil, fmt.Errorf("message has %d content blocks; use CreateMessageWithToolsHandler to support multiple content", len(m.Content)) - } - var content Content - if len(m.Content) > 0 { - content = m.Content[0] - } - msgs = append(msgs, &SamplingMessage{Content: content, Role: m.Role}) - } - return &CreateMessageParams{ - Meta: p.Meta, - IncludeContext: p.IncludeContext, - MaxTokens: p.MaxTokens, - Messages: msgs, - Metadata: p.Metadata, - ModelPreferences: p.ModelPreferences, - StopSequences: p.StopSequences, - SystemPrompt: p.SystemPrompt, - Temperature: p.Temperature, - }, nil -} - -// SamplingMessageV2 describes a message issued to or received from an -// LLM API, supporting array content for parallel tool calls. The "V2" refers -// to the 2025-11-25 spec, which changed content from a single block to -// single-or-array. In v2 of the SDK, this will replace [SamplingMessage]. -// -// When marshaling, a single-element Content slice is marshaled as a single -// object for compatibility with pre-2025-11-25 implementations. When -// unmarshaling, a single JSON content object is accepted and wrapped in a -// one-element slice. -type SamplingMessageV2 struct { - Content []Content `json:"content"` - Role Role `json:"role"` -} - -var samplingWithToolsAllow = map[string]bool{ - "text": true, "image": true, "audio": true, - "tool_use": true, "tool_result": true, -} - -// MarshalJSON marshals the message. A single-element Content slice is marshaled -// as a single object for backward compatibility. -func (m *SamplingMessageV2) MarshalJSON() ([]byte, error) { - if len(m.Content) == 1 { - return json.Marshal(&SamplingMessage{Content: m.Content[0], Role: m.Role}) - } - type msg SamplingMessageV2 // avoid recursion - return json.Marshal((*msg)(m)) -} - -func (m *SamplingMessageV2) UnmarshalJSON(data []byte) error { - type msg SamplingMessageV2 // avoid recursion - var wire struct { - msg - Content json.RawMessage `json:"content"` - } - if err := internaljson.Unmarshal(data, &wire); err != nil { - return err - } - var err error - if wire.msg.Content, err = unmarshalContent(wire.Content, samplingWithToolsAllow); err != nil { - return err - } - *m = SamplingMessageV2(wire.msg) - return nil -} - -// The client's response to a sampling/create_message request from the server. -// The client should inform the user before returning the sampled message, to -// allow them to inspect the response (human in the loop) and decide whether to -// allow the server to see it. -type CreateMessageResult struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - Content Content `json:"content"` - // The name of the model that generated the message. - Model string `json:"model"` - Role Role `json:"role"` - // The reason why sampling stopped, if known. - // - // Standard values: - // - "endTurn": natural end of the assistant's turn - // - "stopSequence": a stop sequence was encountered - // - "maxTokens": reached the maximum token limit - // - "toolUse": the model wants to use one or more tools - StopReason string `json:"stopReason,omitempty"` -} - -func (*CreateMessageResult) isResult() {} -func (r *CreateMessageResult) UnmarshalJSON(data []byte) error { - type result CreateMessageResult // avoid recursion - var wire struct { - result - Content *wireContent `json:"content"` - } - if err := internaljson.Unmarshal(data, &wire); err != nil { - return err - } - var err error - if wire.result.Content, err = contentFromWire(wire.Content, map[string]bool{"text": true, "image": true, "audio": true}); err != nil { - return err - } - *r = CreateMessageResult(wire.result) - return nil -} - -// CreateMessageWithToolsResult is the client's response to a -// sampling/create_message request that included tools. Content is a slice to -// support parallel tool calls (multiple tool_use blocks in one response). -// -// Use [ServerSession.CreateMessageWithTools] to send a sampling request with -// tools and receive this result type. -// -// When unmarshaling, a single JSON content object is accepted and wrapped in a -// one-element slice, for compatibility with clients that return a single block. -type CreateMessageWithToolsResult struct { - Meta `json:"_meta,omitempty"` - Content []Content `json:"content"` - Model string `json:"model"` - Role Role `json:"role"` - // The reason why sampling stopped. - // - // Standard values: "endTurn", "stopSequence", "maxTokens", "toolUse". - StopReason string `json:"stopReason,omitempty"` -} - -// createMessageWithToolsResultAllow lists content types valid in assistant responses. -// tool_result is excluded: it only appears in user messages. -var createMessageWithToolsResultAllow = map[string]bool{ - "text": true, "image": true, "audio": true, - "tool_use": true, -} - -func (*CreateMessageWithToolsResult) isResult() {} - -// MarshalJSON marshals the result. When Content has a single element, it is -// marshaled as a single object for compatibility with pre-2025-11-25 -// implementations that expect a single content block. -func (r *CreateMessageWithToolsResult) MarshalJSON() ([]byte, error) { - if len(r.Content) == 1 { - return json.Marshal(&CreateMessageResult{ - Meta: r.Meta, - Content: r.Content[0], - Model: r.Model, - Role: r.Role, - StopReason: r.StopReason, - }) - } - type result CreateMessageWithToolsResult // avoid recursion - return json.Marshal((*result)(r)) -} - -func (r *CreateMessageWithToolsResult) UnmarshalJSON(data []byte) error { - type result CreateMessageWithToolsResult // avoid recursion - var wire struct { - result - Content json.RawMessage `json:"content"` - } - if err := internaljson.Unmarshal(data, &wire); err != nil { - return err - } - var err error - if wire.result.Content, err = unmarshalContent(wire.Content, createMessageWithToolsResultAllow); err != nil { - return err - } - *r = CreateMessageWithToolsResult(wire.result) - return nil -} - -// toWithTools converts a CreateMessageResult to CreateMessageWithToolsResult. -func (r *CreateMessageResult) toWithTools() *CreateMessageWithToolsResult { - var content []Content - if r.Content != nil { - content = []Content{r.Content} - } - return &CreateMessageWithToolsResult{ - Meta: r.Meta, - Content: content, - Model: r.Model, - Role: r.Role, - StopReason: r.StopReason, - } -} - -type GetPromptParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // Arguments to use for templating the prompt. - Arguments map[string]string `json:"arguments,omitempty"` - // The name of the prompt or prompt template. - Name string `json:"name"` -} - -func (x *GetPromptParams) isParams() {} -func (x *GetPromptParams) GetProgressToken() any { return getProgressToken(x) } -func (x *GetPromptParams) SetProgressToken(t any) { setProgressToken(x, t) } - -// The server's response to a prompts/get request from the client. -type GetPromptResult struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // An optional description for the prompt. - Description string `json:"description,omitempty"` - Messages []*PromptMessage `json:"messages"` -} - -func (*GetPromptResult) isResult() {} - -// InitializeParams is sent by the client to initialize the session. -type InitializeParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // Capabilities describes the client's capabilities. - Capabilities *ClientCapabilities `json:"capabilities"` - // ClientInfo provides information about the client. - ClientInfo *Implementation `json:"clientInfo"` - // ProtocolVersion is the latest version of the Model Context Protocol that - // the client supports. - ProtocolVersion string `json:"protocolVersion"` -} - -func (p *InitializeParams) toV2() *initializeParamsV2 { - return &initializeParamsV2{ - InitializeParams: *p, - Capabilities: p.Capabilities.toV2(), - } -} - -// initializeParamsV2 works around the mistake in #607: Capabilities.Roots -// should have been a pointer. -type initializeParamsV2 struct { - InitializeParams - Capabilities *clientCapabilitiesV2 `json:"capabilities"` -} - -func (p *initializeParamsV2) toV1() *InitializeParams { - p1 := p.InitializeParams - if p.Capabilities != nil { - p1.Capabilities = p.Capabilities.toV1() - } - return &p1 -} - -func (x *InitializeParams) isParams() {} -func (x *InitializeParams) GetProgressToken() any { return getProgressToken(x) } -func (x *InitializeParams) SetProgressToken(t any) { setProgressToken(x, t) } - -// InitializeResult is sent by the server in response to an initialize request -// from the client. -type InitializeResult struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // Capabilities describes the server's capabilities. - Capabilities *ServerCapabilities `json:"capabilities"` - // Instructions describing how to use the server and its features. - // - // This can be used by clients to improve the LLM's understanding of available - // tools, resources, etc. It can be thought of like a "hint" to the model. For - // example, this information may be added to the system prompt. - Instructions string `json:"instructions,omitempty"` - // The version of the Model Context Protocol that the server wants to use. This - // may not match the version that the client requested. If the client cannot - // support this version, it must disconnect. - ProtocolVersion string `json:"protocolVersion"` - ServerInfo *Implementation `json:"serverInfo"` -} - -func (*InitializeResult) isResult() {} - -type InitializedParams struct { - // Meta is reserved by the protocol to allow clients and servers to attach - // additional metadata to their responses. - Meta `json:"_meta,omitempty"` -} - -func (x *InitializedParams) isParams() {} -func (x *InitializedParams) GetProgressToken() any { return getProgressToken(x) } -func (x *InitializedParams) SetProgressToken(t any) { setProgressToken(x, t) } - -type ListPromptsParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // An opaque token representing the current pagination position. If provided, - // the server should return results starting after this cursor. - Cursor string `json:"cursor,omitempty"` -} - -func (x *ListPromptsParams) isParams() {} -func (x *ListPromptsParams) GetProgressToken() any { return getProgressToken(x) } -func (x *ListPromptsParams) SetProgressToken(t any) { setProgressToken(x, t) } -func (x *ListPromptsParams) cursorPtr() *string { return &x.Cursor } - -// The server's response to a prompts/list request from the client. -type ListPromptsResult struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // An opaque token representing the pagination position after the last returned - // result. If present, there may be more results available. - NextCursor string `json:"nextCursor,omitempty"` - Prompts []*Prompt `json:"prompts"` -} - -func (x *ListPromptsResult) isResult() {} -func (x *ListPromptsResult) nextCursorPtr() *string { return &x.NextCursor } - -type ListResourceTemplatesParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // An opaque token representing the current pagination position. If provided, - // the server should return results starting after this cursor. - Cursor string `json:"cursor,omitempty"` -} - -func (x *ListResourceTemplatesParams) isParams() {} -func (x *ListResourceTemplatesParams) GetProgressToken() any { return getProgressToken(x) } -func (x *ListResourceTemplatesParams) SetProgressToken(t any) { setProgressToken(x, t) } -func (x *ListResourceTemplatesParams) cursorPtr() *string { return &x.Cursor } - -// The server's response to a resources/templates/list request from the client. -type ListResourceTemplatesResult struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // An opaque token representing the pagination position after the last returned - // result. If present, there may be more results available. - NextCursor string `json:"nextCursor,omitempty"` - ResourceTemplates []*ResourceTemplate `json:"resourceTemplates"` -} - -func (x *ListResourceTemplatesResult) isResult() {} -func (x *ListResourceTemplatesResult) nextCursorPtr() *string { return &x.NextCursor } - -type ListResourcesParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // An opaque token representing the current pagination position. If provided, - // the server should return results starting after this cursor. - Cursor string `json:"cursor,omitempty"` -} - -func (x *ListResourcesParams) isParams() {} -func (x *ListResourcesParams) GetProgressToken() any { return getProgressToken(x) } -func (x *ListResourcesParams) SetProgressToken(t any) { setProgressToken(x, t) } -func (x *ListResourcesParams) cursorPtr() *string { return &x.Cursor } - -// The server's response to a resources/list request from the client. -type ListResourcesResult struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // An opaque token representing the pagination position after the last returned - // result. If present, there may be more results available. - NextCursor string `json:"nextCursor,omitempty"` - Resources []*Resource `json:"resources"` -} - -func (x *ListResourcesResult) isResult() {} -func (x *ListResourcesResult) nextCursorPtr() *string { return &x.NextCursor } - -type ListRootsParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` -} - -func (x *ListRootsParams) isParams() {} -func (x *ListRootsParams) GetProgressToken() any { return getProgressToken(x) } -func (x *ListRootsParams) SetProgressToken(t any) { setProgressToken(x, t) } - -// The client's response to a roots/list request from the server. This result -// contains an array of Root objects, each representing a root directory or file -// that the server can operate on. -type ListRootsResult struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - Roots []*Root `json:"roots"` -} - -func (*ListRootsResult) isResult() {} - -type ListToolsParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // An opaque token representing the current pagination position. If provided, - // the server should return results starting after this cursor. - Cursor string `json:"cursor,omitempty"` -} - -func (x *ListToolsParams) isParams() {} -func (x *ListToolsParams) GetProgressToken() any { return getProgressToken(x) } -func (x *ListToolsParams) SetProgressToken(t any) { setProgressToken(x, t) } -func (x *ListToolsParams) cursorPtr() *string { return &x.Cursor } - -// The server's response to a tools/list request from the client. -type ListToolsResult struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // An opaque token representing the pagination position after the last returned - // result. If present, there may be more results available. - NextCursor string `json:"nextCursor,omitempty"` - Tools []*Tool `json:"tools"` -} - -func (x *ListToolsResult) isResult() {} -func (x *ListToolsResult) nextCursorPtr() *string { return &x.NextCursor } - -// The severity of a log message. -// -// These map to syslog message severities, as specified in RFC-5424: -// https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1 -type LoggingLevel string - -type LoggingMessageParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // The data to be logged, such as a string message or an object. Any JSON - // serializable type is allowed here. - Data any `json:"data"` - // The severity of this log message. - Level LoggingLevel `json:"level"` - // An optional name of the logger issuing this message. - Logger string `json:"logger,omitempty"` -} - -func (x *LoggingMessageParams) isParams() {} -func (x *LoggingMessageParams) GetProgressToken() any { return getProgressToken(x) } -func (x *LoggingMessageParams) SetProgressToken(t any) { setProgressToken(x, t) } - -// Hints to use for model selection. -// -// Keys not declared here are currently left unspecified by the spec and are up -// to the client to interpret. -type ModelHint struct { - // A hint for a model name. - // - // The client should treat this as a substring of a model name; for example: - - // `claude-3-5-sonnet` should match `claude-3-5-sonnet-20241022` - `sonnet` - // should match `claude-3-5-sonnet-20241022`, `claude-3-sonnet-20240229`, etc. - - // `claude` should match any Claude model - // - // The client may also map the string to a different provider's model name or a - // different model family, as long as it fills a similar niche; for example: - - // `gemini-1.5-flash` could match `claude-3-haiku-20240307` - Name string `json:"name,omitempty"` -} - -// The server's preferences for model selection, requested of the client during -// sampling. -// -// Because LLMs can vary along multiple dimensions, choosing the "best" model is -// rarely straightforward. Different models excel in different areas—some are -// faster but less capable, others are more capable but more expensive, and so -// on. This interface allows servers to express their priorities across multiple -// dimensions to help clients make an appropriate selection for their use case. -// -// These preferences are always advisory. The client may ignore them. It is also -// up to the client to decide how to interpret these preferences and how to -// balance them against other considerations. -type ModelPreferences struct { - // How much to prioritize cost when selecting a model. A value of 0 means cost - // is not important, while a value of 1 means cost is the most important factor. - CostPriority float64 `json:"costPriority,omitempty"` - // Optional hints to use for model selection. - // - // If multiple hints are specified, the client must evaluate them in order (such - // that the first match is taken). - // - // The client should prioritize these hints over the numeric priorities, but may - // still use the priorities to select from ambiguous matches. - Hints []*ModelHint `json:"hints,omitempty"` - // How much to prioritize intelligence and capabilities when selecting a model. - // A value of 0 means intelligence is not important, while a value of 1 means - // intelligence is the most important factor. - IntelligencePriority float64 `json:"intelligencePriority,omitempty"` - // How much to prioritize sampling speed (latency) when selecting a model. A - // value of 0 means speed is not important, while a value of 1 means speed is - // the most important factor. - SpeedPriority float64 `json:"speedPriority,omitempty"` -} - -type PingParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` -} - -func (x *PingParams) isParams() {} -func (x *PingParams) GetProgressToken() any { return getProgressToken(x) } -func (x *PingParams) SetProgressToken(t any) { setProgressToken(x, t) } - -type ProgressNotificationParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // The progress token which was given in the initial request, used to associate - // this notification with the request that is proceeding. - ProgressToken any `json:"progressToken"` - // An optional message describing the current progress. - Message string `json:"message,omitempty"` - // The progress thus far. This should increase every time progress is made, even - // if the total is unknown. - Progress float64 `json:"progress"` - // Total number of items to process (or total progress required), if known. - // Zero means unknown. - Total float64 `json:"total,omitempty"` -} - -func (*ProgressNotificationParams) isParams() {} - -// IconTheme specifies the theme an icon is designed for. -type IconTheme string - -const ( - // IconThemeLight indicates the icon is designed for a light background. - IconThemeLight IconTheme = "light" - // IconThemeDark indicates the icon is designed for a dark background. - IconThemeDark IconTheme = "dark" -) - -// Icon provides visual identifiers for their resources, tools, prompts, and implementations -// See [/specification/draft/basic/index#icons] for notes on icons -// -// TODO(iamsurajbobade): update specification url from draft. -type Icon struct { - // Source is A URI pointing to the icon resource (required). This can be: - // - An HTTP/HTTPS URL pointing to an image file - // - A data URI with base64-encoded image data - Source string `json:"src"` - // Optional MIME type if the server's type is missing or generic - MIMEType string `json:"mimeType,omitempty"` - // Optional size specification (e.g., ["48x48"], ["any"] for scalable formats like SVG, or ["48x48", "96x96"] for multiple sizes) - Sizes []string `json:"sizes,omitempty"` - // Optional theme specifier. "light" indicates the icon is designed for a light - // background, "dark" indicates the icon is designed for a dark background. - Theme IconTheme `json:"theme,omitempty"` -} - -// A prompt or prompt template that the server offers. -type Prompt struct { - // See [specification/2025-06-18/basic/index#general-fields] for notes on _meta - // usage. - Meta `json:"_meta,omitempty"` - // A list of arguments to use for templating the prompt. - Arguments []*PromptArgument `json:"arguments,omitempty"` - // An optional description of what this prompt provides - Description string `json:"description,omitempty"` - // Intended for programmatic or logical use, but used as a display name in past - // specs or fallback (if title isn't present). - Name string `json:"name"` - // Intended for UI and end-user contexts — optimized to be human-readable and - // easily understood, even by those unfamiliar with domain-specific terminology. - Title string `json:"title,omitempty"` - // Icons for the prompt, if any. - Icons []Icon `json:"icons,omitempty"` -} - -// Describes an argument that a prompt can accept. -type PromptArgument struct { - // Intended for programmatic or logical use, but used as a display name in past - // specs or fallback (if title isn't present). - Name string `json:"name"` - // Intended for UI and end-user contexts — optimized to be human-readable and - // easily understood, even by those unfamiliar with domain-specific terminology. - Title string `json:"title,omitempty"` - // A human-readable description of the argument. - Description string `json:"description,omitempty"` - // Whether this argument must be provided. - Required bool `json:"required,omitempty"` -} - -type PromptListChangedParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` -} - -func (x *PromptListChangedParams) isParams() {} -func (x *PromptListChangedParams) GetProgressToken() any { return getProgressToken(x) } -func (x *PromptListChangedParams) SetProgressToken(t any) { setProgressToken(x, t) } - -// Describes a message returned as part of a prompt. -// -// This is similar to SamplingMessage, but also supports the embedding of -// resources from the MCP server. -type PromptMessage struct { - Content Content `json:"content"` - Role Role `json:"role"` -} - -// UnmarshalJSON handles the unmarshalling of content into the Content -// interface. -func (m *PromptMessage) UnmarshalJSON(data []byte) error { - type msg PromptMessage // avoid recursion - var wire struct { - msg - Content *wireContent `json:"content"` - } - if err := internaljson.Unmarshal(data, &wire); err != nil { - return err - } - var err error - if wire.msg.Content, err = contentFromWire(wire.Content, nil); err != nil { - return err - } - *m = PromptMessage(wire.msg) - return nil -} - -type ReadResourceParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // The URI of the resource to read. The URI can use any protocol; it is up to - // the server how to interpret it. - URI string `json:"uri"` -} - -func (x *ReadResourceParams) isParams() {} -func (x *ReadResourceParams) GetProgressToken() any { return getProgressToken(x) } -func (x *ReadResourceParams) SetProgressToken(t any) { setProgressToken(x, t) } - -// The server's response to a resources/read request from the client. -type ReadResourceResult struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - Contents []*ResourceContents `json:"contents"` -} - -func (*ReadResourceResult) isResult() {} - -// A known resource that the server is capable of reading. -type Resource struct { - // See [specification/2025-06-18/basic/index#general-fields] for notes on _meta - // usage. - Meta `json:"_meta,omitempty"` - // Optional annotations for the client. - Annotations *Annotations `json:"annotations,omitempty"` - // A description of what this resource represents. - // - // This can be used by clients to improve the LLM's understanding of available - // resources. It can be thought of like a "hint" to the model. - Description string `json:"description,omitempty"` - // The MIME type of this resource, if known. - MIMEType string `json:"mimeType,omitempty"` - // Intended for programmatic or logical use, but used as a display name in past - // specs or fallback (if title isn't present). - Name string `json:"name"` - // The size of the raw resource content, in bytes (i.e., before base64 encoding - // or any tokenization), if known. - // - // This can be used by Hosts to display file sizes and estimate context window - // usage. - Size int64 `json:"size,omitempty"` - // Intended for UI and end-user contexts — optimized to be human-readable and - // easily understood, even by those unfamiliar with domain-specific terminology. - // - // If not provided, the name should be used for display (except for Tool, where - // Annotations.Title should be given precedence over using name, if - // present). - Title string `json:"title,omitempty"` - // The URI of this resource. - URI string `json:"uri"` - // Icons for the resource, if any. - Icons []Icon `json:"icons,omitempty"` -} - -type ResourceListChangedParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` -} - -func (x *ResourceListChangedParams) isParams() {} -func (x *ResourceListChangedParams) GetProgressToken() any { return getProgressToken(x) } -func (x *ResourceListChangedParams) SetProgressToken(t any) { setProgressToken(x, t) } - -// A template description for resources available on the server. -type ResourceTemplate struct { - // See [specification/2025-06-18/basic/index#general-fields] for notes on _meta - // usage. - Meta `json:"_meta,omitempty"` - // Optional annotations for the client. - Annotations *Annotations `json:"annotations,omitempty"` - // A description of what this template is for. - // - // This can be used by clients to improve the LLM's understanding of available - // resources. It can be thought of like a "hint" to the model. - Description string `json:"description,omitempty"` - // The MIME type for all resources that match this template. This should only be - // included if all resources matching this template have the same type. - MIMEType string `json:"mimeType,omitempty"` - // Intended for programmatic or logical use, but used as a display name in past - // specs or fallback (if title isn't present). - Name string `json:"name"` - // Intended for UI and end-user contexts — optimized to be human-readable and - // easily understood, even by those unfamiliar with domain-specific terminology. - // - // If not provided, the name should be used for display (except for Tool, where - // Annotations.Title should be given precedence over using name, if - // present). - Title string `json:"title,omitempty"` - // A URI template (according to RFC 6570) that can be used to construct resource - // URIs. - URITemplate string `json:"uriTemplate"` - // Icons for the resource template, if any. - Icons []Icon `json:"icons,omitempty"` -} - -// The sender or recipient of messages and data in a conversation. -type Role string - -// Represents a root directory or file that the server can operate on. -type Root struct { - // See [specification/2025-06-18/basic/index#general-fields] for notes on _meta - // usage. - Meta `json:"_meta,omitempty"` - // An optional name for the root. This can be used to provide a human-readable - // identifier for the root, which may be useful for display purposes or for - // referencing the root in other parts of the application. - Name string `json:"name,omitempty"` - // The URI identifying the root. This *must* start with file:// for now. This - // restriction may be relaxed in future versions of the protocol to allow other - // URI schemes. - URI string `json:"uri"` -} - -type RootsListChangedParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` -} - -func (x *RootsListChangedParams) isParams() {} -func (x *RootsListChangedParams) GetProgressToken() any { return getProgressToken(x) } -func (x *RootsListChangedParams) SetProgressToken(t any) { setProgressToken(x, t) } - -// TODO: to be consistent with ServerCapabilities, move the capability types -// below directly above ClientCapabilities. - -// SamplingCapabilities describes the client's support for sampling. -type SamplingCapabilities struct { - // Context indicates the client supports includeContext values other than "none". - Context *SamplingContextCapabilities `json:"context,omitempty"` - // Tools indicates the client supports tools and toolChoice in sampling requests. - Tools *SamplingToolsCapabilities `json:"tools,omitempty"` -} - -// SamplingContextCapabilities indicates the client supports context inclusion. -type SamplingContextCapabilities struct{} - -// SamplingToolsCapabilities indicates the client supports tool use in sampling. -type SamplingToolsCapabilities struct{} - -// ToolChoice controls how the model uses tools during sampling. -type ToolChoice struct { - // Mode controls tool invocation behavior: - // - "auto": Model decides whether to use tools (default) - // - "required": Model must use at least one tool - // - "none": Model must not use any tools - Mode string `json:"mode,omitempty"` -} - -// ElicitationCapabilities describes the capabilities for elicitation. -// -// If neither Form nor URL is set, the 'Form' capabilitiy is assumed. -type ElicitationCapabilities struct { - Form *FormElicitationCapabilities `json:"form,omitempty"` - URL *URLElicitationCapabilities `json:"url,omitempty"` -} - -// FormElicitationCapabilities describes capabilities for form elicitation. -type FormElicitationCapabilities struct{} - -// URLElicitationCapabilities describes capabilities for url elicitation. -type URLElicitationCapabilities struct{} - -// Describes a message issued to or received from an LLM API. -// -// For assistant messages, Content may be text, image, audio, or tool_use. -// For user messages, Content may be text, image, audio, or tool_result. -type SamplingMessage struct { - Content Content `json:"content"` - Role Role `json:"role"` -} - -// UnmarshalJSON handles the unmarshalling of content into the Content -// interface. -func (m *SamplingMessage) UnmarshalJSON(data []byte) error { - type msg SamplingMessage // avoid recursion - var wire struct { - msg - Content *wireContent `json:"content"` - } - if err := internaljson.Unmarshal(data, &wire); err != nil { - return err - } - // Allow text, image, audio, tool_use, and tool_result in sampling messages - var err error - if wire.msg.Content, err = contentFromWire(wire.Content, map[string]bool{"text": true, "image": true, "audio": true, "tool_use": true, "tool_result": true}); err != nil { - return err - } - *m = SamplingMessage(wire.msg) - return nil -} - -type SetLoggingLevelParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // The level of logging that the client wants to receive from the server. The - // server should send all logs at this level and higher (i.e., more severe) to - // the client as notifications/message. - Level LoggingLevel `json:"level"` -} - -func (x *SetLoggingLevelParams) isParams() {} -func (x *SetLoggingLevelParams) GetProgressToken() any { return getProgressToken(x) } -func (x *SetLoggingLevelParams) SetProgressToken(t any) { setProgressToken(x, t) } - -// Definition for a tool the client can call. -type Tool struct { - // See [specification/2025-06-18/basic/index#general-fields] for notes on _meta - // usage. - Meta `json:"_meta,omitempty"` - // Optional additional tool information. - // - // Display name precedence order is: title, annotations.title, then name. - Annotations *ToolAnnotations `json:"annotations,omitempty"` - // A human-readable description of the tool. - // - // This can be used by clients to improve the LLM's understanding of available - // tools. It can be thought of like a "hint" to the model. - Description string `json:"description,omitempty"` - // InputSchema holds a JSON Schema object defining the expected parameters - // for the tool. - // - // From the server, this field may be set to any value that JSON-marshals to - // valid JSON schema (including json.RawMessage). However, for tools added - // using [AddTool], which automatically validates inputs and outputs, the - // schema must be in a draft the SDK understands. Currently, the SDK uses - // github.com/google/jsonschema-go for inference and validation, which only - // supports the 2020-12 draft of JSON schema. To do your own validation, use - // [Server.AddTool]. - // - // From the client, this field will hold the default JSON marshaling of the - // server's input schema (a map[string]any). - InputSchema any `json:"inputSchema"` - // Intended for programmatic or logical use, but used as a display name in past - // specs or fallback (if title isn't present). - Name string `json:"name"` - // OutputSchema holds an optional JSON Schema object defining the structure - // of the tool's output returned in the StructuredContent field of a - // CallToolResult. - // - // From the server, this field may be set to any value that JSON-marshals to - // valid JSON schema (including json.RawMessage). However, for tools added - // using [AddTool], which automatically validates inputs and outputs, the - // schema must be in a draft the SDK understands. Currently, the SDK uses - // github.com/google/jsonschema-go for inference and validation, which only - // supports the 2020-12 draft of JSON schema. To do your own validation, use - // [Server.AddTool]. - // - // From the client, this field will hold the default JSON marshaling of the - // server's output schema (a map[string]any). - OutputSchema any `json:"outputSchema,omitempty"` - // Intended for UI and end-user contexts — optimized to be human-readable and - // easily understood, even by those unfamiliar with domain-specific terminology. - // If not provided, Annotations.Title should be used for display if present, - // otherwise Name. - Title string `json:"title,omitempty"` - // Icons for the tool, if any. - Icons []Icon `json:"icons,omitempty"` -} - -// Additional properties describing a Tool to clients. -// -// NOTE: all properties in ToolAnnotations are hints. They are not -// guaranteed to provide a faithful description of tool behavior (including -// descriptive properties like title). -// -// Clients should never make tool use decisions based on ToolAnnotations -// received from untrusted servers. -type ToolAnnotations struct { - // If true, the tool may perform destructive updates to its environment. If - // false, the tool performs only additive updates. - // - // (This property is meaningful only when ReadOnlyHint == false.) - // - // Default: true - DestructiveHint *bool `json:"destructiveHint,omitempty"` - // If true, calling the tool repeatedly with the same arguments will have no - // additional effect on the its environment. - // - // (This property is meaningful only when ReadOnlyHint == false.) - // - // Default: false - IdempotentHint bool `json:"idempotentHint,omitempty"` - // If true, this tool may interact with an "open world" of external entities. If - // false, the tool's domain of interaction is closed. For example, the world of - // a web search tool is open, whereas that of a memory tool is not. - // - // Default: true - OpenWorldHint *bool `json:"openWorldHint,omitempty"` - // If true, the tool does not modify its environment. - // - // Default: false - ReadOnlyHint bool `json:"readOnlyHint,omitempty"` - // A human-readable title for the tool. - Title string `json:"title,omitempty"` -} - -type ToolListChangedParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` -} - -func (x *ToolListChangedParams) isParams() {} -func (x *ToolListChangedParams) GetProgressToken() any { return getProgressToken(x) } -func (x *ToolListChangedParams) SetProgressToken(t any) { setProgressToken(x, t) } - -// Sent from the client to request resources/updated notifications from the -// server whenever a particular resource changes. -type SubscribeParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // The URI of the resource to subscribe to. - URI string `json:"uri"` -} - -func (*SubscribeParams) isParams() {} - -// Sent from the client to request cancellation of resources/updated -// notifications from the server. This should follow a previous -// resources/subscribe request. -type UnsubscribeParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // The URI of the resource to unsubscribe from. - URI string `json:"uri"` -} - -func (*UnsubscribeParams) isParams() {} - -// A notification from the server to the client, informing it that a resource -// has changed and may need to be read again. This should only be sent if the -// client previously sent a resources/subscribe request. -type ResourceUpdatedNotificationParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // The URI of the resource that has been updated. This might be a sub-resource of the one that the client actually subscribed to. - URI string `json:"uri"` -} - -func (*ResourceUpdatedNotificationParams) isParams() {} - -// TODO(jba): add CompleteRequest and related types. - -// A request from the server to elicit additional information from the user via the client. -type ElicitParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // The mode of elicitation to use. - // - // If unset, will be inferred from the other fields. - Mode string `json:"mode"` - // The message to present to the user. - Message string `json:"message"` - // A JSON schema object defining the requested elicitation schema. - // - // From the server, this field may be set to any value that can JSON-marshal - // to valid JSON schema (including json.RawMessage for raw schema values). - // Internally, the SDK uses github.com/google/jsonschema-go for validation, - // which only supports the 2020-12 draft of the JSON schema spec. - // - // From the client, this field will use the default JSON marshaling (a - // map[string]any). - // - // Only top-level properties are allowed, without nesting. - // - // This is only used for "form" elicitation. - RequestedSchema any `json:"requestedSchema,omitempty"` - // The URL to present to the user. - // - // This is only used for "url" elicitation. - URL string `json:"url,omitempty"` - // The ID of the elicitation. - // - // This is only used for "url" elicitation. - ElicitationID string `json:"elicitationId,omitempty"` -} - -func (x *ElicitParams) isParams() {} - -func (x *ElicitParams) GetProgressToken() any { return getProgressToken(x) } -func (x *ElicitParams) SetProgressToken(t any) { setProgressToken(x, t) } - -// The client's response to an elicitation/create request from the server. -type ElicitResult struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // The user action in response to the elicitation. - // - "accept": User submitted the form/confirmed the action - // - "decline": User explicitly declined the action - // - "cancel": User dismissed without making an explicit choice - Action string `json:"action"` - // The submitted form data, only present when action is "accept". - // Contains values matching the requested schema. - Content map[string]any `json:"content,omitempty"` -} - -func (*ElicitResult) isResult() {} - -// ElicitationCompleteParams is sent from the server to the client, informing it that an out-of-band elicitation interaction has completed. -type ElicitationCompleteParams struct { - // This property is reserved by the protocol to allow clients and servers to - // attach additional metadata to their responses. - Meta `json:"_meta,omitempty"` - // The ID of the elicitation that has completed. This must correspond to the - // elicitationId from the original elicitation/create request. - ElicitationID string `json:"elicitationId"` -} - -func (*ElicitationCompleteParams) isParams() {} - -// An Implementation describes the name and version of an MCP implementation, with an optional -// title for UI representation. -type Implementation struct { - // Intended for programmatic or logical use, but used as a display name in past - // specs or fallback (if title isn't present). - Name string `json:"name"` - // Intended for UI and end-user contexts — optimized to be human-readable and - // easily understood, even by those unfamiliar with domain-specific terminology. - Title string `json:"title,omitempty"` - Version string `json:"version"` - // WebsiteURL for the server, if any. - WebsiteURL string `json:"websiteUrl,omitempty"` - // Icons for the Server, if any. - Icons []Icon `json:"icons,omitempty"` -} - -// CompletionCapabilities describes the server's support for argument autocompletion. -type CompletionCapabilities struct{} - -// LoggingCapabilities describes the server's support for sending log messages to the client. -type LoggingCapabilities struct{} - -// PromptCapabilities describes the server's support for prompts. -type PromptCapabilities struct { - // Whether this server supports notifications for changes to the prompt list. - ListChanged bool `json:"listChanged,omitempty"` -} - -// ResourceCapabilities describes the server's support for resources. -type ResourceCapabilities struct { - // ListChanged reports whether the client supports notifications for - // changes to the resource list. - ListChanged bool `json:"listChanged,omitempty"` - // Subscribe reports whether this server supports subscribing to resource - // updates. - Subscribe bool `json:"subscribe,omitempty"` -} - -// ToolCapabilities describes the server's support for tools. -type ToolCapabilities struct { - // ListChanged reports whether the client supports notifications for - // changes to the tool list. - ListChanged bool `json:"listChanged,omitempty"` -} - -// ServerCapabilities describes capabilities that a server supports. -type ServerCapabilities struct { - // NOTE: any addition to ServerCapabilities must also be reflected in - // [ServerCapabilities.clone]. - - // Experimental reports non-standard capabilities that the server supports. - // The caller should not modify the map after assigning it. - Experimental map[string]any `json:"experimental,omitempty"` - // Extensions reports extensions that the server supports. - // Keys are extension identifiers in "{vendor-prefix}/{extension-name}" format. - // Values are per-extension settings objects; use [ServerCapabilities.AddExtension] - // to ensure nil settings are normalized to empty objects. - // The caller should not modify the map or its values after assigning it. - Extensions map[string]any `json:"extensions,omitempty"` - // Completions is present if the server supports argument autocompletion - // suggestions. - Completions *CompletionCapabilities `json:"completions,omitempty"` - // Logging is present if the server supports log messages. - Logging *LoggingCapabilities `json:"logging,omitempty"` - // Prompts is present if the server supports prompts. - Prompts *PromptCapabilities `json:"prompts,omitempty"` - // Resources is present if the server supports resourcs. - Resources *ResourceCapabilities `json:"resources,omitempty"` - // Tools is present if the supports tools. - Tools *ToolCapabilities `json:"tools,omitempty"` -} - -// AddExtension adds an extension with the given name and settings. -// If settings is nil, an empty map is used to ensure valid JSON serialization -// (the spec requires an object, not null). -// The settings map should not be modified after the call. -func (c *ServerCapabilities) AddExtension(name string, settings map[string]any) { - if c.Extensions == nil { - c.Extensions = make(map[string]any) - } - if settings == nil { - settings = map[string]any{} - } - c.Extensions[name] = settings -} - -// clone returns a copy of the ServerCapabilities. -// Values in the Extensions and Experimental maps are shallow-copied. -func (c *ServerCapabilities) clone() *ServerCapabilities { - cp := *c - cp.Experimental = maps.Clone(c.Experimental) - cp.Extensions = maps.Clone(c.Extensions) - cp.Completions = shallowClone(c.Completions) - cp.Logging = shallowClone(c.Logging) - cp.Prompts = shallowClone(c.Prompts) - cp.Resources = shallowClone(c.Resources) - cp.Tools = shallowClone(c.Tools) - return &cp -} - -const ( - methodCallTool = "tools/call" - notificationCancelled = "notifications/cancelled" - methodComplete = "completion/complete" - methodCreateMessage = "sampling/createMessage" - methodElicit = "elicitation/create" - notificationElicitationComplete = "notifications/elicitation/complete" - methodGetPrompt = "prompts/get" - methodInitialize = "initialize" - notificationInitialized = "notifications/initialized" - methodListPrompts = "prompts/list" - methodListResourceTemplates = "resources/templates/list" - methodListResources = "resources/list" - methodListRoots = "roots/list" - methodListTools = "tools/list" - notificationLoggingMessage = "notifications/message" - methodPing = "ping" - notificationProgress = "notifications/progress" - notificationPromptListChanged = "notifications/prompts/list_changed" - methodReadResource = "resources/read" - notificationResourceListChanged = "notifications/resources/list_changed" - notificationResourceUpdated = "notifications/resources/updated" - notificationRootsListChanged = "notifications/roots/list_changed" - methodSetLevel = "logging/setLevel" - methodSubscribe = "resources/subscribe" - notificationToolListChanged = "notifications/tools/list_changed" - methodUnsubscribe = "resources/unsubscribe" -) diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/requests.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/requests.go deleted file mode 100644 index 4280941..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/requests.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// This file holds the request types. - -package mcp - -type ( - CallToolRequest = ServerRequest[*CallToolParamsRaw] - CompleteRequest = ServerRequest[*CompleteParams] - GetPromptRequest = ServerRequest[*GetPromptParams] - InitializedRequest = ServerRequest[*InitializedParams] - ListPromptsRequest = ServerRequest[*ListPromptsParams] - ListResourcesRequest = ServerRequest[*ListResourcesParams] - ListResourceTemplatesRequest = ServerRequest[*ListResourceTemplatesParams] - ListToolsRequest = ServerRequest[*ListToolsParams] - ProgressNotificationServerRequest = ServerRequest[*ProgressNotificationParams] - ReadResourceRequest = ServerRequest[*ReadResourceParams] - RootsListChangedRequest = ServerRequest[*RootsListChangedParams] - SubscribeRequest = ServerRequest[*SubscribeParams] - UnsubscribeRequest = ServerRequest[*UnsubscribeParams] -) - -type ( - CreateMessageRequest = ClientRequest[*CreateMessageParams] - CreateMessageWithToolsRequest = ClientRequest[*CreateMessageWithToolsParams] - ElicitRequest = ClientRequest[*ElicitParams] - initializedClientRequest = ClientRequest[*InitializedParams] - InitializeRequest = ClientRequest[*InitializeParams] - ListRootsRequest = ClientRequest[*ListRootsParams] - LoggingMessageRequest = ClientRequest[*LoggingMessageParams] - ProgressNotificationClientRequest = ClientRequest[*ProgressNotificationParams] - PromptListChangedRequest = ClientRequest[*PromptListChangedParams] - ResourceListChangedRequest = ClientRequest[*ResourceListChangedParams] - ResourceUpdatedNotificationRequest = ClientRequest[*ResourceUpdatedNotificationParams] - ToolListChangedRequest = ClientRequest[*ToolListChangedParams] - ElicitationCompleteNotificationRequest = ClientRequest[*ElicitationCompleteParams] -) diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/resource.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/resource.go deleted file mode 100644 index bc4b3cb..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/resource.go +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package mcp - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io" - "net/url" - "os" - "path/filepath" - "strings" - - "github.com/modelcontextprotocol/go-sdk/internal/util" - "github.com/modelcontextprotocol/go-sdk/jsonrpc" - "github.com/yosida95/uritemplate/v3" -) - -// A serverResource associates a Resource with its handler. -type serverResource struct { - resource *Resource - handler ResourceHandler -} - -// A serverResourceTemplate associates a ResourceTemplate with its handler. -type serverResourceTemplate struct { - resourceTemplate *ResourceTemplate - handler ResourceHandler -} - -// A ResourceHandler is a function that reads a resource. -// It will be called when the client calls [ClientSession.ReadResource]. -// If it cannot find the resource, it should return the result of calling [ResourceNotFoundError]. -type ResourceHandler func(context.Context, *ReadResourceRequest) (*ReadResourceResult, error) - -// ResourceNotFoundError returns an error indicating that a resource being read could -// not be found. -func ResourceNotFoundError(uri string) error { - return &jsonrpc.Error{ - Code: CodeResourceNotFound, - Message: "Resource not found", - Data: json.RawMessage(fmt.Sprintf(`{"uri":%q}`, uri)), - } -} - -// readFileResource reads from the filesystem at a URI relative to dirFilepath, respecting -// the roots. -// dirFilepath and rootFilepaths are absolute filesystem paths. -func readFileResource(rawURI, dirFilepath string, rootFilepaths []string) ([]byte, error) { - uriFilepath, err := computeURIFilepath(rawURI, dirFilepath, rootFilepaths) - if err != nil { - return nil, err - } - - var data []byte - err = withFile(dirFilepath, uriFilepath, func(f *os.File) error { - var err error - data, err = io.ReadAll(f) - return err - }) - if os.IsNotExist(err) { - err = ResourceNotFoundError(rawURI) - } - return data, err -} - -// computeURIFilepath returns a path relative to dirFilepath. -// The dirFilepath and rootFilepaths are absolute file paths. -func computeURIFilepath(rawURI, dirFilepath string, rootFilepaths []string) (string, error) { - // We use "file path" to mean a filesystem path. - uri, err := url.Parse(rawURI) - if err != nil { - return "", err - } - if uri.Scheme != "file" { - return "", fmt.Errorf("URI is not a file: %s", uri) - } - if uri.Path == "" { - // A more specific error than the one below, to catch the - // common mistake "file://foo". - return "", errors.New("empty path") - } - // The URI's path is interpreted relative to dirFilepath, and in the local filesystem. - // It must not try to escape its directory. - uriFilepathRel, err := filepath.Localize(strings.TrimPrefix(uri.Path, "/")) - if err != nil { - return "", fmt.Errorf("%q cannot be localized: %w", uriFilepathRel, err) - } - - // Check roots, if there are any. - if len(rootFilepaths) > 0 { - // To check against the roots, we need an absolute file path, not relative to the directory. - // uriFilepath is local, so the joined path is under dirFilepath. - uriFilepathAbs := filepath.Join(dirFilepath, uriFilepathRel) - rootOK := false - // Check that the requested file path is under some root. - // Since both paths are absolute, that's equivalent to filepath.Rel constructing - // a local path. - for _, rootFilepathAbs := range rootFilepaths { - if rel, err := filepath.Rel(rootFilepathAbs, uriFilepathAbs); err == nil && filepath.IsLocal(rel) { - rootOK = true - break - } - } - if !rootOK { - return "", fmt.Errorf("URI path %q is not under any root", uriFilepathAbs) - } - } - return uriFilepathRel, nil -} - -// withFile calls f on the file at join(dir, rel), -// protecting against path traversal attacks. -func withFile(dir, rel string, f func(*os.File) error) (err error) { - r, err := os.OpenRoot(dir) - if err != nil { - return err - } - defer r.Close() - file, err := r.Open(rel) - if err != nil { - return err - } - // Record error, in case f writes. - defer func() { err = errors.Join(err, file.Close()) }() - return f(file) -} - -// fileRoots transforms the Roots obtained from the client into absolute paths on -// the local filesystem. -// TODO(jba): expose this functionality to user ResourceHandlers, -// so they don't have to repeat it. -func fileRoots(rawRoots []*Root) ([]string, error) { - var fileRoots []string - for _, r := range rawRoots { - fr, err := fileRoot(r) - if err != nil { - return nil, err - } - fileRoots = append(fileRoots, fr) - } - return fileRoots, nil -} - -// fileRoot returns the absolute path for Root. -func fileRoot(root *Root) (_ string, err error) { - defer util.Wrapf(&err, "root %q", root.URI) - - // Convert to absolute file path. - rurl, err := url.Parse(root.URI) - if err != nil { - return "", err - } - if rurl.Scheme != "file" { - return "", errors.New("not a file URI") - } - if rurl.Path == "" { - // A more specific error than the one below, to catch the - // common mistake "file://foo". - return "", errors.New("empty path") - } - // We don't want Localize here: we want an absolute path, which is not local. - fileRoot := filepath.Clean(filepath.FromSlash(rurl.Path)) - if !filepath.IsAbs(fileRoot) { - return "", errors.New("not an absolute path") - } - return fileRoot, nil -} - -// Matches reports whether the receiver's uri template matches the uri. -func (sr *serverResourceTemplate) Matches(uri string) bool { - tmpl, err := uritemplate.New(sr.resourceTemplate.URITemplate) - if err != nil { - return false - } - return tmpl.Regexp().MatchString(uri) -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/schema_cache.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/schema_cache.go deleted file mode 100644 index 5fb032d..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/schema_cache.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package mcp - -import ( - "reflect" - "sync" - - "github.com/google/jsonschema-go/jsonschema" -) - -// A SchemaCache caches JSON schemas to avoid repeated reflection and resolution. -// -// This is useful for stateless server deployments (one [Server] per request) -// where tools are re-registered on every request. Without caching, each -// [AddTool] call triggers expensive reflection-based schema generation. -// -// A SchemaCache is safe for concurrent use by multiple goroutines. -// -// # Trade-offs -// -// The cache is unbounded: it stores one entry per unique Go type or schema -// pointer. For typical MCP servers with a fixed set of tools, memory usage -// is negligible. However, if tool input types are generated dynamically, -// the cache will grow without bound. -// -// The cache uses pointer identity for pre-defined schemas. If a schema's -// contents change but the pointer remains the same, stale resolved schemas -// may be returned. In practice, this is not an issue because tool schemas -// are typically defined once at startup. -type SchemaCache struct { - byType sync.Map // reflect.Type -> *cachedSchema - bySchema sync.Map // *jsonschema.Schema -> *jsonschema.Resolved -} - -type cachedSchema struct { - schema *jsonschema.Schema - resolved *jsonschema.Resolved -} - -// NewSchemaCache creates a new [SchemaCache]. -func NewSchemaCache() *SchemaCache { - return &SchemaCache{} -} - -func (c *SchemaCache) getByType(t reflect.Type) (*jsonschema.Schema, *jsonschema.Resolved, bool) { - if v, ok := c.byType.Load(t); ok { - cs := v.(*cachedSchema) - return cs.schema, cs.resolved, true - } - return nil, nil, false -} - -func (c *SchemaCache) setByType(t reflect.Type, schema *jsonschema.Schema, resolved *jsonschema.Resolved) { - c.byType.Store(t, &cachedSchema{schema: schema, resolved: resolved}) -} - -func (c *SchemaCache) getBySchema(schema *jsonschema.Schema) (*jsonschema.Resolved, bool) { - if v, ok := c.bySchema.Load(schema); ok { - return v.(*jsonschema.Resolved), true - } - return nil, false -} - -func (c *SchemaCache) setBySchema(schema *jsonschema.Schema, resolved *jsonschema.Resolved) { - c.bySchema.Store(schema, resolved) -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/server.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/server.go deleted file mode 100644 index 327f450..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/server.go +++ /dev/null @@ -1,1649 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package mcp - -import ( - "bytes" - "context" - "crypto/rand" - "encoding/base64" - "encoding/gob" - "encoding/json" - "errors" - "fmt" - "iter" - "log/slog" - "maps" - "net/url" - "path/filepath" - "reflect" - "slices" - "sync" - "sync/atomic" - "time" - - "github.com/google/jsonschema-go/jsonschema" - internaljson "github.com/modelcontextprotocol/go-sdk/internal/json" - "github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2" - "github.com/modelcontextprotocol/go-sdk/internal/util" - "github.com/modelcontextprotocol/go-sdk/jsonrpc" - "github.com/yosida95/uritemplate/v3" -) - -// DefaultPageSize is the default for [ServerOptions.PageSize]. -const DefaultPageSize = 1000 - -// A Server is an instance of an MCP server. -// -// Servers expose server-side MCP features, which can serve one or more MCP -// sessions by using [Server.Run]. -type Server struct { - // fixed at creation - impl *Implementation - opts ServerOptions - - mu sync.Mutex - prompts *featureSet[*serverPrompt] - tools *featureSet[*serverTool] - resources *featureSet[*serverResource] - resourceTemplates *featureSet[*serverResourceTemplate] - sessions []*ServerSession - sendingMethodHandler_ MethodHandler - receivingMethodHandler_ MethodHandler - resourceSubscriptions map[string]map[*ServerSession]bool // uri -> session -> bool - pendingNotifications map[string]*time.Timer // notification name -> timer for pending notification send - customMethods map[string]methodInfo -} - -// NOTE: ParamsBase, ResultBase, and AddReceivingCustomMethod are additions to -// the upstream go-sdk to route custom JSON-RPC methods through receiving -// handler calls like any built-in MCP method, as needed by the MCP interceptors -// extension (SEP). This is a reference implementation, so there's some -// inefficiency; receivingMethodInfos() merges maps on every request instead of -// caching. - -// ParamsBase can be embedded by types outside this package to satisfy the -// mcp.Params interface, including its unexported marker method. -type ParamsBase struct { - Meta `json:"_meta,omitempty"` -} - -func (x *ParamsBase) isParams() {} -func (x *ParamsBase) GetProgressToken() any { return getProgressToken(x) } -func (x *ParamsBase) SetProgressToken(t any) { setProgressToken(x, t) } - -// ResultBase can be embedded by types outside this package to satisfy the -// mcp.Result interface, including its unexported marker method. -type ResultBase struct { - Meta `json:"_meta,omitempty"` -} - -func (x *ResultBase) isResult() {} - -// AddReceivingCustomMethod registers a typed custom JSON-RPC method that flows -// through receiving handler calls like any built-in MCP method. P must embed -// ParamsBase and R must embed ResultBase to satisfy the interface constraints. -// Go does not support generic methods, so this is a package-level function. -func AddReceivingCustomMethod[P paramsPtr[T], R Result, T any]( - s *Server, method string, - handler typedServerMethodHandler[P, R], -) { - s.mu.Lock() - defer s.mu.Unlock() - // missingParamsOK: custom methods may legally omit params (e.g. interceptors/list). - s.customMethods[method] = newServerMethodInfo(handler, missingParamsOK) -} - -// hasCustomMethod reports whether the given method is registered as a custom method. -func (s *Server) hasCustomMethod(method string) bool { - s.mu.Lock() - defer s.mu.Unlock() - _, ok := s.customMethods[method] - return ok -} - -// ServerOptions is used to configure behavior of the server. -type ServerOptions struct { - // Optional instructions for connected clients. - Instructions string - // Logger may be set to a non-nil value to enable logging of server activity. - Logger *slog.Logger - // If non-nil, called when "notifications/initialized" is received. - InitializedHandler func(context.Context, *InitializedRequest) - // PageSize is the maximum number of items to return in a single page for - // list methods (e.g. ListTools). - // - // If zero, defaults to [DefaultPageSize]. - PageSize int - // If non-nil, called when "notifications/roots/list_changed" is received. - RootsListChangedHandler func(context.Context, *RootsListChangedRequest) - // If non-nil, called when "notifications/progress" is received. - ProgressNotificationHandler func(context.Context, *ProgressNotificationServerRequest) - // If non-nil, called when "completion/complete" is received. - CompletionHandler func(context.Context, *CompleteRequest) (*CompleteResult, error) - // If non-zero, defines an interval for regular "ping" requests. - // If the peer fails to respond to pings originating from the keepalive check, - // the session is automatically closed. - KeepAlive time.Duration - // Function called when a client session subscribes to a resource. - SubscribeHandler func(context.Context, *SubscribeRequest) error - // Function called when a client session unsubscribes from a resource. - UnsubscribeHandler func(context.Context, *UnsubscribeRequest) error - - // Capabilities optionally configures the server's default capabilities, - // before any capabilities are inferred from other configuration or server - // features. - // - // If Capabilities is nil, the default server capabilities are {"logging":{}}, - // for historical reasons. Setting Capabilities to a non-nil value overrides - // this default. For example, setting Capabilities to `&ServerCapabilities{}` - // disables the logging capability. - // - // # Interaction with capability inference - // - // "tools", "prompts", and "resources" capabilities are automatically added when - // tools, prompts, or resources are added to the server (for example, via - // [Server.AddPrompt]), with default value `{"listChanged":true}`. Similarly, - // if the [ClientOptions.SubscribeHandler] or - // [ClientOptions.CompletionHandler] are set, the inferred capabilities are - // adjusted accordingly. - // - // Any non-nil field in Capabilities overrides the inferred value. - // For example: - // - // - To advertise the "tools" capability, even if no tools are added, set - // Capabilities.Tools to &ToolCapabilities{ListChanged:true}. - // - To disable tool list notifications, set Capabilities.Tools to - // &ToolCapabilities{}. - // - // Conversely, if Capabilities does not set a field (for example, if the - // Prompts field is nil), the inferred capability will be used. - Capabilities *ServerCapabilities - - // If true, advertises the prompts capability during initialization, - // even if no prompts have been registered. - // - // Deprecated: Use Capabilities instead. - HasPrompts bool - // If true, advertises the resources capability during initialization, - // even if no resources have been registered. - // - // Deprecated: Use Capabilities instead. - HasResources bool - // If true, advertises the tools capability during initialization, - // even if no tools have been registered. - // - // Deprecated: Use Capabilities instead. - HasTools bool - // SchemaCache, if non-nil, caches JSON schemas to avoid repeated - // reflection. This is useful for stateless server deployments where - // a new [Server] is created for each request. See [SchemaCache] for - // trade-offs and usage guidance. - SchemaCache *SchemaCache - - // GetSessionID provides the next session ID to use for an incoming request. - // If nil, a default randomly generated ID will be used. - // - // Session IDs should be globally unique across the scope of the server, - // which may span multiple processes in the case of distributed servers. - // - // As a special case, if GetSessionID returns the empty string, the - // Mcp-Session-Id header will not be set. - GetSessionID func() string -} - -// NewServer creates a new MCP server. The resulting server has no features: -// add features using the various Server.AddXXX methods, and the [AddTool] function. -// -// The server can be connected to one or more MCP clients using [Server.Run]. -// -// The first argument must not be nil. -// -// If non-nil, the provided options are used to configure the server. -func NewServer(impl *Implementation, options *ServerOptions) *Server { - if impl == nil { - panic("nil Implementation") - } - var opts ServerOptions - if options != nil { - opts = *options - } - options = nil // prevent reuse - if opts.PageSize < 0 { - panic(fmt.Errorf("invalid page size %d", opts.PageSize)) - } - if opts.PageSize == 0 { - opts.PageSize = DefaultPageSize - } - if opts.SubscribeHandler != nil && opts.UnsubscribeHandler == nil { - panic("SubscribeHandler requires UnsubscribeHandler") - } - if opts.UnsubscribeHandler != nil && opts.SubscribeHandler == nil { - panic("UnsubscribeHandler requires SubscribeHandler") - } - - if opts.GetSessionID == nil { - opts.GetSessionID = rand.Text - } - - if opts.Logger == nil { // ensure we have a logger - opts.Logger = ensureLogger(nil) - } - - return &Server{ - impl: impl, - opts: opts, - prompts: newFeatureSet(func(p *serverPrompt) string { return p.prompt.Name }), - tools: newFeatureSet(func(t *serverTool) string { return t.tool.Name }), - resources: newFeatureSet(func(r *serverResource) string { return r.resource.URI }), - resourceTemplates: newFeatureSet(func(t *serverResourceTemplate) string { return t.resourceTemplate.URITemplate }), - sendingMethodHandler_: defaultSendingMethodHandler, - receivingMethodHandler_: defaultReceivingMethodHandler[*ServerSession], - resourceSubscriptions: make(map[string]map[*ServerSession]bool), - pendingNotifications: make(map[string]*time.Timer), - customMethods: make(map[string]methodInfo), - } -} - -// AddPrompt adds a [Prompt] to the server, or replaces one with the same name. -func (s *Server) AddPrompt(p *Prompt, h PromptHandler) { - // Assume there was a change, since add replaces existing items. - // (It's possible an item was replaced with an identical one, but not worth checking.) - s.changeAndNotify( - notificationPromptListChanged, - func() bool { s.prompts.add(&serverPrompt{p, h}); return true }) -} - -// RemovePrompts removes the prompts with the given names. -// It is not an error to remove a nonexistent prompt. -func (s *Server) RemovePrompts(names ...string) { - s.changeAndNotify(notificationPromptListChanged, func() bool { return s.prompts.remove(names...) }) -} - -// AddTool adds a [Tool] to the server, or replaces one with the same name. -// The Tool argument must not be modified after this call. -// -// The tool's input schema must be non-nil and have the type "object". For a tool -// that takes no input, or one where any input is valid, set [Tool.InputSchema] to -// `{"type": "object"}`, using your preferred library or `json.RawMessage`. -// -// If present, [Tool.OutputSchema] must also have type "object". -// -// When the handler is invoked as part of a CallTool request, req.Params.Arguments -// will be a json.RawMessage. -// -// Unmarshaling the arguments and validating them against the input schema are the -// caller's responsibility. -// -// Validating the result against the output schema, if any, is the caller's responsibility. -// -// Setting the result's Content, StructuredContent and IsError fields are the caller's -// responsibility. -// -// Most users should use the top-level function [AddTool], which handles all these -// responsibilities. -func (s *Server) AddTool(t *Tool, h ToolHandler) { - if err := validateToolName(t.Name); err != nil { - s.opts.Logger.Error(fmt.Sprintf("AddTool: invalid tool name %q: %v", t.Name, err)) - } - if t.InputSchema == nil { - // This prevents the tool author from forgetting to write a schema where - // one should be provided. If we papered over this by supplying the empty - // schema, then every input would be validated and the problem wouldn't be - // discovered until runtime, when the LLM sent bad data. - panic(fmt.Errorf("AddTool %q: missing input schema", t.Name)) - } - if s, ok := t.InputSchema.(*jsonschema.Schema); ok { - if s.Type != "object" { - panic(fmt.Errorf(`AddTool %q: input schema must have type "object"`, t.Name)) - } - } else { - var m map[string]any - if err := remarshal(t.InputSchema, &m); err != nil { - panic(fmt.Errorf("AddTool %q: can't marshal input schema to a JSON object: %v", t.Name, err)) - } - if typ := m["type"]; typ != "object" { - panic(fmt.Errorf(`AddTool %q: input schema must have type "object" (got %v)`, t.Name, typ)) - } - } - if t.OutputSchema != nil { - if s, ok := t.OutputSchema.(*jsonschema.Schema); ok { - if s.Type != "object" { - panic(fmt.Errorf(`AddTool %q: output schema must have type "object"`, t.Name)) - } - } else { - var m map[string]any - if err := remarshal(t.OutputSchema, &m); err != nil { - panic(fmt.Errorf("AddTool %q: can't marshal output schema to a JSON object: %v", t.Name, err)) - } - if typ := m["type"]; typ != "object" { - panic(fmt.Errorf(`AddTool %q: output schema must have type "object" (got %v)`, t.Name, typ)) - } - } - } - st := &serverTool{tool: t, handler: h} - // Assume there was a change, since add replaces existing tools. - // (It's possible a tool was replaced with an identical one, but not worth checking.) - // TODO: Batch these changes by size and time? The typescript SDK doesn't. - // TODO: Surface notify error here? best not, in case we need to batch. - s.changeAndNotify(notificationToolListChanged, func() bool { s.tools.add(st); return true }) -} - -func toolForErr[In, Out any](t *Tool, h ToolHandlerFor[In, Out], cache *SchemaCache) (*Tool, ToolHandler, error) { - tt := *t - - // Special handling for an "any" input: treat as an empty object. - if reflect.TypeFor[In]() == reflect.TypeFor[any]() && t.InputSchema == nil { - tt.InputSchema = &jsonschema.Schema{Type: "object"} - } - - var inputResolved *jsonschema.Resolved - if _, err := setSchema[In](&tt.InputSchema, &inputResolved, cache); err != nil { - return nil, nil, fmt.Errorf("input schema: %w", err) - } - - // Handling for zero values: - // - // If Out is a pointer type and we've derived the output schema from its - // element type, use the zero value of its element type in place of a typed - // nil. - var ( - elemZero any // only non-nil if Out is a pointer type - outputResolved *jsonschema.Resolved - ) - if t.OutputSchema != nil || reflect.TypeFor[Out]() != reflect.TypeFor[any]() { - var err error - elemZero, err = setSchema[Out](&tt.OutputSchema, &outputResolved, cache) - if err != nil { - return nil, nil, fmt.Errorf("output schema: %v", err) - } - } - - th := func(ctx context.Context, req *CallToolRequest) (*CallToolResult, error) { - var input json.RawMessage - if req.Params.Arguments != nil { - input = req.Params.Arguments - } - // Validate input and apply defaults. - var err error - input, err = applySchema(input, inputResolved) - if err != nil { - // TODO(#450): should this be considered a tool error? (and similar below) - return nil, fmt.Errorf("%w: validating \"arguments\": %v", jsonrpc2.ErrInvalidParams, err) - } - - // Unmarshal and validate args. - var in In - if input != nil { - if err := internaljson.Unmarshal(input, &in); err != nil { - return nil, fmt.Errorf("%w: %v", jsonrpc2.ErrInvalidParams, err) - } - } - - // Call typed handler. - res, out, err := h(ctx, req, in) - // Handle server errors appropriately: - // - If the handler returns a structured error (like jsonrpc.Error), return it directly - // - If the handler returns a regular error, wrap it in a CallToolResult with IsError=true - // - This allows tools to distinguish between protocol errors and tool execution errors - if err != nil { - // Check if this is already a structured JSON-RPC error - if wireErr, ok := err.(*jsonrpc.Error); ok { - return nil, wireErr - } - // For regular errors, embed them in the tool result as per MCP spec - var errRes CallToolResult - errRes.SetError(err) - return &errRes, nil - } - - if res == nil { - res = &CallToolResult{} - } - - // Marshal the output and put the RawMessage in the StructuredContent field. - var outval any = out - if elemZero != nil { - // Avoid typed nil, which will serialize as JSON null. - // Instead, use the zero value of the unpointered type. - var z Out - if any(out) == any(z) { // zero is only non-nil if Out is a pointer type - outval = elemZero - } - } - if outval != nil { - outbytes, err := json.Marshal(outval) - if err != nil { - return nil, fmt.Errorf("marshaling output: %w", err) - } - outJSON := json.RawMessage(outbytes) - // Validate the output JSON, and apply defaults. - // - // We validate against the JSON, rather than the output value, as - // some types may have custom JSON marshalling (issue #447). - outJSON, err = applySchema(outJSON, outputResolved) - if err != nil { - return nil, fmt.Errorf("validating tool output: %w", err) - } - res.StructuredContent = outJSON // avoid a second marshal over the wire - - // If the Content field isn't being used, return the serialized JSON in a - // TextContent block, as the spec suggests: - // https://modelcontextprotocol.io/specification/2025-06-18/server/tools#structured-content. - if res.Content == nil { - res.Content = []Content{&TextContent{ - Text: string(outJSON), - }} - } - } - return res, nil - } // end of handler - - return &tt, th, nil -} - -// setSchema sets the schema and resolved schema corresponding to the type T. -// -// If sfield is nil, the schema is derived from T. -// -// Pointers are treated equivalently to non-pointers when deriving the schema. -// If an indirection occurred to derive the schema, a non-nil zero value is -// returned to be used in place of the typed nil zero value. -// -// Note that if sfield already holds a schema, zero will be nil even if T is a -// pointer: if the user provided the schema, they may have intentionally -// derived it from the pointer type, and handling of zero values is up to them. -// -// If cache is non-nil, schemas are cached to avoid repeated reflection. -// -// TODO(rfindley): we really shouldn't ever return 'null' results. Maybe we -// should have a jsonschema.Zero(schema) helper? -func setSchema[T any](sfield *any, rfield **jsonschema.Resolved, cache *SchemaCache) (zero any, err error) { - rt := reflect.TypeFor[T]() - if rt.Kind() == reflect.Pointer { - rt = rt.Elem() - zero = reflect.Zero(rt).Interface() - } - - var internalSchema *jsonschema.Schema - - if *sfield == nil { - // No schema provided: check cache, or generate via reflection. - if cache != nil { - if schema, resolved, ok := cache.getByType(rt); ok { - *sfield = schema - *rfield = resolved - return zero, nil - } - } - - internalSchema, err = jsonschema.ForType(rt, &jsonschema.ForOptions{}) - if err != nil { - return zero, err - } - *sfield = internalSchema - - resolved, err := internalSchema.Resolve(&jsonschema.ResolveOptions{ValidateDefaults: true}) - if err != nil { - return zero, err - } - *rfield = resolved - if cache != nil { - cache.setByType(rt, internalSchema, resolved) - } - return zero, nil - } - - // Schema was provided: check cache by pointer, or resolve it. - if providedSchema, ok := (*sfield).(*jsonschema.Schema); ok { - if cache != nil { - if resolved, ok := cache.getBySchema(providedSchema); ok { - *rfield = resolved - return zero, nil - } - } - internalSchema = providedSchema - } else { - // Schema provided as different type (e.g., map): remarshal to *Schema. - if err := remarshal(*sfield, &internalSchema); err != nil { - return zero, err - } - } - - resolved, err := internalSchema.Resolve(&jsonschema.ResolveOptions{ValidateDefaults: true}) - if err != nil { - return zero, err - } - *rfield = resolved - - if cache != nil { - if providedSchema, ok := (*sfield).(*jsonschema.Schema); ok { - cache.setBySchema(providedSchema, resolved) - } - } - - return zero, nil -} - -// AddTool adds a tool and typed tool handler to the server. -// -// If the tool's input schema is nil, it is set to the schema inferred from the -// In type parameter. Types are inferred from Go types, and property -// descriptions are read from the 'jsonschema' struct tag. Internally, the SDK -// uses the github.com/google/jsonschema-go package for inference and -// validation. The In type argument must be a map or a struct, so that its -// inferred JSON Schema has type "object", as required by the spec. As a -// special case, if the In type is 'any', the tool's input schema is set to an -// empty object schema value. -// -// If the tool's output schema is nil, and the Out type is not 'any', the -// output schema is set to the schema inferred from the Out type argument, -// which must also be a map or struct. If the Out type is 'any', the output -// schema is omitted. -// -// Unlike [Server.AddTool], AddTool does a lot automatically, and forces -// tools to conform to the MCP spec. See [ToolHandlerFor] for a detailed -// description of this automatic behavior. -func AddTool[In, Out any](s *Server, t *Tool, h ToolHandlerFor[In, Out]) { - tt, hh, err := toolForErr(t, h, s.opts.SchemaCache) - if err != nil { - panic(fmt.Sprintf("AddTool: tool %q: %v", t.Name, err)) - } - s.AddTool(tt, hh) -} - -// RemoveTools removes the tools with the given names. -// It is not an error to remove a nonexistent tool. -func (s *Server) RemoveTools(names ...string) { - s.changeAndNotify(notificationToolListChanged, func() bool { return s.tools.remove(names...) }) -} - -// AddResource adds a [Resource] to the server, or replaces one with the same URI. -// AddResource panics if the resource URI is invalid or not absolute (has an empty scheme). -func (s *Server) AddResource(r *Resource, h ResourceHandler) { - s.changeAndNotify(notificationResourceListChanged, - func() bool { - if _, err := url.Parse(r.URI); err != nil { - panic(err) // url.Parse includes the URI in the error - } - s.resources.add(&serverResource{r, h}) - return true - }) -} - -// RemoveResources removes the resources with the given URIs. -// It is not an error to remove a nonexistent resource. -func (s *Server) RemoveResources(uris ...string) { - s.changeAndNotify(notificationResourceListChanged, func() bool { return s.resources.remove(uris...) }) -} - -// AddResourceTemplate adds a [ResourceTemplate] to the server, or replaces one with the same URI. -// AddResourceTemplate panics if a URI template is invalid or not absolute (has an empty scheme). -func (s *Server) AddResourceTemplate(t *ResourceTemplate, h ResourceHandler) { - s.changeAndNotify(notificationResourceListChanged, - func() bool { - // Validate the URI template syntax - _, err := uritemplate.New(t.URITemplate) - if err != nil { - panic(fmt.Errorf("URI template %q is invalid: %w", t.URITemplate, err)) - } - s.resourceTemplates.add(&serverResourceTemplate{t, h}) - return true - }) -} - -// RemoveResourceTemplates removes the resource templates with the given URI templates. -// It is not an error to remove a nonexistent resource. -func (s *Server) RemoveResourceTemplates(uriTemplates ...string) { - s.changeAndNotify(notificationResourceListChanged, func() bool { return s.resourceTemplates.remove(uriTemplates...) }) -} - -func (s *Server) capabilities() *ServerCapabilities { - s.mu.Lock() - defer s.mu.Unlock() - - // Start with user-provided capabilities as defaults, or use SDK defaults. - var caps *ServerCapabilities - if s.opts.Capabilities != nil { - // Deep copy the user-provided capabilities to avoid mutation. - caps = s.opts.Capabilities.clone() - } else { - // SDK defaults: only logging capability. - caps = &ServerCapabilities{ - Logging: &LoggingCapabilities{}, - } - } - - // Augment with tools capability if tools exist or legacy HasTools is set. - if s.opts.HasTools || s.tools.len() > 0 { - if caps.Tools == nil { - caps.Tools = &ToolCapabilities{ListChanged: true} - } - } - - // Augment with prompts capability if prompts exist or legacy HasPrompts is set. - if s.opts.HasPrompts || s.prompts.len() > 0 { - if caps.Prompts == nil { - caps.Prompts = &PromptCapabilities{ListChanged: true} - } - } - - // Augment with resources capability if resources/templates exist or legacy HasResources is set. - if s.opts.HasResources || s.resources.len() > 0 || s.resourceTemplates.len() > 0 { - if caps.Resources == nil { - caps.Resources = &ResourceCapabilities{ListChanged: true} - } - if s.opts.SubscribeHandler != nil { - caps.Resources.Subscribe = true - } - } - - // Augment with completions capability if handler is set. - if s.opts.CompletionHandler != nil { - if caps.Completions == nil { - caps.Completions = &CompletionCapabilities{} - } - } - - return caps -} - -func (s *Server) complete(ctx context.Context, req *CompleteRequest) (*CompleteResult, error) { - if s.opts.CompletionHandler == nil { - return nil, jsonrpc2.ErrMethodNotFound - } - return s.opts.CompletionHandler(ctx, req) -} - -// Map from notification name to its corresponding params. The params have no fields, -// so a single struct can be reused. -var changeNotificationParams = map[string]Params{ - notificationToolListChanged: &ToolListChangedParams{}, - notificationPromptListChanged: &PromptListChangedParams{}, - notificationResourceListChanged: &ResourceListChangedParams{}, -} - -// How long to wait before sending a change notification. -const notificationDelay = 10 * time.Millisecond - -// changeAndNotify is called when a feature is added or removed. -// It calls change, which should do the work and report whether a change actually occurred. -// If there was a change, it sets a timer to send a notification. -// This debounces change notifications: a single notification is sent after -// multiple changes occur in close proximity. -func (s *Server) changeAndNotify(notification string, change func() bool) { - s.mu.Lock() - defer s.mu.Unlock() - if change() && s.shouldSendListChangedNotification(notification) { - // Reset the outstanding delayed call, if any. - if t := s.pendingNotifications[notification]; t == nil { - s.pendingNotifications[notification] = time.AfterFunc(notificationDelay, func() { s.notifySessions(notification) }) - } else { - t.Reset(notificationDelay) - } - } -} - -// notifySessions sends the notification n to all existing sessions. -// It is called asynchronously by changeAndNotify. -func (s *Server) notifySessions(n string) { - s.mu.Lock() - sessions := slices.Clone(s.sessions) - s.pendingNotifications[n] = nil - s.mu.Unlock() // Don't hold the lock during notification: it causes deadlock. - notifySessions(sessions, n, changeNotificationParams[n], s.opts.Logger) -} - -// shouldSendListChangedNotification checks if the server's capabilities allow -// sending the given list-changed notification. -func (s *Server) shouldSendListChangedNotification(notification string) bool { - // Get effective capabilities (considering user-provided defaults). - caps := s.opts.Capabilities - - switch notification { - case notificationToolListChanged: - // If user didn't specify capabilities, default behavior sends notifications. - if caps == nil || caps.Tools == nil { - return true - } - return caps.Tools.ListChanged - case notificationPromptListChanged: - if caps == nil || caps.Prompts == nil { - return true - } - return caps.Prompts.ListChanged - case notificationResourceListChanged: - if caps == nil || caps.Resources == nil { - return true - } - return caps.Resources.ListChanged - default: - // Unknown notification, allow by default. - return true - } -} - -// Sessions returns an iterator that yields the current set of server sessions. -// -// There is no guarantee that the iterator observes sessions that are added or -// removed during iteration. -func (s *Server) Sessions() iter.Seq[*ServerSession] { - s.mu.Lock() - clients := slices.Clone(s.sessions) - s.mu.Unlock() - return slices.Values(clients) -} - -func (s *Server) listPrompts(_ context.Context, req *ListPromptsRequest) (*ListPromptsResult, error) { - s.mu.Lock() - defer s.mu.Unlock() - if req.Params == nil { - req.Params = &ListPromptsParams{} - } - return paginateList(s.prompts, s.opts.PageSize, req.Params, &ListPromptsResult{}, func(res *ListPromptsResult, prompts []*serverPrompt) { - res.Prompts = []*Prompt{} // avoid JSON null - for _, p := range prompts { - res.Prompts = append(res.Prompts, p.prompt) - } - }) -} - -func (s *Server) getPrompt(ctx context.Context, req *GetPromptRequest) (*GetPromptResult, error) { - s.mu.Lock() - prompt, ok := s.prompts.get(req.Params.Name) - s.mu.Unlock() - if !ok { - // Return a proper JSON-RPC error with the correct error code - return nil, &jsonrpc.Error{ - Code: jsonrpc.CodeInvalidParams, - Message: fmt.Sprintf("unknown prompt %q", req.Params.Name), - } - } - return prompt.handler(ctx, req) -} - -func (s *Server) listTools(_ context.Context, req *ListToolsRequest) (*ListToolsResult, error) { - s.mu.Lock() - defer s.mu.Unlock() - if req.Params == nil { - req.Params = &ListToolsParams{} - } - return paginateList(s.tools, s.opts.PageSize, req.Params, &ListToolsResult{}, func(res *ListToolsResult, tools []*serverTool) { - res.Tools = []*Tool{} // avoid JSON null - for _, t := range tools { - res.Tools = append(res.Tools, t.tool) - } - }) -} - -func (s *Server) callTool(ctx context.Context, req *CallToolRequest) (*CallToolResult, error) { - s.mu.Lock() - st, ok := s.tools.get(req.Params.Name) - s.mu.Unlock() - if !ok { - return nil, &jsonrpc.Error{ - Code: jsonrpc.CodeInvalidParams, - Message: fmt.Sprintf("unknown tool %q", req.Params.Name), - } - } - res, err := st.handler(ctx, req) - if err == nil && res != nil && res.Content == nil { - res2 := *res - res2.Content = []Content{} // avoid "null" - res = &res2 - } - return res, err -} - -func (s *Server) listResources(_ context.Context, req *ListResourcesRequest) (*ListResourcesResult, error) { - s.mu.Lock() - defer s.mu.Unlock() - if req.Params == nil { - req.Params = &ListResourcesParams{} - } - return paginateList(s.resources, s.opts.PageSize, req.Params, &ListResourcesResult{}, func(res *ListResourcesResult, resources []*serverResource) { - res.Resources = []*Resource{} // avoid JSON null - for _, r := range resources { - res.Resources = append(res.Resources, r.resource) - } - }) -} - -func (s *Server) listResourceTemplates(_ context.Context, req *ListResourceTemplatesRequest) (*ListResourceTemplatesResult, error) { - s.mu.Lock() - defer s.mu.Unlock() - if req.Params == nil { - req.Params = &ListResourceTemplatesParams{} - } - return paginateList(s.resourceTemplates, s.opts.PageSize, req.Params, &ListResourceTemplatesResult{}, - func(res *ListResourceTemplatesResult, rts []*serverResourceTemplate) { - res.ResourceTemplates = []*ResourceTemplate{} // avoid JSON null - for _, rt := range rts { - res.ResourceTemplates = append(res.ResourceTemplates, rt.resourceTemplate) - } - }) -} - -func (s *Server) readResource(ctx context.Context, req *ReadResourceRequest) (*ReadResourceResult, error) { - uri := req.Params.URI - // Look up the resource URI in the lists of resources and resource templates. - // This is a security check as well as an information lookup. - handler, mimeType, ok := s.lookupResourceHandler(uri) - if !ok { - // Don't expose the server configuration to the client. - // Treat an unregistered resource the same as a registered one that couldn't be found. - return nil, ResourceNotFoundError(uri) - } - res, err := handler(ctx, req) - if err != nil { - return nil, err - } - if res == nil || res.Contents == nil { - return nil, fmt.Errorf("reading resource %s: read handler returned nil information", uri) - } - // As a convenience, populate some fields. - for _, c := range res.Contents { - if c.URI == "" { - c.URI = uri - } - if c.MIMEType == "" { - c.MIMEType = mimeType - } - } - return res, nil -} - -// lookupResourceHandler returns the resource handler and MIME type for the resource or -// resource template matching uri. If none, the last return value is false. -func (s *Server) lookupResourceHandler(uri string) (ResourceHandler, string, bool) { - s.mu.Lock() - defer s.mu.Unlock() - // Try resources first. - if r, ok := s.resources.get(uri); ok { - return r.handler, r.resource.MIMEType, true - } - // Look for matching template. - for rt := range s.resourceTemplates.all() { - if rt.Matches(uri) { - return rt.handler, rt.resourceTemplate.MIMEType, true - } - } - return nil, "", false -} - -// fileResourceHandler returns a ReadResourceHandler that reads paths using dir as -// a base directory. -// It honors client roots and protects against path traversal attacks. -// -// The dir argument should be a filesystem path. It need not be absolute, but -// that is recommended to avoid a dependency on the current working directory (the -// check against client roots is done with an absolute path). If dir is not absolute -// and the current working directory is unavailable, fileResourceHandler panics. -// -// Lexical path traversal attacks, where the path has ".." elements that escape dir, -// are always caught. Go 1.24 and above also protects against symlink-based attacks, -// where symlinks under dir lead out of the tree. -func fileResourceHandler(dir string) ResourceHandler { - // Convert dir to an absolute path. - dirFilepath, err := filepath.Abs(dir) - if err != nil { - panic(err) - } - return func(ctx context.Context, req *ReadResourceRequest) (_ *ReadResourceResult, err error) { - defer util.Wrapf(&err, "reading resource %s", req.Params.URI) - - // TODO(#25): use a memoizing API here. - rootRes, err := req.Session.ListRoots(ctx, nil) - if err != nil { - return nil, fmt.Errorf("listing roots: %w", err) - } - roots, err := fileRoots(rootRes.Roots) - if err != nil { - return nil, err - } - data, err := readFileResource(req.Params.URI, dirFilepath, roots) - if err != nil { - return nil, err - } - // TODO(jba): figure out mime type. Omit for now: Server.readResource will fill it in. - return &ReadResourceResult{Contents: []*ResourceContents{ - {URI: req.Params.URI, Blob: data}, - }}, nil - } -} - -// ResourceUpdated sends a notification to all clients that have subscribed to the -// resource specified in params. This method is the primary way for a -// server author to signal that a resource has changed. -func (s *Server) ResourceUpdated(ctx context.Context, params *ResourceUpdatedNotificationParams) error { - s.mu.Lock() - subscribedSessions := s.resourceSubscriptions[params.URI] - sessions := slices.Collect(maps.Keys(subscribedSessions)) - s.mu.Unlock() - notifySessions(sessions, notificationResourceUpdated, params, s.opts.Logger) - s.opts.Logger.Info("resource updated notification sent", "uri", params.URI, "subscriber_count", len(sessions)) - return nil -} - -func (s *Server) subscribe(ctx context.Context, req *SubscribeRequest) (*emptyResult, error) { - if s.opts.SubscribeHandler == nil { - return nil, fmt.Errorf("%w: server does not support resource subscriptions", jsonrpc2.ErrMethodNotFound) - } - if err := s.opts.SubscribeHandler(ctx, req); err != nil { - return nil, err - } - - s.mu.Lock() - defer s.mu.Unlock() - if s.resourceSubscriptions[req.Params.URI] == nil { - s.resourceSubscriptions[req.Params.URI] = make(map[*ServerSession]bool) - } - s.resourceSubscriptions[req.Params.URI][req.Session] = true - s.opts.Logger.Info("resource subscribed", "uri", req.Params.URI, "session_id", req.Session.ID()) - - return &emptyResult{}, nil -} - -func (s *Server) unsubscribe(ctx context.Context, req *UnsubscribeRequest) (*emptyResult, error) { - if s.opts.UnsubscribeHandler == nil { - return nil, jsonrpc2.ErrMethodNotFound - } - - if err := s.opts.UnsubscribeHandler(ctx, req); err != nil { - return nil, err - } - - s.mu.Lock() - defer s.mu.Unlock() - if subscribedSessions, ok := s.resourceSubscriptions[req.Params.URI]; ok { - delete(subscribedSessions, req.Session) - if len(subscribedSessions) == 0 { - delete(s.resourceSubscriptions, req.Params.URI) - } - } - s.opts.Logger.Info("resource unsubscribed", "uri", req.Params.URI, "session_id", req.Session.ID()) - - return &emptyResult{}, nil -} - -// Run runs the server over the given transport, which must be persistent. -// -// Run blocks until the client terminates the connection or the provided -// context is cancelled. If the context is cancelled, Run closes the connection. -// -// If tools have been added to the server before this call, then the server will -// advertise the capability for tools, including the ability to send list-changed notifications. -// If no tools have been added, the server will not have the tool capability. -// The same goes for other features like prompts and resources. -// -// Run is a convenience for servers that handle a single session (or one session at a time). -// It need not be called on servers that are used for multiple concurrent connections, -// as with [StreamableHTTPHandler]. -func (s *Server) Run(ctx context.Context, t Transport) error { - s.opts.Logger.Info("server run start") - ss, err := s.Connect(ctx, t, nil) - if err != nil { - s.opts.Logger.Error("server connect failed", "error", err) - return err - } - - ssClosed := make(chan error) - go func() { - ssClosed <- ss.Wait() - }() - - select { - case <-ctx.Done(): - ss.Close() - <-ssClosed // wait until waiting go routine above actually completes - s.opts.Logger.Error("server run cancelled", "error", ctx.Err()) - return ctx.Err() - case err := <-ssClosed: - if err != nil { - s.opts.Logger.Error("server session ended with error", "error", err) - } else { - s.opts.Logger.Info("server session ended") - } - return err - } -} - -// bind implements the binder[*ServerSession] interface, so that Servers can -// be connected using [connect]. -func (s *Server) bind(mcpConn Connection, conn *jsonrpc2.Connection, state *ServerSessionState, onClose func()) *ServerSession { - assert(mcpConn != nil && conn != nil, "nil connection") - ss := &ServerSession{conn: conn, mcpConn: mcpConn, server: s, onClose: onClose} - if state != nil { - ss.state = *state - } - s.mu.Lock() - s.sessions = append(s.sessions, ss) - s.mu.Unlock() - s.opts.Logger.Info("server session connected", "session_id", ss.ID()) - return ss -} - -// disconnect implements the binder[*ServerSession] interface, so that -// Servers can be connected using [connect]. -func (s *Server) disconnect(cc *ServerSession) { - s.mu.Lock() - defer s.mu.Unlock() - s.sessions = slices.DeleteFunc(s.sessions, func(cc2 *ServerSession) bool { - return cc2 == cc - }) - - for _, subscribedSessions := range s.resourceSubscriptions { - delete(subscribedSessions, cc) - } - s.opts.Logger.Info("server session disconnected", "session_id", cc.ID()) -} - -// ServerSessionOptions configures the server session. -type ServerSessionOptions struct { - State *ServerSessionState - - onClose func() // used to clean up associated resources -} - -// Connect connects the MCP server over the given transport and starts handling -// messages. -// -// It returns a connection object that may be used to terminate the connection -// (with [Connection.Close]), or await client termination (with -// [Connection.Wait]). -// -// If opts.State is non-nil, it is the initial state for the server. -func (s *Server) Connect(ctx context.Context, t Transport, opts *ServerSessionOptions) (*ServerSession, error) { - var state *ServerSessionState - var onClose func() - if opts != nil { - state = opts.State - onClose = opts.onClose - } - - s.opts.Logger.Info("server connecting") - ss, err := connect(ctx, t, s, state, onClose) - if err != nil { - s.opts.Logger.Error("server connect error", "error", err) - return nil, err - } - return ss, nil -} - -// TODO: (nit) move all ServerSession methods below the ServerSession declaration. -func (ss *ServerSession) initialized(ctx context.Context, params *InitializedParams) (Result, error) { - if params == nil { - // Since we use nilness to signal 'initialized' state, we must ensure that - // params are non-nil. - params = new(InitializedParams) - } - var wasInit, wasInitd bool - ss.updateState(func(state *ServerSessionState) { - wasInit = state.InitializeParams != nil - wasInitd = state.InitializedParams != nil - if wasInit && !wasInitd { - state.InitializedParams = params - } - }) - - if !wasInit { - ss.server.opts.Logger.Error("initialized before initialize") - return nil, fmt.Errorf("%q before %q", notificationInitialized, methodInitialize) - } - if wasInitd { - ss.server.opts.Logger.Error("duplicate initialized notification") - return nil, fmt.Errorf("duplicate %q received", notificationInitialized) - } - if ss.server.opts.KeepAlive > 0 { - ss.startKeepalive(ss.server.opts.KeepAlive) - } - if h := ss.server.opts.InitializedHandler; h != nil { - h(ctx, serverRequestFor(ss, params)) - } - ss.server.opts.Logger.Info("session initialized") - return nil, nil -} - -func (s *Server) callRootsListChangedHandler(ctx context.Context, req *RootsListChangedRequest) (Result, error) { - if h := s.opts.RootsListChangedHandler; h != nil { - h(ctx, req) - } - return nil, nil -} - -func (ss *ServerSession) callProgressNotificationHandler(ctx context.Context, p *ProgressNotificationParams) (Result, error) { - if h := ss.server.opts.ProgressNotificationHandler; h != nil { - h(ctx, serverRequestFor(ss, p)) - } - return nil, nil -} - -// NotifyProgress sends a progress notification from the server to the client -// associated with this session. -// This is typically used to report on the status of a long-running request -// that was initiated by the client. -func (ss *ServerSession) NotifyProgress(ctx context.Context, params *ProgressNotificationParams) error { - return handleNotify(ctx, notificationProgress, newServerRequest(ss, orZero[Params](params))) -} - -func newServerRequest[P Params](ss *ServerSession, params P) *ServerRequest[P] { - return &ServerRequest[P]{Session: ss, Params: params} -} - -// A ServerSession is a logical connection from a single MCP client. Its -// methods can be used to send requests or notifications to the client. Create -// a session by calling [Server.Connect]. -// -// Call [ServerSession.Close] to close the connection, or await client -// termination with [ServerSession.Wait]. -type ServerSession struct { - // Ensure that onClose is called at most once. - // We defensively use an atomic CompareAndSwap rather than a sync.Once, in case the - // onClose callback triggers a re-entrant call to Close. - calledOnClose atomic.Bool - onClose func() - - server *Server - conn *jsonrpc2.Connection - mcpConn Connection - keepaliveCancel context.CancelFunc // TODO: theory around why keepaliveCancel need not be guarded - - mu sync.Mutex - state ServerSessionState -} - -func (ss *ServerSession) updateState(mut func(*ServerSessionState)) { - ss.mu.Lock() - mut(&ss.state) - copy := ss.state - ss.mu.Unlock() - if c, ok := ss.mcpConn.(serverConnection); ok { - c.sessionUpdated(copy) - } -} - -// hasInitialized reports whether the server has received the initialized -// notification. -// -// TODO(findleyr): use this to prevent change notifications. -func (ss *ServerSession) hasInitialized() bool { - ss.mu.Lock() - defer ss.mu.Unlock() - return ss.state.InitializedParams != nil -} - -// checkInitialized returns a formatted error if the server has not yet -// received the initialized notification. -func (ss *ServerSession) checkInitialized(method string) error { - if !ss.hasInitialized() { - // TODO(rfindley): enable this check. - // Right now is is flaky, because server tests don't await the initialized notification. - // Perhaps requests should simply block until they have received the initialized notification - - // if strings.HasPrefix(method, "notifications/") { - // return fmt.Errorf("must not send %q before %q is received", method, notificationInitialized) - // } else { - // return fmt.Errorf("cannot call %q before %q is received", method, notificationInitialized) - // } - } - return nil -} - -func (ss *ServerSession) ID() string { - if c, ok := ss.mcpConn.(hasSessionID); ok { - return c.SessionID() - } - return "" -} - -// Ping pings the client. -func (ss *ServerSession) Ping(ctx context.Context, params *PingParams) error { - _, err := handleSend[*emptyResult](ctx, methodPing, newServerRequest(ss, orZero[Params](params))) - return err -} - -// ListRoots lists the client roots. -func (ss *ServerSession) ListRoots(ctx context.Context, params *ListRootsParams) (*ListRootsResult, error) { - if err := ss.checkInitialized(methodListRoots); err != nil { - return nil, err - } - return handleSend[*ListRootsResult](ctx, methodListRoots, newServerRequest(ss, orZero[Params](params))) -} - -// CreateMessage sends a sampling request to the client. -// -// If the client returns multiple content blocks (e.g. parallel tool calls), -// CreateMessage returns an error. Use [ServerSession.CreateMessageWithTools] -// for tool-enabled sampling. -func (ss *ServerSession) CreateMessage(ctx context.Context, params *CreateMessageParams) (*CreateMessageResult, error) { - if err := ss.checkInitialized(methodCreateMessage); err != nil { - return nil, err - } - if params == nil { - params = &CreateMessageParams{Messages: []*SamplingMessage{}} - } - if params.Messages == nil { - p2 := *params - p2.Messages = []*SamplingMessage{} // avoid JSON "null" - params = &p2 - } - res, err := handleSend[*CreateMessageWithToolsResult](ctx, methodCreateMessage, newServerRequest(ss, orZero[Params](params))) - if err != nil { - return nil, err - } - // Downconvert to singular content. - if len(res.Content) > 1 { - return nil, fmt.Errorf("CreateMessage result has %d content blocks; use CreateMessageWithTools for multiple content", len(res.Content)) - } - var content Content - if len(res.Content) > 0 { - content = res.Content[0] - } - return &CreateMessageResult{ - Meta: res.Meta, - Content: content, - Model: res.Model, - Role: res.Role, - StopReason: res.StopReason, - }, nil -} - -// CreateMessageWithTools sends a sampling request with tools to the client, -// returning a [CreateMessageWithToolsResult] that supports array content -// (for parallel tool calls). Use this instead of [ServerSession.CreateMessage] -// when the request includes tools. -func (ss *ServerSession) CreateMessageWithTools(ctx context.Context, params *CreateMessageWithToolsParams) (*CreateMessageWithToolsResult, error) { - if err := ss.checkInitialized(methodCreateMessage); err != nil { - return nil, err - } - if params == nil { - params = &CreateMessageWithToolsParams{Messages: []*SamplingMessageV2{}} - } - if params.Messages == nil { - p2 := *params - p2.Messages = []*SamplingMessageV2{} // avoid JSON "null" - params = &p2 - } - return handleSend[*CreateMessageWithToolsResult](ctx, methodCreateMessage, newServerRequest(ss, orZero[Params](params))) -} - -// Elicit sends an elicitation request to the client asking for user input. -func (ss *ServerSession) Elicit(ctx context.Context, params *ElicitParams) (*ElicitResult, error) { - if err := ss.checkInitialized(methodElicit); err != nil { - return nil, err - } - if params == nil { - return nil, fmt.Errorf("%w: params cannot be nil", jsonrpc2.ErrInvalidParams) - } - - if params.Mode == "" { - params2 := *params - if params.URL != "" || params.ElicitationID != "" { - params2.Mode = "url" - } else { - params2.Mode = "form" - } - params = ¶ms2 - } - - if iparams := ss.InitializeParams(); iparams == nil || iparams.Capabilities == nil || iparams.Capabilities.Elicitation == nil { - return nil, fmt.Errorf("client does not support elicitation") - } - caps := ss.InitializeParams().Capabilities.Elicitation - switch params.Mode { - case "form": - if caps.Form == nil && caps.URL != nil { - // Note: if both 'Form' and 'URL' are nil, we assume the client supports - // form elicitation for backward compatibility. - return nil, errors.New(`client does not support "form" elicitation`) - } - case "url": - if caps.URL == nil { - return nil, errors.New(`client does not support "url" elicitation`) - } - } - - res, err := handleSend[*ElicitResult](ctx, methodElicit, newServerRequest(ss, orZero[Params](params))) - if err != nil { - return nil, err - } - - if res.Action != "accept" { - return res, nil - } - - if params.RequestedSchema == nil { - return res, nil - } - schema, err := validateElicitSchema(params.RequestedSchema) - if err != nil { - return nil, err - } - if schema == nil { - return res, nil - } - - resolved, err := schema.Resolve(nil) - if err != nil { - return nil, err - } - if err := resolved.Validate(res.Content); err != nil { - return nil, fmt.Errorf("elicitation result content does not match requested schema: %v", err) - } - err = resolved.ApplyDefaults(&res.Content) - if err != nil { - return nil, fmt.Errorf("failed to apply schema defalts to elicitation result: %v", err) - } - - return res, nil -} - -// Log sends a log message to the client. -// The message is not sent if the client has not called SetLevel, or if its level -// is below that of the last SetLevel. -func (ss *ServerSession) Log(ctx context.Context, params *LoggingMessageParams) error { - ss.mu.Lock() - logLevel := ss.state.LogLevel - ss.mu.Unlock() - if logLevel == "" { - // The spec is unclear, but seems to imply that no log messages are sent until the client - // sets the level. - // TODO(jba): read other SDKs, possibly file an issue. - return nil - } - if compareLevels(params.Level, logLevel) < 0 { - return nil - } - return handleNotify(ctx, notificationLoggingMessage, newServerRequest(ss, orZero[Params](params))) -} - -// AddSendingMiddleware wraps the current sending method handler using the provided -// middleware. Middleware is applied from right to left, so that the first one is -// executed first. -// -// For example, AddSendingMiddleware(m1, m2, m3) augments the method handler as -// m1(m2(m3(handler))). -// -// Sending middleware is called when a request is sent. It is useful for tasks -// such as tracing, metrics, and adding progress tokens. -func (s *Server) AddSendingMiddleware(middleware ...Middleware) { - s.mu.Lock() - defer s.mu.Unlock() - addMiddleware(&s.sendingMethodHandler_, middleware) -} - -// AddReceivingMiddleware wraps the current receiving method handler using -// the provided middleware. Middleware is applied from right to left, so that the -// first one is executed first. -// -// For example, AddReceivingMiddleware(m1, m2, m3) augments the method handler as -// m1(m2(m3(handler))). -// -// Receiving middleware is called when a request is received. It is useful for tasks -// such as authentication, request logging and metrics. -func (s *Server) AddReceivingMiddleware(middleware ...Middleware) { - s.mu.Lock() - defer s.mu.Unlock() - addMiddleware(&s.receivingMethodHandler_, middleware) -} - -// serverMethodInfos maps from the RPC method name to serverMethodInfos. -// -// The 'allowMissingParams' values are extracted from the protocol schema. -// TODO(rfindley): actually load and validate the protocol schema, rather than -// curating these method flags. -var serverMethodInfos = map[string]methodInfo{ - methodComplete: newServerMethodInfo(serverMethod((*Server).complete), 0), - methodInitialize: initializeMethodInfo(), - methodPing: newServerMethodInfo(serverSessionMethod((*ServerSession).ping), missingParamsOK), - methodListPrompts: newServerMethodInfo(serverMethod((*Server).listPrompts), missingParamsOK), - methodGetPrompt: newServerMethodInfo(serverMethod((*Server).getPrompt), 0), - methodListTools: newServerMethodInfo(serverMethod((*Server).listTools), missingParamsOK), - methodCallTool: newServerMethodInfo(serverMethod((*Server).callTool), 0), - methodListResources: newServerMethodInfo(serverMethod((*Server).listResources), missingParamsOK), - methodListResourceTemplates: newServerMethodInfo(serverMethod((*Server).listResourceTemplates), missingParamsOK), - methodReadResource: newServerMethodInfo(serverMethod((*Server).readResource), 0), - methodSetLevel: newServerMethodInfo(serverSessionMethod((*ServerSession).setLevel), 0), - methodSubscribe: newServerMethodInfo(serverMethod((*Server).subscribe), 0), - methodUnsubscribe: newServerMethodInfo(serverMethod((*Server).unsubscribe), 0), - notificationCancelled: newServerMethodInfo(serverSessionMethod((*ServerSession).cancel), notification|missingParamsOK), - notificationInitialized: newServerMethodInfo(serverSessionMethod((*ServerSession).initialized), notification|missingParamsOK), - notificationRootsListChanged: newServerMethodInfo(serverMethod((*Server).callRootsListChangedHandler), notification|missingParamsOK), - notificationProgress: newServerMethodInfo(serverSessionMethod((*ServerSession).callProgressNotificationHandler), notification), -} - -// initializeMethodInfo handles the workaround for #607: we must set -// params.Capabilities.RootsV2. -func initializeMethodInfo() methodInfo { - info := newServerMethodInfo(serverSessionMethod((*ServerSession).initialize), 0) - info.unmarshalParams = func(m json.RawMessage) (Params, error) { - var params *initializeParamsV2 - if m != nil { - if err := internaljson.Unmarshal(m, ¶ms); err != nil { - return nil, fmt.Errorf("unmarshaling %q into a %T: %w", m, params, err) - } - } - if params == nil { - return nil, fmt.Errorf(`missing required "params"`) - } - return params.toV1(), nil - } - return info -} - -func (ss *ServerSession) sendingMethodInfos() map[string]methodInfo { return clientMethodInfos } - -func (ss *ServerSession) receivingMethodInfos() map[string]methodInfo { - infos := make(map[string]methodInfo) - maps.Copy(infos, serverMethodInfos) - maps.Copy(infos, ss.server.customMethods) - return infos -} - -func (ss *ServerSession) sendingMethodHandler() MethodHandler { - s := ss.server - s.mu.Lock() - defer s.mu.Unlock() - return s.sendingMethodHandler_ -} - -func (ss *ServerSession) receivingMethodHandler() MethodHandler { - s := ss.server - s.mu.Lock() - defer s.mu.Unlock() - return s.receivingMethodHandler_ -} - -// getConn implements [session.getConn]. -func (ss *ServerSession) getConn() *jsonrpc2.Connection { return ss.conn } - -// handle invokes the method described by the given JSON RPC request. -func (ss *ServerSession) handle(ctx context.Context, req *jsonrpc.Request) (any, error) { - ss.mu.Lock() - initialized := ss.state.InitializeParams != nil - ss.mu.Unlock() - - // From the spec: - // "The client SHOULD NOT send requests other than pings before the server - // has responded to the initialize request." - switch req.Method { - case methodInitialize, methodPing, notificationInitialized: - default: - if !initialized { - ss.server.opts.Logger.Error("method invalid during initialization", "method", req.Method) - return nil, fmt.Errorf("method %q is invalid during session initialization", req.Method) - } - } - - // modelcontextprotocol/go-sdk#26: handle calls asynchronously, and - // notifications synchronously, except for 'initialize' which shouldn't be - // asynchronous to other - if req.IsCall() && req.Method != methodInitialize { - jsonrpc2.Async(ctx) - } - - // For the streamable transport, we need the request ID to correlate - // server->client calls and notifications to the incoming request from which - // they originated. See [idContextKey] for details. - ctx = context.WithValue(ctx, idContextKey{}, req.ID) - return handleReceive(ctx, ss, req) -} - -// InitializeParams returns the InitializeParams provided during the client's -// initial connection. -func (ss *ServerSession) InitializeParams() *InitializeParams { - ss.mu.Lock() - defer ss.mu.Unlock() - return ss.state.InitializeParams -} - -func (ss *ServerSession) initialize(ctx context.Context, params *InitializeParams) (*InitializeResult, error) { - if params == nil { - return nil, fmt.Errorf("%w: \"params\" must be be provided", jsonrpc2.ErrInvalidParams) - } - ss.updateState(func(state *ServerSessionState) { - state.InitializeParams = params - }) - - s := ss.server - return &InitializeResult{ - // TODO(rfindley): alter behavior when falling back to an older version: - // reject unsupported features. - ProtocolVersion: negotiatedVersion(params.ProtocolVersion), - Capabilities: s.capabilities(), - Instructions: s.opts.Instructions, - ServerInfo: s.impl, - }, nil -} - -func (ss *ServerSession) ping(context.Context, *PingParams) (*emptyResult, error) { - return &emptyResult{}, nil -} - -// cancel is a placeholder: cancellation is handled the jsonrpc2 package. -// -// It should never be invoked in practice because cancellation is preempted, -// but having its signature here facilitates the construction of methodInfo -// that can be used to validate incoming cancellation notifications. -func (ss *ServerSession) cancel(context.Context, *CancelledParams) (Result, error) { - return nil, nil -} - -func (ss *ServerSession) setLevel(_ context.Context, params *SetLoggingLevelParams) (*emptyResult, error) { - ss.updateState(func(state *ServerSessionState) { - state.LogLevel = params.Level - }) - ss.server.opts.Logger.Info("client log level set", "level", params.Level) - return &emptyResult{}, nil -} - -// Close performs a graceful shutdown of the connection, preventing new -// requests from being handled, and waiting for ongoing requests to return. -// Close then terminates the connection. -// -// Close is idempotent and concurrency safe. -func (ss *ServerSession) Close() error { - if ss.keepaliveCancel != nil { - // Note: keepaliveCancel access is safe without a mutex because: - // 1. keepaliveCancel is only written once during startKeepalive (happens-before all Close calls) - // 2. context.CancelFunc is safe to call multiple times and from multiple goroutines - // 3. The keepalive goroutine calls Close on ping failure, but this is safe since - // Close is idempotent and conn.Close() handles concurrent calls correctly - ss.keepaliveCancel() - } - err := ss.conn.Close() - - if ss.onClose != nil && ss.calledOnClose.CompareAndSwap(false, true) { - ss.onClose() - } - - return err -} - -// Wait waits for the connection to be closed by the client. -func (ss *ServerSession) Wait() error { - return ss.conn.Wait() -} - -// startKeepalive starts the keepalive mechanism for this server session. -func (ss *ServerSession) startKeepalive(interval time.Duration) { - startKeepalive(ss, interval, &ss.keepaliveCancel) -} - -// pageToken is the internal structure for the opaque pagination cursor. -// It will be Gob-encoded and then Base64-encoded for use as a string token. -type pageToken struct { - LastUID string // The unique ID of the last resource seen. -} - -// encodeCursor encodes a unique identifier (UID) into a opaque pagination cursor -// by serializing a pageToken struct. -func encodeCursor(uid string) (string, error) { - var buf bytes.Buffer - token := pageToken{LastUID: uid} - encoder := gob.NewEncoder(&buf) - if err := encoder.Encode(token); err != nil { - return "", fmt.Errorf("failed to encode page token: %w", err) - } - return base64.URLEncoding.EncodeToString(buf.Bytes()), nil -} - -// decodeCursor decodes an opaque pagination cursor into the original pageToken struct. -func decodeCursor(cursor string) (*pageToken, error) { - decodedBytes, err := base64.URLEncoding.DecodeString(cursor) - if err != nil { - return nil, fmt.Errorf("failed to decode cursor: %w", err) - } - - var token pageToken - buf := bytes.NewBuffer(decodedBytes) - decoder := gob.NewDecoder(buf) - if err := decoder.Decode(&token); err != nil { - return nil, fmt.Errorf("failed to decode page token: %w, cursor: %v", err, cursor) - } - return &token, nil -} - -// paginateList is a generic helper that returns a paginated slice of items -// from a featureSet. It populates the provided result res with the items -// and sets its next cursor for subsequent pages. -// If there are no more pages, the next cursor within the result will be an empty string. -func paginateList[P listParams, R listResult[T], T any](fs *featureSet[T], pageSize int, params P, res R, setFunc func(R, []T)) (R, error) { - var seq iter.Seq[T] - if params.cursorPtr() == nil || *params.cursorPtr() == "" { - seq = fs.all() - } else { - pageToken, err := decodeCursor(*params.cursorPtr()) - // According to the spec, invalid cursors should return Invalid params. - if err != nil { - var zero R - return zero, jsonrpc2.ErrInvalidParams - } - seq = fs.above(pageToken.LastUID) - } - var count int - var features []T - for f := range seq { - count++ - // If we've seen pageSize + 1 elements, we've gathered enough info to determine - // if there's a next page. Stop processing the sequence. - if count == pageSize+1 { - break - } - features = append(features, f) - } - setFunc(res, features) - // No remaining pages. - if count < pageSize+1 { - return res, nil - } - nextCursor, err := encodeCursor(fs.uniqueID(features[len(features)-1])) - if err != nil { - var zero R - return zero, err - } - *res.nextCursorPtr() = nextCursor - return res, nil -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/session.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/session.go deleted file mode 100644 index dcf9888..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/session.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package mcp - -// hasSessionID is the interface which, if implemented by connections, informs -// the session about their session ID. -// -// TODO(rfindley): remove SessionID methods from connections, when it doesn't -// make sense. Or remove it from the Sessions entirely: why does it even need -// to be exposed? -type hasSessionID interface { - SessionID() string -} - -// ServerSessionState is the state of a session. -type ServerSessionState struct { - // InitializeParams are the parameters from 'initialize'. - InitializeParams *InitializeParams `json:"initializeParams"` - - // InitializedParams are the parameters from 'notifications/initialized'. - InitializedParams *InitializedParams `json:"initializedParams"` - - // LogLevel is the logging level for the session. - LogLevel LoggingLevel `json:"logLevel"` - - // TODO: resource subscriptions -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/shared.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/shared.go deleted file mode 100644 index bda00c2..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/shared.go +++ /dev/null @@ -1,611 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// This file contains code shared between client and server, including -// method handler and middleware definitions. -// -// Much of this is here so that we can factor out commonalities using -// generics. If this becomes unwieldy, it can perhaps be simplified with -// reflection. - -package mcp - -import ( - "context" - "encoding/json" - "fmt" - "log/slog" - "net/http" - "reflect" - "slices" - "strings" - "time" - - "github.com/modelcontextprotocol/go-sdk/auth" - internaljson "github.com/modelcontextprotocol/go-sdk/internal/json" - "github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2" - "github.com/modelcontextprotocol/go-sdk/jsonrpc" -) - -const ( - // latestProtocolVersion is the latest protocol version that this version of - // the SDK supports. - // - // It is the version that the client sends in the initialization request, and - // the default version used by the server. - latestProtocolVersion = protocolVersion20250618 - protocolVersion20251125 = "2025-11-25" // not yet released - protocolVersion20250618 = "2025-06-18" - protocolVersion20250326 = "2025-03-26" - protocolVersion20241105 = "2024-11-05" -) - -var supportedProtocolVersions = []string{ - protocolVersion20251125, - protocolVersion20250618, - protocolVersion20250326, - protocolVersion20241105, -} - -// negotiatedVersion returns the effective protocol version to use, given a -// client version. -func negotiatedVersion(clientVersion string) string { - // In general, prefer to use the clientVersion, but if we don't support the - // client's version, use the latest version. - // - // This handles the case where a new spec version is released, and the SDK - // does not support it yet. - if !slices.Contains(supportedProtocolVersions, clientVersion) { - return latestProtocolVersion - } - return clientVersion -} - -// A MethodHandler handles MCP messages. -// For methods, exactly one of the return values must be nil. -// For notifications, both must be nil. -type MethodHandler func(ctx context.Context, method string, req Request) (result Result, err error) - -// A Session is either a [ClientSession] or a [ServerSession]. -type Session interface { - // ID returns the session ID, or the empty string if there is none. - ID() string - - sendingMethodInfos() map[string]methodInfo - receivingMethodInfos() map[string]methodInfo - sendingMethodHandler() MethodHandler - receivingMethodHandler() MethodHandler - getConn() *jsonrpc2.Connection -} - -// Middleware is a function from [MethodHandler] to [MethodHandler]. -type Middleware func(MethodHandler) MethodHandler - -// addMiddleware wraps the handler in the middleware functions. -func addMiddleware(handlerp *MethodHandler, middleware []Middleware) { - for _, m := range slices.Backward(middleware) { - *handlerp = m(*handlerp) - } -} - -func defaultSendingMethodHandler(ctx context.Context, method string, req Request) (Result, error) { - info, ok := req.GetSession().sendingMethodInfos()[method] - if !ok { - // This can be called from user code, with an arbitrary value for method. - return nil, jsonrpc2.ErrNotHandled - } - params := req.GetParams() - if initParams, ok := params.(*InitializeParams); ok { - // Fix the marshaling of initialize params, to work around #607. - // - // The initialize params we produce should never be nil, nor have nil - // capabilities, so any panic here is a bug. - params = initParams.toV2() - } - // Notifications don't have results. - if strings.HasPrefix(method, "notifications/") { - return nil, req.GetSession().getConn().Notify(ctx, method, params) - } - // Create the result to unmarshal into. - // The concrete type of the result is the return type of the receiving function. - res := info.newResult() - if err := call(ctx, req.GetSession().getConn(), method, params, res); err != nil { - return nil, err - } - return res, nil -} - -// Helper method to avoid typed nil. -func orZero[T any, P *U, U any](p P) T { - if p == nil { - var zero T - return zero - } - return any(p).(T) -} - -func handleNotify(ctx context.Context, method string, req Request) error { - mh := req.GetSession().sendingMethodHandler() - _, err := mh(ctx, method, req) - return err -} - -func handleSend[R Result](ctx context.Context, method string, req Request) (R, error) { - mh := req.GetSession().sendingMethodHandler() - // mh might be user code, so ensure that it returns the right values for the jsonrpc2 protocol. - res, err := mh(ctx, method, req) - if err != nil { - var z R - return z, err - } - return res.(R), nil -} - -// defaultReceivingMethodHandler is the initial MethodHandler for servers and clients, before being wrapped by middleware. -func defaultReceivingMethodHandler[S Session](ctx context.Context, method string, req Request) (Result, error) { - info, ok := req.GetSession().receivingMethodInfos()[method] - if !ok { - // This can be called from user code, with an arbitrary value for method. - return nil, jsonrpc2.ErrNotHandled - } - return info.handleMethod(ctx, method, req) -} - -func handleReceive[S Session](ctx context.Context, session S, jreq *jsonrpc.Request) (Result, error) { - info, err := checkRequest(jreq, session.receivingMethodInfos()) - if err != nil { - return nil, err - } - params, err := info.unmarshalParams(jreq.Params) - if err != nil { - return nil, fmt.Errorf("handling '%s': %w", jreq.Method, err) - } - - mh := session.receivingMethodHandler() - re, _ := jreq.Extra.(*RequestExtra) - req := info.newRequest(session, params, re) - // mh might be user code, so ensure that it returns the right values for the jsonrpc2 protocol. - res, err := mh(ctx, jreq.Method, req) - if err != nil { - return nil, err - } - return res, nil -} - -// checkRequest checks the given request against the provided method info, to -// ensure it is a valid MCP request. -// -// If valid, the relevant method info is returned. Otherwise, a non-nil error -// is returned describing why the request is invalid. -// -// This is extracted from request handling so that it can be called in the -// transport layer to preemptively reject bad requests. -func checkRequest(req *jsonrpc.Request, infos map[string]methodInfo) (methodInfo, error) { - info, ok := infos[req.Method] - if !ok { - return methodInfo{}, fmt.Errorf("%w: %q unsupported", jsonrpc2.ErrNotHandled, req.Method) - } - if info.flags¬ification != 0 && req.IsCall() { - return methodInfo{}, fmt.Errorf("%w: unexpected id for %q", jsonrpc2.ErrInvalidRequest, req.Method) - } - if info.flags¬ification == 0 && !req.IsCall() { - return methodInfo{}, fmt.Errorf("%w: missing id for %q", jsonrpc2.ErrInvalidRequest, req.Method) - } - // missingParamsOK is checked here to catch the common case where "params" is - // missing entirely. - // - // However, it's checked again after unmarshalling to catch the rare but - // possible case where "params" is JSON null (see https://go.dev/issue/33835). - if info.flags&missingParamsOK == 0 && len(req.Params) == 0 { - return methodInfo{}, fmt.Errorf("%w: missing required \"params\"", jsonrpc2.ErrInvalidRequest) - } - return info, nil -} - -// methodInfo is information about sending and receiving a method. -type methodInfo struct { - // flags is a collection of flags controlling how the JSONRPC method is - // handled. See individual flag values for documentation. - flags methodFlags - // Unmarshal params from the wire into a Params struct. - // Used on the receive side. - unmarshalParams func(json.RawMessage) (Params, error) - newRequest func(Session, Params, *RequestExtra) Request - // Run the code when a call to the method is received. - // Used on the receive side. - handleMethod MethodHandler - // Create a pointer to a Result struct. - // Used on the send side. - newResult func() Result -} - -// The following definitions support converting from typed to untyped method handlers. -// Type parameter meanings: -// - S: sessions -// - P: params -// - R: results - -// A typedMethodHandler is like a MethodHandler, but with type information. -type ( - typedClientMethodHandler[P Params, R Result] func(context.Context, *ClientRequest[P]) (R, error) - typedServerMethodHandler[P Params, R Result] func(context.Context, *ServerRequest[P]) (R, error) -) - -type paramsPtr[T any] interface { - *T - Params -} - -type methodFlags int - -const ( - notification methodFlags = 1 << iota // method is a notification, not request - missingParamsOK // params may be missing or null -) - -func newClientMethodInfo[P paramsPtr[T], R Result, T any](d typedClientMethodHandler[P, R], flags methodFlags) methodInfo { - mi := newMethodInfo[P, R](flags) - mi.newRequest = func(s Session, p Params, _ *RequestExtra) Request { - r := &ClientRequest[P]{Session: s.(*ClientSession)} - if p != nil { - r.Params = p.(P) - } - return r - } - mi.handleMethod = MethodHandler(func(ctx context.Context, _ string, req Request) (Result, error) { - return d(ctx, req.(*ClientRequest[P])) - }) - return mi -} - -func newServerMethodInfo[P paramsPtr[T], R Result, T any](d typedServerMethodHandler[P, R], flags methodFlags) methodInfo { - mi := newMethodInfo[P, R](flags) - mi.newRequest = func(s Session, p Params, re *RequestExtra) Request { - r := &ServerRequest[P]{Session: s.(*ServerSession), Extra: re} - if p != nil { - r.Params = p.(P) - } - return r - } - mi.handleMethod = MethodHandler(func(ctx context.Context, _ string, req Request) (Result, error) { - return d(ctx, req.(*ServerRequest[P])) - }) - return mi -} - -// newMethodInfo creates a methodInfo from a typedMethodHandler. -// -// If isRequest is set, the method is treated as a request rather than a -// notification. -func newMethodInfo[P paramsPtr[T], R Result, T any](flags methodFlags) methodInfo { - return methodInfo{ - flags: flags, - unmarshalParams: func(m json.RawMessage) (Params, error) { - var p P - if m != nil { - if err := internaljson.Unmarshal(m, &p); err != nil { - return nil, fmt.Errorf("unmarshaling %q into a %T: %w", m, p, err) - } - } - // We must check missingParamsOK here, in addition to checkRequest, to - // catch the edge cases where "params" is set to JSON null. - // See also https://go.dev/issue/33835. - // - // We need to ensure that p is non-null to guard against crashes, as our - // internal code or externally provided handlers may assume that params - // is non-null. - if flags&missingParamsOK == 0 && p == nil { - return nil, fmt.Errorf("%w: missing required \"params\"", jsonrpc2.ErrInvalidRequest) - } - return orZero[Params](p), nil - }, - // newResult is used on the send side, to construct the value to unmarshal the result into. - // R is a pointer to a result struct. There is no way to "unpointer" it without reflection. - // TODO(jba): explore generic approaches to this, perhaps by treating R in - // the signature as the unpointered type. - newResult: func() Result { return reflect.New(reflect.TypeFor[R]().Elem()).Interface().(R) }, - } -} - -// serverMethod is glue for creating a typedMethodHandler from a method on Server. -func serverMethod[P Params, R Result]( - f func(*Server, context.Context, *ServerRequest[P]) (R, error), -) typedServerMethodHandler[P, R] { - return func(ctx context.Context, req *ServerRequest[P]) (R, error) { - return f(req.Session.server, ctx, req) - } -} - -// clientMethod is glue for creating a typedMethodHandler from a method on Client. -func clientMethod[P Params, R Result]( - f func(*Client, context.Context, *ClientRequest[P]) (R, error), -) typedClientMethodHandler[P, R] { - return func(ctx context.Context, req *ClientRequest[P]) (R, error) { - return f(req.Session.client, ctx, req) - } -} - -// serverSessionMethod is glue for creating a typedServerMethodHandler from a method on ServerSession. -func serverSessionMethod[P Params, R Result](f func(*ServerSession, context.Context, P) (R, error)) typedServerMethodHandler[P, R] { - return func(ctx context.Context, req *ServerRequest[P]) (R, error) { - return f(req.GetSession().(*ServerSession), ctx, req.Params) - } -} - -// clientSessionMethod is glue for creating a typedMethodHandler from a method on ServerSession. -func clientSessionMethod[P Params, R Result](f func(*ClientSession, context.Context, P) (R, error)) typedClientMethodHandler[P, R] { - return func(ctx context.Context, req *ClientRequest[P]) (R, error) { - return f(req.GetSession().(*ClientSession), ctx, req.Params) - } -} - -// MCP-specific error codes. -const ( - // CodeResourceNotFound indicates that a requested resource could not be found. - CodeResourceNotFound = -32002 - // CodeURLElicitationRequired indicates that the server requires URL elicitation - // before processing the request. The client should execute the elicitation handler - // with the elicitations provided in the error data. - CodeURLElicitationRequired = -32042 -) - -// URLElicitationRequiredError returns an error indicating that URL elicitation is required -// before the request can be processed. The elicitations parameter should contain the -// elicitation requests that must be completed. -func URLElicitationRequiredError(elicitations []*ElicitParams) error { - // Validate that all elicitations are URL mode - for _, elicit := range elicitations { - mode := elicit.Mode - if mode == "" { - mode = "form" // default mode - } - if mode != "url" { - panic(fmt.Sprintf("URLElicitationRequiredError requires all elicitations to be URL mode, got %q", mode)) - } - } - - data, err := json.Marshal(map[string]any{ - "elicitations": elicitations, - }) - if err != nil { - // This should never happen with valid ElicitParams - panic(fmt.Sprintf("failed to marshal elicitations: %v", err)) - } - return &jsonrpc.Error{ - Code: CodeURLElicitationRequired, - Message: "URL elicitation required", - Data: json.RawMessage(data), - } -} - -// Internal error codes -const ( - // The error code if the method exists and was called properly, but the peer does not support it. - // - // TODO(rfindley): this code is wrong, and we should fix it to be - // consistent with other SDKs. - codeUnsupportedMethod = -31001 -) - -// notifySessions calls Notify on all the sessions. -// Should be called on a copy of the peer sessions. -// The logger must be non-nil. -func notifySessions[S Session, P Params](sessions []S, method string, params P, logger *slog.Logger) { - if sessions == nil { - return - } - // Notify with the background context, so the messages are sent on the - // standalone stream. - // TODO: make this timeout configurable, or call handleNotify asynchronously. - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - - // TODO: there's a potential spec violation here, when the feature list - // changes before the session (client or server) is initialized. - for _, s := range sessions { - req := newRequest(s, params) - if err := handleNotify(ctx, method, req); err != nil { - logger.Warn(fmt.Sprintf("calling %s: %v", method, err)) - } - } -} - -func newRequest[S Session, P Params](s S, p P) Request { - switch s := any(s).(type) { - case *ClientSession: - return &ClientRequest[P]{Session: s, Params: p} - case *ServerSession: - return &ServerRequest[P]{Session: s, Params: p} - default: - panic("bad session") - } -} - -// Meta is additional metadata for requests, responses and other types. -type Meta map[string]any - -// GetMeta returns metadata from a value. -func (m Meta) GetMeta() map[string]any { return m } - -// SetMeta sets the metadata on a value. -func (m *Meta) SetMeta(x map[string]any) { *m = x } - -const progressTokenKey = "progressToken" - -func getProgressToken(p Params) any { - return p.GetMeta()[progressTokenKey] -} - -func setProgressToken(p Params, pt any) { - switch pt.(type) { - // Support int32 and int64 for atomic.IntNN. - case int, int32, int64, string: - default: - panic(fmt.Sprintf("progress token %v is of type %[1]T, not int or string", pt)) - } - m := p.GetMeta() - if m == nil { - m = map[string]any{} - } - m[progressTokenKey] = pt -} - -// A Request is a method request with parameters and additional information, such as the session. -// Request is implemented by [*ClientRequest] and [*ServerRequest]. -type Request interface { - isRequest() - GetSession() Session - GetParams() Params - // GetExtra returns the Extra field for ServerRequests, and nil for ClientRequests. - GetExtra() *RequestExtra -} - -// A ClientRequest is a request to a client. -type ClientRequest[P Params] struct { - Session *ClientSession - Params P -} - -// A ServerRequest is a request to a server. -type ServerRequest[P Params] struct { - Session *ServerSession - Params P - Extra *RequestExtra -} - -// RequestExtra is extra information included in requests, typically from -// the transport layer. -type RequestExtra struct { - TokenInfo *auth.TokenInfo // bearer token info (e.g. from OAuth) if any - Header http.Header // header from HTTP request, if any - - // If set, CloseSSEStream explicitly closes the current SSE request stream. - // - // [SEP-1699] introduced server-side SSE stream disconnection: for - // long-running requests, servers may opt to close the SSE stream and - // ask the client to retry at a later time. CloseSSEStream implements this - // feature; if RetryAfter is set, an event is sent with a `retry:` field - // to configure the reconnection delay. - // - // [SEP-1699]: https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1699 - CloseSSEStream func(CloseSSEStreamArgs) -} - -// CloseSSEStreamArgs are arguments for [RequestExtra.CloseSSEStream]. -type CloseSSEStreamArgs struct { - // RetryAfter configures the reconnection delay sent to the client via the - // SSE retry field. If zero, no retry field is sent. - RetryAfter time.Duration -} - -func (*ClientRequest[P]) isRequest() {} -func (*ServerRequest[P]) isRequest() {} - -func (r *ClientRequest[P]) GetSession() Session { return r.Session } -func (r *ServerRequest[P]) GetSession() Session { return r.Session } - -func (r *ClientRequest[P]) GetParams() Params { return r.Params } -func (r *ServerRequest[P]) GetParams() Params { return r.Params } - -func (r *ClientRequest[P]) GetExtra() *RequestExtra { return nil } -func (r *ServerRequest[P]) GetExtra() *RequestExtra { return r.Extra } - -func serverRequestFor[P Params](s *ServerSession, p P) *ServerRequest[P] { - return &ServerRequest[P]{Session: s, Params: p} -} - -func clientRequestFor[P Params](s *ClientSession, p P) *ClientRequest[P] { - return &ClientRequest[P]{Session: s, Params: p} -} - -// Params is a parameter (input) type for an MCP call or notification. -type Params interface { - // GetMeta returns metadata from a value. - GetMeta() map[string]any - // SetMeta sets the metadata on a value. - SetMeta(map[string]any) - - // isParams discourages implementation of Params outside of this package. - isParams() -} - -// RequestParams is a parameter (input) type for an MCP request. -type RequestParams interface { - Params - - // GetProgressToken returns the progress token from the params' Meta field, or nil - // if there is none. - GetProgressToken() any - - // SetProgressToken sets the given progress token into the params' Meta field. - // It panics if its argument is not an int or a string. - SetProgressToken(any) -} - -// Result is a result of an MCP call. -type Result interface { - // isResult discourages implementation of Result outside of this package. - isResult() - - // GetMeta returns metadata from a value. - GetMeta() map[string]any - // SetMeta sets the metadata on a value. - SetMeta(map[string]any) -} - -// emptyResult is returned by methods that have no result, like ping. -// Those methods cannot return nil, because jsonrpc2 cannot handle nils. -type emptyResult struct{} - -func (*emptyResult) isResult() {} -func (*emptyResult) GetMeta() map[string]any { panic("should never be called") } -func (*emptyResult) SetMeta(map[string]any) { panic("should never be called") } - -type listParams interface { - // Returns a pointer to the param's Cursor field. - cursorPtr() *string -} - -type listResult[T any] interface { - // Returns a pointer to the param's NextCursor field. - nextCursorPtr() *string -} - -// keepaliveSession represents a session that supports keepalive functionality. -type keepaliveSession interface { - Ping(ctx context.Context, params *PingParams) error - Close() error -} - -// startKeepalive starts the keepalive mechanism for a session. -// It assigns the cancel function to the provided cancelPtr and starts a goroutine -// that sends ping messages at the specified interval. -func startKeepalive(session keepaliveSession, interval time.Duration, cancelPtr *context.CancelFunc) { - ctx, cancel := context.WithCancel(context.Background()) - // Assign cancel function before starting goroutine to avoid race condition. - // We cannot return it because the caller may need to cancel during the - // window between goroutine scheduling and function return. - *cancelPtr = cancel - - go func() { - ticker := time.NewTicker(interval) - defer ticker.Stop() - - for { - select { - case <-ctx.Done(): - return - case <-ticker.C: - pingCtx, pingCancel := context.WithTimeout(context.Background(), interval/2) - err := session.Ping(pingCtx, nil) - pingCancel() - if err != nil { - // Ping failed, close the session - _ = session.Close() - return - } - } - } - }() -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/sse.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/sse.go deleted file mode 100644 index e57dad1..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/sse.go +++ /dev/null @@ -1,489 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package mcp - -import ( - "bytes" - "context" - "crypto/rand" - "fmt" - "io" - "net/http" - "net/url" - "sync" - - "github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2" - "github.com/modelcontextprotocol/go-sdk/jsonrpc" -) - -// This file implements support for SSE (HTTP with server-sent events) -// transport server and client. -// https://modelcontextprotocol.io/specification/2024-11-05/basic/transports -// -// The transport is simple, at least relative to the new streamable transport -// introduced in the 2025-03-26 version of the spec. In short: -// -// 1. Sessions are initiated via a hanging GET request, which streams -// server->client messages as SSE 'message' events. -// 2. The first event in the SSE stream must be an 'endpoint' event that -// informs the client of the session endpoint. -// 3. The client POSTs client->server messages to the session endpoint. -// -// Therefore, the each new GET request hands off its responsewriter to an -// [SSEServerTransport] type that abstracts the transport as follows: -// - Write writes a new event to the responseWriter, or fails if the GET has -// exited. -// - Read reads off a message queue that is pushed to via POST requests. -// - Close causes the hanging GET to exit. - -// SSEHandler is an http.Handler that serves SSE-based MCP sessions as defined by -// the [2024-11-05 version] of the MCP spec. -// -// [2024-11-05 version]: https://modelcontextprotocol.io/specification/2024-11-05/basic/transports -type SSEHandler struct { - getServer func(request *http.Request) *Server - opts SSEOptions - onConnection func(*ServerSession) // for testing; must not block - - mu sync.Mutex - sessions map[string]*SSEServerTransport -} - -// SSEOptions specifies options for an [SSEHandler]. -// for now, it is empty, but may be extended in future. -// https://github.com/modelcontextprotocol/go-sdk/issues/507 -type SSEOptions struct{} - -// NewSSEHandler returns a new [SSEHandler] that creates and manages MCP -// sessions created via incoming HTTP requests. -// -// Sessions are created when the client issues a GET request to the server, -// which must accept text/event-stream responses (server-sent events). -// For each such request, a new [SSEServerTransport] is created with a distinct -// messages endpoint, and connected to the server returned by getServer. -// The SSEHandler also handles requests to the message endpoints, by -// delegating them to the relevant server transport. -// -// The getServer function may return a distinct [Server] for each new -// request, or reuse an existing server. If it returns nil, the handler -// will return a 400 Bad Request. -func NewSSEHandler(getServer func(request *http.Request) *Server, opts *SSEOptions) *SSEHandler { - s := &SSEHandler{ - getServer: getServer, - sessions: make(map[string]*SSEServerTransport), - } - - if opts != nil { - s.opts = *opts - } - - return s -} - -// A SSEServerTransport is a logical SSE session created through a hanging GET -// request. -// -// Use [SSEServerTransport.Connect] to initiate the flow of messages. -// -// When connected, it returns the following [Connection] implementation: -// - Writes are SSE 'message' events to the GET response. -// - Reads are received from POSTs to the session endpoint, via -// [SSEServerTransport.ServeHTTP]. -// - Close terminates the hanging GET. -// -// The transport is itself an [http.Handler]. It is the caller's responsibility -// to ensure that the resulting transport serves HTTP requests on the given -// session endpoint. -// -// Each SSEServerTransport may be connected (via [Server.Connect]) at most -// once, since [SSEServerTransport.ServeHTTP] serves messages to the connected -// session. -// -// Most callers should instead use an [SSEHandler], which transparently handles -// the delegation to SSEServerTransports. -type SSEServerTransport struct { - // Endpoint is the endpoint for this session, where the client can POST - // messages. - Endpoint string - - // Response is the hanging response body to the incoming GET request. - Response http.ResponseWriter - - // incoming is the queue of incoming messages. - // It is never closed, and by convention, incoming is non-nil if and only if - // the transport is connected. - incoming chan jsonrpc.Message - - // We must guard both pushes to the incoming queue and writes to the response - // writer, because incoming POST requests are arbitrarily concurrent and we - // need to ensure we don't write push to the queue, or write to the - // ResponseWriter, after the session GET request exits. - mu sync.Mutex // also guards writes to Response - closed bool // set when the stream is closed - done chan struct{} // closed when the connection is closed -} - -// ServeHTTP handles POST requests to the transport endpoint. -func (t *SSEServerTransport) ServeHTTP(w http.ResponseWriter, req *http.Request) { - if t.incoming == nil { - http.Error(w, "session not connected", http.StatusInternalServerError) - return - } - - // Read and parse the message. - data, err := io.ReadAll(req.Body) - if err != nil { - http.Error(w, "failed to read body", http.StatusBadRequest) - return - } - // Optionally, we could just push the data onto a channel, and let the - // message fail to parse when it is read. This failure seems a bit more - // useful - msg, err := jsonrpc2.DecodeMessage(data) - if err != nil { - http.Error(w, "failed to parse body", http.StatusBadRequest) - return - } - if req, ok := msg.(*jsonrpc.Request); ok { - if _, err := checkRequest(req, serverMethodInfos); err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - } - select { - case t.incoming <- msg: - w.WriteHeader(http.StatusAccepted) - case <-t.done: - http.Error(w, "session closed", http.StatusBadRequest) - } -} - -// Connect sends the 'endpoint' event to the client. -// See [SSEServerTransport] for more details on the [Connection] implementation. -func (t *SSEServerTransport) Connect(context.Context) (Connection, error) { - if t.incoming != nil { - return nil, fmt.Errorf("already connected") - } - t.incoming = make(chan jsonrpc.Message, 100) - t.done = make(chan struct{}) - _, err := writeEvent(t.Response, Event{ - Name: "endpoint", - Data: []byte(t.Endpoint), - }) - if err != nil { - return nil, err - } - return &sseServerConn{t: t}, nil -} - -func (h *SSEHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { - sessionID := req.URL.Query().Get("sessionid") - - // TODO: consider checking Content-Type here. For now, we are lax. - - // For POST requests, the message body is a message to send to a session. - if req.Method == http.MethodPost { - // Look up the session. - if sessionID == "" { - http.Error(w, "sessionid must be provided", http.StatusBadRequest) - return - } - h.mu.Lock() - session := h.sessions[sessionID] - h.mu.Unlock() - if session == nil { - http.Error(w, "session not found", http.StatusNotFound) - return - } - - session.ServeHTTP(w, req) - return - } - - if req.Method != http.MethodGet { - w.Header().Set("Allow", "GET, POST") - http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) - return - } - - // GET requests create a new session, and serve messages over SSE. - - // TODO: it's not entirely documented whether we should check Accept here. - // Let's again be lax and assume the client will accept SSE. - - w.Header().Set("Content-Type", "text/event-stream") - w.Header().Set("Cache-Control", "no-cache") - w.Header().Set("Connection", "keep-alive") - - sessionID = rand.Text() - endpoint, err := req.URL.Parse("?sessionid=" + sessionID) - if err != nil { - http.Error(w, "internal error: failed to create endpoint", http.StatusInternalServerError) - return - } - - transport := &SSEServerTransport{Endpoint: endpoint.RequestURI(), Response: w} - - // The session is terminated when the request exits. - h.mu.Lock() - h.sessions[sessionID] = transport - h.mu.Unlock() - defer func() { - h.mu.Lock() - delete(h.sessions, sessionID) - h.mu.Unlock() - }() - - server := h.getServer(req) - if server == nil { - // The getServer argument to NewSSEHandler returned nil. - http.Error(w, "no server available", http.StatusBadRequest) - return - } - ss, err := server.Connect(req.Context(), transport, nil) - if err != nil { - http.Error(w, "connection failed", http.StatusInternalServerError) - return - } - if h.onConnection != nil { - h.onConnection(ss) - } - defer ss.Close() // close the transport when the GET exits - - select { - case <-req.Context().Done(): - case <-transport.done: - } -} - -// sseServerConn implements the [Connection] interface for a single [SSEServerTransport]. -// It hides the Connection interface from the SSEServerTransport API. -type sseServerConn struct { - t *SSEServerTransport -} - -// TODO(jba): get the session ID. (Not urgent because SSE transports have been removed from the spec.) -func (s *sseServerConn) SessionID() string { return "" } - -// Read implements jsonrpc2.Reader. -func (s *sseServerConn) Read(ctx context.Context) (jsonrpc.Message, error) { - select { - case <-ctx.Done(): - return nil, ctx.Err() - case msg := <-s.t.incoming: - return msg, nil - case <-s.t.done: - return nil, io.EOF - } -} - -// Write implements jsonrpc2.Writer. -func (s *sseServerConn) Write(ctx context.Context, msg jsonrpc.Message) error { - if ctx.Err() != nil { - return ctx.Err() - } - - data, err := jsonrpc2.EncodeMessage(msg) - if err != nil { - return err - } - - s.t.mu.Lock() - defer s.t.mu.Unlock() - - // Note that it is invalid to write to a ResponseWriter after ServeHTTP has - // exited, and so we must lock around this write and check isDone, which is - // set before the hanging GET exits. - if s.t.closed { - return io.EOF - } - - _, err = writeEvent(s.t.Response, Event{Name: "message", Data: data}) - return err -} - -// Close implements io.Closer, and closes the session. -// -// It must be safe to call Close more than once, as the close may -// asynchronously be initiated by either the server closing its connection, or -// by the hanging GET exiting. -func (s *sseServerConn) Close() error { - s.t.mu.Lock() - defer s.t.mu.Unlock() - if !s.t.closed { - s.t.closed = true - close(s.t.done) - } - return nil -} - -// An SSEClientTransport is a [Transport] that can communicate with an MCP -// endpoint serving the SSE transport defined by the 2024-11-05 version of the -// spec. -// -// https://modelcontextprotocol.io/specification/2024-11-05/basic/transports -type SSEClientTransport struct { - // Endpoint is the SSE endpoint to connect to. - Endpoint string - - // HTTPClient is the client to use for making HTTP requests. If nil, - // http.DefaultClient is used. - HTTPClient *http.Client -} - -// Connect connects through the client endpoint. -func (c *SSEClientTransport) Connect(ctx context.Context) (Connection, error) { - parsedURL, err := url.Parse(c.Endpoint) - if err != nil { - return nil, fmt.Errorf("invalid endpoint: %v", err) - } - req, err := http.NewRequestWithContext(ctx, "GET", c.Endpoint, nil) - if err != nil { - return nil, err - } - httpClient := c.HTTPClient - if httpClient == nil { - httpClient = http.DefaultClient - } - req.Header.Set("Accept", "text/event-stream") - resp, err := httpClient.Do(req) - if err != nil { - return nil, err - } - - // Check HTTP status code before attempting to parse SSE events. - // This ensures proper error reporting for authentication failures (401), - // authorization failures (403), and other HTTP errors. - if resp.StatusCode < 200 || resp.StatusCode >= 300 { - resp.Body.Close() - return nil, fmt.Errorf("failed to connect: %s", http.StatusText(resp.StatusCode)) - } - - msgEndpoint, err := func() (*url.URL, error) { - var evt Event - for evt, err = range scanEvents(resp.Body) { - break - } - if err != nil { - return nil, err - } - if evt.Name != "endpoint" { - return nil, fmt.Errorf("first event is %q, want %q", evt.Name, "endpoint") - } - raw := string(evt.Data) - return parsedURL.Parse(raw) - }() - if err != nil { - resp.Body.Close() - return nil, fmt.Errorf("missing endpoint: %v", err) - } - - // From here on, the stream takes ownership of resp.Body. - s := &sseClientConn{ - client: httpClient, - msgEndpoint: msgEndpoint, - incoming: make(chan []byte, 100), - body: resp.Body, - done: make(chan struct{}), - } - - go func() { - defer s.Close() // close the transport when the GET exits - - for evt, err := range scanEvents(resp.Body) { - if err != nil { - return - } - select { - case s.incoming <- evt.Data: - case <-s.done: - return - } - } - }() - - return s, nil -} - -// An sseClientConn is a logical jsonrpc2 connection that implements the client -// half of the SSE protocol: -// - Writes are POSTS to the session endpoint. -// - Reads are SSE 'message' events, and pushes them onto a buffered channel. -// - Close terminates the GET request. -type sseClientConn struct { - client *http.Client // HTTP client to use for requests - msgEndpoint *url.URL // session endpoint for POSTs - incoming chan []byte // queue of incoming messages - - mu sync.Mutex - body io.ReadCloser // body of the hanging GET - closed bool // set when the stream is closed - done chan struct{} // closed when the stream is closed -} - -// TODO(jba): get the session ID. (Not urgent because SSE transports have been removed from the spec.) -func (c *sseClientConn) SessionID() string { return "" } - -func (c *sseClientConn) isDone() bool { - c.mu.Lock() - defer c.mu.Unlock() - return c.closed -} - -func (c *sseClientConn) Read(ctx context.Context) (jsonrpc.Message, error) { - select { - case <-ctx.Done(): - return nil, ctx.Err() - - case <-c.done: - return nil, io.EOF - - case data := <-c.incoming: - // TODO(rfindley): do we really need to check this? We receive from c.done above. - if c.isDone() { - return nil, io.EOF - } - msg, err := jsonrpc2.DecodeMessage(data) - if err != nil { - return nil, err - } - return msg, nil - } -} - -func (c *sseClientConn) Write(ctx context.Context, msg jsonrpc.Message) error { - data, err := jsonrpc2.EncodeMessage(msg) - if err != nil { - return err - } - if c.isDone() { - return io.EOF - } - req, err := http.NewRequestWithContext(ctx, "POST", c.msgEndpoint.String(), bytes.NewReader(data)) - if err != nil { - return err - } - req.Header.Set("Content-Type", "application/json") - resp, err := c.client.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - if resp.StatusCode < 200 || resp.StatusCode >= 300 { - return fmt.Errorf("failed to write: %s", resp.Status) - } - return nil -} - -func (c *sseClientConn) Close() error { - c.mu.Lock() - defer c.mu.Unlock() - if !c.closed { - c.closed = true - _ = c.body.Close() - close(c.done) - } - return nil -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/streamable.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/streamable.go deleted file mode 100644 index 207e63e..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/streamable.go +++ /dev/null @@ -1,2203 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// NOTE: see streamable_server.go and streamable_client.go for detailed -// documentation of the streamable server design. -// TODO: move the client and server logic into those files. - -package mcp - -import ( - "bytes" - "context" - crand "crypto/rand" - "encoding/json" - "errors" - "fmt" - "io" - "log/slog" - "maps" - "math" - "math/rand/v2" - "net" - "net/http" - "slices" - "strconv" - "strings" - "sync" - "time" - - "github.com/modelcontextprotocol/go-sdk/auth" - internaljson "github.com/modelcontextprotocol/go-sdk/internal/json" - "github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2" - "github.com/modelcontextprotocol/go-sdk/internal/mcpgodebug" - "github.com/modelcontextprotocol/go-sdk/internal/util" - "github.com/modelcontextprotocol/go-sdk/internal/xcontext" - "github.com/modelcontextprotocol/go-sdk/jsonrpc" -) - -const ( - protocolVersionHeader = "Mcp-Protocol-Version" - sessionIDHeader = "Mcp-Session-Id" - lastEventIDHeader = "Last-Event-ID" -) - -// A StreamableHTTPHandler is an http.Handler that serves streamable MCP -// sessions, as defined by the [MCP spec]. -// -// [MCP spec]: https://modelcontextprotocol.io/2025/03/26/streamable-http-transport.html -type StreamableHTTPHandler struct { - getServer func(*http.Request) *Server - opts StreamableHTTPOptions - - onTransportDeletion func(sessionID string) // for testing - - mu sync.Mutex - sessions map[string]*sessionInfo // keyed by session ID -} - -type sessionInfo struct { - session *ServerSession - transport *StreamableServerTransport - // userID is the user ID from the TokenInfo when the session was created. - // If non-empty, subsequent requests must have the same user ID to prevent - // session hijacking. - userID string - - // If timeout is set, automatically close the session after an idle period. - timeout time.Duration - timerMu sync.Mutex - refs int // reference count - timer *time.Timer -} - -// startPOST signals that a POST request for this session is starting (which -// carries a client->server message), pausing the session timeout if it was -// running. -// -// TODO: we may want to also pause the timer when resuming non-standalone SSE -// streams, but that is tricy to implement. Clients should generally make -// keepalive pings if they want to keep the session live. -func (i *sessionInfo) startPOST() { - if i.timeout <= 0 { - return - } - - i.timerMu.Lock() - defer i.timerMu.Unlock() - - if i.timer == nil { - return // timer stopped permanently - } - if i.refs == 0 { - i.timer.Stop() - } - i.refs++ -} - -// endPOST sigals that a request for this session is ending, starting the -// timeout if there are no other requests running. -func (i *sessionInfo) endPOST() { - if i.timeout <= 0 { - return - } - - i.timerMu.Lock() - defer i.timerMu.Unlock() - - if i.timer == nil { - return // timer stopped permanently - } - - i.refs-- - assert(i.refs >= 0, "negative ref count") - if i.refs == 0 { - i.timer.Reset(i.timeout) - } -} - -// stopTimer stops the inactivity timer permanently. -func (i *sessionInfo) stopTimer() { - i.timerMu.Lock() - defer i.timerMu.Unlock() - if i.timer != nil { - i.timer.Stop() - i.timer = nil - } -} - -// StreamableHTTPOptions configures the StreamableHTTPHandler. -type StreamableHTTPOptions struct { - // Stateless controls whether the session is 'stateless'. - // - // A stateless server does not validate the Mcp-Session-Id header, and uses a - // temporary session with default initialization parameters. Any - // server->client request is rejected immediately as there's no way for the - // client to respond. Server->Client notifications may reach the client if - // they are made in the context of an incoming request, as described in the - // documentation for [StreamableServerTransport]. - Stateless bool - - // TODO(#148): support session retention (?) - - // JSONResponse causes streamable responses to return application/json rather - // than text/event-stream ([§2.1.5] of the spec). - // - // [§2.1.5]: https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#sending-messages-to-the-server - JSONResponse bool - - // Logger specifies the logger to use. - // If nil, do not log. - Logger *slog.Logger - - // EventStore enables stream resumption. - // - // If set, EventStore will be used to persist stream events and replay them - // upon stream resumption. - EventStore EventStore - - // SessionTimeout configures a timeout for idle sessions. - // - // When sessions receive no new HTTP requests from the client for this - // duration, they are automatically closed. - // - // If SessionTimeout is the zero value, idle sessions are never closed. - SessionTimeout time.Duration - - // DisableLocalhostProtection disables automatic DNS rebinding protection. - // By default, requests arriving via a localhost address (127.0.0.1, [::1]) - // that have a non-localhost Host header are rejected with 403 Forbidden. - // This protects against DNS rebinding attacks regardless of whether the - // server is listening on localhost specifically or on 0.0.0.0. - // - // Only disable this if you understand the security implications. - // See: https://modelcontextprotocol.io/specification/2025-11-25/basic/security_best_practices#local-mcp-server-compromise - DisableLocalhostProtection bool -} - -// NewStreamableHTTPHandler returns a new [StreamableHTTPHandler]. -// -// The getServer function is used to create or look up servers for new -// sessions. It is OK for getServer to return the same server multiple times. -// If getServer returns nil, a 400 Bad Request will be served. -func NewStreamableHTTPHandler(getServer func(*http.Request) *Server, opts *StreamableHTTPOptions) *StreamableHTTPHandler { - h := &StreamableHTTPHandler{ - getServer: getServer, - sessions: make(map[string]*sessionInfo), - } - if opts != nil { - h.opts = *opts - } - - if h.opts.Logger == nil { // ensure we have a logger - h.opts.Logger = ensureLogger(nil) - } - - return h -} - -// closeAll closes all ongoing sessions, for tests. -// -// TODO(rfindley): investigate the best API for callers to configure their -// session lifecycle. (?) -// -// Should we allow passing in a session store? That would allow the handler to -// be stateless. -func (h *StreamableHTTPHandler) closeAll() { - // TODO: if we ever expose this outside of tests, we'll need to do better - // than simply collecting sessions while holding the lock: we need to prevent - // new sessions from being added. - // - // Currently, sessions remove themselves from h.sessions when closed, so we - // can't call Close while holding the lock. - h.mu.Lock() - sessionInfos := slices.Collect(maps.Values(h.sessions)) - h.sessions = nil - h.mu.Unlock() - for _, s := range sessionInfos { - s.session.Close() - } -} - -// disablelocalhostprotection is a compatibility parameter that allows to disable -// DNS rebinding protection, which was added in the 1.4.0 version of the SDK. -// See the documentation for the mcpgodebug package for instructions how to enable it. -// The option will be removed in the 1.6.0 version of the SDK. -var disablelocalhostprotection = mcpgodebug.Value("disablelocalhostprotection") - -func (h *StreamableHTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { - // DNS rebinding protection: auto-enabled for localhost servers. - // See: https://modelcontextprotocol.io/specification/2025-11-25/basic/security_best_practices#local-mcp-server-compromise - if !h.opts.DisableLocalhostProtection && disablelocalhostprotection != "1" { - if localAddr, ok := req.Context().Value(http.LocalAddrContextKey).(net.Addr); ok && localAddr != nil { - if util.IsLoopback(localAddr.String()) && !util.IsLoopback(req.Host) { - http.Error(w, fmt.Sprintf("Forbidden: invalid Host header %q", req.Host), http.StatusForbidden) - return - } - } - } - - // Allow multiple 'Accept' headers. - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Accept#syntax - accept := strings.Split(strings.Join(req.Header.Values("Accept"), ","), ",") - var jsonOK, streamOK bool - for _, c := range accept { - switch strings.TrimSpace(c) { - case "application/json", "application/*": - jsonOK = true - case "text/event-stream", "text/*": - streamOK = true - case "*/*": - jsonOK = true - streamOK = true - } - } - - if req.Method == http.MethodGet { - if !streamOK { - http.Error(w, "Accept must contain 'text/event-stream' for GET requests", http.StatusBadRequest) - return - } - } else if (!jsonOK || !streamOK) && req.Method != http.MethodDelete { // TODO: consolidate with handling of http method below. - http.Error(w, "Accept must contain both 'application/json' and 'text/event-stream'", http.StatusBadRequest) - return - } - - sessionID := req.Header.Get(sessionIDHeader) - var sessInfo *sessionInfo - if sessionID != "" { - h.mu.Lock() - sessInfo = h.sessions[sessionID] - h.mu.Unlock() - if sessInfo == nil && !h.opts.Stateless { - // Unless we're in 'stateless' mode, which doesn't perform any Session-ID - // validation, we require that the session ID matches a known session. - // - // In stateless mode, a temporary transport is be created below. - http.Error(w, "session not found", http.StatusNotFound) - return - } - // Prevent session hijacking: if the session was created with a user ID, - // verify that subsequent requests come from the same user. - if sessInfo != nil && sessInfo.userID != "" { - tokenInfo := auth.TokenInfoFromContext(req.Context()) - if tokenInfo == nil || tokenInfo.UserID != sessInfo.userID { - http.Error(w, "session user mismatch", http.StatusForbidden) - return - } - } - } - - if req.Method == http.MethodDelete { - if sessionID == "" { - http.Error(w, "Bad Request: DELETE requires an Mcp-Session-Id header", http.StatusBadRequest) - return - } - if sessInfo != nil { // sessInfo may be nil in stateless mode - // Closing the session also removes it from h.sessions, due to the - // onClose callback. - sessInfo.session.Close() - } - w.WriteHeader(http.StatusNoContent) - return - } - - switch req.Method { - case http.MethodPost, http.MethodGet: - if req.Method == http.MethodGet && (h.opts.Stateless || sessionID == "") { - if h.opts.Stateless { - // Per MCP spec: server MUST return 405 if it doesn't offer SSE stream. - // In stateless mode, GET (SSE streaming) is not supported. - // RFC 9110 §15.5.6: 405 responses MUST include Allow header. - w.Header().Set("Allow", "POST") - http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) - } else { - // In stateful mode, GET is supported but requires a session ID. - // This is a precondition error, similar to DELETE without session. - http.Error(w, "Bad Request: GET requires an Mcp-Session-Id header", http.StatusBadRequest) - } - return - } - default: - // RFC 9110 §15.5.6: 405 responses MUST include Allow header. - if h.opts.Stateless { - w.Header().Set("Allow", "POST") - } else { - w.Header().Set("Allow", "GET, POST, DELETE") - } - http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) - return - } - - // [§2.7] of the spec (2025-06-18) states: - // - // "If using HTTP, the client MUST include the MCP-Protocol-Version: - // HTTP header on all subsequent requests to the MCP - // server, allowing the MCP server to respond based on the MCP protocol - // version. - // - // For example: MCP-Protocol-Version: 2025-06-18 - // The protocol version sent by the client SHOULD be the one negotiated during - // initialization. - // - // For backwards compatibility, if the server does not receive an - // MCP-Protocol-Version header, and has no other way to identify the version - - // for example, by relying on the protocol version negotiated during - // initialization - the server SHOULD assume protocol version 2025-03-26. - // - // If the server receives a request with an invalid or unsupported - // MCP-Protocol-Version, it MUST respond with 400 Bad Request." - // - // Since this wasn't present in the 2025-03-26 version of the spec, this - // effectively means: - // 1. IF the client provides a version header, it must be a supported - // version. - // 2. In stateless mode, where we've lost the state of the initialize - // request, we assume that whatever the client tells us is the truth (or - // assume 2025-03-26 if the client doesn't say anything). - // - // This logic matches the typescript SDK. - // - // [§2.7]: https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#protocol-version-header - protocolVersion := req.Header.Get(protocolVersionHeader) - if protocolVersion == "" { - protocolVersion = protocolVersion20250326 - } - if !slices.Contains(supportedProtocolVersions, protocolVersion) { - http.Error(w, fmt.Sprintf("Bad Request: Unsupported protocol version (supported versions: %s)", strings.Join(supportedProtocolVersions, ",")), http.StatusBadRequest) - return - } - - if sessInfo == nil { - server := h.getServer(req) - if server == nil { - // The getServer argument to NewStreamableHTTPHandler returned nil. - http.Error(w, "no server available", http.StatusBadRequest) - return - } - if sessionID == "" { - // In stateless mode, sessionID may be nonempty even if there's no - // existing transport. - sessionID = server.opts.GetSessionID() - } - transport := &StreamableServerTransport{ - SessionID: sessionID, - Stateless: h.opts.Stateless, - EventStore: h.opts.EventStore, - jsonResponse: h.opts.JSONResponse, - logger: h.opts.Logger, - server: server, - } - - // Sessions without a session ID are also stateless: there's no way to - // address them. - stateless := h.opts.Stateless || sessionID == "" - // To support stateless mode, we initialize the session with a default - // state, so that it doesn't reject subsequent requests. - var connectOpts *ServerSessionOptions - if stateless { - // Peek at the body to see if it is initialize or initialized. - // We want those to be handled as usual. - var hasInitialize, hasInitialized bool - { - // TODO: verify that this allows protocol version negotiation for - // stateless servers. - body, err := io.ReadAll(req.Body) - if err != nil { - http.Error(w, "failed to read body", http.StatusBadRequest) - return - } - req.Body.Close() - - // Reset the body so that it can be read later. - req.Body = io.NopCloser(bytes.NewBuffer(body)) - - msgs, _, err := readBatch(body) - if err == nil { - for _, msg := range msgs { - if req, ok := msg.(*jsonrpc.Request); ok { - switch req.Method { - case methodInitialize: - hasInitialize = true - case notificationInitialized: - hasInitialized = true - } - } - } - } - } - - // If we don't have InitializeParams or InitializedParams in the request, - // set the initial state to a default value. - state := new(ServerSessionState) - if !hasInitialize { - state.InitializeParams = &InitializeParams{ - ProtocolVersion: protocolVersion, - } - } - if !hasInitialized { - state.InitializedParams = new(InitializedParams) - } - state.LogLevel = "info" - connectOpts = &ServerSessionOptions{ - State: state, - } - } else { - // Cleanup is only required in stateful mode, as transportation is - // not stored in the map otherwise. - connectOpts = &ServerSessionOptions{ - onClose: func() { - h.mu.Lock() - defer h.mu.Unlock() - if info, ok := h.sessions[transport.SessionID]; ok { - info.stopTimer() - delete(h.sessions, transport.SessionID) - if h.onTransportDeletion != nil { - h.onTransportDeletion(transport.SessionID) - } - } - }, - } - } - - // Pass req.Context() here, to allow middleware to add context values. - // The context is detached in the jsonrpc2 library when handling the - // long-running stream. - session, err := server.Connect(req.Context(), transport, connectOpts) - if err != nil { - http.Error(w, "failed connection", http.StatusInternalServerError) - return - } - // Capture the user ID from the token info to enable session hijacking - // prevention on subsequent requests. - var userID string - if tokenInfo := auth.TokenInfoFromContext(req.Context()); tokenInfo != nil { - userID = tokenInfo.UserID - } - sessInfo = &sessionInfo{ - session: session, - transport: transport, - userID: userID, - } - - if stateless { - // Stateless mode: close the session when the request exits. - defer session.Close() // close the fake session after handling the request - } else { - // Otherwise, save the transport so that it can be reused - - // Clean up the session when it times out. - // - // Note that the timer here may fire multiple times, but - // sessInfo.session.Close is idempotent. - if h.opts.SessionTimeout > 0 { - sessInfo.timeout = h.opts.SessionTimeout - sessInfo.timer = time.AfterFunc(sessInfo.timeout, func() { - sessInfo.session.Close() - }) - } - h.mu.Lock() - h.sessions[transport.SessionID] = sessInfo - h.mu.Unlock() - defer func() { - // If initialization failed, clean up the session (#578). - if session.InitializeParams() == nil { - // Initialization failed. - session.Close() - } - }() - } - } - - if req.Method == http.MethodPost { - sessInfo.startPOST() - defer sessInfo.endPOST() - } - - sessInfo.transport.ServeHTTP(w, req) -} - -// A StreamableServerTransport implements the server side of the MCP streamable -// transport. -// -// Each StreamableServerTransport must be connected (via [Server.Connect]) at -// most once, since [StreamableServerTransport.ServeHTTP] serves messages to -// the connected session. -// -// Reads from the streamable server connection receive messages from http POST -// requests from the client. Writes to the streamable server connection are -// sent either to the related stream, or to the standalone SSE stream, -// according to the following rules: -// - JSON-RPC responses to incoming requests are always routed to the -// appropriate HTTP response. -// - Requests or notifications made with a context.Context value derived from -// an incoming request handler, are routed to the HTTP response -// corresponding to that request, unless it has already terminated, in -// which case they are routed to the standalone SSE stream. -// - Requests or notifications made with a detached context.Context value are -// routed to the standalone SSE stream. -type StreamableServerTransport struct { - // SessionID is the ID of this session. - // - // If SessionID is the empty string, this is a 'stateless' session, which has - // limited ability to communicate with the client. Otherwise, the session ID - // must be globally unique, that is, different from any other session ID - // anywhere, past and future. (We recommend using a crypto random number - // generator to produce one, as with [crypto/rand.Text].) - SessionID string - - // Stateless controls whether the eventstore is 'Stateless'. Server sessions - // connected to a stateless transport are disallowed from making outgoing - // requests. - // - // See also [StreamableHTTPOptions.Stateless]. - Stateless bool - - // EventStore enables stream resumption. - // - // If set, EventStore will be used to persist stream events and replay them - // upon stream resumption. - EventStore EventStore - - // jsonResponse, if set, tells the server to prefer to respond to requests - // using application/json responses rather than text/event-stream. - // - // Specifically, responses will be application/json whenever incoming POST - // request contain only a single message. In this case, notifications or - // requests made within the context of a server request will be sent to the - // standalone SSE stream, if any. - // - // TODO(rfindley): jsonResponse should be exported, since - // StreamableHTTPOptions.JSONResponse is exported, and we want to allow users - // to write their own streamable HTTP handler. - jsonResponse bool - - // optional logger provided through the [StreamableHTTPOptions.Logger]. - // - // TODO(rfindley): logger should be exported, since we want to allow users - // to write their own streamable HTTP handler. - logger *slog.Logger - - // server is a reference to the Server for custom method dispatch. - server *Server - - // connection is non-nil if and only if the transport has been connected. - connection *streamableServerConn -} - -// Connect implements the [Transport] interface. -func (t *StreamableServerTransport) Connect(ctx context.Context) (Connection, error) { - if t.connection != nil { - return nil, fmt.Errorf("transport already connected") - } - t.connection = &streamableServerConn{ - sessionID: t.SessionID, - stateless: t.Stateless, - eventStore: t.EventStore, - jsonResponse: t.jsonResponse, - server: t.server, - logger: ensureLogger(t.logger), // see #556: must be non-nil - incoming: make(chan jsonrpc.Message, 10), - done: make(chan struct{}), - streams: make(map[string]*stream), - requestStreams: make(map[jsonrpc.ID]string), - } - // Stream 0 corresponds to the standalone SSE stream. - // - // It is always text/event-stream, since it must carry arbitrarily many - // messages. - var err error - t.connection.streams[""], err = t.connection.newStream(ctx, nil, "") - if err != nil { - return nil, err - } - return t.connection, nil -} - -type streamableServerConn struct { - sessionID string - stateless bool - jsonResponse bool - eventStore EventStore - server *Server // reference to Server for custom method checks - - logger *slog.Logger - - incoming chan jsonrpc.Message // messages from the client to the server - - mu sync.Mutex // guards all fields below - - // Sessions are closed exactly once. - isDone bool - done chan struct{} - - // Sessions can have multiple logical connections (which we call streams), - // corresponding to HTTP requests. Additionally, streams may be resumed by - // subsequent HTTP requests, when the HTTP connection is terminated - // unexpectedly. - // - // Therefore, we use a logical stream ID to key the stream state, and - // perform the accounting described below when incoming HTTP requests are - // handled. - - // streams holds the logical streams for this session, keyed by their ID. - // - // Lifecycle: streams persist until all of their responses are received from - // the server. - streams map[string]*stream - - // requestStreams maps incoming requests to their logical stream ID. - // - // Lifecycle: requestStreams persist until their response is received. - requestStreams map[jsonrpc.ID]string -} - -func (c *streamableServerConn) SessionID() string { - return c.sessionID -} - -// A stream is a single logical stream of SSE events within a server session. -// A stream begins with a client request, or with a client GET that has -// no Last-Event-ID header. -// -// A stream ends only when its session ends; we cannot determine its end otherwise, -// since a client may send a GET with a Last-Event-ID that references the stream -// at any time. -type stream struct { - // id is the logical ID for the stream, unique within a session. - // - // The standalone SSE stream has id "". - id string - - // logger is used for logging errors during stream operations. - logger *slog.Logger - - // mu guards the fields below, as well as storage of new messages in the - // connection's event store (if any). - mu sync.Mutex - - // If pendingJSONMessages is non-nil, this is a JSON stream and messages are - // collected here until the stream is complete, at which point they are - // flushed as a single JSON response. Note that the non-nilness of this field - // is significant, as it signals the expected content type. - // - // Note: if we remove support for batching, this could just be a bool. - pendingJSONMessages []json.RawMessage - - // w is the HTTP response writer for this stream. A non-nil w indicates - // that the stream is claimed by an HTTP request (the hanging POST or GET); - // it is set to nil when the request completes. - w http.ResponseWriter - - // done is closed to release the hanging HTTP request. - // - // Invariant: a non-nil done implies w is also non-nil, though the converse - // is not necessarily true: done is set to nil when it is closed, to avoid - // duplicate closure. - done chan struct{} - - // lastIdx is the index of the last written SSE event, for event ID generation. - // It starts at -1 since indices start at 0. - lastIdx int - - // protocolVersion is the protocol version for this stream. - protocolVersion string - - // requests is the set of unanswered incoming requests for the stream. - // - // Requests are removed when their response has been received. - // In practice, there is only one request, but in the 2025-03-26 version of - // the spec and earlier there was a concept of batching, in which POST - // payloads could hold multiple requests or responses. - requests map[jsonrpc.ID]struct{} -} - -// close sends a 'close' event to the client (if protocolVersion >= 2025-11-25 -// and reconnectAfter > 0) and closes the done channel. -// -// The done channel is set to nil after closing, so that done != nil implies -// the stream is active and done is open. This simplifies checks elsewhere. -func (s *stream) close(reconnectAfter time.Duration) { - s.mu.Lock() - defer s.mu.Unlock() - if s.done == nil { - return // stream not connected or already closed - } - if s.protocolVersion >= protocolVersion20251125 && reconnectAfter > 0 { - reconnectStr := strconv.FormatInt(reconnectAfter.Milliseconds(), 10) - if _, err := writeEvent(s.w, Event{ - Name: "close", - Retry: reconnectStr, - }); err != nil { - s.logger.Warn(fmt.Sprintf("Writing close event: %v", err)) - } - } - close(s.done) - s.done = nil -} - -// release releases the stream from its HTTP request, allowing it to be -// claimed by another request (e.g., for resumption). -func (s *stream) release() { - s.mu.Lock() - defer s.mu.Unlock() - s.w = nil - s.done = nil // may already be nil, if the stream is done or closed -} - -// deliverLocked writes data to the stream (for SSE) or stores it in -// pendingJSONMessages (for JSON mode). The eventID is used for SSE event ID; -// pass "" to omit. -// -// If responseTo is valid, it is removed from the requests map. When all -// requests have been responded to, the done channel is closed and set to nil. -// -// Returns true if the stream is now done (all requests have been responded to). -// The done value is always accurate, even if an error is returned. -// -// s.mu must be held when calling this method. -func (s *stream) deliverLocked(data []byte, eventID string, responseTo jsonrpc.ID) (done bool, err error) { - // First, record the response. We must do this *before* returning an error - // below, as even if the stream is disconnected we want to update our - // accounting. - if responseTo.IsValid() { - delete(s.requests, responseTo) - } - // Now, try to deliver the message to the client. - done = len(s.requests) == 0 && s.id != "" - if s.done == nil { - return done, fmt.Errorf("stream not connected or already closed") - } - if done { - defer func() { close(s.done); s.done = nil }() - } - // Try to write to the response. - // - // If we get here, the request is still hanging (because s.done != nil - // implies s.w != nil), but may have been cancelled by the client/http layer: - // there's a brief race between request cancellation and releasing the - // stream. - if s.pendingJSONMessages != nil { - s.pendingJSONMessages = append(s.pendingJSONMessages, data) - if done { - // Flush all pending messages as JSON response. - var toWrite []byte - if len(s.pendingJSONMessages) == 1 { - toWrite = s.pendingJSONMessages[0] - } else { - toWrite, err = json.Marshal(s.pendingJSONMessages) - if err != nil { - return done, err - } - } - if _, err := s.w.Write(toWrite); err != nil { - return done, err - } - } - } else { - // SSE mode: write event to response writer. - s.lastIdx++ - if _, err := writeEvent(s.w, Event{Name: "message", Data: data, ID: eventID}); err != nil { - return done, err - } - } - return done, nil -} - -// doneLocked reports whether the stream is logically complete. -// -// s.requests was populated when reading the POST body, requests are deleted as -// they are responded to. Once all requests have been responded to, the stream -// is done. -// -// s.mu must be held while calling this function. -func (s *stream) doneLocked() bool { - return len(s.requests) == 0 && s.id != "" -} - -func (c *streamableServerConn) newStream(ctx context.Context, requests map[jsonrpc.ID]struct{}, id string) (*stream, error) { - if c.eventStore != nil { - if err := c.eventStore.Open(ctx, c.sessionID, id); err != nil { - return nil, err - } - } - return &stream{ - id: id, - requests: requests, - lastIdx: -1, // indices start at 0, incremented before each write - logger: c.logger, - }, nil -} - -// We track the incoming request ID inside the handler context using -// idContextValue, so that notifications and server->client calls that occur in -// the course of handling incoming requests are correlated with the incoming -// request that caused them, and can be dispatched as server-sent events to the -// correct HTTP request. -// -// Currently, this is implemented in [ServerSession.handle]. This is not ideal, -// because it means that a user of the MCP package couldn't implement the -// streamable transport, as they'd lack this privileged access. -// -// If we ever wanted to expose this mechanism, we have a few options: -// 1. Make ServerSession an interface, and provide an implementation of -// ServerSession to handlers that closes over the incoming request ID. -// 2. Expose a 'HandlerTransport' interface that allows transports to provide -// a handler middleware, so that we don't hard-code this behavior in -// ServerSession.handle. -// 3. Add a `func ForRequest(context.Context) jsonrpc.ID` accessor that lets -// any transport access the incoming request ID. -// -// For now, by giving only the StreamableServerTransport access to the request -// ID, we avoid having to make this API decision. -type idContextKey struct{} - -// ServeHTTP handles a single HTTP request for the session. -func (t *StreamableServerTransport) ServeHTTP(w http.ResponseWriter, req *http.Request) { - if t.connection == nil { - http.Error(w, "transport not connected", http.StatusInternalServerError) - return - } - switch req.Method { - case http.MethodGet: - t.connection.serveGET(w, req) - case http.MethodPost: - t.connection.servePOST(w, req) - default: - // Should not be reached, as this is checked in StreamableHTTPHandler.ServeHTTP. - w.Header().Set("Allow", "GET, POST") - http.Error(w, "unsupported method", http.StatusMethodNotAllowed) - return - } -} - -// serveGET streams messages to a hanging http GET, with stream ID and last -// message parsed from the Last-Event-ID header. -// -// It returns an HTTP status code and error message. -func (c *streamableServerConn) serveGET(w http.ResponseWriter, req *http.Request) { - // streamID "" corresponds to the default GET request. - streamID := "" - // By default, we haven't seen a last index. Since indices start at 0, we represent - // that by -1. This is incremented just before each event is written. - lastIdx := -1 - if len(req.Header.Values(lastEventIDHeader)) > 0 { - eid := req.Header.Get(lastEventIDHeader) - var ok bool - streamID, lastIdx, ok = parseEventID(eid) - if !ok { - http.Error(w, fmt.Sprintf("malformed Last-Event-ID %q", eid), http.StatusBadRequest) - return - } - if c.eventStore == nil { - http.Error(w, "stream replay unsupported", http.StatusBadRequest) - return - } - } - - ctx := req.Context() - - // Read the protocol version from the header. For GET requests, this should - // always be present since GET only happens after initialization. - protocolVersion := req.Header.Get(protocolVersionHeader) - if protocolVersion == "" { - protocolVersion = protocolVersion20250326 - } - - stream, done := c.acquireStream(ctx, w, streamID, lastIdx, protocolVersion) - if stream == nil { - return - } - defer stream.release() - c.hangResponse(ctx, done) -} - -// hangResponse blocks the HTTP response until one of three conditions is met: -// - ctx is cancelled (the client disconnected or the request timed out) -// - done is closed (all responses have been sent, or the stream was explicitly closed) -// - the session is closed -// -// This keeps the HTTP connection open so that server-sent events can be -// written to the response. -func (c *streamableServerConn) hangResponse(ctx context.Context, done <-chan struct{}) { - select { - case <-ctx.Done(): - case <-done: - case <-c.done: - } -} - -// acquireStream replays all events since lastIdx, and acquires the ongoing -// stream, if any. If non-nil, the resulting stream will be registered for -// receiving new messages, and the stream's done channel will be closed when -// all related messages have been delivered. -// -// If any errors occur, they will be written to w and the resulting stream will -// be nil. The resulting stream may also be nil if the stream is complete. -// -// Importantly, this function must hold the stream mutex until done replaying -// all messages, so that no delivery or storage of new messages occurs while -// the stream is still replaying. -// -// protocolVersion is the protocol version for this stream, used to determine -// feature support (e.g. prime and close events were added in 2025-11-25). -func (c *streamableServerConn) acquireStream(ctx context.Context, w http.ResponseWriter, streamID string, lastIdx int, protocolVersion string) (*stream, chan struct{}) { - // if tempStream is set, the stream is done and we're just replaying messages. - // - // We record a temporary stream to claim exclusive replay rights. The spec - // (https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#resumability-and-redelivery) - // does not explicitly require exclusive replay, but we enforce it defensively. - tempStream := false - c.mu.Lock() - s, ok := c.streams[streamID] - if !ok { - // The stream is logically done, but claim exclusive rights to replay it by - // adding a temporary entry in the streams map. - // - // We create this entry with a non-nil w, to ensure it isn't claimed by - // another request before we lock it below. - tempStream = true - s = &stream{ - id: streamID, - w: w, - } - c.streams[streamID] = s - - // Since this stream is transient, we must clean up after replaying. - defer func() { - c.mu.Lock() - delete(c.streams, streamID) - c.mu.Unlock() - }() - } - c.mu.Unlock() - - s.mu.Lock() - defer s.mu.Unlock() - - // Check that this stream wasn't claimed by another request. - if !tempStream && s.w != nil { - http.Error(w, "stream ID conflicts with ongoing stream", http.StatusConflict) - return nil, nil - } - - // Collect events to replay. Collect them all before writing, so that we - // have an opportunity to set the HTTP status code on an error. - // - // As indicated above, we must do that while holding stream.mu, so that no - // new messages are added to the eventstore until we've replayed all previous - // messages, and registered our delivery function. - var toReplay [][]byte - if c.eventStore != nil { - for data, err := range c.eventStore.After(ctx, c.SessionID(), s.id, lastIdx) { - if err != nil { - // We can't replay events, perhaps because the underlying event store - // has garbage collected its storage. - // - // We must be careful here: any 404 will signal to the client that the - // *session* is not found, rather than the stream. - // - // 400 is not really accurate, but should at least have no side effects. - // Other SDKs (typescript) do not have a mechanism for events to be purged. - http.Error(w, "failed to replay events", http.StatusBadRequest) - return nil, nil - } - if len(data) > 0 { - toReplay = append(toReplay, data) - } - } - } - - w.Header().Set("Cache-Control", "no-cache, no-transform") - w.Header().Set("Content-Type", "text/event-stream") // Accept checked in [StreamableHTTPHandler] - w.Header().Set("Connection", "keep-alive") - - if s.id == "" { - // Issue #410: the standalone SSE stream is likely not to receive messages - // for a long time. Ensure that headers are flushed. - w.WriteHeader(http.StatusOK) - if f, ok := w.(http.Flusher); ok { - f.Flush() - } - } - - for _, data := range toReplay { - lastIdx++ - e := Event{Name: "message", Data: data} - if c.eventStore != nil { - e.ID = formatEventID(s.id, lastIdx) - } - if _, err := writeEvent(w, e); err != nil { - return nil, nil - } - } - - if tempStream || s.doneLocked() { - // Nothing more to do. - return nil, nil - } - - // The stream is not done: set up delivery state before the stream is - // unlocked, allowing the connection to write new events. - s.w = w - s.done = make(chan struct{}) - s.lastIdx = lastIdx - s.protocolVersion = protocolVersion - return s, s.done -} - -// servePOST handles an incoming message, and replies with either an outgoing -// message stream or single response object, depending on whether the -// jsonResponse option is set. -// -// It returns an HTTP status code and error message. -func (c *streamableServerConn) servePOST(w http.ResponseWriter, req *http.Request) { - if len(req.Header.Values(lastEventIDHeader)) > 0 { - http.Error(w, "can't send Last-Event-ID for POST request", http.StatusBadRequest) - return - } - - // Read incoming messages. - body, err := io.ReadAll(req.Body) - if err != nil { - http.Error(w, "failed to read body", http.StatusBadRequest) - return - } - if len(body) == 0 { - http.Error(w, "POST requires a non-empty body", http.StatusBadRequest) - return - } - // TODO(#674): once we've documented the support matrix for 2025-03-26 and - // earlier, drop support for matching entirely; that will simplify this - // logic. - incoming, isBatch, err := readBatch(body) - if err != nil { - http.Error(w, fmt.Sprintf("malformed payload: %v", err), http.StatusBadRequest) - return - } - - protocolVersion := req.Header.Get(protocolVersionHeader) - if protocolVersion == "" { - protocolVersion = protocolVersion20250326 - } - - if isBatch && protocolVersion >= protocolVersion20250618 { - http.Error(w, fmt.Sprintf("JSON-RPC batching is not supported in %s and later (request version: %s)", protocolVersion20250618, protocolVersion), http.StatusBadRequest) - return - } - - // TODO(rfindley): no tests fail if we reject batch JSON requests entirely. - // We need to test this with older protocol versions. - // if isBatch && c.jsonResponse { - // http.Error(w, "server does not support batch requests", http.StatusBadRequest) - // return - // } - - calls := make(map[jsonrpc.ID]struct{}) - tokenInfo := auth.TokenInfoFromContext(req.Context()) - isInitialize := false - var initializeProtocolVersion string - for _, msg := range incoming { - if jreq, ok := msg.(*jsonrpc.Request); ok { - // Preemptively check that this is a valid request, so that we can fail - // the HTTP request. If we didn't do this, a request with a bad method or - // missing ID could be silently swallowed. - // - // Custom methods registered via AddCustomMethod bypass the standard - // method info check — they only need a valid request ID. - isCustom := c.server != nil && c.server.hasCustomMethod(jreq.Method) - if !isCustom { - if _, err := checkRequest(jreq, serverMethodInfos); err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - } else if !jreq.IsCall() { - http.Error(w, fmt.Sprintf("missing id for %q", jreq.Method), http.StatusBadRequest) - return - } - if jreq.Method == methodInitialize { - isInitialize = true - // Extract the protocol version from InitializeParams. - var params InitializeParams - if err := internaljson.Unmarshal(jreq.Params, ¶ms); err == nil { - initializeProtocolVersion = params.ProtocolVersion - } - } - // Include metadata for all requests (including notifications). - jreq.Extra = &RequestExtra{ - TokenInfo: tokenInfo, - Header: req.Header, - } - if jreq.IsCall() { - calls[jreq.ID] = struct{}{} - // See the doc for CloseSSEStream: allow the request handler to - // explicitly close the ongoing stream. - jreq.Extra.(*RequestExtra).CloseSSEStream = func(args CloseSSEStreamArgs) { - c.mu.Lock() - streamID, ok := c.requestStreams[jreq.ID] - var stream *stream - if ok { - stream = c.streams[streamID] - } - c.mu.Unlock() - - if stream != nil { - stream.close(args.RetryAfter) - } - } - } - } - } - - // The prime and close events were added in protocol version 2025-11-25 (SEP-1699). - // Use the version from InitializeParams if this is an initialize request, - // otherwise use the protocol version header. - effectiveVersion := protocolVersion - if isInitialize && initializeProtocolVersion != "" { - effectiveVersion = initializeProtocolVersion - } - - // If we don't have any calls, we can just publish the incoming messages and return. - // No need to track a logical stream. - // - // See section [§2.1.4] of the spec: "If the server accepts the input, the - // server MUST return HTTP status code 202 Accepted with no body." - // - // [§2.1.4]: https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#sending-messages-to-the-server - if len(calls) == 0 { - for _, msg := range incoming { - select { - case c.incoming <- msg: - case <-c.done: - // The session is closing. Since we haven't yet written any data to the - // response, we can signal to the client that the session is gone. - http.Error(w, "session is closing", http.StatusNotFound) - return - } - } - w.WriteHeader(http.StatusAccepted) - return - } - - // Invariant: we have at least one call. - // - // Create a logical stream to track its responses. - // Important: don't publish the incoming messages until the stream is - // registered, as the server may attempt to respond to imcoming messages as - // soon as they're published. - stream, err := c.newStream(req.Context(), calls, crand.Text()) - if err != nil { - http.Error(w, fmt.Sprintf("storing stream: %v", err), http.StatusInternalServerError) - return - } - - // Set response headers. Accept was checked in [StreamableHTTPHandler]. - w.Header().Set("Cache-Control", "no-cache, no-transform") - if c.jsonResponse { - w.Header().Set("Content-Type", "application/json") - } else { - w.Header().Set("Content-Type", "text/event-stream") - w.Header().Set("Connection", "keep-alive") - } - if c.sessionID != "" && isInitialize { - w.Header().Set(sessionIDHeader, c.sessionID) - } - - // Set up stream delivery state. - stream.w = w - done := make(chan struct{}) - stream.done = done - stream.protocolVersion = effectiveVersion - if c.jsonResponse { - // JSON mode: collect messages in pendingJSONMessages until done. - // Set pendingJSONMessages to a non-nil value to signal that this is an - // application/json stream. - stream.pendingJSONMessages = []json.RawMessage{} - } else { - // SSE mode: write a priming event if supported. - if c.eventStore != nil && effectiveVersion >= protocolVersion20251125 { - // Write a priming event, as defined by [§2.1.6] of the spec. - // - // [§2.1.6]: https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#sending-messages-to-the-server - // - // We must also write it to the event store in order for indexes to - // align. - if err := c.eventStore.Append(req.Context(), c.sessionID, stream.id, nil); err != nil { - c.logger.Warn(fmt.Sprintf("Storing priming event: %v", err)) - } - stream.lastIdx++ - e := Event{Name: "prime", ID: formatEventID(stream.id, stream.lastIdx)} - if _, err := writeEvent(w, e); err != nil { - c.logger.Warn(fmt.Sprintf("Writing priming event: %v", err)) - } - } - } - - // TODO(rfindley): if we have no event store, we should really cancel all - // remaining requests here, since the client will never get the results. - defer stream.release() - - // The stream is now set up to deliver messages. - // - // Register it before publishing incoming messages. - c.mu.Lock() - c.streams[stream.id] = stream - for reqID := range calls { - c.requestStreams[reqID] = stream.id - } - c.mu.Unlock() - - // Publish incoming messages. - for _, msg := range incoming { - select { - case c.incoming <- msg: - // Note: don't select on req.Context().Done() here, since we've already - // received the requests and may have already published a response message - // or notification. The client could resume the stream. - // - // In fact, this send could be in a separate goroutine. - case <-c.done: - // Session closed: we don't know if any data has been written, so it's - // too late to write a status code here. - return - } - } - - c.hangResponse(req.Context(), done) -} - -// Event IDs: encode both the logical connection ID and the index, as -// _, to be consistent with the typescript implementation. - -// formatEventID returns the event ID to use for the logical connection ID -// streamID and message index idx. -// -// See also [parseEventID]. -func formatEventID(sid string, idx int) string { - return fmt.Sprintf("%s_%d", sid, idx) -} - -// parseEventID parses a Last-Event-ID value into a logical stream id and -// index. -// -// See also [formatEventID]. -func parseEventID(eventID string) (streamID string, idx int, ok bool) { - parts := strings.Split(eventID, "_") - if len(parts) != 2 { - return "", 0, false - } - streamID = parts[0] - idx, err := strconv.Atoi(parts[1]) - if err != nil || idx < 0 { - return "", 0, false - } - return streamID, idx, true -} - -// Read implements the [Connection] interface. -func (c *streamableServerConn) Read(ctx context.Context) (jsonrpc.Message, error) { - select { - case <-ctx.Done(): - return nil, ctx.Err() - case msg, ok := <-c.incoming: - if !ok { - return nil, io.EOF - } - return msg, nil - case <-c.done: - return nil, io.EOF - } -} - -// Write implements the [Connection] interface. -func (c *streamableServerConn) Write(ctx context.Context, msg jsonrpc.Message) error { - // Throughout this function, note that any error that wraps ErrRejected - // indicates a does not cause the connection to break. - // - // Most errors don't break the connection: unlike a true bidirectional - // stream, a failure to deliver to a stream is not an indication that the - // logical session is broken. - data, err := jsonrpc2.EncodeMessage(msg) - if err != nil { - return err - } - - if req, ok := msg.(*jsonrpc.Request); ok && req.IsCall() && (c.stateless || c.sessionID == "") { - // Requests aren't possible with stateless servers, or when there's no session ID. - return fmt.Errorf("%w: stateless servers cannot make requests", jsonrpc2.ErrRejected) - } - - // Find the incoming request that this write relates to, if any. - var ( - relatedRequest jsonrpc.ID - responseTo jsonrpc.ID // if valid, the message is a response to this request - ) - if resp, ok := msg.(*jsonrpc.Response); ok { - // If the message is a response, it relates to its request (of course). - relatedRequest = resp.ID - responseTo = resp.ID - } else { - // Otherwise, we check to see if it request was made in the context of an - // ongoing request. This may not be the case if the request was made with - // an unrelated context. - if v := ctx.Value(idContextKey{}); v != nil { - relatedRequest = v.(jsonrpc.ID) - } - } - - // If the stream is application/json, but the message is not a response, we - // must send it out of band to the standalone SSE stream. - if c.jsonResponse && !responseTo.IsValid() { - relatedRequest = jsonrpc.ID{} - } - - // Write the message to the stream. - var s *stream - c.mu.Lock() - if relatedRequest.IsValid() { - if streamID, ok := c.requestStreams[relatedRequest]; ok { - s = c.streams[streamID] - } - } else { - s = c.streams[""] // standalone SSE stream - } - if responseTo.IsValid() { - // Once we've responded to a request, disallow related messages by removing - // the stream association. This also releases memory. - delete(c.requestStreams, responseTo) - } - sessionClosed := c.isDone - c.mu.Unlock() - - if s == nil { - // The request was made in the context of an ongoing request, but that - // request is complete. - // - // In the future, we could be less strict and allow the request to land on - // the standalone SSE stream. - return fmt.Errorf("%w: write to closed stream", jsonrpc2.ErrRejected) - } - if sessionClosed { - return errors.New("session is closed") - } - - s.mu.Lock() - defer s.mu.Unlock() - - // Store in eventStore before delivering. - // TODO(rfindley): we should only append if the response is SSE, not JSON, by - // pushing down into the delivery layer. - delivered := false - var errs []error - if c.eventStore != nil { - if err := c.eventStore.Append(ctx, c.sessionID, s.id, data); err != nil { - errs = append(errs, err) - } else { - delivered = true - } - } - - // Compute eventID for SSE streams with event store. - // Use s.lastIdx + 1 because deliverLocked increments before writing. - var eventID string - if c.eventStore != nil { - eventID = formatEventID(s.id, s.lastIdx+1) - } - - done, err := s.deliverLocked(data, eventID, responseTo) - if err != nil { - errs = append(errs, err) - } else { - delivered = true - } - - if done { - c.mu.Lock() - delete(c.streams, s.id) - c.mu.Unlock() - } - - if !delivered { - return fmt.Errorf("%w: undelivered message: %v", jsonrpc2.ErrRejected, errors.Join(errs...)) - } - return nil -} - -// Close implements the [Connection] interface. -func (c *streamableServerConn) Close() error { - c.mu.Lock() - defer c.mu.Unlock() - if !c.isDone { - c.isDone = true - close(c.done) - if c.eventStore != nil { - // TODO: find a way to plumb a context here, or an event store with a long-running - // close operation can take arbitrary time. Alternative: impose a fixed timeout here. - return c.eventStore.SessionClosed(context.TODO(), c.sessionID) - } - } - return nil -} - -// A StreamableClientTransport is a [Transport] that can communicate with an MCP -// endpoint serving the streamable HTTP transport defined by the 2025-03-26 -// version of the spec. -type StreamableClientTransport struct { - Endpoint string - HTTPClient *http.Client - // MaxRetries is the maximum number of times to attempt a reconnect before giving up. - // It defaults to 5. To disable retries, use a negative number. - MaxRetries int - - // DisableStandaloneSSE controls whether the client establishes a standalone SSE stream - // for receiving server-initiated messages. - // - // When false (the default), after initialization the client sends an HTTP GET request - // to establish a persistent server-sent events (SSE) connection. This allows the server - // to send messages to the client at any time, such as ToolListChangedNotification or - // other server-initiated requests and notifications. The connection persists for the - // lifetime of the session and automatically reconnects if interrupted. - // - // When true, the client does not establish the standalone SSE stream. The client will - // only receive responses to its own POST requests. Server-initiated messages will not - // be received. - // - // According to the MCP specification, the standalone SSE stream is optional. - // Setting DisableStandaloneSSE to true is useful when: - // - You only need request-response communication and don't need server-initiated notifications - // - The server doesn't properly handle GET requests for SSE streams - // - You want to avoid maintaining a persistent connection - DisableStandaloneSSE bool - - // OAuthHandler is an optional field that, if provided, will be used to authorize the requests. - OAuthHandler auth.OAuthHandler - - // TODO(rfindley): propose exporting these. - // If strict is set, the transport is in 'strict mode', where any violation - // of the MCP spec causes a failure. - strict bool - // If logger is set, it is used to log aspects of the transport, such as spec - // violations that were ignored. - logger *slog.Logger -} - -// These settings are not (yet) exposed to the user in -// StreamableClientTransport. -const ( - // reconnectGrowFactor is the multiplicative factor by which the delay increases after each attempt. - // A value of 1.0 results in a constant delay, while a value of 2.0 would double it each time. - // It must be 1.0 or greater if MaxRetries is greater than 0. - reconnectGrowFactor = 1.5 - // reconnectMaxDelay caps the backoff delay, preventing it from growing indefinitely. - reconnectMaxDelay = 30 * time.Second -) - -var ( - // reconnectInitialDelay is the base delay for the first reconnect attempt. - // - // Mutable for testing. - reconnectInitialDelay = 1 * time.Second -) - -// Connect implements the [Transport] interface. -// -// The resulting [Connection] writes messages via POST requests to the -// transport URL with the Mcp-Session-Id header set, and reads messages from -// hanging requests. -// -// When closed, the connection issues a DELETE request to terminate the logical -// session. -func (t *StreamableClientTransport) Connect(ctx context.Context) (Connection, error) { - client := t.HTTPClient - if client == nil { - client = http.DefaultClient - } - maxRetries := t.MaxRetries - if maxRetries == 0 { - maxRetries = 5 - } else if maxRetries < 0 { - maxRetries = 0 - } - // Create a new cancellable context that will manage the connection's lifecycle. - // This is crucial for cleanly shutting down the background SSE listener by - // cancelling its blocking network operations, which prevents hangs on exit. - // - // This context should be detached from the incoming context: the standalone - // SSE request should not break when the connection context is done. - // - // For example, consider that the user may want to wait at most 5s to connect - // to the server, and therefore uses a context with a 5s timeout when calling - // client.Connect. Let's suppose that Connect returns after 1s, and the user - // starts using the resulting session. If we didn't detach here, the session - // would break after 4s, when the background SSE stream is terminated. - // - // Instead, creating a cancellable context detached from the incoming context - // allows us to preserve context values (which may be necessary for auth - // middleware), yet only cancel the standalone stream when the connection is closed. - connCtx, cancel := context.WithCancel(xcontext.Detach(ctx)) - conn := &streamableClientConn{ - url: t.Endpoint, - client: client, - incoming: make(chan jsonrpc.Message, 10), - done: make(chan struct{}), - maxRetries: maxRetries, - strict: t.strict, - logger: ensureLogger(t.logger), // must be non-nil for safe logging - ctx: connCtx, - cancel: cancel, - failed: make(chan struct{}), - disableStandaloneSSE: t.DisableStandaloneSSE, - oauthHandler: t.OAuthHandler, - } - return conn, nil -} - -type streamableClientConn struct { - url string - client *http.Client - ctx context.Context // connection context, detached from Connect - cancel context.CancelFunc // cancels ctx - incoming chan jsonrpc.Message - maxRetries int - strict bool // from [StreamableClientTransport.strict] - logger *slog.Logger // from [StreamableClientTransport.logger] - - // disableStandaloneSSE controls whether to disable the standalone SSE stream - // for receiving server-to-client notifications when no request is in flight. - disableStandaloneSSE bool // from [StreamableClientTransport.DisableStandaloneSSE] - - // oauthHandler is the OAuth handler for the connection. - oauthHandler auth.OAuthHandler // from [StreamableClientTransport.OAuthHandler] - - // Guard calls to Close, as it may be called multiple times. - closeOnce sync.Once - closeErr error - done chan struct{} // signal graceful termination - - // Logical reads are distributed across multiple http requests. Whenever any - // of them fails to process their response, we must break the connection, by - // failing the pending Read. - // - // Achieve this by storing the failure message, and signalling when reads are - // broken. See also [streamableClientConn.fail] and - // [streamableClientConn.failure]. - failOnce sync.Once - _failure error - failed chan struct{} // signal failure - - // Guard the initialization state. - mu sync.Mutex - initializedResult *InitializeResult - sessionID string -} - -var _ clientConnection = (*streamableClientConn)(nil) - -func (c *streamableClientConn) sessionUpdated(state clientSessionState) { - c.mu.Lock() - c.initializedResult = state.InitializeResult - c.mu.Unlock() - - // Start the standalone SSE stream as soon as we have the initialized - // result, if continuous listening is enabled. - // - // § 2.2: The client MAY issue an HTTP GET to the MCP endpoint. This can be - // used to open an SSE stream, allowing the server to communicate to the - // client, without the client first sending data via HTTP POST. - // - // We have to wait for initialized, because until we've received - // initialized, we don't know whether the server requires a sessionID. - // - // § 2.5: A server using the Streamable HTTP transport MAY assign a session - // ID at initialization time, by including it in a Mcp-Session-Id header - // on the HTTP response containing the InitializeResult. - if !c.disableStandaloneSSE { - c.connectStandaloneSSE() - } -} - -func (c *streamableClientConn) connectStandaloneSSE() { - resp, err := c.connectSSE(c.ctx, "", 0, true) - if err != nil { - // If the client didn't cancel the request, and failure breaks the logical - // session. - if c.ctx.Err() == nil { - c.fail(fmt.Errorf("standalone SSE request failed (session ID: %v): %v", c.sessionID, err)) - } - return - } - - // [§2.2.3]: "The server MUST either return Content-Type: - // text/event-stream in response to this HTTP GET, or else return HTTP - // 405 Method Not Allowed, indicating that the server does not offer an - // SSE stream at this endpoint." - // - // [§2.2.3]: https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#listening-for-messages-from-the-server - if resp.StatusCode == http.StatusMethodNotAllowed { - // The server doesn't support the standalone SSE stream. - resp.Body.Close() - return - } - if resp.Header.Get("Content-Type") != "text/event-stream" { - // modelcontextprotocol/go-sdk#736: some servers return 200 OK or redirect with - // non-SSE content type instead of text/event-stream for the standalone - // SSE stream. - c.logger.Warn(fmt.Sprintf("got Content-Type %s instead of text/event-stream for standalone SSE stream", resp.Header.Get("Content-Type"))) - resp.Body.Close() - return - } - if resp.StatusCode >= 400 && resp.StatusCode < 500 && !c.strict { - // modelcontextprotocol/go-sdk#393,#610: some servers return NotFound or - // other status codes instead of MethodNotAllowed for the standalone SSE - // stream. - // - // Treat this like MethodNotAllowed in non-strict mode. - c.logger.Warn(fmt.Sprintf("got %d instead of 405 for standalone SSE stream", resp.StatusCode)) - resp.Body.Close() - return - } - summary := "standalone SSE stream" - if err := c.checkResponse(summary, resp); err != nil { - c.fail(err) - return - } - go c.handleSSE(c.ctx, summary, resp, nil) -} - -// fail handles an asynchronous error while reading. -// -// If err is non-nil, it is terminal, and subsequent (or pending) Reads will -// fail. -// -// If err wraps ErrSessionMissing, the failure indicates that the session is no -// longer present on the server, and no final DELETE will be performed when -// closing the connection. -func (c *streamableClientConn) fail(err error) { - if err != nil { - c.failOnce.Do(func() { - c._failure = err - close(c.failed) - }) - } -} - -func (c *streamableClientConn) failure() error { - select { - case <-c.failed: - return c._failure - default: - return nil - } -} - -func (c *streamableClientConn) SessionID() string { - c.mu.Lock() - defer c.mu.Unlock() - return c.sessionID -} - -// Read implements the [Connection] interface. -func (c *streamableClientConn) Read(ctx context.Context) (jsonrpc.Message, error) { - if err := c.failure(); err != nil { - return nil, err - } - select { - case <-ctx.Done(): - return nil, ctx.Err() - case <-c.failed: - return nil, c.failure() - case <-c.done: - return nil, io.EOF - case msg := <-c.incoming: - return msg, nil - } -} - -// Write implements the [Connection] interface. -func (c *streamableClientConn) Write(ctx context.Context, msg jsonrpc.Message) error { - if err := c.failure(); err != nil { - return err - } - - var requestSummary string - var forCall *jsonrpc.Request - switch msg := msg.(type) { - case *jsonrpc.Request: - requestSummary = fmt.Sprintf("sending %q", msg.Method) - if msg.IsCall() { - forCall = msg - } - case *jsonrpc.Response: - requestSummary = fmt.Sprintf("sending jsonrpc response #%d", msg.ID) - default: - panic("unreachable") - } - - data, err := jsonrpc.EncodeMessage(msg) - if err != nil { - return fmt.Errorf("%s: %v", requestSummary, err) - } - - doRequest := func() (*http.Request, *http.Response, error) { - req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.url, bytes.NewReader(data)) - if err != nil { - return nil, nil, err - } - req.Header.Set("Content-Type", "application/json") - req.Header.Set("Accept", "application/json, text/event-stream") - if err := c.setMCPHeaders(req); err != nil { - // Failure to set headers means that the request was not sent. - // Wrap with ErrRejected so the jsonrpc2 connection doesn't set writeErr - // and permanently break the connection. - return nil, nil, fmt.Errorf("%s: %w: %v", requestSummary, jsonrpc2.ErrRejected, err) - } - resp, err := c.client.Do(req) - if err != nil { - // Any error from client.Do means the request didn't reach the server. - // Wrap with ErrRejected so the jsonrpc2 connection doesn't set writeErr - // and permanently break the connection. - err = fmt.Errorf("%s: %w: %v", requestSummary, jsonrpc2.ErrRejected, err) - } - return req, resp, err - } - - req, resp, err := doRequest() - if err != nil { - return err - } - - if (resp.StatusCode == http.StatusUnauthorized || resp.StatusCode == http.StatusForbidden) && c.oauthHandler != nil { - if err := c.oauthHandler.Authorize(ctx, req, resp); err != nil { - // Wrap with ErrRejected so the jsonrpc2 connection doesn't set writeErr - // and permanently break the connection. - // Wrap the authorization error as well for client inspection. - return fmt.Errorf("%s: %w: %w", requestSummary, jsonrpc2.ErrRejected, err) - } - // Retry the request after successful authorization. - _, resp, err = doRequest() - if err != nil { - return err - } - } - - if err := c.checkResponse(requestSummary, resp); err != nil { - // Only fail the connection for non-transient errors. - // Transient errors (wrapped with ErrRejected) should not break the connection. - if !errors.Is(err, jsonrpc2.ErrRejected) { - c.fail(err) - } - return err - } - - if sessionID := resp.Header.Get(sessionIDHeader); sessionID != "" { - c.mu.Lock() - hadSessionID := c.sessionID - if hadSessionID == "" { - c.sessionID = sessionID - } - c.mu.Unlock() - if hadSessionID != "" && hadSessionID != sessionID { - resp.Body.Close() - return fmt.Errorf("mismatching session IDs %q and %q", hadSessionID, sessionID) - } - } - - if forCall == nil { - resp.Body.Close() - - // [§2.1.4]: "If the input is a JSON-RPC response or notification: - // If the server accepts the input, the server MUST return HTTP status code 202 Accepted with no body." - // - // [§2.1.4]: https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#listening-for-messages-from-the-server - if resp.StatusCode != http.StatusNoContent && resp.StatusCode != http.StatusAccepted { - errMsg := fmt.Sprintf("unexpected status code %d from non-call", resp.StatusCode) - // Some servers return 200, even with an empty json body. - // - // In strict mode, return an error to the caller. - c.logger.Warn(errMsg) - if c.strict { - return errors.New(errMsg) - } - } - return nil - } - - contentType := strings.TrimSpace(strings.SplitN(resp.Header.Get("Content-Type"), ";", 2)[0]) - switch contentType { - case "application/json": - go c.handleJSON(requestSummary, resp) - - case "text/event-stream": - var forCall *jsonrpc.Request - if jsonReq, ok := msg.(*jsonrpc.Request); ok && jsonReq.IsCall() { - forCall = jsonReq - } - // Handle the resulting stream. Note that ctx comes from the call, and - // therefore is already cancelled when the JSON-RPC request is cancelled - // (or rather, context cancellation is what *triggers* JSON-RPC - // cancellation) - go c.handleSSE(ctx, requestSummary, resp, forCall) - - default: - resp.Body.Close() - return fmt.Errorf("%s: unsupported content type %q", requestSummary, contentType) - } - return nil -} - -func (c *streamableClientConn) setMCPHeaders(req *http.Request) error { - c.mu.Lock() - defer c.mu.Unlock() - - if c.oauthHandler != nil { - ts, err := c.oauthHandler.TokenSource(c.ctx) - if err != nil { - return err - } - if ts != nil { - token, err := ts.Token() - if err != nil { - return err - } - if token != nil { - req.Header.Set("Authorization", "Bearer "+token.AccessToken) - } - } - } - if c.initializedResult != nil { - req.Header.Set(protocolVersionHeader, c.initializedResult.ProtocolVersion) - } - if c.sessionID != "" { - req.Header.Set(sessionIDHeader, c.sessionID) - } - return nil -} - -func (c *streamableClientConn) handleJSON(requestSummary string, resp *http.Response) { - body, err := io.ReadAll(resp.Body) - resp.Body.Close() - if err != nil { - c.fail(fmt.Errorf("%s: failed to read body: %v", requestSummary, err)) - return - } - msg, err := jsonrpc.DecodeMessage(body) - if err != nil { - c.fail(fmt.Errorf("%s: failed to decode response: %v", requestSummary, err)) - return - } - select { - case c.incoming <- msg: - case <-c.done: - // The connection was closed by the client; exit gracefully. - } -} - -// handleSSE manages the lifecycle of an SSE connection. It can be either -// persistent (for the main GET listener) or temporary (for a POST response). -// -// If forCall is set, it is the call that initiated the stream, and the -// stream is complete when we receive its response. Otherwise, this is the -// standalone stream. -func (c *streamableClientConn) handleSSE(ctx context.Context, requestSummary string, resp *http.Response, forCall *jsonrpc2.Request) { - // Track the last event ID to detect progress. - // The retry counter is only reset when progress is made (lastEventID advances). - // This prevents infinite retry loops when a server repeatedly terminates - // connections without making progress (#679). - var prevLastEventID string - retriesWithoutProgress := 0 - - for { - lastEventID, reconnectDelay, clientClosed := c.processStream(ctx, requestSummary, resp, forCall) - - // If the connection was closed by the client, we're done. - if clientClosed { - return - } - // If we don't have a last event ID, we can never get the call response, so - // there's nothing to resume. For the standalone stream, we can reconnect, - // but we may just miss messages. - if lastEventID == "" && forCall != nil { - return - } - - // Check if we made progress (lastEventID advanced). - // Only reset the retry counter when actual progress is made. - if lastEventID != "" && lastEventID != prevLastEventID { - // Progress was made: reset the retry counter. - retriesWithoutProgress = 0 - prevLastEventID = lastEventID - } else { - // No progress: increment the retry counter. - retriesWithoutProgress++ - if retriesWithoutProgress > c.maxRetries { - if ctx.Err() == nil { - c.fail(fmt.Errorf("%s: exceeded %d retries without progress (session ID: %v)", requestSummary, c.maxRetries, c.sessionID)) - } - return - } - } - - // The stream was interrupted or ended by the server. Attempt to reconnect. - newResp, err := c.connectSSE(ctx, lastEventID, reconnectDelay, false) - if err != nil { - // If the client didn't cancel this request, any failure to execute it - // breaks the logical MCP session. - if ctx.Err() == nil { - // All reconnection attempts failed: fail the connection. - c.fail(fmt.Errorf("%s: failed to reconnect (session ID: %v): %v", requestSummary, c.sessionID, err)) - } - return - } - - resp = newResp - if err := c.checkResponse(requestSummary, resp); err != nil { - c.fail(err) - return - } - } -} - -// checkResponse checks the status code of the provided response, and -// translates it into an error if the request was unsuccessful. -// -// The response body is close if a non-nil error is returned. -func (c *streamableClientConn) checkResponse(requestSummary string, resp *http.Response) (err error) { - defer func() { - if err != nil { - resp.Body.Close() - } - }() - // §2.5.3: "The server MAY terminate the session at any time, after - // which it MUST respond to requests containing that session ID with HTTP - // 404 Not Found." - if resp.StatusCode == http.StatusNotFound { - // Return an ErrSessionMissing to avoid sending a redundant DELETE when the - // session is already gone. - return fmt.Errorf("%s: failed to connect (session ID: %v): %w", requestSummary, c.sessionID, ErrSessionMissing) - } - // Transient server errors (502, 503, 504, 429) should not break the connection. - // Wrap them with ErrRejected so the jsonrpc2 layer doesn't set writeErr. - if isTransientHTTPStatus(resp.StatusCode) { - return fmt.Errorf("%w: %s: %v", jsonrpc2.ErrRejected, requestSummary, http.StatusText(resp.StatusCode)) - } - if resp.StatusCode < 200 || resp.StatusCode >= 300 { - return fmt.Errorf("%s: %v", requestSummary, http.StatusText(resp.StatusCode)) - } - return nil -} - -// processStream reads from a single response body, sending events to the -// incoming channel. It returns the ID of the last processed event and a flag -// indicating if the connection was closed by the client. If resp is nil, it -// returns "", false. -func (c *streamableClientConn) processStream(ctx context.Context, requestSummary string, resp *http.Response, forCall *jsonrpc.Request) (lastEventID string, reconnectDelay time.Duration, clientClosed bool) { - defer func() { - // Drain any remaining unprocessed body. This allows the connection to be re-used after closing. - io.Copy(io.Discard, resp.Body) - resp.Body.Close() - }() - for evt, err := range scanEvents(resp.Body) { - if err != nil { - if ctx.Err() != nil { - return "", 0, true // don't reconnect: client cancelled - } - - // Malformed events are hard errors that indicate corrupted data or protocol - // violations. These should fail the connection permanently. - if errors.Is(err, errMalformedEvent) { - c.fail(fmt.Errorf("%s: %v", requestSummary, err)) - return "", 0, true - } - - break - } - - if evt.ID != "" { - lastEventID = evt.ID - } - - if evt.Retry != "" { - if n, err := strconv.ParseInt(evt.Retry, 10, 64); err == nil { - reconnectDelay = time.Duration(n) * time.Millisecond - } - } - - // According to SSE specification - // (https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation) - // events with an empty data buffer are allowed. - // In MCP these can be priming events (SEP-1699) that carry only a Last-Event-ID for stream resumption. - if len(evt.Data) == 0 { - continue - } - - // According to SSE spec, events with no name default to "message" - if evt.Name != "" && evt.Name != "message" { - continue - } - - msg, err := jsonrpc.DecodeMessage(evt.Data) - if err != nil { - c.fail(fmt.Errorf("%s: failed to decode event: %v", requestSummary, err)) - return "", 0, true - } - - select { - case c.incoming <- msg: - // Check if this is the response to our call, which terminates the request. - // (it could also be a server->client request or notification). - if jsonResp, ok := msg.(*jsonrpc.Response); ok && forCall != nil { - // TODO: we should never get a response when forReq is nil (the standalone SSE request). - // We should detect this case. - if jsonResp.ID == forCall.ID { - return "", 0, true - } - } - - case <-c.done: - // The connection was closed by the client; exit gracefully. - return "", 0, true - } - } - // The loop finished without an error, indicating the server closed the stream. - // - // If the lastEventID is "", the stream is not retryable and we should - // report a synthetic error for the call. - // - // Note that this is different from the cancellation case above, since the - // caller is still waiting for a response that will never come. - if lastEventID == "" && forCall != nil { - errmsg := &jsonrpc2.Response{ - ID: forCall.ID, - Error: fmt.Errorf("request terminated without response"), - } - select { - case c.incoming <- errmsg: - case <-c.done: - } - } - return lastEventID, reconnectDelay, false -} - -// connectSSE handles the logic of connecting a text/event-stream connection. -// -// If lastEventID is set, it is the last-event ID of a stream being resumed. -// -// If connection fails, connectSSE retries with an exponential backoff -// strategy. It returns a new, valid HTTP response if successful, or an error -// if all retries are exhausted. -// -// reconnectDelay is the delay set by the server using the SSE retry field, or -// 0. -// -// If initial is set, this is the initial attempt. -// -// If connectSSE exits due to context cancellation, the result is (nil, ctx.Err()). -func (c *streamableClientConn) connectSSE(ctx context.Context, lastEventID string, reconnectDelay time.Duration, initial bool) (*http.Response, error) { - var finalErr error - attempt := 0 - if !initial { - // We've already connected successfully once, so delay subsequent - // reconnections. Otherwise, if the server returns 200 but terminates the - // connection, we'll reconnect as fast as we can, ad infinitum. - // - // TODO: we should consider also setting a limit on total attempts for one - // logical request. - attempt = 1 - } - delay := calculateReconnectDelay(attempt) - if reconnectDelay > 0 { - delay = reconnectDelay // honor the server's requested initial delay - } - for ; attempt <= c.maxRetries; attempt++ { - select { - case <-c.done: - return nil, fmt.Errorf("connection closed by client during reconnect") - - case <-ctx.Done(): - // If the connection context is canceled, the request below will not - // succeed anyway. - return nil, ctx.Err() - - case <-time.After(delay): - req, err := http.NewRequestWithContext(ctx, http.MethodGet, c.url, nil) - if err != nil { - return nil, err - } - if err := c.setMCPHeaders(req); err != nil { - return nil, err - } - if lastEventID != "" { - req.Header.Set(lastEventIDHeader, lastEventID) - } - req.Header.Set("Accept", "text/event-stream") - resp, err := c.client.Do(req) - if err != nil { - finalErr = err // Store the error and try again. - delay = calculateReconnectDelay(attempt + 1) - continue - } - return resp, nil - } - } - // If the loop completes, all retries have failed, or the client is closing. - if finalErr != nil { - return nil, fmt.Errorf("connection failed after %d attempts: %w", c.maxRetries, finalErr) - } - return nil, fmt.Errorf("connection aborted after %d attempts", c.maxRetries) -} - -// Close implements the [Connection] interface. -func (c *streamableClientConn) Close() error { - c.closeOnce.Do(func() { - if errors.Is(c.failure(), ErrSessionMissing) { - // If the session is missing, no need to delete it. - } else { - req, err := http.NewRequestWithContext(c.ctx, http.MethodDelete, c.url, nil) - if err != nil { - c.closeErr = err - } else { - if err := c.setMCPHeaders(req); err != nil { - c.closeErr = err - } else if _, err := c.client.Do(req); err != nil { - c.closeErr = err - } - } - } - - // Cancel any hanging network requests after cleanup. - c.cancel() - close(c.done) - }) - return c.closeErr -} - -// calculateReconnectDelay calculates a delay using exponential backoff with full jitter. -func calculateReconnectDelay(attempt int) time.Duration { - if attempt == 0 { - return 0 - } - // Calculate the exponential backoff using the grow factor. - backoffDuration := time.Duration(float64(reconnectInitialDelay) * math.Pow(reconnectGrowFactor, float64(attempt-1))) - // Cap the backoffDuration at maxDelay. - backoffDuration = min(backoffDuration, reconnectMaxDelay) - - // Use a full jitter using backoffDuration - jitter := rand.N(backoffDuration) - - return backoffDuration + jitter -} - -// isTransientHTTPStatus reports whether the HTTP status code indicates a -// transient server error that should not permanently break the connection. -func isTransientHTTPStatus(statusCode int) bool { - switch statusCode { - case http.StatusInternalServerError, // 500 - http.StatusBadGateway, // 502 - http.StatusServiceUnavailable, // 503 - http.StatusGatewayTimeout, // 504 - http.StatusTooManyRequests: // 429 - return true - } - return false -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/streamable_client.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/streamable_client.go deleted file mode 100644 index c2cc25b..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/streamable_client.go +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// TODO: move client-side streamable HTTP logic from streamable.go to this file. - -package mcp - -/* -Streamable HTTP Client Design - -This document describes the client-side implementation of the MCP streamable -HTTP transport, as defined by the MCP spec: -https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#streamable-http - -# Overview - -The client-side streamable transport allows an MCP client to communicate with a -server over HTTP, sending messages via POST and receiving responses via either -JSON or server-sent events (SSE). The implementation consists of two main -components: - - ┌─────────────────────────────────────────────────────────────────┐ - │ [StreamableClientTransport] │ - │ Transport configuration; creates connections via Connect() │ - └─────────────────────────────────────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────────────────┐ - │ [streamableClientConn] │ - │ Connection implementation; handles HTTP request/response │ - └─────────────────────────────────────────────────────────────────┘ - │ - ├──────────────────────────────────────┐ - ▼ ▼ - ┌─────────────────────────────────────────┐ ┌────────────────────────────────────┐ - │ POST request handlers │ │ Standalone SSE stream │ - │ (one per outgoing message/call) │ │ (server-initiated messages) │ - └─────────────────────────────────────────┘ └────────────────────────────────────┘ - -# Sessions - -The client maintains a session with the server, identified by a session ID -(Mcp-Session-Id header): - - - Session ID is received from the server after initialization - - Client includes the session ID in all subsequent requests - - Session ends when the client calls Close() (sends DELETE) or server returns 404 - -[streamableClientConn] stores the session state: - - [streamableClientConn.sessionID]: Server-assigned session identifier - - [streamableClientConn.initializedResult]: Protocol version and server capabilities - -# Connection Lifecycle - -1. Connect: [StreamableClientTransport.Connect] creates a [streamableClientConn] - with a detached context for the connection's lifetime. The context is detached - to prevent the standalone SSE stream from being cancelled when the original - Connect context times out. - -2. Initialize: The MCP client sends initialize/initialized messages. Upon - receiving [InitializeResult], the connection: - - Stores the negotiated protocol version for the Mcp-Protocol-Version header - - Captures the session ID from the Mcp-Session-Id response header - - Starts the standalone SSE stream via [streamableClientConn.connectStandaloneSSE] - -3. Operation: Messages are sent via POST, responses received via JSON or SSE. - -4. Close: [streamableClientConn.Close] sends a DELETE request to terminate - the session (unless the session is already gone), then cancels the connection - context to clean up the standalone SSE stream. - -# Sending Messages (Write) - -[streamableClientConn.Write] sends all outgoing messages via HTTP POST: - - POST /endpoint - Content-Type: application/json - Accept: application/json, text/event-stream - Mcp-Protocol-Version: - Mcp-Session-Id: - - - -The server may respond with: - - 202 Accepted: Message received, no response body (notifications/responses) - - 200 OK with application/json: Single JSON-RPC response - - 200 OK with text/event-stream: SSE stream of responses - -# Receiving Messages (Read) - -[streamableClientConn.Read] returns messages from the [streamableClientConn.incoming] -channel, which is populated by multiple concurrent goroutines: - -1. POST response handlers ([streamableClientConn.handleJSON] and - [streamableClientConn.handleSSE]): Process responses from POST requests - -2. Standalone SSE stream: Receives server-initiated requests and notifications - -The client handles both response formats: - - JSON: [streamableClientConn.handleJSON] reads body, decodes message - - SSE: [streamableClientConn.handleSSE] scans events, decodes each message - -# Standalone SSE Stream - -After initialization, [streamableClientConn.sessionUpdated] triggers -[streamableClientConn.connectStandaloneSSE] to open a GET request for -server-initiated messages: - - GET /endpoint - Accept: text/event-stream - Mcp-Session-Id: - -Stream behavior: - - Optional: Server may return 405 Method Not Allowed (spec-compliant) or - other 4xx errors (tolerated in non-strict mode for compatibility) - - Persistent: Runs for the connection lifetime in a background goroutine - - Resumable: Uses Last-Event-ID header on reconnection if server provides event IDs - - Reconnects: Automatic reconnection with exponential backoff on interruption - -# Stream Resumption - -When an SSE stream (standalone or POST response) is interrupted, the client -attempts to reconnect using [streamableClientConn.connectSSE]: - -Event ID tracking: - - [streamableClientConn.processStream] tracks the last received event ID - - On reconnection, the Last-Event-ID header is set to resume from that point - - Server replays missed events if it has an [EventStore] configured - -See [calculateReconnectDelay] for the reconnect delay details. - -Server-initiated reconnection (SEP-1699) - - SSE retry field: Sets the delay for the next reconnect attempt - - If server doesn't provide event IDs, non-standalone streams don't reconnect - -# Response Formats - -The client must handle two response formats from POST requests: - -1. application/json: Single JSON-RPC response - - Body contains one JSON-RPC message - - Handled by [streamableClientConn.handleJSON] - - Simpler but doesn't support streaming or server-initiated messages - -2. text/event-stream: SSE stream of messages - - Body contains SSE events with JSON-RPC messages - - Handled by [streamableClientConn.handleSSE] - - Supports multiple messages and server-initiated communication - - Stream completes when the response to the originating call is received - -# HTTP Methods - - - POST: Send JSON-RPC messages (requests, responses, notifications) - - Used by [streamableClientConn.Write] - - Response may be JSON or SSE - - - GET: Open or resume SSE stream for server-initiated messages - - Used by [streamableClientConn.connectSSE] - - Always expects text/event-stream response (or 405) - - - DELETE: Terminate the session - - Used by [streamableClientConn.Close] - - Skipped if session is already known to be gone ([ErrSessionMissing]) - -# Error Handling - -Errors are categorized and handled differently: - -1. Transient (recoverable via reconnection): - - Network interruption during SSE streaming - - Connection reset or timeout - - Triggers reconnection in [streamableClientConn.handleSSE] - -2. Terminal (breaks the connection): - - 404 Not Found: Session terminated by server ([ErrSessionMissing]) - - Message decode errors: Protocol violation - - Context cancellation: Client closed connection - - Mismatched session IDs: Protocol error - - See issue #683: our terminal errors are too strict. - -Terminal errors are stored via [streamableClientConn.fail] and returned by -subsequent [streamableClientConn.Read] calls. The [streamableClientConn.failed] -channel signals that the connection is broken. - -Special case: [ErrSessionMissing] indicates the server has terminated the session, -so [streamableClientConn.Close] skips the DELETE request. - -# Protocol Version Header - -After initialization, all requests include: - - Mcp-Protocol-Version: - -This header (set by [streamableClientConn.setMCPHeaders]): - - Allows the server to handle requests per the negotiated protocol - - Is omitted before initialization completes - - Uses the version from [streamableClientConn.initializedResult] - -# Key Implementation Details - -[StreamableClientTransport] configuration: - - [StreamableClientTransport.Endpoint]: URL of the MCP server - - [StreamableClientTransport.HTTPClient]: Custom HTTP client (optional) - - [StreamableClientTransport.MaxRetries]: Reconnection attempts (default 5) - -[streamableClientConn] handles the [Connection] interface: - - [streamableClientConn.Read]: Returns messages from incoming channel - - [streamableClientConn.Write]: Sends messages via POST, starts response handlers - - [streamableClientConn.Close]: Sends DELETE, cancels context, closes done channel - -State management: - - [streamableClientConn.incoming]: Buffered channel for received messages - - [streamableClientConn.sessionID]: Server-assigned session identifier - - [streamableClientConn.initializedResult]: Cached for protocol version header - - [streamableClientConn.failed]: Channel closed on terminal error - - [streamableClientConn.done]: Channel closed on graceful shutdown - - [streamableClientConn.ctx]: Detached context for connection lifetime - - [streamableClientConn.cancel]: Cancels ctx to terminate SSE streams - -Context handling: - - Connection context is detached from [StreamableClientTransport.Connect] context - using [xcontext.Detach] to preserve context values (for auth middleware) while - preventing premature cancellation of the standalone SSE stream - - Individual POST requests use caller-provided contexts for cancellation -*/ diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/streamable_server.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/streamable_server.go deleted file mode 100644 index 8a573e5..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/streamable_server.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// TODO: move server-side streamable HTTP logic from streamable.go to this file. - -package mcp - -/* -Streamable HTTP Server Design - -This document describes the server-side implementation of the MCP streamable -HTTP transport, as defined by the MCP spec: -https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#streamable-http - -# Overview - -The streamable HTTP transport enables MCP communication over HTTP, with -server-sent events (SSE) for server-to-client messages. The implementation -consists of several layered components: - - ┌─────────────────────────────────────────────────────────────────┐ - │ [StreamableHTTPHandler] │ - │ http.Handler that manages sessions and routes HTTP requests │ - └─────────────────────────────────────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────────────────┐ - │ [StreamableServerTransport] │ - │ transport implementation, one per session; exposes ServeHTTP │ - └─────────────────────────────────────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────────────────┐ - │ [streamableServerConn] │ - │ Connection implementation, handles message routing │ - └─────────────────────────────────────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────────────────┐ - │ [stream] │ - │ Logical message channel within a session, may be resumed │ - └─────────────────────────────────────────────────────────────────┘ - -# Sessions - -As with other transports, a session represents a logical MCP connection between -a client and server. In the streamable transport, sessions are identified by a -unique session ID (Mcp-Session-Id header) and persist across multiple HTTP -requests. - -[StreamableHTTPHandler] maintains a map of active sessions ([sessionInfo]), -each containing: - - The [ServerSession] (MCP-level session state) - - The [StreamableServerTransport] (for message I/O) - - Optional timeout management for idle session cleanup - -Sessions are created on the first POST request (typically containing the -initialize request) and destroyed either by: - - Client sending a DELETE request - - Session timeout due to inactivity - - Server explicitly closing the session - -# Streams - -Within a session, there can be multiple concurrent "streams" - logical channels -for message delivery. This is distinct from HTTP streams; a single [stream] may -span multiple HTTP request/response cycles (via resumption). - -There are two types of streams: - -1. Optional standalone SSE stream (id = ""): - - Created when client sends a GET request to the endpoint - - Used for server-initiated messages (requests/notifications to client) - - Persists for the lifetime of the session - - Only one standalone stream per session - -2. Request streams (id = random string): - - Created for each POST request containing JSON-RPC calls - - Used to route responses back to the originating HTTP request - - Completed when all responses have been sent - - Can be resumed via GET with Last-Event-ID if interrupted - -# Message Routing - -When the server writes a message, it must be routed to the correct [stream]: - - - Responses: Routed to the stream that originated the request - - Requests/Notifications made during request handling: Routed to the same - stream as the triggering request (via context) - - Requests/Notifications made outside request handling: Routed to the - standalone SSE stream - -This routing is implemented using: - - [streamableServerConn.requestStreams] maps request IDs to stream IDs - - [idContextKey] is used to store the originating request ID in Context - - [streamableServerConn.streams] maps stream IDs to [stream] objects - -# Stream Resumption - -If an HTTP connection is interrupted (network issues, etc.), clients can -resume a stream by sending a GET request with the Last-Event-ID header. -This requires an [EventStore] to be configured on the server. - - - [EventStore.Open] is called when a new stream is created - - [EventStore.Append] is called for each message written to the stream - - [EventStore.After] is called to replay messages after a given index - - [EventStore.SessionClosed] is called when the session ends - -Event IDs are formatted as "_" to identify both the -stream and position within that stream (see [formatEventID] and [parseEventID]). - -# Stateless Mode - -For simpler deployments, the handler supports "stateless" mode -([StreamableHTTPOptions.Stateless]) where: - - No session ID validation is performed - - Each request creates a temporary session that's closed after the request - - Server-to-client requests are not supported (no way to receive response) - -This mode is useful for simple tool servers that don't need bidirectional -communication. - -# Response Formats - -The server can respond to POST requests in two formats: - -1. text/event-stream (default): Messages sent as SSE events, supports - streaming multiple messages and server-initiated communication during - request handling. - -2. application/json ([StreamableHTTPOptions.JSONResponse]): Single JSON - response, simpler but doesn't support streaming. Server-initiated messages - during request handling go to the standalone SSE stream instead. - -# HTTP Methods - - - POST: Send JSON-RPC messages (requests, responses, notifications) - - GET: Open standalone SSE stream or resume an interrupted stream - - DELETE: Terminate the session - -# Key Implementation Details - -The [stream] struct manages delivery of messages to HTTP responses. - -Fields: - - [stream.w] is the ResponseWriter for the current HTTP response (non-nil indicates claimed) - - [stream.done] is closed to release the hanging HTTP request - - [stream.requests] tracks pending request IDs (stream completes when empty) - -Methods: - - [stream.deliverLocked] delivers a message to the stream - - [stream.close] sends a close event and releases the stream - - [stream.release] releases the stream from the HTTP request, allowing resumption - -[streamableServerConn] handles the [Connection] interface: - - [streamableServerConn.Read] receives messages from the incoming channel (fed by POST handlers) - - [streamableServerConn.Write] routes messages to appropriate streams - - [streamableServerConn.Close] terminates the session and notifies the [EventStore] -*/ diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/tool.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/tool.go deleted file mode 100644 index 3ecb59d..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/tool.go +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package mcp - -import ( - "context" - "encoding/json" - "fmt" - "strings" - - "github.com/google/jsonschema-go/jsonschema" - internaljson "github.com/modelcontextprotocol/go-sdk/internal/json" -) - -// A ToolHandler handles a call to tools/call. -// -// This is a low-level API, for use with [Server.AddTool]. It does not do any -// pre- or post-processing of the request or result: the params contain raw -// arguments, no input validation is performed, and the result is returned to -// the user as-is, without any validation of the output. -// -// Most users will write a [ToolHandlerFor] and install it with the generic -// [AddTool] function. -// -// If ToolHandler returns an error, it is treated as a protocol error. By -// contrast, [ToolHandlerFor] automatically populates [CallToolResult.IsError] -// and [CallToolResult.Content] accordingly. -type ToolHandler func(context.Context, *CallToolRequest) (*CallToolResult, error) - -// A ToolHandlerFor handles a call to tools/call with typed arguments and results. -// -// Use [AddTool] to add a ToolHandlerFor to a server. -// -// Unlike [ToolHandler], [ToolHandlerFor] provides significant functionality -// out of the box, and enforces that the tool conforms to the MCP spec: -// - The In type provides a default input schema for the tool, though it may -// be overridden in [AddTool]. -// - The input value is automatically unmarshaled from req.Params.Arguments. -// - The input value is automatically validated against its input schema. -// Invalid input is rejected before getting to the handler. -// - If the Out type is not the empty interface [any], it provides the -// default output schema for the tool (which again may be overridden in -// [AddTool]). -// - The Out value is used to populate result.StructuredOutput. -// - If [CallToolResult.Content] is unset, it is populated with the JSON -// content of the output. -// - An error result is treated as a tool error, rather than a protocol -// error, and is therefore packed into CallToolResult.Content, with -// [IsError] set. -// -// For these reasons, most users can ignore the [CallToolRequest] argument and -// [CallToolResult] return values entirely. In fact, it is permissible to -// return a nil CallToolResult, if you only care about returning a output value -// or error. The effective result will be populated as described above. -type ToolHandlerFor[In, Out any] func(_ context.Context, request *CallToolRequest, input In) (result *CallToolResult, output Out, _ error) - -// A serverTool is a tool definition that is bound to a tool handler. -type serverTool struct { - tool *Tool - handler ToolHandler -} - -// applySchema validates whether data is valid JSON according to the provided -// schema, after applying schema defaults. -// -// Returns the JSON value augmented with defaults. -func applySchema(data json.RawMessage, resolved *jsonschema.Resolved) (json.RawMessage, error) { - // TODO: use reflection to create the struct type to unmarshal into. - // Separate validation from assignment. - - // Use default JSON marshalling for validation. - // - // This avoids inconsistent representation due to custom marshallers, such as - // time.Time (issue #449). - // - // Additionally, unmarshalling into a map ensures that the resulting JSON is - // at least {}, even if data is empty. For example, arguments is technically - // an optional property of callToolParams, and we still want to apply the - // defaults in this case. - // - // TODO(rfindley): in which cases can resolved be nil? - if resolved != nil { - v := make(map[string]any) - if len(data) > 0 { - if err := internaljson.Unmarshal(data, &v); err != nil { - return nil, fmt.Errorf("unmarshaling arguments: %w", err) - } - } - if err := resolved.ApplyDefaults(&v); err != nil { - return nil, fmt.Errorf("applying schema defaults:\n%w", err) - } - if err := resolved.Validate(&v); err != nil { - return nil, err - } - // We must re-marshal with the default values applied. - var err error - data, err = json.Marshal(v) - if err != nil { - return nil, fmt.Errorf("marshalling with defaults: %v", err) - } - } - return data, nil -} - -// validateToolName checks whether name is a valid tool name, reporting a -// non-nil error if not. -func validateToolName(name string) error { - if name == "" { - return fmt.Errorf("tool name cannot be empty") - } - if len(name) > 128 { - return fmt.Errorf("tool name exceeds maximum length of 128 characters (current: %d)", len(name)) - } - // For consistency with other SDKs, report characters in the order the appear - // in the name. - var invalidChars []string - seen := make(map[rune]bool) - for _, r := range name { - if !validToolNameRune(r) { - if !seen[r] { - invalidChars = append(invalidChars, fmt.Sprintf("%q", string(r))) - seen[r] = true - } - } - } - if len(invalidChars) > 0 { - return fmt.Errorf("tool name contains invalid characters: %s", strings.Join(invalidChars, ", ")) - } - return nil -} - -// validToolNameRune reports whether r is valid within tool names. -func validToolNameRune(r rune) bool { - return (r >= 'a' && r <= 'z') || - (r >= 'A' && r <= 'Z') || - (r >= '0' && r <= '9') || - r == '_' || r == '-' || r == '.' -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/transport.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/transport.go deleted file mode 100644 index 5f2a500..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/transport.go +++ /dev/null @@ -1,660 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package mcp - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io" - "log" - "net" - "os" - "sync" - - internaljson "github.com/modelcontextprotocol/go-sdk/internal/json" - "github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2" - "github.com/modelcontextprotocol/go-sdk/internal/xcontext" - "github.com/modelcontextprotocol/go-sdk/jsonrpc" -) - -// ErrConnectionClosed is returned when sending a message to a connection that -// is closed or in the process of closing. -var ErrConnectionClosed = errors.New("connection closed") - -// ErrSessionMissing is returned when the session is known to not be present on -// the server. -var ErrSessionMissing = errors.New("session not found") - -// A Transport is used to create a bidirectional connection between MCP client -// and server. -// -// Transports should be used for at most one call to [Server.Connect] or -// [Client.Connect]. -type Transport interface { - // Connect returns the logical JSON-RPC connection.. - // - // It is called exactly once by [Server.Connect] or [Client.Connect]. - Connect(ctx context.Context) (Connection, error) -} - -// A Connection is a logical bidirectional JSON-RPC connection. -type Connection interface { - // Read reads the next message to process off the connection. - // - // Connections must allow Read to be called concurrently with Close. In - // particular, calling Close should unblock a Read waiting for input. - Read(context.Context) (jsonrpc.Message, error) - - // Write writes a new message to the connection. - // - // Write may be called concurrently, as calls or responses may occur - // concurrently in user code. - Write(context.Context, jsonrpc.Message) error - - // Close closes the connection. It is implicitly called whenever a Read or - // Write fails. - // - // Close may be called multiple times, potentially concurrently. - Close() error - - // TODO(#148): remove SessionID from this interface. - SessionID() string -} - -// A ClientConnection is a [Connection] that is specific to the MCP client. -// -// If client connections implement this interface, they may receive information -// about changes to the client session. -// -// TODO: should this interface be exported? -type clientConnection interface { - Connection - - // sessionUpdated is called whenever the client session state changes. - sessionUpdated(clientSessionState) -} - -// A serverConnection is a Connection that is specific to the MCP server. -// -// If server connections implement this interface, they receive information -// about changes to the server session. -// -// TODO: should this interface be exported? -type serverConnection interface { - Connection - sessionUpdated(ServerSessionState) -} - -// A StdioTransport is a [Transport] that communicates over stdin/stdout using -// newline-delimited JSON. -type StdioTransport struct{} - -// Connect implements the [Transport] interface. -func (*StdioTransport) Connect(context.Context) (Connection, error) { - return newIOConn(rwc{os.Stdin, nopCloserWriter{os.Stdout}}), nil -} - -// nopCloserWriter is an io.WriteCloser with a trivial Close method. -type nopCloserWriter struct { - io.Writer -} - -func (nopCloserWriter) Close() error { return nil } - -// An IOTransport is a [Transport] that communicates over separate -// io.ReadCloser and io.WriteCloser using newline-delimited JSON. -type IOTransport struct { - Reader io.ReadCloser - Writer io.WriteCloser -} - -// Connect implements the [Transport] interface. -func (t *IOTransport) Connect(context.Context) (Connection, error) { - return newIOConn(rwc{t.Reader, t.Writer}), nil -} - -// An InMemoryTransport is a [Transport] that communicates over an in-memory -// network connection, using newline-delimited JSON. -// -// InMemoryTransports should be constructed using [NewInMemoryTransports], -// which returns two transports connected to each other. -type InMemoryTransport struct { - rwc io.ReadWriteCloser -} - -// Connect implements the [Transport] interface. -func (t *InMemoryTransport) Connect(context.Context) (Connection, error) { - return newIOConn(t.rwc), nil -} - -// NewInMemoryTransports returns two [InMemoryTransport] objects that connect -// to each other. -// -// The resulting transports are symmetrical: use either to connect to a server, -// and then the other to connect to a client. Servers must be connected before -// clients, as the client initializes the MCP session during connection. -func NewInMemoryTransports() (*InMemoryTransport, *InMemoryTransport) { - c1, c2 := net.Pipe() - return &InMemoryTransport{c1}, &InMemoryTransport{c2} -} - -type binder[T handler, State any] interface { - // TODO(rfindley): the bind API has gotten too complicated. Simplify. - bind(Connection, *jsonrpc2.Connection, State, func()) T - disconnect(T) -} - -type handler interface { - handle(ctx context.Context, req *jsonrpc.Request) (any, error) -} - -func connect[H handler, State any](ctx context.Context, t Transport, b binder[H, State], s State, onClose func()) (H, error) { - var zero H - mcpConn, err := t.Connect(ctx) - if err != nil { - return zero, err - } - // If logging is configured, write message logs. - reader, writer := jsonrpc2.Reader(mcpConn), jsonrpc2.Writer(mcpConn) - var ( - h H - preempter canceller - ) - bind := func(conn *jsonrpc2.Connection) jsonrpc2.Handler { - h = b.bind(mcpConn, conn, s, onClose) - preempter.conn = conn - return jsonrpc2.HandlerFunc(h.handle) - } - _ = jsonrpc2.NewConnection(ctx, jsonrpc2.ConnectionConfig{ - Reader: reader, - Writer: writer, - Closer: mcpConn, - Bind: bind, - Preempter: &preempter, - OnDone: func() { - b.disconnect(h) - }, - OnInternalError: func(err error) { log.Printf("jsonrpc2 error: %v", err) }, - }) - assert(preempter.conn != nil, "unbound preempter") - return h, nil -} - -// A canceller is a jsonrpc2.Preempter that cancels in-flight requests on MCP -// cancelled notifications. -type canceller struct { - conn *jsonrpc2.Connection -} - -// Preempt implements [jsonrpc2.Preempter]. -func (c *canceller) Preempt(ctx context.Context, req *jsonrpc.Request) (result any, err error) { - if req.Method == notificationCancelled { - var params CancelledParams - if err := internaljson.Unmarshal(req.Params, ¶ms); err != nil { - return nil, err - } - id, err := jsonrpc2.MakeID(params.RequestID) - if err != nil { - return nil, err - } - go c.conn.Cancel(id) - } - return nil, jsonrpc2.ErrNotHandled -} - -// call executes and awaits a jsonrpc2 call on the given connection, -// translating errors into the mcp domain. -func call(ctx context.Context, conn *jsonrpc2.Connection, method string, params Params, result Result) error { - // The "%w"s in this function expose jsonrpc.Error as part of the API. - call := conn.Call(ctx, method, params) - err := call.Await(ctx, result) - switch { - case errors.Is(err, jsonrpc2.ErrClientClosing), errors.Is(err, jsonrpc2.ErrServerClosing): - return fmt.Errorf("%w: calling %q: %v", ErrConnectionClosed, method, err) - case ctx.Err() != nil: - // Notify the peer of cancellation. - err := conn.Notify(xcontext.Detach(ctx), notificationCancelled, &CancelledParams{ - Reason: ctx.Err().Error(), - RequestID: call.ID().Raw(), - }) - // By default, the jsonrpc2 library waits for graceful shutdown when the - // connection is closed, meaning it expects all outgoing and incoming - // requests to complete. However, for MCP this expectation is unrealistic, - // and can lead to hanging shutdown. For example, if a streamable client is - // killed, the server will not be able to detect this event, except via - // keepalive pings (if they are configured), and so outgoing calls may hang - // indefinitely. - // - // Therefore, we choose to eagerly retire calls, removing them from the - // outgoingCalls map, when the caller context is cancelled: if the caller - // will never receive the response, there's no need to track it. - conn.Retire(call, ctx.Err()) - return errors.Join(ctx.Err(), err) - case err != nil: - return fmt.Errorf("calling %q: %w", method, err) - } - return nil -} - -// A LoggingTransport is a [Transport] that delegates to another transport, -// writing RPC logs to an io.Writer. -type LoggingTransport struct { - Transport Transport - Writer io.Writer -} - -// Connect connects the underlying transport, returning a [Connection] that writes -// logs to the configured destination. -func (t *LoggingTransport) Connect(ctx context.Context) (Connection, error) { - delegate, err := t.Transport.Connect(ctx) - if err != nil { - return nil, err - } - return &loggingConn{delegate: delegate, w: t.Writer}, nil -} - -type loggingConn struct { - delegate Connection - - mu sync.Mutex - w io.Writer -} - -func (c *loggingConn) SessionID() string { return c.delegate.SessionID() } - -// Read is a stream middleware that logs incoming messages. -func (s *loggingConn) Read(ctx context.Context) (jsonrpc.Message, error) { - msg, err := s.delegate.Read(ctx) - - if err != nil { - s.mu.Lock() - fmt.Fprintf(s.w, "read error: %v\n", err) - s.mu.Unlock() - } else { - data, err := jsonrpc2.EncodeMessage(msg) - s.mu.Lock() - if err != nil { - fmt.Fprintf(s.w, "LoggingTransport: failed to marshal: %v", err) - } - fmt.Fprintf(s.w, "read: %s\n", string(data)) - s.mu.Unlock() - } - - return msg, err -} - -// Write is a stream middleware that logs outgoing messages. -func (s *loggingConn) Write(ctx context.Context, msg jsonrpc.Message) error { - err := s.delegate.Write(ctx, msg) - if err != nil { - s.mu.Lock() - fmt.Fprintf(s.w, "write error: %v\n", err) - s.mu.Unlock() - } else { - data, err := jsonrpc2.EncodeMessage(msg) - s.mu.Lock() - if err != nil { - fmt.Fprintf(s.w, "LoggingTransport: failed to marshal: %v", err) - } - fmt.Fprintf(s.w, "write: %s\n", string(data)) - s.mu.Unlock() - } - return err -} - -func (s *loggingConn) Close() error { - return s.delegate.Close() -} - -// A rwc binds an io.ReadCloser and io.WriteCloser together to create an -// io.ReadWriteCloser. -type rwc struct { - rc io.ReadCloser - wc io.WriteCloser -} - -func (r rwc) Read(p []byte) (n int, err error) { - return r.rc.Read(p) -} - -func (r rwc) Write(p []byte) (n int, err error) { - return r.wc.Write(p) -} - -func (r rwc) Close() error { - rcErr := r.rc.Close() - - var wcErr error - if r.wc != nil { // we only allow a nil writer in unit tests - wcErr = r.wc.Close() - } - - return errors.Join(rcErr, wcErr) -} - -// An ioConn is a transport that delimits messages with newlines across -// a bidirectional stream, and supports jsonrpc.2 message batching. -// -// See https://github.com/ndjson/ndjson-spec for discussion of newline -// delimited JSON. -// -// See [msgBatch] for more discussion of message batching. -type ioConn struct { - protocolVersion string // negotiated version, set during session initialization. - - writeMu sync.Mutex // guards Write, which must be concurrency safe. - rwc io.ReadWriteCloser // the underlying stream - - // incoming receives messages from the read loop started in [newIOConn]. - incoming <-chan msgOrErr - - // If outgoiBatch has a positive capacity, it will be used to batch requests - // and notifications before sending. - outgoingBatch []jsonrpc.Message - - // Unread messages in the last batch. Since reads are serialized, there is no - // need to guard here. - queue []jsonrpc.Message - - // batches correlate incoming requests to the batch in which they arrived. - // Since writes may be concurrent to reads, we need to guard this with a mutex. - batchMu sync.Mutex - batches map[jsonrpc2.ID]*msgBatch // lazily allocated - - closeOnce sync.Once - closed chan struct{} - closeErr error -} - -type msgOrErr struct { - msg json.RawMessage - err error -} - -func newIOConn(rwc io.ReadWriteCloser) *ioConn { - var ( - incoming = make(chan msgOrErr) - closed = make(chan struct{}) - ) - // Start a goroutine for reads, so that we can select on the incoming channel - // in [ioConn.Read] and unblock the read as soon as Close is called (see #224). - // - // This leaks a goroutine if rwc.Read does not unblock after it is closed, - // but that is unavoidable since AFAIK there is no (easy and portable) way to - // guarantee that reads of stdin are unblocked when closed. - go func() { - dec := json.NewDecoder(rwc) - for { - var raw json.RawMessage - err := dec.Decode(&raw) - // If decoding was successful, check for trailing data at the end of the stream. - if err == nil { - // Read the next byte to check if there is trailing data. - var tr [1]byte - if n, readErr := dec.Buffered().Read(tr[:]); n > 0 { - // If read byte is not a newline, it is an error. - // Support both Unix (\n) and Windows (\r\n) line endings. - if tr[0] != '\n' && tr[0] != '\r' { - err = fmt.Errorf("invalid trailing data at the end of stream") - } - } else if readErr != nil && readErr != io.EOF { - err = readErr - } - } - select { - case incoming <- msgOrErr{msg: raw, err: err}: - case <-closed: - return - } - if err != nil { - return - } - } - }() - return &ioConn{ - rwc: rwc, - incoming: incoming, - closed: closed, - } -} - -func (c *ioConn) SessionID() string { return "" } - -func (c *ioConn) sessionUpdated(state ServerSessionState) { - protocolVersion := "" - if state.InitializeParams != nil { - protocolVersion = state.InitializeParams.ProtocolVersion - } - if protocolVersion == "" { - protocolVersion = protocolVersion20250326 - } - c.protocolVersion = negotiatedVersion(protocolVersion) -} - -// addBatch records a msgBatch for an incoming batch payload. -// It returns an error if batch is malformed, containing previously seen IDs. -// -// See [msgBatch] for more. -func (t *ioConn) addBatch(batch *msgBatch) error { - t.batchMu.Lock() - defer t.batchMu.Unlock() - for id := range batch.unresolved { - if _, ok := t.batches[id]; ok { - return fmt.Errorf("%w: batch contains previously seen request %v", jsonrpc2.ErrInvalidRequest, id.Raw()) - } - } - for id := range batch.unresolved { - if t.batches == nil { - t.batches = make(map[jsonrpc2.ID]*msgBatch) - } - t.batches[id] = batch - } - return nil -} - -// updateBatch records a response in the message batch tracking the -// corresponding incoming call, if any. -// -// The second result reports whether resp was part of a batch. If this is true, -// the first result is nil if the batch is still incomplete, or the full set of -// batch responses if resp completed the batch. -func (t *ioConn) updateBatch(resp *jsonrpc.Response) ([]*jsonrpc.Response, bool) { - t.batchMu.Lock() - defer t.batchMu.Unlock() - - if batch, ok := t.batches[resp.ID]; ok { - idx, ok := batch.unresolved[resp.ID] - if !ok { - panic("internal error: inconsistent batches") - } - batch.responses[idx] = resp - delete(batch.unresolved, resp.ID) - delete(t.batches, resp.ID) - if len(batch.unresolved) == 0 { - return batch.responses, true - } - return nil, true - } - return nil, false -} - -// A msgBatch records information about an incoming batch of jsonrpc.2 calls. -// -// The jsonrpc.2 spec (https://www.jsonrpc.org/specification#batch) says: -// -// "The Server should respond with an Array containing the corresponding -// Response objects, after all of the batch Request objects have been -// processed. A Response object SHOULD exist for each Request object, except -// that there SHOULD NOT be any Response objects for notifications. The Server -// MAY process a batch rpc call as a set of concurrent tasks, processing them -// in any order and with any width of parallelism." -// -// Therefore, a msgBatch keeps track of outstanding calls and their responses. -// When there are no unresolved calls, the response payload is sent. -type msgBatch struct { - unresolved map[jsonrpc2.ID]int - responses []*jsonrpc.Response -} - -func (t *ioConn) Read(ctx context.Context) (jsonrpc.Message, error) { - // As a matter of principle, enforce that reads on a closed context return an - // error. - select { - case <-ctx.Done(): - return nil, ctx.Err() - default: - } - if len(t.queue) > 0 { - next := t.queue[0] - t.queue = t.queue[1:] - return next, nil - } - - var raw json.RawMessage - select { - case <-ctx.Done(): - return nil, ctx.Err() - - case v := <-t.incoming: - if v.err != nil { - return nil, v.err - } - raw = v.msg - - case <-t.closed: - return nil, io.EOF - } - - msgs, batch, err := readBatch(raw) - if err != nil { - return nil, err - } - if batch && t.protocolVersion >= protocolVersion20250618 { - return nil, fmt.Errorf("JSON-RPC batching is not supported in %s and later (request version: %s)", protocolVersion20250618, t.protocolVersion) - } - - t.queue = msgs[1:] - - if batch { - var respBatch *msgBatch // track incoming requests in the batch - for _, msg := range msgs { - if req, ok := msg.(*jsonrpc.Request); ok { - if respBatch == nil { - respBatch = &msgBatch{ - unresolved: make(map[jsonrpc2.ID]int), - } - } - if _, ok := respBatch.unresolved[req.ID]; ok { - return nil, fmt.Errorf("duplicate message ID %q", req.ID) - } - respBatch.unresolved[req.ID] = len(respBatch.responses) - respBatch.responses = append(respBatch.responses, nil) - } - } - if respBatch != nil { - // The batch contains one or more incoming requests to track. - if err := t.addBatch(respBatch); err != nil { - return nil, err - } - } - } - return msgs[0], err -} - -// readBatch reads batch data, which may be either a single JSON-RPC message, -// or an array of JSON-RPC messages. -func readBatch(data []byte) (msgs []jsonrpc.Message, isBatch bool, _ error) { - // Try to read an array of messages first. - var rawBatch []json.RawMessage - if err := internaljson.Unmarshal(data, &rawBatch); err == nil { - if len(rawBatch) == 0 { - return nil, true, fmt.Errorf("empty batch") - } - for _, raw := range rawBatch { - msg, err := jsonrpc2.DecodeMessage(raw) - if err != nil { - return nil, true, err - } - msgs = append(msgs, msg) - } - return msgs, true, nil - } - // Try again with a single message. - msg, err := jsonrpc2.DecodeMessage(data) - return []jsonrpc.Message{msg}, false, err -} - -func (t *ioConn) Write(ctx context.Context, msg jsonrpc.Message) error { - // As in [ioConn.Read], enforce that Writes on a closed context are an error. - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - - t.writeMu.Lock() - defer t.writeMu.Unlock() - - // Batching support: if msg is a Response, it may have completed a batch, so - // check that first. Otherwise, it is a request or notification, and we may - // want to collect it into a batch before sending, if we're configured to use - // outgoing batches. - if resp, ok := msg.(*jsonrpc.Response); ok { - if batch, ok := t.updateBatch(resp); ok { - if len(batch) > 0 { - data, err := marshalMessages(batch) - if err != nil { - return err - } - data = append(data, '\n') - _, err = t.rwc.Write(data) - return err - } - return nil - } - } else if len(t.outgoingBatch) < cap(t.outgoingBatch) { - t.outgoingBatch = append(t.outgoingBatch, msg) - if len(t.outgoingBatch) == cap(t.outgoingBatch) { - data, err := marshalMessages(t.outgoingBatch) - t.outgoingBatch = t.outgoingBatch[:0] - if err != nil { - return err - } - data = append(data, '\n') - _, err = t.rwc.Write(data) - return err - } - return nil - } - data, err := jsonrpc2.EncodeMessage(msg) - if err != nil { - return fmt.Errorf("marshaling message: %v", err) - } - data = append(data, '\n') // newline delimited - _, err = t.rwc.Write(data) - return err -} - -func (t *ioConn) Close() error { - t.closeOnce.Do(func() { - t.closeErr = t.rwc.Close() - close(t.closed) - }) - return t.closeErr -} - -func marshalMessages[T jsonrpc.Message](msgs []T) ([]byte, error) { - var rawMsgs []json.RawMessage - for _, msg := range msgs { - raw, err := jsonrpc2.EncodeMessage(msg) - if err != nil { - return nil, fmt.Errorf("encoding batch message: %w", err) - } - rawMsgs = append(rawMsgs, raw) - } - return json.Marshal(rawMsgs) -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/util.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/util.go deleted file mode 100644 index 8ffaa74..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/mcp/util.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package mcp - -import ( - "encoding/json" - - internaljson "github.com/modelcontextprotocol/go-sdk/internal/json" -) - -func assert(cond bool, msg string) { - if !cond { - panic(msg) - } -} - -// remarshal marshals from to JSON, and then unmarshals into to, which must be -// a pointer type. -func remarshal(from, to any) error { - data, err := json.Marshal(from) - if err != nil { - return err - } - if err := internaljson.Unmarshal(data, to); err != nil { - return err - } - return nil -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/oauthex/auth_meta.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/oauthex/auth_meta.go deleted file mode 100644 index b05d80b..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/oauthex/auth_meta.go +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// This file implements Authorization Server Metadata. -// See https://www.rfc-editor.org/rfc/rfc8414.html. - -//go:build mcp_go_client_oauth - -package oauthex - -import ( - "context" - "errors" - "fmt" - "net/http" - "net/url" - - "github.com/modelcontextprotocol/go-sdk/internal/util" -) - -// AuthServerMeta represents the metadata for an OAuth 2.0 authorization server, -// as defined in [RFC 8414]. -// -// Not supported: -// - signed metadata -// -// Note: URL fields in this struct are validated by validateAuthServerMetaURLs to -// prevent XSS attacks. If you add a new URL field, you must also add it to that -// function. -// -// [RFC 8414]: https://tools.ietf.org/html/rfc8414) -type AuthServerMeta struct { - // Issuer is the REQUIRED URL identifying the authorization server. - Issuer string `json:"issuer"` - - // AuthorizationEndpoint is the REQUIRED URL of the server's OAuth 2.0 authorization endpoint. - AuthorizationEndpoint string `json:"authorization_endpoint"` - - // TokenEndpoint is the REQUIRED URL of the server's OAuth 2.0 token endpoint. - TokenEndpoint string `json:"token_endpoint"` - - // JWKSURI is the REQUIRED URL of the server's JSON Web Key Set [JWK] document. - JWKSURI string `json:"jwks_uri"` - - // RegistrationEndpoint is the RECOMMENDED URL of the server's OAuth 2.0 Dynamic Client Registration endpoint. - RegistrationEndpoint string `json:"registration_endpoint,omitempty"` - - // ScopesSupported is a RECOMMENDED JSON array of strings containing a list of the OAuth 2.0 - // "scope" values that this server supports. - ScopesSupported []string `json:"scopes_supported,omitempty"` - - // ResponseTypesSupported is a REQUIRED JSON array of strings containing a list of the OAuth 2.0 - // "response_type" values that this server supports. - ResponseTypesSupported []string `json:"response_types_supported"` - - // ResponseModesSupported is a RECOMMENDED JSON array of strings containing a list of the OAuth 2.0 - // "response_mode" values that this server supports. - ResponseModesSupported []string `json:"response_modes_supported,omitempty"` - - // GrantTypesSupported is a RECOMMENDED JSON array of strings containing a list of the OAuth 2.0 - // grant type values that this server supports. - GrantTypesSupported []string `json:"grant_types_supported,omitempty"` - - // TokenEndpointAuthMethodsSupported is a RECOMMENDED JSON array of strings containing a list of - // client authentication methods supported by this token endpoint. - TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported,omitempty"` - - // TokenEndpointAuthSigningAlgValuesSupported is a RECOMMENDED JSON array of strings containing - // a list of the JWS signing algorithms ("alg" values) supported by the token endpoint for - // the signature on the JWT used to authenticate the client. - TokenEndpointAuthSigningAlgValuesSupported []string `json:"token_endpoint_auth_signing_alg_values_supported,omitempty"` - - // ServiceDocumentation is a RECOMMENDED URL of a page containing human-readable documentation - // for the service. - ServiceDocumentation string `json:"service_documentation,omitempty"` - - // UILocalesSupported is a RECOMMENDED JSON array of strings representing supported - // BCP47 [RFC5646] language tag values for display in the user interface. - UILocalesSupported []string `json:"ui_locales_supported,omitempty"` - - // OpPolicyURI is a RECOMMENDED URL that the server provides to the person registering - // the client to read about the server's operator policies. - OpPolicyURI string `json:"op_policy_uri,omitempty"` - - // OpTOSURI is a RECOMMENDED URL that the server provides to the person registering the - // client to read about the server's terms of service. - OpTOSURI string `json:"op_tos_uri,omitempty"` - - // RevocationEndpoint is a RECOMMENDED URL of the server's OAuth 2.0 revocation endpoint. - RevocationEndpoint string `json:"revocation_endpoint,omitempty"` - - // RevocationEndpointAuthMethodsSupported is a RECOMMENDED JSON array of strings containing - // a list of client authentication methods supported by this revocation endpoint. - RevocationEndpointAuthMethodsSupported []string `json:"revocation_endpoint_auth_methods_supported,omitempty"` - - // RevocationEndpointAuthSigningAlgValuesSupported is a RECOMMENDED JSON array of strings - // containing a list of the JWS signing algorithms ("alg" values) supported by the revocation - // endpoint for the signature on the JWT used to authenticate the client. - RevocationEndpointAuthSigningAlgValuesSupported []string `json:"revocation_endpoint_auth_signing_alg_values_supported,omitempty"` - - // IntrospectionEndpoint is a RECOMMENDED URL of the server's OAuth 2.0 introspection endpoint. - IntrospectionEndpoint string `json:"introspection_endpoint,omitempty"` - - // IntrospectionEndpointAuthMethodsSupported is a RECOMMENDED JSON array of strings containing - // a list of client authentication methods supported by this introspection endpoint. - IntrospectionEndpointAuthMethodsSupported []string `json:"introspection_endpoint_auth_methods_supported,omitempty"` - - // IntrospectionEndpointAuthSigningAlgValuesSupported is a RECOMMENDED JSON array of strings - // containing a list of the JWS signing algorithms ("alg" values) supported by the introspection - // endpoint for the signature on the JWT used to authenticate the client. - IntrospectionEndpointAuthSigningAlgValuesSupported []string `json:"introspection_endpoint_auth_signing_alg_values_supported,omitempty"` - - // CodeChallengeMethodsSupported is a RECOMMENDED JSON array of strings containing a list of - // PKCE code challenge methods supported by this authorization server. - CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported,omitempty"` - - // ClientIDMetadataDocumentSupported is a boolean indicating whether the authorization server - // supports client ID metadata documents. - ClientIDMetadataDocumentSupported bool `json:"client_id_metadata_document_supported,omitempty"` -} - -// GetAuthServerMeta issues a GET request to retrieve authorization server metadata -// from an OAuth authorization server with the given metadataURL. -// -// It follows [RFC 8414]: -// - The metadataURL must use HTTPS or be a local address. -// - The Issuer field is checked against metadataURL.Issuer. -// -// It also verifies that the authorization server supports PKCE and that the URLs -// in the metadata don't use dangerous schemes. -// -// It returns an error if the request fails with a non-4xx status code or the fetched -// metadata doesn't pass security validations. -// It returns nil if the request fails with a 4xx status code. -// -// [RFC 8414]: https://tools.ietf.org/html/rfc8414 -func GetAuthServerMeta(ctx context.Context, metadataURL, issuer string, c *http.Client) (*AuthServerMeta, error) { - u, err := url.Parse(metadataURL) - if err != nil { - return nil, err - } - // Only allow HTTP for local addresses (testing or development purposes). - if !util.IsLoopback(u.Host) && u.Scheme != "https" { - return nil, fmt.Errorf("metadataURL %q does not use HTTPS", metadataURL) - } - asm, err := getJSON[AuthServerMeta](ctx, c, metadataURL, 1<<20) - if err != nil { - var httpErr *httpStatusError - if errors.As(err, &httpErr) { - if 400 <= httpErr.StatusCode && httpErr.StatusCode < 500 { - return nil, nil - } - } - return nil, fmt.Errorf("%v", err) // Do not expose error types. - } - if asm.Issuer != issuer { - // Validate the Issuer field (see RFC 8414, section 3.3). - return nil, fmt.Errorf("metadata issuer %q does not match issuer URL %q", asm.Issuer, issuer) - } - - if len(asm.CodeChallengeMethodsSupported) == 0 { - return nil, fmt.Errorf("authorization server at %s does not implement PKCE", issuer) - } - - // Validate endpoint URLs to prevent XSS attacks (see #526). - if err := validateAuthServerMetaURLs(asm); err != nil { - return nil, err - } - - return asm, nil -} - -// validateAuthServerMetaURLs validates all URL fields in AuthServerMeta -// to ensure they don't use dangerous schemes that could enable XSS attacks. -func validateAuthServerMetaURLs(asm *AuthServerMeta) error { - urls := []struct { - name string - value string - }{ - {"authorization_endpoint", asm.AuthorizationEndpoint}, - {"token_endpoint", asm.TokenEndpoint}, - {"jwks_uri", asm.JWKSURI}, - {"registration_endpoint", asm.RegistrationEndpoint}, - {"service_documentation", asm.ServiceDocumentation}, - {"op_policy_uri", asm.OpPolicyURI}, - {"op_tos_uri", asm.OpTOSURI}, - {"revocation_endpoint", asm.RevocationEndpoint}, - {"introspection_endpoint", asm.IntrospectionEndpoint}, - } - - for _, u := range urls { - if err := checkURLScheme(u.value); err != nil { - return fmt.Errorf("%s: %w", u.name, err) - } - } - return nil -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/oauthex/dcr.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/oauthex/dcr.go deleted file mode 100644 index 6db3025..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/oauthex/dcr.go +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// This file implements Authorization Server Metadata. -// See https://www.rfc-editor.org/rfc/rfc8414.html. - -//go:build mcp_go_client_oauth - -package oauthex - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "io" - "net/http" - "time" - - internaljson "github.com/modelcontextprotocol/go-sdk/internal/json" -) - -// ClientRegistrationMetadata represents the client metadata fields for the DCR POST request (RFC 7591). -// -// Note: URL fields in this struct are validated by validateClientRegistrationURLs -// to prevent XSS attacks. If you add a new URL field, you must also add it to -// that function. -type ClientRegistrationMetadata struct { - // RedirectURIs is a REQUIRED JSON array of redirection URI strings for use in - // redirect-based flows (such as the authorization code grant). - RedirectURIs []string `json:"redirect_uris"` - - // TokenEndpointAuthMethod is an OPTIONAL string indicator of the requested - // authentication method for the token endpoint. - // If omitted, the default is "client_secret_basic". - TokenEndpointAuthMethod string `json:"token_endpoint_auth_method,omitempty"` - - // GrantTypes is an OPTIONAL JSON array of OAuth 2.0 grant type strings - // that the client will restrict itself to using. - // If omitted, the default is ["authorization_code"]. - GrantTypes []string `json:"grant_types,omitempty"` - - // ResponseTypes is an OPTIONAL JSON array of OAuth 2.0 response type strings - // that the client will restrict itself to using. - // If omitted, the default is ["code"]. - ResponseTypes []string `json:"response_types,omitempty"` - - // ClientName is a RECOMMENDED human-readable name of the client to be presented - // to the end-user. - ClientName string `json:"client_name,omitempty"` - - // ClientURI is a RECOMMENDED URL of a web page providing information about the client. - ClientURI string `json:"client_uri,omitempty"` - - // LogoURI is an OPTIONAL URL of a logo for the client, which may be displayed - // to the end-user. - LogoURI string `json:"logo_uri,omitempty"` - - // Scope is an OPTIONAL string containing a space-separated list of scope values - // that the client will restrict itself to using. - Scope string `json:"scope,omitempty"` - - // Contacts is an OPTIONAL JSON array of strings representing ways to contact - // people responsible for this client (e.g., email addresses). - Contacts []string `json:"contacts,omitempty"` - - // TOSURI is an OPTIONAL URL that the client provides to the end-user - // to read about the client's terms of service. - TOSURI string `json:"tos_uri,omitempty"` - - // PolicyURI is an OPTIONAL URL that the client provides to the end-user - // to read about the client's privacy policy. - PolicyURI string `json:"policy_uri,omitempty"` - - // JWKSURI is an OPTIONAL URL for the client's JSON Web Key Set [JWK] document. - // This is preferred over the 'jwks' parameter. - JWKSURI string `json:"jwks_uri,omitempty"` - - // JWKS is an OPTIONAL client's JSON Web Key Set [JWK] document, passed by value. - // This is an alternative to providing a JWKSURI. - JWKS string `json:"jwks,omitempty"` - - // SoftwareID is an OPTIONAL unique identifier string for the client software, - // constant across all instances and versions. - SoftwareID string `json:"software_id,omitempty"` - - // SoftwareVersion is an OPTIONAL version identifier string for the client software. - SoftwareVersion string `json:"software_version,omitempty"` - - // SoftwareStatement is an OPTIONAL JWT that asserts client metadata values. - // Values in the software statement take precedence over other metadata values. - SoftwareStatement string `json:"software_statement,omitempty"` -} - -// ClientRegistrationResponse represents the fields returned by the Authorization Server -// (RFC 7591, Section 3.2.1 and 3.2.2). -type ClientRegistrationResponse struct { - // ClientRegistrationMetadata contains all registered client metadata, returned by the - // server on success, potentially with modified or defaulted values. - ClientRegistrationMetadata - - // ClientID is the REQUIRED newly issued OAuth 2.0 client identifier. - ClientID string `json:"client_id"` - - // ClientSecret is an OPTIONAL client secret string. - ClientSecret string `json:"client_secret,omitempty"` - - // ClientIDIssuedAt is an OPTIONAL Unix timestamp when the ClientID was issued. - ClientIDIssuedAt time.Time `json:"client_id_issued_at,omitempty"` - - // ClientSecretExpiresAt is the REQUIRED (if client_secret is issued) Unix - // timestamp when the secret expires, or 0 if it never expires. - ClientSecretExpiresAt time.Time `json:"client_secret_expires_at,omitempty"` -} - -func (r *ClientRegistrationResponse) MarshalJSON() ([]byte, error) { - type alias ClientRegistrationResponse - var clientIDIssuedAt int64 - var clientSecretExpiresAt int64 - - if !r.ClientIDIssuedAt.IsZero() { - clientIDIssuedAt = r.ClientIDIssuedAt.Unix() - } - if !r.ClientSecretExpiresAt.IsZero() { - clientSecretExpiresAt = r.ClientSecretExpiresAt.Unix() - } - - return json.Marshal(&struct { - ClientIDIssuedAt int64 `json:"client_id_issued_at,omitempty"` - ClientSecretExpiresAt int64 `json:"client_secret_expires_at,omitempty"` - *alias - }{ - ClientIDIssuedAt: clientIDIssuedAt, - ClientSecretExpiresAt: clientSecretExpiresAt, - alias: (*alias)(r), - }) -} - -func (r *ClientRegistrationResponse) UnmarshalJSON(data []byte) error { - type alias ClientRegistrationResponse - aux := &struct { - ClientIDIssuedAt int64 `json:"client_id_issued_at,omitempty"` - ClientSecretExpiresAt int64 `json:"client_secret_expires_at,omitempty"` - *alias - }{ - alias: (*alias)(r), - } - if err := internaljson.Unmarshal(data, &aux); err != nil { - return err - } - if aux.ClientIDIssuedAt != 0 { - r.ClientIDIssuedAt = time.Unix(aux.ClientIDIssuedAt, 0) - } - if aux.ClientSecretExpiresAt != 0 { - r.ClientSecretExpiresAt = time.Unix(aux.ClientSecretExpiresAt, 0) - } - return nil -} - -// ClientRegistrationError is the error response from the Authorization Server -// for a failed registration attempt (RFC 7591, Section 3.2.2). -type ClientRegistrationError struct { - // ErrorCode is the REQUIRED error code if registration failed (RFC 7591, 3.2.2). - ErrorCode string `json:"error"` - - // ErrorDescription is an OPTIONAL human-readable error message. - ErrorDescription string `json:"error_description,omitempty"` -} - -func (e *ClientRegistrationError) Error() string { - return fmt.Sprintf("registration failed: %s (%s)", e.ErrorCode, e.ErrorDescription) -} - -// RegisterClient performs Dynamic Client Registration according to RFC 7591. -func RegisterClient(ctx context.Context, registrationEndpoint string, clientMeta *ClientRegistrationMetadata, c *http.Client) (*ClientRegistrationResponse, error) { - if registrationEndpoint == "" { - return nil, fmt.Errorf("registration_endpoint is required") - } - - if c == nil { - c = http.DefaultClient - } - - payload, err := json.Marshal(clientMeta) - if err != nil { - return nil, fmt.Errorf("failed to marshal client metadata: %w", err) - } - - req, err := http.NewRequestWithContext(ctx, "POST", registrationEndpoint, bytes.NewBuffer(payload)) - if err != nil { - return nil, fmt.Errorf("failed to create registration request: %w", err) - } - - req.Header.Set("Content-Type", "application/json") - req.Header.Set("Accept", "application/json") - - resp, err := c.Do(req) - if err != nil { - return nil, fmt.Errorf("registration request failed: %w", err) - } - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("failed to read registration response body: %w", err) - } - - if resp.StatusCode == http.StatusCreated { - var regResponse ClientRegistrationResponse - if err := internaljson.Unmarshal(body, ®Response); err != nil { - return nil, fmt.Errorf("failed to decode successful registration response: %w (%s)", err, string(body)) - } - if regResponse.ClientID == "" { - return nil, fmt.Errorf("registration response is missing required 'client_id' field") - } - // Validate URL fields to prevent XSS attacks (see #526). - if err := validateClientRegistrationURLs(®Response.ClientRegistrationMetadata); err != nil { - return nil, err - } - return ®Response, nil - } - - if resp.StatusCode == http.StatusBadRequest { - var regError ClientRegistrationError - if err := internaljson.Unmarshal(body, ®Error); err != nil { - return nil, fmt.Errorf("failed to decode registration error response: %w (%s)", err, string(body)) - } - return nil, ®Error - } - - return nil, fmt.Errorf("registration failed with status %s: %s", resp.Status, string(body)) -} - -// validateClientRegistrationURLs validates all URL fields in ClientRegistrationMetadata -// to ensure they don't use dangerous schemes that could enable XSS attacks. -func validateClientRegistrationURLs(meta *ClientRegistrationMetadata) error { - // Validate redirect URIs - for i, uri := range meta.RedirectURIs { - if err := checkURLScheme(uri); err != nil { - return fmt.Errorf("redirect_uris[%d]: %w", i, err) - } - } - - // Validate other URL fields - urls := []struct { - name string - value string - }{ - {"client_uri", meta.ClientURI}, - {"logo_uri", meta.LogoURI}, - {"tos_uri", meta.TOSURI}, - {"policy_uri", meta.PolicyURI}, - {"jwks_uri", meta.JWKSURI}, - } - - for _, u := range urls { - if err := checkURLScheme(u.value); err != nil { - return fmt.Errorf("%s: %w", u.name, err) - } - } - return nil -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/oauthex/oauth2.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/oauthex/oauth2.go deleted file mode 100644 index 836a420..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/oauthex/oauth2.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// Package oauthex implements extensions to OAuth2. - -//go:build mcp_go_client_oauth - -package oauthex - -import ( - "context" - "encoding/json" - "fmt" - "io" - "mime" - "net/http" - "net/url" - "strings" -) - -type httpStatusError struct { - StatusCode int -} - -func (e *httpStatusError) Error() string { - return fmt.Sprintf("bad status %d", e.StatusCode) -} - -// getJSON retrieves JSON and unmarshals JSON from the URL, as specified in both -// RFC 9728 and RFC 8414. -// It will not read more than limit bytes from the body. -func getJSON[T any](ctx context.Context, c *http.Client, url string, limit int64) (*T, error) { - req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) - if err != nil { - return nil, err - } - if c == nil { - c = http.DefaultClient - } - res, err := c.Do(req) - if err != nil { - return nil, err - } - defer res.Body.Close() - - if res.StatusCode != http.StatusOK { - return nil, &httpStatusError{StatusCode: res.StatusCode} - } - ct := res.Header.Get("Content-Type") - mediaType, _, err := mime.ParseMediaType(ct) - if err != nil || mediaType != "application/json" { - return nil, fmt.Errorf("bad content type %q", ct) - } - - var t T - dec := json.NewDecoder(io.LimitReader(res.Body, limit)) - if err := dec.Decode(&t); err != nil { - return nil, err - } - return &t, nil -} - -// checkURLScheme ensures that its argument is a valid URL with a scheme -// that prevents XSS attacks. -// See #526. -func checkURLScheme(u string) error { - if u == "" { - return nil - } - uu, err := url.Parse(u) - if err != nil { - return err - } - scheme := strings.ToLower(uu.Scheme) - if scheme == "javascript" || scheme == "data" || scheme == "vbscript" { - return fmt.Errorf("URL has disallowed scheme %q", scheme) - } - return nil -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/oauthex/oauthex.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/oauthex/oauthex.go deleted file mode 100644 index 151da7e..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/oauthex/oauthex.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// Package oauthex implements extensions to OAuth2. -package oauthex diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/oauthex/resource_meta.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/oauthex/resource_meta.go deleted file mode 100644 index 8b911ca..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/oauthex/resource_meta.go +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// This file implements Protected Resource Metadata. -// See https://www.rfc-editor.org/rfc/rfc9728.html. - -//go:build mcp_go_client_oauth - -package oauthex - -import ( - "context" - "errors" - "fmt" - "net/http" - "net/url" - "path" - "strings" - "unicode" - - "github.com/modelcontextprotocol/go-sdk/internal/util" -) - -const defaultProtectedResourceMetadataURI = "/.well-known/oauth-protected-resource" - -// GetProtectedResourceMetadataFromID issues a GET request to retrieve protected resource -// metadata from a resource server by its ID. -// The resource ID is an HTTPS URL, typically with a host:port and possibly a path. -// For example: -// -// https://example.com/server -// -// This function, following the spec (§3), inserts the default well-known path into the -// URL. In our example, the result would be -// -// https://example.com/.well-known/oauth-protected-resource/server -// -// It then retrieves the metadata at that location using the given client (or the -// default client if nil) and validates its resource field against resourceID. -// -// Deprecated: Use [GetProtectedResourceMetadata] instead. This function will be removed in v1.5.0. -func GetProtectedResourceMetadataFromID(ctx context.Context, resourceID string, c *http.Client) (_ *ProtectedResourceMetadata, err error) { - defer util.Wrapf(&err, "GetProtectedResourceMetadataFromID(%q)", resourceID) - - u, err := url.Parse(resourceID) - if err != nil { - return nil, err - } - // Insert well-known URI into URL. - u.Path = path.Join(defaultProtectedResourceMetadataURI, u.Path) - return GetProtectedResourceMetadata(ctx, u.String(), resourceID, c) -} - -// GetProtectedResourceMetadataFromHeader retrieves protected resource metadata -// using information in the given header, using the given client (or the default -// client if nil). -// It issues a GET request to a URL discovered by parsing the WWW-Authenticate headers in the given request. -// Per RFC 9728 section 3.3, it validates that the resource field of the resulting metadata -// matches the serverURL (the URL that the client used to make the original request to the resource server). -// If there is no metadata URL in the header, it returns nil, nil. -// -// Deprecated: Use [GetProtectedResourceMetadata] instead. This function will be removed in v1.5.0. -func GetProtectedResourceMetadataFromHeader(ctx context.Context, serverURL string, header http.Header, c *http.Client) (_ *ProtectedResourceMetadata, err error) { - headers := header[http.CanonicalHeaderKey("WWW-Authenticate")] - if len(headers) == 0 { - return nil, nil - } - cs, err := ParseWWWAuthenticate(headers) - if err != nil { - return nil, err - } - metadataURL := resourceMetadataURL(cs) - if metadataURL == "" { - return nil, nil - } - return GetProtectedResourceMetadata(ctx, metadataURL, serverURL, c) -} - -// resourceMetadataURL returns a resource metadata URL from the given "WWW-Authenticate" header challenges, -// or the empty string if there is none. -func resourceMetadataURL(cs []Challenge) string { - for _, c := range cs { - if u := c.Params["resource_metadata"]; u != "" { - return u - } - } - return "" -} - -// GetProtectedResourceMetadataFromID issues a GET request to retrieve protected resource -// metadata from a resource server. -// The metadataURL is typically a URL with a host:port and possibly a path. -// The resourceURL is the resource URI the metadataURL is for. -// The following checks are performed: -// - The metadataURL must use HTTPS or be a local address. -// - The resource field of the resulting metadata must match the resourceURL. -// - The authorization_servers field of the resulting metadata is checked for dangerous URL schemes. -func GetProtectedResourceMetadata(ctx context.Context, metadataURL, resourceURL string, c *http.Client) (_ *ProtectedResourceMetadata, err error) { - defer util.Wrapf(&err, "GetProtectedResourceMetadata(%q)", metadataURL) - u, err := url.Parse(metadataURL) - if err != nil { - return nil, err - } - // Only allow HTTP for local addresses (testing or development purposes). - if !util.IsLoopback(u.Host) && u.Scheme != "https" { - return nil, fmt.Errorf("metadataURL %q does not use HTTPS", metadataURL) - } - prm, err := getJSON[ProtectedResourceMetadata](ctx, c, metadataURL, 1<<20) - if err != nil { - return nil, err - } - // Validate the Resource field (see RFC 9728, section 3.3). - if prm.Resource != resourceURL { - return nil, fmt.Errorf("got metadata resource %q, want %q", prm.Resource, resourceURL) - } - // Validate the authorization server URLs to prevent XSS attacks (see #526). - for _, u := range prm.AuthorizationServers { - if err := checkURLScheme(u); err != nil { - return nil, err - } - } - return prm, nil -} - -// ParseWWWAuthenticate parses a WWW-Authenticate header string. -// The header format is defined in RFC 9110, Section 11.6.1, and can contain -// one or more challenges, separated by commas. -// It returns a slice of challenges or an error if one of the headers is malformed. -func ParseWWWAuthenticate(headers []string) ([]Challenge, error) { - var challenges []Challenge - for _, h := range headers { - challengeStrings, err := splitChallenges(h) - if err != nil { - return nil, err - } - for _, cs := range challengeStrings { - if strings.TrimSpace(cs) == "" { - continue - } - challenge, err := parseSingleChallenge(cs) - if err != nil { - return nil, fmt.Errorf("failed to parse challenge %q: %w", cs, err) - } - challenges = append(challenges, challenge) - } - } - return challenges, nil -} - -// splitChallenges splits a header value containing one or more challenges. -// It correctly handles commas within quoted strings and distinguishes between -// commas separating auth-params and commas separating challenges. -func splitChallenges(header string) ([]string, error) { - var challenges []string - inQuotes := false - start := 0 - for i, r := range header { - if r == '"' { - if i > 0 && header[i-1] != '\\' { - inQuotes = !inQuotes - } else if i == 0 { - // A challenge begins with an auth-scheme, which is a token, which cannot contain - // a quote. - return nil, errors.New(`challenge begins with '"'`) - } - } else if r == ',' && !inQuotes { - // This is a potential challenge separator. - // A new challenge does not start with `key=value`. - // We check if the part after the comma looks like a parameter. - lookahead := strings.TrimSpace(header[i+1:]) - eqPos := strings.Index(lookahead, "=") - - isParam := false - if eqPos > 0 { - // Check if the part before '=' is a single token (no spaces). - token := lookahead[:eqPos] - if strings.IndexFunc(token, unicode.IsSpace) == -1 { - isParam = true - } - } - - if !isParam { - // The part after the comma does not look like a parameter, - // so this comma separates challenges. - challenges = append(challenges, header[start:i]) - start = i + 1 - } - } - } - // Add the last (or only) challenge to the list. - challenges = append(challenges, header[start:]) - return challenges, nil -} - -// parseSingleChallenge parses a string containing exactly one challenge. -// challenge = auth-scheme [ 1*SP ( token68 / #auth-param ) ] -func parseSingleChallenge(s string) (Challenge, error) { - s = strings.TrimSpace(s) - if s == "" { - return Challenge{}, errors.New("empty challenge string") - } - - scheme, paramsStr, found := strings.Cut(s, " ") - c := Challenge{Scheme: strings.ToLower(scheme)} - if !found { - return c, nil - } - - params := make(map[string]string) - - // Parse the key-value parameters. - for paramsStr != "" { - // Find the end of the parameter key. - keyEnd := strings.Index(paramsStr, "=") - if keyEnd <= 0 { - return Challenge{}, fmt.Errorf("malformed auth parameter: expected key=value, but got %q", paramsStr) - } - key := strings.TrimSpace(paramsStr[:keyEnd]) - - // Move the string past the key and the '='. - paramsStr = strings.TrimSpace(paramsStr[keyEnd+1:]) - - var value string - if strings.HasPrefix(paramsStr, "\"") { - // The value is a quoted string. - paramsStr = paramsStr[1:] // Consume the opening quote. - var valBuilder strings.Builder - i := 0 - for ; i < len(paramsStr); i++ { - // Handle escaped characters. - if paramsStr[i] == '\\' && i+1 < len(paramsStr) { - valBuilder.WriteByte(paramsStr[i+1]) - i++ // We've consumed two characters. - } else if paramsStr[i] == '"' { - // End of the quoted string. - break - } else { - valBuilder.WriteByte(paramsStr[i]) - } - } - - // A quoted string must be terminated. - if i == len(paramsStr) { - return Challenge{}, fmt.Errorf("unterminated quoted string in auth parameter") - } - - value = valBuilder.String() - // Move the string past the value and the closing quote. - paramsStr = strings.TrimSpace(paramsStr[i+1:]) - } else { - // The value is a token. It ends at the next comma or the end of the string. - commaPos := strings.Index(paramsStr, ",") - if commaPos == -1 { - value = paramsStr - paramsStr = "" - } else { - value = strings.TrimSpace(paramsStr[:commaPos]) - paramsStr = strings.TrimSpace(paramsStr[commaPos:]) // Keep comma for next check - } - } - if value == "" { - return Challenge{}, fmt.Errorf("no value for auth param %q", key) - } - - // Per RFC 9110, parameter keys are case-insensitive. - params[strings.ToLower(key)] = value - - // If there is a comma, consume it and continue to the next parameter. - if strings.HasPrefix(paramsStr, ",") { - paramsStr = strings.TrimSpace(paramsStr[1:]) - } else if paramsStr != "" { - // If there's content but it's not a new parameter, the format is wrong. - return Challenge{}, fmt.Errorf("malformed auth parameter: expected comma after value, but got %q", paramsStr) - } - } - - // Per RFC 9110, the scheme is case-insensitive. - return Challenge{Scheme: strings.ToLower(scheme), Params: params}, nil -} diff --git a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/oauthex/resource_meta_public.go b/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/oauthex/resource_meta_public.go deleted file mode 100644 index 3bf7d9a..0000000 --- a/go/sdk/vendor/github.com/modelcontextprotocol/go-sdk/oauthex/resource_meta_public.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2025 The Go MCP SDK Authors. All rights reserved. -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// This file implements Protected Resource Metadata. -// See https://www.rfc-editor.org/rfc/rfc9728.html. - -// This is a temporary file to expose the required objects to the main package. - -package oauthex - -// ProtectedResourceMetadata is the metadata for an OAuth 2.0 protected resource, -// as defined in section 2 of https://www.rfc-editor.org/rfc/rfc9728.html. -// -// The following features are not supported: -// - additional keys (§2, last sentence) -// - human-readable metadata (§2.1) -// - signed metadata (§2.2) -type ProtectedResourceMetadata struct { - // Resource (resource) is the protected resource's resource identifier. - // Required. - Resource string `json:"resource"` - - // AuthorizationServers (authorization_servers) is an optional slice containing a list of - // OAuth authorization server issuer identifiers (as defined in RFC 8414) that can be - // used with this protected resource. - AuthorizationServers []string `json:"authorization_servers,omitempty"` - - // JWKSURI (jwks_uri) is an optional URL of the protected resource's JSON Web Key (JWK) Set - // document. This contains public keys belonging to the protected resource, such as - // signing key(s) that the resource server uses to sign resource responses. - JWKSURI string `json:"jwks_uri,omitempty"` - - // ScopesSupported (scopes_supported) is a recommended slice containing a list of scope - // values (as defined in RFC 6749) used in authorization requests to request access - // to this protected resource. - ScopesSupported []string `json:"scopes_supported,omitempty"` - - // BearerMethodsSupported (bearer_methods_supported) is an optional slice containing - // a list of the supported methods of sending an OAuth 2.0 bearer token to the - // protected resource. Defined values are "header", "body", and "query". - BearerMethodsSupported []string `json:"bearer_methods_supported,omitempty"` - - // ResourceSigningAlgValuesSupported (resource_signing_alg_values_supported) is an optional - // slice of JWS signing algorithms (alg values) supported by the protected - // resource for signing resource responses. - ResourceSigningAlgValuesSupported []string `json:"resource_signing_alg_values_supported,omitempty"` - - // ResourceName (resource_name) is a human-readable name of the protected resource - // intended for display to the end user. It is RECOMMENDED that this field be included. - // This value may be internationalized. - ResourceName string `json:"resource_name,omitempty"` - - // ResourceDocumentation (resource_documentation) is an optional URL of a page containing - // human-readable information for developers using the protected resource. - // This value may be internationalized. - ResourceDocumentation string `json:"resource_documentation,omitempty"` - - // ResourcePolicyURI (resource_policy_uri) is an optional URL of a page containing - // human-readable policy information on how a client can use the data provided. - // This value may be internationalized. - ResourcePolicyURI string `json:"resource_policy_uri,omitempty"` - - // ResourceTOSURI (resource_tos_uri) is an optional URL of a page containing the protected - // resource's human-readable terms of service. This value may be internationalized. - ResourceTOSURI string `json:"resource_tos_uri,omitempty"` - - // TLSClientCertificateBoundAccessTokens (tls_client_certificate_bound_access_tokens) is an - // optional boolean indicating support for mutual-TLS client certificate-bound - // access tokens (RFC 8705). Defaults to false if omitted. - TLSClientCertificateBoundAccessTokens bool `json:"tls_client_certificate_bound_access_tokens,omitempty"` - - // AuthorizationDetailsTypesSupported (authorization_details_types_supported) is an optional - // slice of 'type' values supported by the resource server for the - // 'authorization_details' parameter (RFC 9396). - AuthorizationDetailsTypesSupported []string `json:"authorization_details_types_supported,omitempty"` - - // DPOPSigningAlgValuesSupported (dpop_signing_alg_values_supported) is an optional - // slice of JWS signing algorithms supported by the resource server for validating - // DPoP proof JWTs (RFC 9449). - DPOPSigningAlgValuesSupported []string `json:"dpop_signing_alg_values_supported,omitempty"` - - // DPOPBoundAccessTokensRequired (dpop_bound_access_tokens_required) is an optional boolean - // specifying whether the protected resource always requires the use of DPoP-bound - // access tokens (RFC 9449). Defaults to false if omitted. - DPOPBoundAccessTokensRequired bool `json:"dpop_bound_access_tokens_required,omitempty"` - - // SignedMetadata (signed_metadata) is an optional JWT containing metadata parameters - // about the protected resource as claims. If present, these values take precedence - // over values conveyed in plain JSON. - // TODO:implement. - // Note that §2.2 says it's okay to ignore this. - // SignedMetadata string `json:"signed_metadata,omitempty"` -} - -// Challenge represents a single authentication challenge from a WWW-Authenticate header. -// As per RFC 9110, Section 11.6.1, a challenge consists of a scheme and optional parameters. -type Challenge struct { - // Scheme is the authentication scheme (e.g., "Bearer", "Basic"). - // It is case-insensitive. A parsed value will always be lower-case. - Scheme string - // Params is a map of authentication parameters. - // Keys are case-insensitive. Parsed keys are always lower-case. - Params map[string]string -} diff --git a/go/sdk/vendor/github.com/pmezard/go-difflib/LICENSE b/go/sdk/vendor/github.com/pmezard/go-difflib/LICENSE deleted file mode 100644 index c67dad6..0000000 --- a/go/sdk/vendor/github.com/pmezard/go-difflib/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2013, Patrick Mezard -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - The names of its contributors may not be used to endorse or promote -products derived from this software without specific prior written -permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/go/sdk/vendor/github.com/pmezard/go-difflib/difflib/difflib.go b/go/sdk/vendor/github.com/pmezard/go-difflib/difflib/difflib.go deleted file mode 100644 index 2a73737..0000000 --- a/go/sdk/vendor/github.com/pmezard/go-difflib/difflib/difflib.go +++ /dev/null @@ -1,775 +0,0 @@ -// Package difflib is a partial port of Python difflib module. -// -// It provides tools to compare sequences of strings and generate textual diffs. -// -// The following class and functions have been ported: -// -// - SequenceMatcher -// -// - unified_diff -// -// - context_diff -// -// Getting unified diffs was the main goal of the port. Keep in mind this code -// is mostly suitable to output text differences in a human friendly way, there -// are no guarantees generated diffs are consumable by patch(1). -package difflib - -import ( - "bufio" - "bytes" - "fmt" - "io" - "strings" -) - -func min(a, b int) int { - if a < b { - return a - } - return b -} - -func max(a, b int) int { - if a > b { - return a - } - return b -} - -func calculateRatio(matches, length int) float64 { - if length > 0 { - return 2.0 * float64(matches) / float64(length) - } - return 1.0 -} - -type Match struct { - A int - B int - Size int -} - -type OpCode struct { - Tag byte - I1 int - I2 int - J1 int - J2 int -} - -// SequenceMatcher compares sequence of strings. The basic -// algorithm predates, and is a little fancier than, an algorithm -// published in the late 1980's by Ratcliff and Obershelp under the -// hyperbolic name "gestalt pattern matching". The basic idea is to find -// the longest contiguous matching subsequence that contains no "junk" -// elements (R-O doesn't address junk). The same idea is then applied -// recursively to the pieces of the sequences to the left and to the right -// of the matching subsequence. This does not yield minimal edit -// sequences, but does tend to yield matches that "look right" to people. -// -// SequenceMatcher tries to compute a "human-friendly diff" between two -// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the -// longest *contiguous* & junk-free matching subsequence. That's what -// catches peoples' eyes. The Windows(tm) windiff has another interesting -// notion, pairing up elements that appear uniquely in each sequence. -// That, and the method here, appear to yield more intuitive difference -// reports than does diff. This method appears to be the least vulnerable -// to synching up on blocks of "junk lines", though (like blank lines in -// ordinary text files, or maybe "

" lines in HTML files). That may be -// because this is the only method of the 3 that has a *concept* of -// "junk" . -// -// Timing: Basic R-O is cubic time worst case and quadratic time expected -// case. SequenceMatcher is quadratic time for the worst case and has -// expected-case behavior dependent in a complicated way on how many -// elements the sequences have in common; best case time is linear. -type SequenceMatcher struct { - a []string - b []string - b2j map[string][]int - IsJunk func(string) bool - autoJunk bool - bJunk map[string]struct{} - matchingBlocks []Match - fullBCount map[string]int - bPopular map[string]struct{} - opCodes []OpCode -} - -func NewMatcher(a, b []string) *SequenceMatcher { - m := SequenceMatcher{autoJunk: true} - m.SetSeqs(a, b) - return &m -} - -func NewMatcherWithJunk(a, b []string, autoJunk bool, - isJunk func(string) bool) *SequenceMatcher { - - m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk} - m.SetSeqs(a, b) - return &m -} - -// Set two sequences to be compared. -func (m *SequenceMatcher) SetSeqs(a, b []string) { - m.SetSeq1(a) - m.SetSeq2(b) -} - -// Set the first sequence to be compared. The second sequence to be compared is -// not changed. -// -// SequenceMatcher computes and caches detailed information about the second -// sequence, so if you want to compare one sequence S against many sequences, -// use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other -// sequences. -// -// See also SetSeqs() and SetSeq2(). -func (m *SequenceMatcher) SetSeq1(a []string) { - if &a == &m.a { - return - } - m.a = a - m.matchingBlocks = nil - m.opCodes = nil -} - -// Set the second sequence to be compared. The first sequence to be compared is -// not changed. -func (m *SequenceMatcher) SetSeq2(b []string) { - if &b == &m.b { - return - } - m.b = b - m.matchingBlocks = nil - m.opCodes = nil - m.fullBCount = nil - m.chainB() -} - -func (m *SequenceMatcher) chainB() { - // Populate line -> index mapping - b2j := map[string][]int{} - for i, s := range m.b { - indices := b2j[s] - indices = append(indices, i) - b2j[s] = indices - } - - // Purge junk elements - m.bJunk = map[string]struct{}{} - if m.IsJunk != nil { - junk := m.bJunk - for s, _ := range b2j { - if m.IsJunk(s) { - junk[s] = struct{}{} - } - } - for s, _ := range junk { - delete(b2j, s) - } - } - - // Purge remaining popular elements - popular := map[string]struct{}{} - n := len(m.b) - if m.autoJunk && n >= 200 { - ntest := n/100 + 1 - for s, indices := range b2j { - if len(indices) > ntest { - popular[s] = struct{}{} - } - } - for s, _ := range popular { - delete(b2j, s) - } - } - m.bPopular = popular - m.b2j = b2j -} - -func (m *SequenceMatcher) isBJunk(s string) bool { - _, ok := m.bJunk[s] - return ok -} - -// Find longest matching block in a[alo:ahi] and b[blo:bhi]. -// -// If IsJunk is not defined: -// -// Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where -// -// alo <= i <= i+k <= ahi -// blo <= j <= j+k <= bhi -// -// and for all (i',j',k') meeting those conditions, -// -// k >= k' -// i <= i' -// and if i == i', j <= j' -// -// In other words, of all maximal matching blocks, return one that -// starts earliest in a, and of all those maximal matching blocks that -// start earliest in a, return the one that starts earliest in b. -// -// If IsJunk is defined, first the longest matching block is -// determined as above, but with the additional restriction that no -// junk element appears in the block. Then that block is extended as -// far as possible by matching (only) junk elements on both sides. So -// the resulting block never matches on junk except as identical junk -// happens to be adjacent to an "interesting" match. -// -// If no blocks match, return (alo, blo, 0). -func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match { - // CAUTION: stripping common prefix or suffix would be incorrect. - // E.g., - // ab - // acab - // Longest matching block is "ab", but if common prefix is - // stripped, it's "a" (tied with "b"). UNIX(tm) diff does so - // strip, so ends up claiming that ab is changed to acab by - // inserting "ca" in the middle. That's minimal but unintuitive: - // "it's obvious" that someone inserted "ac" at the front. - // Windiff ends up at the same place as diff, but by pairing up - // the unique 'b's and then matching the first two 'a's. - besti, bestj, bestsize := alo, blo, 0 - - // find longest junk-free match - // during an iteration of the loop, j2len[j] = length of longest - // junk-free match ending with a[i-1] and b[j] - j2len := map[int]int{} - for i := alo; i != ahi; i++ { - // look at all instances of a[i] in b; note that because - // b2j has no junk keys, the loop is skipped if a[i] is junk - newj2len := map[int]int{} - for _, j := range m.b2j[m.a[i]] { - // a[i] matches b[j] - if j < blo { - continue - } - if j >= bhi { - break - } - k := j2len[j-1] + 1 - newj2len[j] = k - if k > bestsize { - besti, bestj, bestsize = i-k+1, j-k+1, k - } - } - j2len = newj2len - } - - // Extend the best by non-junk elements on each end. In particular, - // "popular" non-junk elements aren't in b2j, which greatly speeds - // the inner loop above, but also means "the best" match so far - // doesn't contain any junk *or* popular non-junk elements. - for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) && - m.a[besti-1] == m.b[bestj-1] { - besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 - } - for besti+bestsize < ahi && bestj+bestsize < bhi && - !m.isBJunk(m.b[bestj+bestsize]) && - m.a[besti+bestsize] == m.b[bestj+bestsize] { - bestsize += 1 - } - - // Now that we have a wholly interesting match (albeit possibly - // empty!), we may as well suck up the matching junk on each - // side of it too. Can't think of a good reason not to, and it - // saves post-processing the (possibly considerable) expense of - // figuring out what to do with it. In the case of an empty - // interesting match, this is clearly the right thing to do, - // because no other kind of match is possible in the regions. - for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) && - m.a[besti-1] == m.b[bestj-1] { - besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 - } - for besti+bestsize < ahi && bestj+bestsize < bhi && - m.isBJunk(m.b[bestj+bestsize]) && - m.a[besti+bestsize] == m.b[bestj+bestsize] { - bestsize += 1 - } - - return Match{A: besti, B: bestj, Size: bestsize} -} - -// Return list of triples describing matching subsequences. -// -// Each triple is of the form (i, j, n), and means that -// a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in -// i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are -// adjacent triples in the list, and the second is not the last triple in the -// list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe -// adjacent equal blocks. -// -// The last triple is a dummy, (len(a), len(b), 0), and is the only -// triple with n==0. -func (m *SequenceMatcher) GetMatchingBlocks() []Match { - if m.matchingBlocks != nil { - return m.matchingBlocks - } - - var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match - matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match { - match := m.findLongestMatch(alo, ahi, blo, bhi) - i, j, k := match.A, match.B, match.Size - if match.Size > 0 { - if alo < i && blo < j { - matched = matchBlocks(alo, i, blo, j, matched) - } - matched = append(matched, match) - if i+k < ahi && j+k < bhi { - matched = matchBlocks(i+k, ahi, j+k, bhi, matched) - } - } - return matched - } - matched := matchBlocks(0, len(m.a), 0, len(m.b), nil) - - // It's possible that we have adjacent equal blocks in the - // matching_blocks list now. - nonAdjacent := []Match{} - i1, j1, k1 := 0, 0, 0 - for _, b := range matched { - // Is this block adjacent to i1, j1, k1? - i2, j2, k2 := b.A, b.B, b.Size - if i1+k1 == i2 && j1+k1 == j2 { - // Yes, so collapse them -- this just increases the length of - // the first block by the length of the second, and the first - // block so lengthened remains the block to compare against. - k1 += k2 - } else { - // Not adjacent. Remember the first block (k1==0 means it's - // the dummy we started with), and make the second block the - // new block to compare against. - if k1 > 0 { - nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) - } - i1, j1, k1 = i2, j2, k2 - } - } - if k1 > 0 { - nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) - } - - nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0}) - m.matchingBlocks = nonAdjacent - return m.matchingBlocks -} - -// Return list of 5-tuples describing how to turn a into b. -// -// Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple -// has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the -// tuple preceding it, and likewise for j1 == the previous j2. -// -// The tags are characters, with these meanings: -// -// 'r' (replace): a[i1:i2] should be replaced by b[j1:j2] -// -// 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case. -// -// 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case. -// -// 'e' (equal): a[i1:i2] == b[j1:j2] -func (m *SequenceMatcher) GetOpCodes() []OpCode { - if m.opCodes != nil { - return m.opCodes - } - i, j := 0, 0 - matching := m.GetMatchingBlocks() - opCodes := make([]OpCode, 0, len(matching)) - for _, m := range matching { - // invariant: we've pumped out correct diffs to change - // a[:i] into b[:j], and the next matching block is - // a[ai:ai+size] == b[bj:bj+size]. So we need to pump - // out a diff to change a[i:ai] into b[j:bj], pump out - // the matching block, and move (i,j) beyond the match - ai, bj, size := m.A, m.B, m.Size - tag := byte(0) - if i < ai && j < bj { - tag = 'r' - } else if i < ai { - tag = 'd' - } else if j < bj { - tag = 'i' - } - if tag > 0 { - opCodes = append(opCodes, OpCode{tag, i, ai, j, bj}) - } - i, j = ai+size, bj+size - // the list of matching blocks is terminated by a - // sentinel with size 0 - if size > 0 { - opCodes = append(opCodes, OpCode{'e', ai, i, bj, j}) - } - } - m.opCodes = opCodes - return m.opCodes -} - -// Isolate change clusters by eliminating ranges with no changes. -// -// Return a generator of groups with up to n lines of context. -// Each group is in the same format as returned by GetOpCodes(). -func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode { - if n < 0 { - n = 3 - } - codes := m.GetOpCodes() - if len(codes) == 0 { - codes = []OpCode{OpCode{'e', 0, 1, 0, 1}} - } - // Fixup leading and trailing groups if they show no changes. - if codes[0].Tag == 'e' { - c := codes[0] - i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 - codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2} - } - if codes[len(codes)-1].Tag == 'e' { - c := codes[len(codes)-1] - i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 - codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)} - } - nn := n + n - groups := [][]OpCode{} - group := []OpCode{} - for _, c := range codes { - i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 - // End the current group and start a new one whenever - // there is a large range with no changes. - if c.Tag == 'e' && i2-i1 > nn { - group = append(group, OpCode{c.Tag, i1, min(i2, i1+n), - j1, min(j2, j1+n)}) - groups = append(groups, group) - group = []OpCode{} - i1, j1 = max(i1, i2-n), max(j1, j2-n) - } - group = append(group, OpCode{c.Tag, i1, i2, j1, j2}) - } - if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') { - groups = append(groups, group) - } - return groups -} - -// Return a measure of the sequences' similarity (float in [0,1]). -// -// Where T is the total number of elements in both sequences, and -// M is the number of matches, this is 2.0*M / T. -// Note that this is 1 if the sequences are identical, and 0 if -// they have nothing in common. -// -// .Ratio() is expensive to compute if you haven't already computed -// .GetMatchingBlocks() or .GetOpCodes(), in which case you may -// want to try .QuickRatio() or .RealQuickRation() first to get an -// upper bound. -func (m *SequenceMatcher) Ratio() float64 { - matches := 0 - for _, m := range m.GetMatchingBlocks() { - matches += m.Size - } - return calculateRatio(matches, len(m.a)+len(m.b)) -} - -// Return an upper bound on ratio() relatively quickly. -// -// This isn't defined beyond that it is an upper bound on .Ratio(), and -// is faster to compute. -func (m *SequenceMatcher) QuickRatio() float64 { - // viewing a and b as multisets, set matches to the cardinality - // of their intersection; this counts the number of matches - // without regard to order, so is clearly an upper bound - if m.fullBCount == nil { - m.fullBCount = map[string]int{} - for _, s := range m.b { - m.fullBCount[s] = m.fullBCount[s] + 1 - } - } - - // avail[x] is the number of times x appears in 'b' less the - // number of times we've seen it in 'a' so far ... kinda - avail := map[string]int{} - matches := 0 - for _, s := range m.a { - n, ok := avail[s] - if !ok { - n = m.fullBCount[s] - } - avail[s] = n - 1 - if n > 0 { - matches += 1 - } - } - return calculateRatio(matches, len(m.a)+len(m.b)) -} - -// Return an upper bound on ratio() very quickly. -// -// This isn't defined beyond that it is an upper bound on .Ratio(), and -// is faster to compute than either .Ratio() or .QuickRatio(). -func (m *SequenceMatcher) RealQuickRatio() float64 { - la, lb := len(m.a), len(m.b) - return calculateRatio(min(la, lb), la+lb) -} - -// Convert range to the "ed" format -func formatRangeUnified(start, stop int) string { - // Per the diff spec at http://www.unix.org/single_unix_specification/ - beginning := start + 1 // lines start numbering with one - length := stop - start - if length == 1 { - return fmt.Sprintf("%d", beginning) - } - if length == 0 { - beginning -= 1 // empty ranges begin at line just before the range - } - return fmt.Sprintf("%d,%d", beginning, length) -} - -// Unified diff parameters -type UnifiedDiff struct { - A []string // First sequence lines - FromFile string // First file name - FromDate string // First file time - B []string // Second sequence lines - ToFile string // Second file name - ToDate string // Second file time - Eol string // Headers end of line, defaults to LF - Context int // Number of context lines -} - -// Compare two sequences of lines; generate the delta as a unified diff. -// -// Unified diffs are a compact way of showing line changes and a few -// lines of context. The number of context lines is set by 'n' which -// defaults to three. -// -// By default, the diff control lines (those with ---, +++, or @@) are -// created with a trailing newline. This is helpful so that inputs -// created from file.readlines() result in diffs that are suitable for -// file.writelines() since both the inputs and outputs have trailing -// newlines. -// -// For inputs that do not have trailing newlines, set the lineterm -// argument to "" so that the output will be uniformly newline free. -// -// The unidiff format normally has a header for filenames and modification -// times. Any or all of these may be specified using strings for -// 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. -// The modification times are normally expressed in the ISO 8601 format. -func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error { - buf := bufio.NewWriter(writer) - defer buf.Flush() - wf := func(format string, args ...interface{}) error { - _, err := buf.WriteString(fmt.Sprintf(format, args...)) - return err - } - ws := func(s string) error { - _, err := buf.WriteString(s) - return err - } - - if len(diff.Eol) == 0 { - diff.Eol = "\n" - } - - started := false - m := NewMatcher(diff.A, diff.B) - for _, g := range m.GetGroupedOpCodes(diff.Context) { - if !started { - started = true - fromDate := "" - if len(diff.FromDate) > 0 { - fromDate = "\t" + diff.FromDate - } - toDate := "" - if len(diff.ToDate) > 0 { - toDate = "\t" + diff.ToDate - } - if diff.FromFile != "" || diff.ToFile != "" { - err := wf("--- %s%s%s", diff.FromFile, fromDate, diff.Eol) - if err != nil { - return err - } - err = wf("+++ %s%s%s", diff.ToFile, toDate, diff.Eol) - if err != nil { - return err - } - } - } - first, last := g[0], g[len(g)-1] - range1 := formatRangeUnified(first.I1, last.I2) - range2 := formatRangeUnified(first.J1, last.J2) - if err := wf("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil { - return err - } - for _, c := range g { - i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 - if c.Tag == 'e' { - for _, line := range diff.A[i1:i2] { - if err := ws(" " + line); err != nil { - return err - } - } - continue - } - if c.Tag == 'r' || c.Tag == 'd' { - for _, line := range diff.A[i1:i2] { - if err := ws("-" + line); err != nil { - return err - } - } - } - if c.Tag == 'r' || c.Tag == 'i' { - for _, line := range diff.B[j1:j2] { - if err := ws("+" + line); err != nil { - return err - } - } - } - } - } - return nil -} - -// Like WriteUnifiedDiff but returns the diff a string. -func GetUnifiedDiffString(diff UnifiedDiff) (string, error) { - w := &bytes.Buffer{} - err := WriteUnifiedDiff(w, diff) - return string(w.Bytes()), err -} - -// Convert range to the "ed" format. -func formatRangeContext(start, stop int) string { - // Per the diff spec at http://www.unix.org/single_unix_specification/ - beginning := start + 1 // lines start numbering with one - length := stop - start - if length == 0 { - beginning -= 1 // empty ranges begin at line just before the range - } - if length <= 1 { - return fmt.Sprintf("%d", beginning) - } - return fmt.Sprintf("%d,%d", beginning, beginning+length-1) -} - -type ContextDiff UnifiedDiff - -// Compare two sequences of lines; generate the delta as a context diff. -// -// Context diffs are a compact way of showing line changes and a few -// lines of context. The number of context lines is set by diff.Context -// which defaults to three. -// -// By default, the diff control lines (those with *** or ---) are -// created with a trailing newline. -// -// For inputs that do not have trailing newlines, set the diff.Eol -// argument to "" so that the output will be uniformly newline free. -// -// The context diff format normally has a header for filenames and -// modification times. Any or all of these may be specified using -// strings for diff.FromFile, diff.ToFile, diff.FromDate, diff.ToDate. -// The modification times are normally expressed in the ISO 8601 format. -// If not specified, the strings default to blanks. -func WriteContextDiff(writer io.Writer, diff ContextDiff) error { - buf := bufio.NewWriter(writer) - defer buf.Flush() - var diffErr error - wf := func(format string, args ...interface{}) { - _, err := buf.WriteString(fmt.Sprintf(format, args...)) - if diffErr == nil && err != nil { - diffErr = err - } - } - ws := func(s string) { - _, err := buf.WriteString(s) - if diffErr == nil && err != nil { - diffErr = err - } - } - - if len(diff.Eol) == 0 { - diff.Eol = "\n" - } - - prefix := map[byte]string{ - 'i': "+ ", - 'd': "- ", - 'r': "! ", - 'e': " ", - } - - started := false - m := NewMatcher(diff.A, diff.B) - for _, g := range m.GetGroupedOpCodes(diff.Context) { - if !started { - started = true - fromDate := "" - if len(diff.FromDate) > 0 { - fromDate = "\t" + diff.FromDate - } - toDate := "" - if len(diff.ToDate) > 0 { - toDate = "\t" + diff.ToDate - } - if diff.FromFile != "" || diff.ToFile != "" { - wf("*** %s%s%s", diff.FromFile, fromDate, diff.Eol) - wf("--- %s%s%s", diff.ToFile, toDate, diff.Eol) - } - } - - first, last := g[0], g[len(g)-1] - ws("***************" + diff.Eol) - - range1 := formatRangeContext(first.I1, last.I2) - wf("*** %s ****%s", range1, diff.Eol) - for _, c := range g { - if c.Tag == 'r' || c.Tag == 'd' { - for _, cc := range g { - if cc.Tag == 'i' { - continue - } - for _, line := range diff.A[cc.I1:cc.I2] { - ws(prefix[cc.Tag] + line) - } - } - break - } - } - - range2 := formatRangeContext(first.J1, last.J2) - wf("--- %s ----%s", range2, diff.Eol) - for _, c := range g { - if c.Tag == 'r' || c.Tag == 'i' { - for _, cc := range g { - if cc.Tag == 'd' { - continue - } - for _, line := range diff.B[cc.J1:cc.J2] { - ws(prefix[cc.Tag] + line) - } - } - break - } - } - } - return diffErr -} - -// Like WriteContextDiff but returns the diff a string. -func GetContextDiffString(diff ContextDiff) (string, error) { - w := &bytes.Buffer{} - err := WriteContextDiff(w, diff) - return string(w.Bytes()), err -} - -// Split a string on "\n" while preserving them. The output can be used -// as input for UnifiedDiff and ContextDiff structures. -func SplitLines(s string) []string { - lines := strings.SplitAfter(s, "\n") - lines[len(lines)-1] += "\n" - return lines -} diff --git a/go/sdk/vendor/github.com/segmentio/asm/LICENSE b/go/sdk/vendor/github.com/segmentio/asm/LICENSE deleted file mode 100644 index 29e1ab6..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2021 Segment - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/go/sdk/vendor/github.com/segmentio/asm/ascii/ascii.go b/go/sdk/vendor/github.com/segmentio/asm/ascii/ascii.go deleted file mode 100644 index 4805146..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/ascii/ascii.go +++ /dev/null @@ -1,53 +0,0 @@ -package ascii - -import _ "github.com/segmentio/asm/cpu" - -// https://graphics.stanford.edu/~seander/bithacks.html#HasLessInWord -const ( - hasLessConstL64 = (^uint64(0)) / 255 - hasLessConstR64 = hasLessConstL64 * 128 - - hasLessConstL32 = (^uint32(0)) / 255 - hasLessConstR32 = hasLessConstL32 * 128 - - hasMoreConstL64 = (^uint64(0)) / 255 - hasMoreConstR64 = hasMoreConstL64 * 128 - - hasMoreConstL32 = (^uint32(0)) / 255 - hasMoreConstR32 = hasMoreConstL32 * 128 -) - -func hasLess64(x, n uint64) bool { - return ((x - (hasLessConstL64 * n)) & ^x & hasLessConstR64) != 0 -} - -func hasLess32(x, n uint32) bool { - return ((x - (hasLessConstL32 * n)) & ^x & hasLessConstR32) != 0 -} - -func hasMore64(x, n uint64) bool { - return (((x + (hasMoreConstL64 * (127 - n))) | x) & hasMoreConstR64) != 0 -} - -func hasMore32(x, n uint32) bool { - return (((x + (hasMoreConstL32 * (127 - n))) | x) & hasMoreConstR32) != 0 -} - -var lowerCase = [256]byte{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, -} diff --git a/go/sdk/vendor/github.com/segmentio/asm/ascii/equal_fold.go b/go/sdk/vendor/github.com/segmentio/asm/ascii/equal_fold.go deleted file mode 100644 index d90d8ca..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/ascii/equal_fold.go +++ /dev/null @@ -1,30 +0,0 @@ -package ascii - -import ( - "github.com/segmentio/asm/internal/unsafebytes" -) - -// EqualFold is a version of bytes.EqualFold designed to work on ASCII input -// instead of UTF-8. -// -// When the program has guarantees that the input is composed of ASCII -// characters only, it allows for greater optimizations. -func EqualFold(a, b []byte) bool { - return EqualFoldString(unsafebytes.String(a), unsafebytes.String(b)) -} - -func HasPrefixFold(s, prefix []byte) bool { - return len(s) >= len(prefix) && EqualFold(s[:len(prefix)], prefix) -} - -func HasSuffixFold(s, suffix []byte) bool { - return len(s) >= len(suffix) && EqualFold(s[len(s)-len(suffix):], suffix) -} - -func HasPrefixFoldString(s, prefix string) bool { - return len(s) >= len(prefix) && EqualFoldString(s[:len(prefix)], prefix) -} - -func HasSuffixFoldString(s, suffix string) bool { - return len(s) >= len(suffix) && EqualFoldString(s[len(s)-len(suffix):], suffix) -} diff --git a/go/sdk/vendor/github.com/segmentio/asm/ascii/equal_fold_amd64.go b/go/sdk/vendor/github.com/segmentio/asm/ascii/equal_fold_amd64.go deleted file mode 100644 index 07cf6cd..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/ascii/equal_fold_amd64.go +++ /dev/null @@ -1,13 +0,0 @@ -// Code generated by command: go run equal_fold_asm.go -pkg ascii -out ../ascii/equal_fold_amd64.s -stubs ../ascii/equal_fold_amd64.go. DO NOT EDIT. - -//go:build !purego -// +build !purego - -package ascii - -// EqualFoldString is a version of strings.EqualFold designed to work on ASCII -// input instead of UTF-8. -// -// When the program has guarantees that the input is composed of ASCII -// characters only, it allows for greater optimizations. -func EqualFoldString(a string, b string) bool diff --git a/go/sdk/vendor/github.com/segmentio/asm/ascii/equal_fold_amd64.s b/go/sdk/vendor/github.com/segmentio/asm/ascii/equal_fold_amd64.s deleted file mode 100644 index 34495a6..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/ascii/equal_fold_amd64.s +++ /dev/null @@ -1,304 +0,0 @@ -// Code generated by command: go run equal_fold_asm.go -pkg ascii -out ../ascii/equal_fold_amd64.s -stubs ../ascii/equal_fold_amd64.go. DO NOT EDIT. - -//go:build !purego -// +build !purego - -#include "textflag.h" - -// func EqualFoldString(a string, b string) bool -// Requires: AVX, AVX2, SSE4.1 -TEXT ·EqualFoldString(SB), NOSPLIT, $0-33 - MOVQ a_base+0(FP), CX - MOVQ a_len+8(FP), DX - MOVQ b_base+16(FP), BX - CMPQ DX, b_len+24(FP) - JNE done - XORQ AX, AX - CMPQ DX, $0x10 - JB init_x86 - BTL $0x08, github·com∕segmentio∕asm∕cpu·X86+0(SB) - JCS init_avx - -init_x86: - LEAQ github·com∕segmentio∕asm∕ascii·lowerCase+0(SB), R9 - XORL SI, SI - -cmp8: - CMPQ DX, $0x08 - JB cmp7 - MOVBLZX (CX)(AX*1), DI - MOVBLZX (BX)(AX*1), R8 - MOVB (R9)(DI*1), DI - XORB (R9)(R8*1), DI - ORB DI, SI - MOVBLZX 1(CX)(AX*1), DI - MOVBLZX 1(BX)(AX*1), R8 - MOVB (R9)(DI*1), DI - XORB (R9)(R8*1), DI - ORB DI, SI - MOVBLZX 2(CX)(AX*1), DI - MOVBLZX 2(BX)(AX*1), R8 - MOVB (R9)(DI*1), DI - XORB (R9)(R8*1), DI - ORB DI, SI - MOVBLZX 3(CX)(AX*1), DI - MOVBLZX 3(BX)(AX*1), R8 - MOVB (R9)(DI*1), DI - XORB (R9)(R8*1), DI - ORB DI, SI - MOVBLZX 4(CX)(AX*1), DI - MOVBLZX 4(BX)(AX*1), R8 - MOVB (R9)(DI*1), DI - XORB (R9)(R8*1), DI - ORB DI, SI - MOVBLZX 5(CX)(AX*1), DI - MOVBLZX 5(BX)(AX*1), R8 - MOVB (R9)(DI*1), DI - XORB (R9)(R8*1), DI - ORB DI, SI - MOVBLZX 6(CX)(AX*1), DI - MOVBLZX 6(BX)(AX*1), R8 - MOVB (R9)(DI*1), DI - XORB (R9)(R8*1), DI - ORB DI, SI - MOVBLZX 7(CX)(AX*1), DI - MOVBLZX 7(BX)(AX*1), R8 - MOVB (R9)(DI*1), DI - XORB (R9)(R8*1), DI - ORB DI, SI - JNE done - ADDQ $0x08, AX - SUBQ $0x08, DX - JMP cmp8 - -cmp7: - CMPQ DX, $0x07 - JB cmp6 - MOVBLZX 6(CX)(AX*1), DI - MOVBLZX 6(BX)(AX*1), R8 - MOVB (R9)(DI*1), DI - XORB (R9)(R8*1), DI - ORB DI, SI - -cmp6: - CMPQ DX, $0x06 - JB cmp5 - MOVBLZX 5(CX)(AX*1), DI - MOVBLZX 5(BX)(AX*1), R8 - MOVB (R9)(DI*1), DI - XORB (R9)(R8*1), DI - ORB DI, SI - -cmp5: - CMPQ DX, $0x05 - JB cmp4 - MOVBLZX 4(CX)(AX*1), DI - MOVBLZX 4(BX)(AX*1), R8 - MOVB (R9)(DI*1), DI - XORB (R9)(R8*1), DI - ORB DI, SI - -cmp4: - CMPQ DX, $0x04 - JB cmp3 - MOVBLZX 3(CX)(AX*1), DI - MOVBLZX 3(BX)(AX*1), R8 - MOVB (R9)(DI*1), DI - XORB (R9)(R8*1), DI - ORB DI, SI - -cmp3: - CMPQ DX, $0x03 - JB cmp2 - MOVBLZX 2(CX)(AX*1), DI - MOVBLZX 2(BX)(AX*1), R8 - MOVB (R9)(DI*1), DI - XORB (R9)(R8*1), DI - ORB DI, SI - -cmp2: - CMPQ DX, $0x02 - JB cmp1 - MOVBLZX 1(CX)(AX*1), DI - MOVBLZX 1(BX)(AX*1), R8 - MOVB (R9)(DI*1), DI - XORB (R9)(R8*1), DI - ORB DI, SI - -cmp1: - CMPQ DX, $0x01 - JB success - MOVBLZX (CX)(AX*1), DI - MOVBLZX (BX)(AX*1), R8 - MOVB (R9)(DI*1), DI - XORB (R9)(R8*1), DI - ORB DI, SI - -done: - SETEQ ret+32(FP) - RET - -success: - MOVB $0x01, ret+32(FP) - RET - -init_avx: - MOVB $0x20, SI - PINSRB $0x00, SI, X12 - VPBROADCASTB X12, Y12 - MOVB $0x1f, SI - PINSRB $0x00, SI, X13 - VPBROADCASTB X13, Y13 - MOVB $0x9a, SI - PINSRB $0x00, SI, X14 - VPBROADCASTB X14, Y14 - MOVB $0x01, SI - PINSRB $0x00, SI, X15 - VPBROADCASTB X15, Y15 - -cmp128: - CMPQ DX, $0x80 - JB cmp64 - VMOVDQU (CX)(AX*1), Y0 - VMOVDQU 32(CX)(AX*1), Y1 - VMOVDQU 64(CX)(AX*1), Y2 - VMOVDQU 96(CX)(AX*1), Y3 - VMOVDQU (BX)(AX*1), Y4 - VMOVDQU 32(BX)(AX*1), Y5 - VMOVDQU 64(BX)(AX*1), Y6 - VMOVDQU 96(BX)(AX*1), Y7 - VXORPD Y0, Y4, Y4 - VPCMPEQB Y12, Y4, Y8 - VORPD Y12, Y0, Y0 - VPADDB Y13, Y0, Y0 - VPCMPGTB Y0, Y14, Y0 - VPAND Y8, Y0, Y0 - VPAND Y15, Y0, Y0 - VPSLLW $0x05, Y0, Y0 - VPCMPEQB Y4, Y0, Y0 - VXORPD Y1, Y5, Y5 - VPCMPEQB Y12, Y5, Y9 - VORPD Y12, Y1, Y1 - VPADDB Y13, Y1, Y1 - VPCMPGTB Y1, Y14, Y1 - VPAND Y9, Y1, Y1 - VPAND Y15, Y1, Y1 - VPSLLW $0x05, Y1, Y1 - VPCMPEQB Y5, Y1, Y1 - VXORPD Y2, Y6, Y6 - VPCMPEQB Y12, Y6, Y10 - VORPD Y12, Y2, Y2 - VPADDB Y13, Y2, Y2 - VPCMPGTB Y2, Y14, Y2 - VPAND Y10, Y2, Y2 - VPAND Y15, Y2, Y2 - VPSLLW $0x05, Y2, Y2 - VPCMPEQB Y6, Y2, Y2 - VXORPD Y3, Y7, Y7 - VPCMPEQB Y12, Y7, Y11 - VORPD Y12, Y3, Y3 - VPADDB Y13, Y3, Y3 - VPCMPGTB Y3, Y14, Y3 - VPAND Y11, Y3, Y3 - VPAND Y15, Y3, Y3 - VPSLLW $0x05, Y3, Y3 - VPCMPEQB Y7, Y3, Y3 - VPAND Y1, Y0, Y0 - VPAND Y3, Y2, Y2 - VPAND Y2, Y0, Y0 - ADDQ $0x80, AX - SUBQ $0x80, DX - VPMOVMSKB Y0, SI - XORL $0xffffffff, SI - JNE done - JMP cmp128 - -cmp64: - CMPQ DX, $0x40 - JB cmp32 - VMOVDQU (CX)(AX*1), Y0 - VMOVDQU 32(CX)(AX*1), Y1 - VMOVDQU (BX)(AX*1), Y2 - VMOVDQU 32(BX)(AX*1), Y3 - VXORPD Y0, Y2, Y2 - VPCMPEQB Y12, Y2, Y4 - VORPD Y12, Y0, Y0 - VPADDB Y13, Y0, Y0 - VPCMPGTB Y0, Y14, Y0 - VPAND Y4, Y0, Y0 - VPAND Y15, Y0, Y0 - VPSLLW $0x05, Y0, Y0 - VPCMPEQB Y2, Y0, Y0 - VXORPD Y1, Y3, Y3 - VPCMPEQB Y12, Y3, Y5 - VORPD Y12, Y1, Y1 - VPADDB Y13, Y1, Y1 - VPCMPGTB Y1, Y14, Y1 - VPAND Y5, Y1, Y1 - VPAND Y15, Y1, Y1 - VPSLLW $0x05, Y1, Y1 - VPCMPEQB Y3, Y1, Y1 - VPAND Y1, Y0, Y0 - ADDQ $0x40, AX - SUBQ $0x40, DX - VPMOVMSKB Y0, SI - XORL $0xffffffff, SI - JNE done - -cmp32: - CMPQ DX, $0x20 - JB cmp16 - VMOVDQU (CX)(AX*1), Y0 - VMOVDQU (BX)(AX*1), Y1 - VXORPD Y0, Y1, Y1 - VPCMPEQB Y12, Y1, Y2 - VORPD Y12, Y0, Y0 - VPADDB Y13, Y0, Y0 - VPCMPGTB Y0, Y14, Y0 - VPAND Y2, Y0, Y0 - VPAND Y15, Y0, Y0 - VPSLLW $0x05, Y0, Y0 - VPCMPEQB Y1, Y0, Y0 - ADDQ $0x20, AX - SUBQ $0x20, DX - VPMOVMSKB Y0, SI - XORL $0xffffffff, SI - JNE done - -cmp16: - CMPQ DX, $0x10 - JLE cmp_tail - VMOVDQU (CX)(AX*1), X0 - VMOVDQU (BX)(AX*1), X1 - VXORPD X0, X1, X1 - VPCMPEQB X12, X1, X2 - VORPD X12, X0, X0 - VPADDB X13, X0, X0 - VPCMPGTB X0, X14, X0 - VPAND X2, X0, X0 - VPAND X15, X0, X0 - VPSLLW $0x05, X0, X0 - VPCMPEQB X1, X0, X0 - ADDQ $0x10, AX - SUBQ $0x10, DX - VPMOVMSKB X0, SI - XORL $0x0000ffff, SI - JNE done - -cmp_tail: - SUBQ $0x10, DX - ADDQ DX, AX - VMOVDQU (CX)(AX*1), X0 - VMOVDQU (BX)(AX*1), X1 - VXORPD X0, X1, X1 - VPCMPEQB X12, X1, X2 - VORPD X12, X0, X0 - VPADDB X13, X0, X0 - VPCMPGTB X0, X14, X0 - VPAND X2, X0, X0 - VPAND X15, X0, X0 - VPSLLW $0x05, X0, X0 - VPCMPEQB X1, X0, X0 - VPMOVMSKB X0, AX - XORL $0x0000ffff, AX - JMP done diff --git a/go/sdk/vendor/github.com/segmentio/asm/ascii/equal_fold_default.go b/go/sdk/vendor/github.com/segmentio/asm/ascii/equal_fold_default.go deleted file mode 100644 index 1ae5a13..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/ascii/equal_fold_default.go +++ /dev/null @@ -1,60 +0,0 @@ -//go:build purego || !amd64 -// +build purego !amd64 - -package ascii - -// EqualFoldString is a version of strings.EqualFold designed to work on ASCII -// input instead of UTF-8. -// -// When the program has guarantees that the input is composed of ASCII -// characters only, it allows for greater optimizations. -func EqualFoldString(a, b string) bool { - if len(a) != len(b) { - return false - } - - var cmp byte - - for len(a) >= 8 { - cmp |= lowerCase[a[0]] ^ lowerCase[b[0]] - cmp |= lowerCase[a[1]] ^ lowerCase[b[1]] - cmp |= lowerCase[a[2]] ^ lowerCase[b[2]] - cmp |= lowerCase[a[3]] ^ lowerCase[b[3]] - cmp |= lowerCase[a[4]] ^ lowerCase[b[4]] - cmp |= lowerCase[a[5]] ^ lowerCase[b[5]] - cmp |= lowerCase[a[6]] ^ lowerCase[b[6]] - cmp |= lowerCase[a[7]] ^ lowerCase[b[7]] - - if cmp != 0 { - return false - } - - a = a[8:] - b = b[8:] - } - - switch len(a) { - case 7: - cmp |= lowerCase[a[6]] ^ lowerCase[b[6]] - fallthrough - case 6: - cmp |= lowerCase[a[5]] ^ lowerCase[b[5]] - fallthrough - case 5: - cmp |= lowerCase[a[4]] ^ lowerCase[b[4]] - fallthrough - case 4: - cmp |= lowerCase[a[3]] ^ lowerCase[b[3]] - fallthrough - case 3: - cmp |= lowerCase[a[2]] ^ lowerCase[b[2]] - fallthrough - case 2: - cmp |= lowerCase[a[1]] ^ lowerCase[b[1]] - fallthrough - case 1: - cmp |= lowerCase[a[0]] ^ lowerCase[b[0]] - } - - return cmp == 0 -} diff --git a/go/sdk/vendor/github.com/segmentio/asm/ascii/valid.go b/go/sdk/vendor/github.com/segmentio/asm/ascii/valid.go deleted file mode 100644 index a5168ef..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/ascii/valid.go +++ /dev/null @@ -1,18 +0,0 @@ -package ascii - -import "github.com/segmentio/asm/internal/unsafebytes" - -// Valid returns true if b contains only ASCII characters. -func Valid(b []byte) bool { - return ValidString(unsafebytes.String(b)) -} - -// ValidBytes returns true if b is an ASCII character. -func ValidByte(b byte) bool { - return b <= 0x7f -} - -// ValidBytes returns true if b is an ASCII character. -func ValidRune(r rune) bool { - return r <= 0x7f -} diff --git a/go/sdk/vendor/github.com/segmentio/asm/ascii/valid_amd64.go b/go/sdk/vendor/github.com/segmentio/asm/ascii/valid_amd64.go deleted file mode 100644 index 72dc7b4..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/ascii/valid_amd64.go +++ /dev/null @@ -1,9 +0,0 @@ -// Code generated by command: go run valid_asm.go -pkg ascii -out ../ascii/valid_amd64.s -stubs ../ascii/valid_amd64.go. DO NOT EDIT. - -//go:build !purego -// +build !purego - -package ascii - -// ValidString returns true if s contains only ASCII characters. -func ValidString(s string) bool diff --git a/go/sdk/vendor/github.com/segmentio/asm/ascii/valid_amd64.s b/go/sdk/vendor/github.com/segmentio/asm/ascii/valid_amd64.s deleted file mode 100644 index 0214b0c..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/ascii/valid_amd64.s +++ /dev/null @@ -1,132 +0,0 @@ -// Code generated by command: go run valid_asm.go -pkg ascii -out ../ascii/valid_amd64.s -stubs ../ascii/valid_amd64.go. DO NOT EDIT. - -//go:build !purego -// +build !purego - -#include "textflag.h" - -// func ValidString(s string) bool -// Requires: AVX, AVX2, SSE4.1 -TEXT ·ValidString(SB), NOSPLIT, $0-17 - MOVQ s_base+0(FP), AX - MOVQ s_len+8(FP), CX - MOVQ $0x8080808080808080, DX - CMPQ CX, $0x10 - JB cmp8 - BTL $0x08, github·com∕segmentio∕asm∕cpu·X86+0(SB) - JCS init_avx - -cmp8: - CMPQ CX, $0x08 - JB cmp4 - TESTQ DX, (AX) - JNZ invalid - ADDQ $0x08, AX - SUBQ $0x08, CX - JMP cmp8 - -cmp4: - CMPQ CX, $0x04 - JB cmp3 - TESTL $0x80808080, (AX) - JNZ invalid - ADDQ $0x04, AX - SUBQ $0x04, CX - -cmp3: - CMPQ CX, $0x03 - JB cmp2 - MOVWLZX (AX), CX - MOVBLZX 2(AX), AX - SHLL $0x10, AX - ORL CX, AX - TESTL $0x80808080, AX - JMP done - -cmp2: - CMPQ CX, $0x02 - JB cmp1 - TESTW $0x8080, (AX) - JMP done - -cmp1: - CMPQ CX, $0x00 - JE done - TESTB $0x80, (AX) - -done: - SETEQ ret+16(FP) - RET - -invalid: - MOVB $0x00, ret+16(FP) - RET - -init_avx: - PINSRQ $0x00, DX, X4 - VPBROADCASTQ X4, Y4 - -cmp256: - CMPQ CX, $0x00000100 - JB cmp128 - VMOVDQU (AX), Y0 - VPOR 32(AX), Y0, Y0 - VMOVDQU 64(AX), Y1 - VPOR 96(AX), Y1, Y1 - VMOVDQU 128(AX), Y2 - VPOR 160(AX), Y2, Y2 - VMOVDQU 192(AX), Y3 - VPOR 224(AX), Y3, Y3 - VPOR Y1, Y0, Y0 - VPOR Y3, Y2, Y2 - VPOR Y2, Y0, Y0 - VPTEST Y0, Y4 - JNZ invalid - ADDQ $0x00000100, AX - SUBQ $0x00000100, CX - JMP cmp256 - -cmp128: - CMPQ CX, $0x80 - JB cmp64 - VMOVDQU (AX), Y0 - VPOR 32(AX), Y0, Y0 - VMOVDQU 64(AX), Y1 - VPOR 96(AX), Y1, Y1 - VPOR Y1, Y0, Y0 - VPTEST Y0, Y4 - JNZ invalid - ADDQ $0x80, AX - SUBQ $0x80, CX - -cmp64: - CMPQ CX, $0x40 - JB cmp32 - VMOVDQU (AX), Y0 - VPOR 32(AX), Y0, Y0 - VPTEST Y0, Y4 - JNZ invalid - ADDQ $0x40, AX - SUBQ $0x40, CX - -cmp32: - CMPQ CX, $0x20 - JB cmp16 - VPTEST (AX), Y4 - JNZ invalid - ADDQ $0x20, AX - SUBQ $0x20, CX - -cmp16: - CMPQ CX, $0x10 - JLE cmp_tail - VPTEST (AX), X4 - JNZ invalid - ADDQ $0x10, AX - SUBQ $0x10, CX - -cmp_tail: - SUBQ $0x10, CX - ADDQ CX, AX - VPTEST (AX), X4 - JMP done diff --git a/go/sdk/vendor/github.com/segmentio/asm/ascii/valid_default.go b/go/sdk/vendor/github.com/segmentio/asm/ascii/valid_default.go deleted file mode 100644 index 715a090..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/ascii/valid_default.go +++ /dev/null @@ -1,48 +0,0 @@ -//go:build purego || !amd64 -// +build purego !amd64 - -package ascii - -import ( - "unsafe" -) - -// ValidString returns true if s contains only ASCII characters. -func ValidString(s string) bool { - p := *(*unsafe.Pointer)(unsafe.Pointer(&s)) - i := uintptr(0) - n := uintptr(len(s)) - - for i+8 <= n { - if (*(*uint64)(unsafe.Pointer(uintptr(p) + i)) & 0x8080808080808080) != 0 { - return false - } - i += 8 - } - - if i+4 <= n { - if (*(*uint32)(unsafe.Pointer(uintptr(p) + i)) & 0x80808080) != 0 { - return false - } - i += 4 - } - - if i == n { - return true - } - - p = unsafe.Pointer(uintptr(p) + i) - - var x uint32 - switch n - i { - case 3: - x = uint32(*(*uint16)(p)) | uint32(*(*uint8)(unsafe.Pointer(uintptr(p) + 2)))<<16 - case 2: - x = uint32(*(*uint16)(p)) - case 1: - x = uint32(*(*uint8)(p)) - default: - return true - } - return (x & 0x80808080) == 0 -} diff --git a/go/sdk/vendor/github.com/segmentio/asm/ascii/valid_print.go b/go/sdk/vendor/github.com/segmentio/asm/ascii/valid_print.go deleted file mode 100644 index aa0db7f..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/ascii/valid_print.go +++ /dev/null @@ -1,18 +0,0 @@ -package ascii - -import "github.com/segmentio/asm/internal/unsafebytes" - -// ValidPrint returns true if b contains only printable ASCII characters. -func ValidPrint(b []byte) bool { - return ValidPrintString(unsafebytes.String(b)) -} - -// ValidPrintBytes returns true if b is an ASCII character. -func ValidPrintByte(b byte) bool { - return 0x20 <= b && b <= 0x7e -} - -// ValidPrintBytes returns true if b is an ASCII character. -func ValidPrintRune(r rune) bool { - return 0x20 <= r && r <= 0x7e -} diff --git a/go/sdk/vendor/github.com/segmentio/asm/ascii/valid_print_amd64.go b/go/sdk/vendor/github.com/segmentio/asm/ascii/valid_print_amd64.go deleted file mode 100644 index b146266..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/ascii/valid_print_amd64.go +++ /dev/null @@ -1,9 +0,0 @@ -// Code generated by command: go run valid_print_asm.go -pkg ascii -out ../ascii/valid_print_amd64.s -stubs ../ascii/valid_print_amd64.go. DO NOT EDIT. - -//go:build !purego -// +build !purego - -package ascii - -// ValidPrintString returns true if s contains only printable ASCII characters. -func ValidPrintString(s string) bool diff --git a/go/sdk/vendor/github.com/segmentio/asm/ascii/valid_print_amd64.s b/go/sdk/vendor/github.com/segmentio/asm/ascii/valid_print_amd64.s deleted file mode 100644 index bc2e20a..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/ascii/valid_print_amd64.s +++ /dev/null @@ -1,185 +0,0 @@ -// Code generated by command: go run valid_print_asm.go -pkg ascii -out ../ascii/valid_print_amd64.s -stubs ../ascii/valid_print_amd64.go. DO NOT EDIT. - -//go:build !purego -// +build !purego - -#include "textflag.h" - -// func ValidPrintString(s string) bool -// Requires: AVX, AVX2, SSE4.1 -TEXT ·ValidPrintString(SB), NOSPLIT, $0-17 - MOVQ s_base+0(FP), AX - MOVQ s_len+8(FP), CX - CMPQ CX, $0x10 - JB init_x86 - BTL $0x08, github·com∕segmentio∕asm∕cpu·X86+0(SB) - JCS init_avx - -init_x86: - CMPQ CX, $0x08 - JB cmp4 - MOVQ $0xdfdfdfdfdfdfdfe0, DX - MOVQ $0x0101010101010101, BX - MOVQ $0x8080808080808080, SI - -cmp8: - MOVQ (AX), DI - MOVQ DI, R8 - LEAQ (DI)(DX*1), R9 - NOTQ R8 - ANDQ R8, R9 - LEAQ (DI)(BX*1), R8 - ORQ R8, DI - ORQ R9, DI - ADDQ $0x08, AX - SUBQ $0x08, CX - TESTQ SI, DI - JNE done - CMPQ CX, $0x08 - JB cmp4 - JMP cmp8 - -cmp4: - CMPQ CX, $0x04 - JB cmp3 - MOVL (AX), DX - MOVL DX, BX - LEAL 3755991008(DX), SI - NOTL BX - ANDL BX, SI - LEAL 16843009(DX), BX - ORL BX, DX - ORL SI, DX - ADDQ $0x04, AX - SUBQ $0x04, CX - TESTL $0x80808080, DX - JNE done - -cmp3: - CMPQ CX, $0x03 - JB cmp2 - MOVWLZX (AX), DX - MOVBLZX 2(AX), AX - SHLL $0x10, AX - ORL DX, AX - ORL $0x20000000, AX - JMP final - -cmp2: - CMPQ CX, $0x02 - JB cmp1 - MOVWLZX (AX), AX - ORL $0x20200000, AX - JMP final - -cmp1: - CMPQ CX, $0x00 - JE done - MOVBLZX (AX), AX - ORL $0x20202000, AX - -final: - MOVL AX, CX - LEAL 3755991008(AX), DX - NOTL CX - ANDL CX, DX - LEAL 16843009(AX), CX - ORL CX, AX - ORL DX, AX - TESTL $0x80808080, AX - -done: - SETEQ ret+16(FP) - RET - -init_avx: - MOVB $0x1f, DL - PINSRB $0x00, DX, X8 - VPBROADCASTB X8, Y8 - MOVB $0x7e, DL - PINSRB $0x00, DX, X9 - VPBROADCASTB X9, Y9 - -cmp128: - CMPQ CX, $0x80 - JB cmp64 - VMOVDQU (AX), Y0 - VMOVDQU 32(AX), Y1 - VMOVDQU 64(AX), Y2 - VMOVDQU 96(AX), Y3 - VPCMPGTB Y8, Y0, Y4 - VPCMPGTB Y9, Y0, Y0 - VPANDN Y4, Y0, Y0 - VPCMPGTB Y8, Y1, Y5 - VPCMPGTB Y9, Y1, Y1 - VPANDN Y5, Y1, Y1 - VPCMPGTB Y8, Y2, Y6 - VPCMPGTB Y9, Y2, Y2 - VPANDN Y6, Y2, Y2 - VPCMPGTB Y8, Y3, Y7 - VPCMPGTB Y9, Y3, Y3 - VPANDN Y7, Y3, Y3 - VPAND Y1, Y0, Y0 - VPAND Y3, Y2, Y2 - VPAND Y2, Y0, Y0 - ADDQ $0x80, AX - SUBQ $0x80, CX - VPMOVMSKB Y0, DX - XORL $0xffffffff, DX - JNE done - JMP cmp128 - -cmp64: - CMPQ CX, $0x40 - JB cmp32 - VMOVDQU (AX), Y0 - VMOVDQU 32(AX), Y1 - VPCMPGTB Y8, Y0, Y2 - VPCMPGTB Y9, Y0, Y0 - VPANDN Y2, Y0, Y0 - VPCMPGTB Y8, Y1, Y3 - VPCMPGTB Y9, Y1, Y1 - VPANDN Y3, Y1, Y1 - VPAND Y1, Y0, Y0 - ADDQ $0x40, AX - SUBQ $0x40, CX - VPMOVMSKB Y0, DX - XORL $0xffffffff, DX - JNE done - -cmp32: - CMPQ CX, $0x20 - JB cmp16 - VMOVDQU (AX), Y0 - VPCMPGTB Y8, Y0, Y1 - VPCMPGTB Y9, Y0, Y0 - VPANDN Y1, Y0, Y0 - ADDQ $0x20, AX - SUBQ $0x20, CX - VPMOVMSKB Y0, DX - XORL $0xffffffff, DX - JNE done - -cmp16: - CMPQ CX, $0x10 - JLE cmp_tail - VMOVDQU (AX), X0 - VPCMPGTB X8, X0, X1 - VPCMPGTB X9, X0, X0 - VPANDN X1, X0, X0 - ADDQ $0x10, AX - SUBQ $0x10, CX - VPMOVMSKB X0, DX - XORL $0x0000ffff, DX - JNE done - -cmp_tail: - SUBQ $0x10, CX - ADDQ CX, AX - VMOVDQU (AX), X0 - VPCMPGTB X8, X0, X1 - VPCMPGTB X9, X0, X0 - VPANDN X1, X0, X0 - VPMOVMSKB X0, DX - XORL $0x0000ffff, DX - JMP done diff --git a/go/sdk/vendor/github.com/segmentio/asm/ascii/valid_print_default.go b/go/sdk/vendor/github.com/segmentio/asm/ascii/valid_print_default.go deleted file mode 100644 index c4dc748..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/ascii/valid_print_default.go +++ /dev/null @@ -1,46 +0,0 @@ -//go:build purego || !amd64 -// +build purego !amd64 - -package ascii - -import "unsafe" - -// ValidString returns true if s contains only printable ASCII characters. -func ValidPrintString(s string) bool { - p := *(*unsafe.Pointer)(unsafe.Pointer(&s)) - i := uintptr(0) - n := uintptr(len(s)) - - for i+8 <= n { - if hasLess64(*(*uint64)(unsafe.Pointer(uintptr(p) + i)), 0x20) || hasMore64(*(*uint64)(unsafe.Pointer(uintptr(p) + i)), 0x7e) { - return false - } - i += 8 - } - - if i+4 <= n { - if hasLess32(*(*uint32)(unsafe.Pointer(uintptr(p) + i)), 0x20) || hasMore32(*(*uint32)(unsafe.Pointer(uintptr(p) + i)), 0x7e) { - return false - } - i += 4 - } - - if i == n { - return true - } - - p = unsafe.Pointer(uintptr(p) + i) - - var x uint32 - switch n - i { - case 3: - x = 0x20000000 | uint32(*(*uint16)(p)) | uint32(*(*uint8)(unsafe.Pointer(uintptr(p) + 2)))<<16 - case 2: - x = 0x20200000 | uint32(*(*uint16)(p)) - case 1: - x = 0x20202000 | uint32(*(*uint8)(p)) - default: - return true - } - return !(hasLess32(x, 0x20) || hasMore32(x, 0x7e)) -} diff --git a/go/sdk/vendor/github.com/segmentio/asm/base64/base64.go b/go/sdk/vendor/github.com/segmentio/asm/base64/base64.go deleted file mode 100644 index d40d31e..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/base64/base64.go +++ /dev/null @@ -1,68 +0,0 @@ -package base64 - -import ( - "encoding/base64" -) - -const ( - StdPadding rune = base64.StdPadding - NoPadding rune = base64.NoPadding - - encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" - encodeURL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" - encodeIMAP = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+," - - letterRange = int8('Z' - 'A' + 1) -) - -// StdEncoding is the standard base64 encoding, as defined in RFC 4648. -var StdEncoding = NewEncoding(encodeStd) - -// URLEncoding is the alternate base64 encoding defined in RFC 4648. -// It is typically used in URLs and file names. -var URLEncoding = NewEncoding(encodeURL) - -// RawStdEncoding is the standard unpadded base64 encoding defined in RFC 4648 section 3.2. -// This is the same as StdEncoding but omits padding characters. -var RawStdEncoding = StdEncoding.WithPadding(NoPadding) - -// RawURLEncoding is the unpadded alternate base64 encoding defined in RFC 4648. -// This is the same as URLEncoding but omits padding characters. -var RawURLEncoding = URLEncoding.WithPadding(NoPadding) - -// NewEncoding returns a new padded Encoding defined by the given alphabet, -// which must be a 64-byte string that does not contain the padding character -// or CR / LF ('\r', '\n'). Unlike the standard library, the encoding alphabet -// cannot be abitrary, and it must follow one of the know standard encoding -// variants. -// -// Required alphabet values: -// - [0,26): characters 'A'..'Z' -// - [26,52): characters 'a'..'z' -// - [52,62): characters '0'..'9' -// -// Flexible alphabet value options: -// - RFC 4648, RFC 1421, RFC 2045, RFC 2152, RFC 4880: '+' and '/' -// - RFC 4648 URI: '-' and '_' -// - RFC 3501: '+' and ',' -// -// The resulting Encoding uses the default padding character ('='), which may -// be changed or disabled via WithPadding. The padding characters is urestricted, -// but it must be a character outside of the encoder alphabet. -func NewEncoding(encoder string) *Encoding { - if len(encoder) != 64 { - panic("encoding alphabet is not 64-bytes long") - } - - if _, ok := allowedEncoding[encoder]; !ok { - panic("non-standard encoding alphabets are not supported") - } - - return newEncoding(encoder) -} - -var allowedEncoding = map[string]struct{}{ - encodeStd: {}, - encodeURL: {}, - encodeIMAP: {}, -} diff --git a/go/sdk/vendor/github.com/segmentio/asm/base64/base64_amd64.go b/go/sdk/vendor/github.com/segmentio/asm/base64/base64_amd64.go deleted file mode 100644 index e4940d7..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/base64/base64_amd64.go +++ /dev/null @@ -1,160 +0,0 @@ -//go:build amd64 && !purego -// +build amd64,!purego - -package base64 - -import ( - "encoding/base64" - - "github.com/segmentio/asm/cpu" - "github.com/segmentio/asm/cpu/x86" - "github.com/segmentio/asm/internal/unsafebytes" -) - -// An Encoding is a radix 64 encoding/decoding scheme, defined by a -// 64-character alphabet. -type Encoding struct { - enc func(dst []byte, src []byte, lut *int8) (int, int) - enclut [32]int8 - - dec func(dst []byte, src []byte, lut *int8) (int, int) - declut [48]int8 - - base *base64.Encoding -} - -const ( - minEncodeLen = 28 - minDecodeLen = 45 -) - -func newEncoding(encoder string) *Encoding { - e := &Encoding{base: base64.NewEncoding(encoder)} - if cpu.X86.Has(x86.AVX2) { - e.enableEncodeAVX2(encoder) - e.enableDecodeAVX2(encoder) - } - return e -} - -func (e *Encoding) enableEncodeAVX2(encoder string) { - // Translate values 0..63 to the Base64 alphabet. There are five sets: - // - // From To Add Index Example - // [0..25] [65..90] +65 0 ABCDEFGHIJKLMNOPQRSTUVWXYZ - // [26..51] [97..122] +71 1 abcdefghijklmnopqrstuvwxyz - // [52..61] [48..57] -4 [2..11] 0123456789 - // [62] [43] -19 12 + - // [63] [47] -16 13 / - tab := [32]int8{int8(encoder[0]), int8(encoder[letterRange]) - letterRange} - for i, ch := range encoder[2*letterRange:] { - tab[2+i] = int8(ch) - 2*letterRange - int8(i) - } - - e.enc = encodeAVX2 - e.enclut = tab -} - -func (e *Encoding) enableDecodeAVX2(encoder string) { - c62, c63 := int8(encoder[62]), int8(encoder[63]) - url := c63 == '_' - if url { - c63 = '/' - } - - // Translate values from the Base64 alphabet using five sets. Values outside - // of these ranges are considered invalid: - // - // From To Add Index Example - // [47] [63] +16 1 / - // [43] [62] +19 2 + - // [48..57] [52..61] +4 3 0123456789 - // [65..90] [0..25] -65 4,5 ABCDEFGHIJKLMNOPQRSTUVWXYZ - // [97..122] [26..51] -71 6,7 abcdefghijklmnopqrstuvwxyz - tab := [48]int8{ - 0, 63 - c63, 62 - c62, 4, -65, -65, -71, -71, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x13, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, - } - tab[(c62&15)+16] = 0x1A - tab[(c63&15)+16] = 0x1A - - if url { - e.dec = decodeAVX2URI - } else { - e.dec = decodeAVX2 - } - e.declut = tab -} - -// WithPadding creates a duplicate Encoding updated with a specified padding -// character, or NoPadding to disable padding. The padding character must not -// be contained in the encoding alphabet, must not be '\r' or '\n', and must -// be no greater than '\xFF'. -func (enc Encoding) WithPadding(padding rune) *Encoding { - enc.base = enc.base.WithPadding(padding) - return &enc -} - -// Strict creates a duplicate encoding updated with strict decoding enabled. -// This requires that trailing padding bits are zero. -func (enc Encoding) Strict() *Encoding { - enc.base = enc.base.Strict() - return &enc -} - -// Encode encodes src using the defined encoding alphabet. -// This will write EncodedLen(len(src)) bytes to dst. -func (enc *Encoding) Encode(dst, src []byte) { - if len(src) >= minEncodeLen && enc.enc != nil { - d, s := enc.enc(dst, src, &enc.enclut[0]) - dst = dst[d:] - src = src[s:] - } - enc.base.Encode(dst, src) -} - -// Encode encodes src using the encoding enc, writing -// EncodedLen(len(src)) bytes to dst. -func (enc *Encoding) EncodeToString(src []byte) string { - buf := make([]byte, enc.base.EncodedLen(len(src))) - enc.Encode(buf, src) - return string(buf) -} - -// EncodedLen calculates the base64-encoded byte length for a message -// of length n. -func (enc *Encoding) EncodedLen(n int) int { - return enc.base.EncodedLen(n) -} - -// Decode decodes src using the defined encoding alphabet. -// This will write DecodedLen(len(src)) bytes to dst and return the number of -// bytes written. -func (enc *Encoding) Decode(dst, src []byte) (n int, err error) { - var d, s int - if len(src) >= minDecodeLen && enc.dec != nil { - d, s = enc.dec(dst, src, &enc.declut[0]) - dst = dst[d:] - src = src[s:] - } - n, err = enc.base.Decode(dst, src) - n += d - return -} - -// DecodeString decodes the base64 encoded string s, returns the decoded -// value as bytes. -func (enc *Encoding) DecodeString(s string) ([]byte, error) { - src := unsafebytes.BytesOf(s) - dst := make([]byte, enc.base.DecodedLen(len(s))) - n, err := enc.Decode(dst, src) - return dst[:n], err -} - -// DecodedLen calculates the decoded byte length for a base64-encoded message -// of length n. -func (enc *Encoding) DecodedLen(n int) int { - return enc.base.DecodedLen(n) -} diff --git a/go/sdk/vendor/github.com/segmentio/asm/base64/base64_default.go b/go/sdk/vendor/github.com/segmentio/asm/base64/base64_default.go deleted file mode 100644 index f5d3d64..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/base64/base64_default.go +++ /dev/null @@ -1,14 +0,0 @@ -//go:build purego || !amd64 -// +build purego !amd64 - -package base64 - -import "encoding/base64" - -// An Encoding is a radix 64 encoding/decoding scheme, defined by a -// 64-character alphabet. -type Encoding = base64.Encoding - -func newEncoding(encoder string) *Encoding { - return base64.NewEncoding(encoder) -} diff --git a/go/sdk/vendor/github.com/segmentio/asm/base64/decode_amd64.go b/go/sdk/vendor/github.com/segmentio/asm/base64/decode_amd64.go deleted file mode 100644 index 1dae5b4..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/base64/decode_amd64.go +++ /dev/null @@ -1,10 +0,0 @@ -// Code generated by command: go run decode_asm.go -pkg base64 -out ../base64/decode_amd64.s -stubs ../base64/decode_amd64.go. DO NOT EDIT. - -//go:build !purego -// +build !purego - -package base64 - -func decodeAVX2(dst []byte, src []byte, lut *int8) (int, int) - -func decodeAVX2URI(dst []byte, src []byte, lut *int8) (int, int) diff --git a/go/sdk/vendor/github.com/segmentio/asm/base64/decode_amd64.s b/go/sdk/vendor/github.com/segmentio/asm/base64/decode_amd64.s deleted file mode 100644 index cc6c779..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/base64/decode_amd64.s +++ /dev/null @@ -1,144 +0,0 @@ -// Code generated by command: go run decode_asm.go -pkg base64 -out ../base64/decode_amd64.s -stubs ../base64/decode_amd64.go. DO NOT EDIT. - -//go:build !purego -// +build !purego - -#include "textflag.h" - -DATA b64_dec_lut_hi<>+0(SB)/8, $0x0804080402011010 -DATA b64_dec_lut_hi<>+8(SB)/8, $0x1010101010101010 -DATA b64_dec_lut_hi<>+16(SB)/8, $0x0804080402011010 -DATA b64_dec_lut_hi<>+24(SB)/8, $0x1010101010101010 -GLOBL b64_dec_lut_hi<>(SB), RODATA|NOPTR, $32 - -DATA b64_dec_madd1<>+0(SB)/8, $0x0140014001400140 -DATA b64_dec_madd1<>+8(SB)/8, $0x0140014001400140 -DATA b64_dec_madd1<>+16(SB)/8, $0x0140014001400140 -DATA b64_dec_madd1<>+24(SB)/8, $0x0140014001400140 -GLOBL b64_dec_madd1<>(SB), RODATA|NOPTR, $32 - -DATA b64_dec_madd2<>+0(SB)/8, $0x0001100000011000 -DATA b64_dec_madd2<>+8(SB)/8, $0x0001100000011000 -DATA b64_dec_madd2<>+16(SB)/8, $0x0001100000011000 -DATA b64_dec_madd2<>+24(SB)/8, $0x0001100000011000 -GLOBL b64_dec_madd2<>(SB), RODATA|NOPTR, $32 - -DATA b64_dec_shuf_lo<>+0(SB)/8, $0x0000000000000000 -DATA b64_dec_shuf_lo<>+8(SB)/8, $0x0600010200000000 -GLOBL b64_dec_shuf_lo<>(SB), RODATA|NOPTR, $16 - -DATA b64_dec_shuf<>+0(SB)/8, $0x090a040506000102 -DATA b64_dec_shuf<>+8(SB)/8, $0x000000000c0d0e08 -DATA b64_dec_shuf<>+16(SB)/8, $0x0c0d0e08090a0405 -DATA b64_dec_shuf<>+24(SB)/8, $0x0000000000000000 -GLOBL b64_dec_shuf<>(SB), RODATA|NOPTR, $32 - -// func decodeAVX2(dst []byte, src []byte, lut *int8) (int, int) -// Requires: AVX, AVX2, SSE4.1 -TEXT ·decodeAVX2(SB), NOSPLIT, $0-72 - MOVQ dst_base+0(FP), AX - MOVQ src_base+24(FP), DX - MOVQ lut+48(FP), SI - MOVQ src_len+32(FP), DI - MOVB $0x2f, CL - PINSRB $0x00, CX, X8 - VPBROADCASTB X8, Y8 - XORQ CX, CX - XORQ BX, BX - VPXOR Y7, Y7, Y7 - VPERMQ $0x44, (SI), Y6 - VPERMQ $0x44, 16(SI), Y4 - VMOVDQA b64_dec_lut_hi<>+0(SB), Y5 - -loop: - VMOVDQU (DX)(BX*1), Y0 - VPSRLD $0x04, Y0, Y2 - VPAND Y8, Y0, Y3 - VPSHUFB Y3, Y4, Y3 - VPAND Y8, Y2, Y2 - VPSHUFB Y2, Y5, Y9 - VPTEST Y9, Y3 - JNE done - VPCMPEQB Y8, Y0, Y3 - VPADDB Y3, Y2, Y2 - VPSHUFB Y2, Y6, Y2 - VPADDB Y0, Y2, Y0 - VPMADDUBSW b64_dec_madd1<>+0(SB), Y0, Y0 - VPMADDWD b64_dec_madd2<>+0(SB), Y0, Y0 - VEXTRACTI128 $0x01, Y0, X1 - VPSHUFB b64_dec_shuf_lo<>+0(SB), X1, X1 - VPSHUFB b64_dec_shuf<>+0(SB), Y0, Y0 - VPBLENDD $0x08, Y1, Y0, Y1 - VPBLENDD $0xc0, Y7, Y1, Y1 - VMOVDQU Y1, (AX)(CX*1) - ADDQ $0x18, CX - ADDQ $0x20, BX - SUBQ $0x20, DI - CMPQ DI, $0x2d - JB done - JMP loop - -done: - MOVQ CX, ret+56(FP) - MOVQ BX, ret1+64(FP) - VZEROUPPER - RET - -// func decodeAVX2URI(dst []byte, src []byte, lut *int8) (int, int) -// Requires: AVX, AVX2, SSE4.1 -TEXT ·decodeAVX2URI(SB), NOSPLIT, $0-72 - MOVB $0x2f, AL - PINSRB $0x00, AX, X0 - VPBROADCASTB X0, Y0 - MOVB $0x5f, AL - PINSRB $0x00, AX, X1 - VPBROADCASTB X1, Y1 - MOVQ dst_base+0(FP), AX - MOVQ src_base+24(FP), DX - MOVQ lut+48(FP), SI - MOVQ src_len+32(FP), DI - MOVB $0x2f, CL - PINSRB $0x00, CX, X10 - VPBROADCASTB X10, Y10 - XORQ CX, CX - XORQ BX, BX - VPXOR Y9, Y9, Y9 - VPERMQ $0x44, (SI), Y8 - VPERMQ $0x44, 16(SI), Y6 - VMOVDQA b64_dec_lut_hi<>+0(SB), Y7 - -loop: - VMOVDQU (DX)(BX*1), Y2 - VPCMPEQB Y2, Y1, Y4 - VPBLENDVB Y4, Y0, Y2, Y2 - VPSRLD $0x04, Y2, Y4 - VPAND Y10, Y2, Y5 - VPSHUFB Y5, Y6, Y5 - VPAND Y10, Y4, Y4 - VPSHUFB Y4, Y7, Y11 - VPTEST Y11, Y5 - JNE done - VPCMPEQB Y10, Y2, Y5 - VPADDB Y5, Y4, Y4 - VPSHUFB Y4, Y8, Y4 - VPADDB Y2, Y4, Y2 - VPMADDUBSW b64_dec_madd1<>+0(SB), Y2, Y2 - VPMADDWD b64_dec_madd2<>+0(SB), Y2, Y2 - VEXTRACTI128 $0x01, Y2, X3 - VPSHUFB b64_dec_shuf_lo<>+0(SB), X3, X3 - VPSHUFB b64_dec_shuf<>+0(SB), Y2, Y2 - VPBLENDD $0x08, Y3, Y2, Y3 - VPBLENDD $0xc0, Y9, Y3, Y3 - VMOVDQU Y3, (AX)(CX*1) - ADDQ $0x18, CX - ADDQ $0x20, BX - SUBQ $0x20, DI - CMPQ DI, $0x2d - JB done - JMP loop - -done: - MOVQ CX, ret+56(FP) - MOVQ BX, ret1+64(FP) - VZEROUPPER - RET diff --git a/go/sdk/vendor/github.com/segmentio/asm/base64/encode_amd64.go b/go/sdk/vendor/github.com/segmentio/asm/base64/encode_amd64.go deleted file mode 100644 index c38060f..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/base64/encode_amd64.go +++ /dev/null @@ -1,8 +0,0 @@ -// Code generated by command: go run encode_asm.go -pkg base64 -out ../base64/encode_amd64.s -stubs ../base64/encode_amd64.go. DO NOT EDIT. - -//go:build !purego -// +build !purego - -package base64 - -func encodeAVX2(dst []byte, src []byte, lut *int8) (int, int) diff --git a/go/sdk/vendor/github.com/segmentio/asm/base64/encode_amd64.s b/go/sdk/vendor/github.com/segmentio/asm/base64/encode_amd64.s deleted file mode 100644 index 2edd27a..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/base64/encode_amd64.s +++ /dev/null @@ -1,88 +0,0 @@ -// Code generated by command: go run encode_asm.go -pkg base64 -out ../base64/encode_amd64.s -stubs ../base64/encode_amd64.go. DO NOT EDIT. - -//go:build !purego -// +build !purego - -#include "textflag.h" - -// func encodeAVX2(dst []byte, src []byte, lut *int8) (int, int) -// Requires: AVX, AVX2, SSE4.1 -TEXT ·encodeAVX2(SB), NOSPLIT, $0-72 - MOVQ dst_base+0(FP), AX - MOVQ src_base+24(FP), DX - MOVQ lut+48(FP), SI - MOVQ src_len+32(FP), DI - MOVB $0x33, CL - PINSRB $0x00, CX, X4 - VPBROADCASTB X4, Y4 - MOVB $0x19, CL - PINSRB $0x00, CX, X5 - VPBROADCASTB X5, Y5 - XORQ CX, CX - XORQ BX, BX - - // Load the 16-byte LUT into both lanes of the register - VPERMQ $0x44, (SI), Y3 - - // Load the first block using a mask to avoid potential fault - VMOVDQU b64_enc_load<>+0(SB), Y0 - VPMASKMOVD -4(DX)(BX*1), Y0, Y0 - -loop: - VPSHUFB b64_enc_shuf<>+0(SB), Y0, Y0 - VPAND b64_enc_mask1<>+0(SB), Y0, Y1 - VPSLLW $0x08, Y1, Y2 - VPSLLW $0x04, Y1, Y1 - VPBLENDW $0xaa, Y2, Y1, Y2 - VPAND b64_enc_mask2<>+0(SB), Y0, Y1 - VPMULHUW b64_enc_mult<>+0(SB), Y1, Y0 - VPOR Y0, Y2, Y0 - VPSUBUSB Y4, Y0, Y1 - VPCMPGTB Y5, Y0, Y2 - VPSUBB Y2, Y1, Y1 - VPSHUFB Y1, Y3, Y1 - VPADDB Y0, Y1, Y0 - VMOVDQU Y0, (AX)(CX*1) - ADDQ $0x20, CX - ADDQ $0x18, BX - SUBQ $0x18, DI - CMPQ DI, $0x20 - JB done - VMOVDQU -4(DX)(BX*1), Y0 - JMP loop - -done: - MOVQ CX, ret+56(FP) - MOVQ BX, ret1+64(FP) - VZEROUPPER - RET - -DATA b64_enc_load<>+0(SB)/8, $0x8000000000000000 -DATA b64_enc_load<>+8(SB)/8, $0x8000000080000000 -DATA b64_enc_load<>+16(SB)/8, $0x8000000080000000 -DATA b64_enc_load<>+24(SB)/8, $0x8000000080000000 -GLOBL b64_enc_load<>(SB), RODATA|NOPTR, $32 - -DATA b64_enc_shuf<>+0(SB)/8, $0x0809070805060405 -DATA b64_enc_shuf<>+8(SB)/8, $0x0e0f0d0e0b0c0a0b -DATA b64_enc_shuf<>+16(SB)/8, $0x0405030401020001 -DATA b64_enc_shuf<>+24(SB)/8, $0x0a0b090a07080607 -GLOBL b64_enc_shuf<>(SB), RODATA|NOPTR, $32 - -DATA b64_enc_mask1<>+0(SB)/8, $0x003f03f0003f03f0 -DATA b64_enc_mask1<>+8(SB)/8, $0x003f03f0003f03f0 -DATA b64_enc_mask1<>+16(SB)/8, $0x003f03f0003f03f0 -DATA b64_enc_mask1<>+24(SB)/8, $0x003f03f0003f03f0 -GLOBL b64_enc_mask1<>(SB), RODATA|NOPTR, $32 - -DATA b64_enc_mask2<>+0(SB)/8, $0x0fc0fc000fc0fc00 -DATA b64_enc_mask2<>+8(SB)/8, $0x0fc0fc000fc0fc00 -DATA b64_enc_mask2<>+16(SB)/8, $0x0fc0fc000fc0fc00 -DATA b64_enc_mask2<>+24(SB)/8, $0x0fc0fc000fc0fc00 -GLOBL b64_enc_mask2<>(SB), RODATA|NOPTR, $32 - -DATA b64_enc_mult<>+0(SB)/8, $0x0400004004000040 -DATA b64_enc_mult<>+8(SB)/8, $0x0400004004000040 -DATA b64_enc_mult<>+16(SB)/8, $0x0400004004000040 -DATA b64_enc_mult<>+24(SB)/8, $0x0400004004000040 -GLOBL b64_enc_mult<>(SB), RODATA|NOPTR, $32 diff --git a/go/sdk/vendor/github.com/segmentio/asm/cpu/arm/arm.go b/go/sdk/vendor/github.com/segmentio/asm/cpu/arm/arm.go deleted file mode 100644 index 47c695a..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/cpu/arm/arm.go +++ /dev/null @@ -1,80 +0,0 @@ -package arm - -import ( - "github.com/segmentio/asm/cpu/cpuid" - . "golang.org/x/sys/cpu" -) - -type CPU cpuid.CPU - -func (cpu CPU) Has(feature Feature) bool { - return cpuid.CPU(cpu).Has(cpuid.Feature(feature)) -} - -func (cpu *CPU) set(feature Feature, enable bool) { - (*cpuid.CPU)(cpu).Set(cpuid.Feature(feature), enable) -} - -type Feature cpuid.Feature - -const ( - SWP Feature = 1 << iota // SWP instruction support - HALF // Half-word load and store support - THUMB // ARM Thumb instruction set - BIT26 // Address space limited to 26-bits - FASTMUL // 32-bit operand, 64-bit result multiplication support - FPA // Floating point arithmetic support - VFP // Vector floating point support - EDSP // DSP Extensions support - JAVA // Java instruction set - IWMMXT // Intel Wireless MMX technology support - CRUNCH // MaverickCrunch context switching and handling - THUMBEE // Thumb EE instruction set - NEON // NEON instruction set - VFPv3 // Vector floating point version 3 support - VFPv3D16 // Vector floating point version 3 D8-D15 - TLS // Thread local storage support - VFPv4 // Vector floating point version 4 support - IDIVA // Integer divide instruction support in ARM mode - IDIVT // Integer divide instruction support in Thumb mode - VFPD32 // Vector floating point version 3 D15-D31 - LPAE // Large Physical Address Extensions - EVTSTRM // Event stream support - AES // AES hardware implementation - PMULL // Polynomial multiplication instruction set - SHA1 // SHA1 hardware implementation - SHA2 // SHA2 hardware implementation - CRC32 // CRC32 hardware implementation -) - -func ABI() CPU { - cpu := CPU(0) - cpu.set(SWP, ARM.HasSWP) - cpu.set(HALF, ARM.HasHALF) - cpu.set(THUMB, ARM.HasTHUMB) - cpu.set(BIT26, ARM.Has26BIT) - cpu.set(FASTMUL, ARM.HasFASTMUL) - cpu.set(FPA, ARM.HasFPA) - cpu.set(VFP, ARM.HasVFP) - cpu.set(EDSP, ARM.HasEDSP) - cpu.set(JAVA, ARM.HasJAVA) - cpu.set(IWMMXT, ARM.HasIWMMXT) - cpu.set(CRUNCH, ARM.HasCRUNCH) - cpu.set(THUMBEE, ARM.HasTHUMBEE) - cpu.set(NEON, ARM.HasNEON) - cpu.set(VFPv3, ARM.HasVFPv3) - cpu.set(VFPv3D16, ARM.HasVFPv3D16) - cpu.set(TLS, ARM.HasTLS) - cpu.set(VFPv4, ARM.HasVFPv4) - cpu.set(IDIVA, ARM.HasIDIVA) - cpu.set(IDIVT, ARM.HasIDIVT) - cpu.set(VFPD32, ARM.HasVFPD32) - cpu.set(LPAE, ARM.HasLPAE) - cpu.set(EVTSTRM, ARM.HasEVTSTRM) - cpu.set(AES, ARM.HasAES) - cpu.set(PMULL, ARM.HasPMULL) - cpu.set(SHA1, ARM.HasSHA1) - cpu.set(SHA2, ARM.HasSHA2) - cpu.set(CRC32, ARM.HasCRC32) - return cpu -} diff --git a/go/sdk/vendor/github.com/segmentio/asm/cpu/arm64/arm64.go b/go/sdk/vendor/github.com/segmentio/asm/cpu/arm64/arm64.go deleted file mode 100644 index 0c5134c..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/cpu/arm64/arm64.go +++ /dev/null @@ -1,74 +0,0 @@ -package arm64 - -import ( - "github.com/segmentio/asm/cpu/cpuid" - . "golang.org/x/sys/cpu" -) - -type CPU cpuid.CPU - -func (cpu CPU) Has(feature Feature) bool { - return cpuid.CPU(cpu).Has(cpuid.Feature(feature)) -} - -func (cpu *CPU) set(feature Feature, enable bool) { - (*cpuid.CPU)(cpu).Set(cpuid.Feature(feature), enable) -} - -type Feature cpuid.Feature - -const ( - FP Feature = 1 << iota // Floating-point instruction set (always available) - ASIMD // Advanced SIMD (always available) - EVTSTRM // Event stream support - AES // AES hardware implementation - PMULL // Polynomial multiplication instruction set - SHA1 // SHA1 hardware implementation - SHA2 // SHA2 hardware implementation - CRC32 // CRC32 hardware implementation - ATOMICS // Atomic memory operation instruction set - FPHP // Half precision floating-point instruction set - ASIMDHP // Advanced SIMD half precision instruction set - CPUID // CPUID identification scheme registers - ASIMDRDM // Rounding double multiply add/subtract instruction set - JSCVT // Javascript conversion from floating-point to integer - FCMA // Floating-point multiplication and addition of complex numbers - LRCPC // Release Consistent processor consistent support - DCPOP // Persistent memory support - SHA3 // SHA3 hardware implementation - SM3 // SM3 hardware implementation - SM4 // SM4 hardware implementation - ASIMDDP // Advanced SIMD double precision instruction set - SHA512 // SHA512 hardware implementation - SVE // Scalable Vector Extensions - ASIMDFHM // Advanced SIMD multiplication FP16 to FP32 -) - -func ABI() CPU { - cpu := CPU(0) - cpu.set(FP, ARM64.HasFP) - cpu.set(ASIMD, ARM64.HasASIMD) - cpu.set(EVTSTRM, ARM64.HasEVTSTRM) - cpu.set(AES, ARM64.HasAES) - cpu.set(PMULL, ARM64.HasPMULL) - cpu.set(SHA1, ARM64.HasSHA1) - cpu.set(SHA2, ARM64.HasSHA2) - cpu.set(CRC32, ARM64.HasCRC32) - cpu.set(ATOMICS, ARM64.HasATOMICS) - cpu.set(FPHP, ARM64.HasFPHP) - cpu.set(ASIMDHP, ARM64.HasASIMDHP) - cpu.set(CPUID, ARM64.HasCPUID) - cpu.set(ASIMDRDM, ARM64.HasASIMDRDM) - cpu.set(JSCVT, ARM64.HasJSCVT) - cpu.set(FCMA, ARM64.HasFCMA) - cpu.set(LRCPC, ARM64.HasLRCPC) - cpu.set(DCPOP, ARM64.HasDCPOP) - cpu.set(SHA3, ARM64.HasSHA3) - cpu.set(SM3, ARM64.HasSM3) - cpu.set(SM4, ARM64.HasSM4) - cpu.set(ASIMDDP, ARM64.HasASIMDDP) - cpu.set(SHA512, ARM64.HasSHA512) - cpu.set(SVE, ARM64.HasSVE) - cpu.set(ASIMDFHM, ARM64.HasASIMDFHM) - return cpu -} diff --git a/go/sdk/vendor/github.com/segmentio/asm/cpu/cpu.go b/go/sdk/vendor/github.com/segmentio/asm/cpu/cpu.go deleted file mode 100644 index 6ddf497..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/cpu/cpu.go +++ /dev/null @@ -1,22 +0,0 @@ -// Pakage cpu provides APIs to detect CPU features available at runtime. -package cpu - -import ( - "github.com/segmentio/asm/cpu/arm" - "github.com/segmentio/asm/cpu/arm64" - "github.com/segmentio/asm/cpu/x86" -) - -var ( - // X86 is the bitset representing the set of the x86 instruction sets are - // supported by the CPU. - X86 = x86.ABI() - - // ARM is the bitset representing which parts of the arm instruction sets - // are supported by the CPU. - ARM = arm.ABI() - - // ARM64 is the bitset representing which parts of the arm64 instruction - // sets are supported by the CPU. - ARM64 = arm64.ABI() -) diff --git a/go/sdk/vendor/github.com/segmentio/asm/cpu/cpuid/cpuid.go b/go/sdk/vendor/github.com/segmentio/asm/cpu/cpuid/cpuid.go deleted file mode 100644 index 0949d3d..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/cpu/cpuid/cpuid.go +++ /dev/null @@ -1,32 +0,0 @@ -// Package cpuid provides generic types used to represent CPU features supported -// by the architecture. -package cpuid - -// CPU is a bitset of feature flags representing the capabilities of various CPU -// architeectures that this package provides optimized assembly routines for. -// -// The intent is to provide a stable ABI between the Go code that generate the -// assembly, and the program that uses the library functions. -type CPU uint64 - -// Feature represents a single CPU feature. -type Feature uint64 - -const ( - // None is a Feature value that has no CPU features enabled. - None Feature = 0 - // All is a Feature value that has all CPU features enabled. - All Feature = 0xFFFFFFFFFFFFFFFF -) - -func (cpu CPU) Has(feature Feature) bool { - return (Feature(cpu) & feature) == feature -} - -func (cpu *CPU) Set(feature Feature, enabled bool) { - if enabled { - *cpu |= CPU(feature) - } else { - *cpu &= ^CPU(feature) - } -} diff --git a/go/sdk/vendor/github.com/segmentio/asm/cpu/x86/x86.go b/go/sdk/vendor/github.com/segmentio/asm/cpu/x86/x86.go deleted file mode 100644 index 9e93537..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/cpu/x86/x86.go +++ /dev/null @@ -1,76 +0,0 @@ -package x86 - -import ( - "github.com/segmentio/asm/cpu/cpuid" - . "golang.org/x/sys/cpu" -) - -type CPU cpuid.CPU - -func (cpu CPU) Has(feature Feature) bool { - return cpuid.CPU(cpu).Has(cpuid.Feature(feature)) -} - -func (cpu *CPU) set(feature Feature, enable bool) { - (*cpuid.CPU)(cpu).Set(cpuid.Feature(feature), enable) -} - -type Feature cpuid.Feature - -const ( - SSE Feature = 1 << iota // SSE functions - SSE2 // P4 SSE functions - SSE3 // Prescott SSE3 functions - SSE41 // Penryn SSE4.1 functions - SSE42 // Nehalem SSE4.2 functions - SSE4A // AMD Barcelona microarchitecture SSE4a instructions - SSSE3 // Conroe SSSE3 functions - AVX // AVX functions - AVX2 // AVX2 functions - AVX512BF16 // AVX-512 BFLOAT16 Instructions - AVX512BITALG // AVX-512 Bit Algorithms - AVX512BW // AVX-512 Byte and Word Instructions - AVX512CD // AVX-512 Conflict Detection Instructions - AVX512DQ // AVX-512 Doubleword and Quadword Instructions - AVX512ER // AVX-512 Exponential and Reciprocal Instructions - AVX512F // AVX-512 Foundation - AVX512IFMA // AVX-512 Integer Fused Multiply-Add Instructions - AVX512PF // AVX-512 Prefetch Instructions - AVX512VBMI // AVX-512 Vector Bit Manipulation Instructions - AVX512VBMI2 // AVX-512 Vector Bit Manipulation Instructions, Version 2 - AVX512VL // AVX-512 Vector Length Extensions - AVX512VNNI // AVX-512 Vector Neural Network Instructions - AVX512VP2INTERSECT // AVX-512 Intersect for D/Q - AVX512VPOPCNTDQ // AVX-512 Vector Population Count Doubleword and Quadword - CMOV // Conditional move -) - -func ABI() CPU { - cpu := CPU(0) - cpu.set(SSE, true) // TODO: golang.org/x/sys/cpu assumes all CPUs have SEE? - cpu.set(SSE2, X86.HasSSE2) - cpu.set(SSE3, X86.HasSSE3) - cpu.set(SSE41, X86.HasSSE41) - cpu.set(SSE42, X86.HasSSE42) - cpu.set(SSE4A, false) // TODO: add upstream support in golang.org/x/sys/cpu? - cpu.set(SSSE3, X86.HasSSSE3) - cpu.set(AVX, X86.HasAVX) - cpu.set(AVX2, X86.HasAVX2) - cpu.set(AVX512BF16, X86.HasAVX512BF16) - cpu.set(AVX512BITALG, X86.HasAVX512BITALG) - cpu.set(AVX512BW, X86.HasAVX512BW) - cpu.set(AVX512CD, X86.HasAVX512CD) - cpu.set(AVX512DQ, X86.HasAVX512DQ) - cpu.set(AVX512ER, X86.HasAVX512ER) - cpu.set(AVX512F, X86.HasAVX512F) - cpu.set(AVX512IFMA, X86.HasAVX512IFMA) - cpu.set(AVX512PF, X86.HasAVX512PF) - cpu.set(AVX512VBMI, X86.HasAVX512VBMI) - cpu.set(AVX512VBMI2, X86.HasAVX512VBMI2) - cpu.set(AVX512VL, X86.HasAVX512VL) - cpu.set(AVX512VNNI, X86.HasAVX512VNNI) - cpu.set(AVX512VP2INTERSECT, false) // TODO: add upstream support in golang.org/x/sys/cpu? - cpu.set(AVX512VPOPCNTDQ, X86.HasAVX512VPOPCNTDQ) - cpu.set(CMOV, true) // TODO: golang.org/x/sys/cpu assumes all CPUs have CMOV? - return cpu -} diff --git a/go/sdk/vendor/github.com/segmentio/asm/internal/unsafebytes/unsafebytes.go b/go/sdk/vendor/github.com/segmentio/asm/internal/unsafebytes/unsafebytes.go deleted file mode 100644 index 913c9cc..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/internal/unsafebytes/unsafebytes.go +++ /dev/null @@ -1,20 +0,0 @@ -package unsafebytes - -import "unsafe" - -func Pointer(b []byte) *byte { - return *(**byte)(unsafe.Pointer(&b)) -} - -func String(b []byte) string { - return *(*string)(unsafe.Pointer(&b)) -} - -func BytesOf(s string) []byte { - return *(*[]byte)(unsafe.Pointer(&sliceHeader{str: s, cap: len(s)})) -} - -type sliceHeader struct { - str string - cap int -} diff --git a/go/sdk/vendor/github.com/segmentio/asm/keyset/keyset.go b/go/sdk/vendor/github.com/segmentio/asm/keyset/keyset.go deleted file mode 100644 index 1943c5f..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/keyset/keyset.go +++ /dev/null @@ -1,40 +0,0 @@ -package keyset - -import ( - "bytes" - - "github.com/segmentio/asm/cpu" - "github.com/segmentio/asm/cpu/arm64" - "github.com/segmentio/asm/cpu/x86" -) - -// New prepares a set of keys for use with Lookup. -// -// An optimized routine is used if the processor supports AVX instructions and -// the maximum length of any of the keys is less than or equal to 16. If New -// returns nil, this indicates that an optimized routine is not available, and -// the caller should use a fallback. -func New(keys [][]byte) []byte { - maxWidth, hasNullByte := checkKeys(keys) - if hasNullByte || maxWidth > 16 || !(cpu.X86.Has(x86.AVX) || cpu.ARM64.Has(arm64.ASIMD)) { - return nil - } - - set := make([]byte, len(keys)*16) - for i, k := range keys { - copy(set[i*16:], k) - } - return set -} - -func checkKeys(keys [][]byte) (maxWidth int, hasNullByte bool) { - for _, k := range keys { - if len(k) > maxWidth { - maxWidth = len(k) - } - if bytes.IndexByte(k, 0) >= 0 { - hasNullByte = true - } - } - return -} diff --git a/go/sdk/vendor/github.com/segmentio/asm/keyset/keyset_amd64.go b/go/sdk/vendor/github.com/segmentio/asm/keyset/keyset_amd64.go deleted file mode 100644 index 9554ee6..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/keyset/keyset_amd64.go +++ /dev/null @@ -1,10 +0,0 @@ -// Code generated by command: go run keyset_asm.go -pkg keyset -out ../keyset/keyset_amd64.s -stubs ../keyset/keyset_amd64.go. DO NOT EDIT. - -//go:build !purego -// +build !purego - -package keyset - -// Lookup searches for a key in a set of keys, returning its index if -// found. If the key cannot be found, the number of keys is returned. -func Lookup(keyset []byte, key []byte) int diff --git a/go/sdk/vendor/github.com/segmentio/asm/keyset/keyset_amd64.s b/go/sdk/vendor/github.com/segmentio/asm/keyset/keyset_amd64.s deleted file mode 100644 index e27d2c4..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/keyset/keyset_amd64.s +++ /dev/null @@ -1,108 +0,0 @@ -// Code generated by command: go run keyset_asm.go -pkg keyset -out ../keyset/keyset_amd64.s -stubs ../keyset/keyset_amd64.go. DO NOT EDIT. - -//go:build !purego -// +build !purego - -#include "textflag.h" - -// func Lookup(keyset []byte, key []byte) int -// Requires: AVX -TEXT ·Lookup(SB), NOSPLIT, $0-56 - MOVQ keyset_base+0(FP), AX - MOVQ keyset_len+8(FP), CX - SHRQ $0x04, CX - MOVQ key_base+24(FP), DX - MOVQ key_len+32(FP), BX - MOVQ key_cap+40(FP), SI - CMPQ BX, $0x10 - JA not_found - CMPQ SI, $0x10 - JB safe_load - -load: - VMOVUPS (DX), X0 - -prepare: - VPXOR X2, X2, X2 - VPCMPEQB X1, X1, X1 - LEAQ blend_masks<>+16(SB), DX - SUBQ BX, DX - VMOVUPS (DX), X3 - VPBLENDVB X3, X0, X2, X0 - XORQ DX, DX - MOVQ CX, BX - SHRQ $0x02, BX - SHLQ $0x02, BX - -bigloop: - CMPQ DX, BX - JE loop - VPCMPEQB (AX), X0, X8 - VPTEST X1, X8 - JCS done - VPCMPEQB 16(AX), X0, X9 - VPTEST X1, X9 - JCS found1 - VPCMPEQB 32(AX), X0, X10 - VPTEST X1, X10 - JCS found2 - VPCMPEQB 48(AX), X0, X11 - VPTEST X1, X11 - JCS found3 - ADDQ $0x04, DX - ADDQ $0x40, AX - JMP bigloop - -loop: - CMPQ DX, CX - JE done - VPCMPEQB (AX), X0, X2 - VPTEST X1, X2 - JCS done - INCQ DX - ADDQ $0x10, AX - JMP loop - JMP done - -found3: - INCQ DX - -found2: - INCQ DX - -found1: - INCQ DX - -done: - MOVQ DX, ret+48(FP) - RET - -not_found: - MOVQ CX, ret+48(FP) - RET - -safe_load: - MOVQ DX, SI - ANDQ $0x00000fff, SI - CMPQ SI, $0x00000ff0 - JBE load - MOVQ $0xfffffffffffffff0, SI - ADDQ BX, SI - VMOVUPS (DX)(SI*1), X0 - LEAQ shuffle_masks<>+16(SB), DX - SUBQ BX, DX - VMOVUPS (DX), X1 - VPSHUFB X1, X0, X0 - JMP prepare - -DATA blend_masks<>+0(SB)/8, $0xffffffffffffffff -DATA blend_masks<>+8(SB)/8, $0xffffffffffffffff -DATA blend_masks<>+16(SB)/8, $0x0000000000000000 -DATA blend_masks<>+24(SB)/8, $0x0000000000000000 -GLOBL blend_masks<>(SB), RODATA|NOPTR, $32 - -DATA shuffle_masks<>+0(SB)/8, $0x0706050403020100 -DATA shuffle_masks<>+8(SB)/8, $0x0f0e0d0c0b0a0908 -DATA shuffle_masks<>+16(SB)/8, $0x0706050403020100 -DATA shuffle_masks<>+24(SB)/8, $0x0f0e0d0c0b0a0908 -GLOBL shuffle_masks<>(SB), RODATA|NOPTR, $32 diff --git a/go/sdk/vendor/github.com/segmentio/asm/keyset/keyset_arm64.go b/go/sdk/vendor/github.com/segmentio/asm/keyset/keyset_arm64.go deleted file mode 100644 index feafabe..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/keyset/keyset_arm64.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build !purego -// +build !purego - -package keyset - -// Lookup searches for a key in a set of keys, returning its index if -// found. If the key cannot be found, the number of keys is returned. -func Lookup(keyset []byte, key []byte) int diff --git a/go/sdk/vendor/github.com/segmentio/asm/keyset/keyset_arm64.s b/go/sdk/vendor/github.com/segmentio/asm/keyset/keyset_arm64.s deleted file mode 100644 index 20acb99..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/keyset/keyset_arm64.s +++ /dev/null @@ -1,143 +0,0 @@ -//go:build !purego -// +build !purego - -#include "textflag.h" - -// func Lookup(keyset []byte, key []byte) int -TEXT ·Lookup(SB), NOSPLIT, $0-56 - MOVD keyset+0(FP), R0 - MOVD keyset_len+8(FP), R1 - MOVD key+24(FP), R2 - MOVD key_len+32(FP), R3 - MOVD key_cap+40(FP), R4 - - // None of the keys in the set are greater than 16 bytes, so if the input - // key is we can jump straight to not found. - CMP $16, R3 - BHI notfound - - // We'll be moving the keyset pointer (R0) forward as we compare keys, so - // make a copy of the starting point (R6). Also add the byte length (R1) to - // obtain a pointer to the end of the keyset (R5). - MOVD R0, R6 - ADD R0, R1, R5 - - // Prepare a 64-bit mask of all ones. - MOVD $-1, R7 - - // Prepare a vector of all zeroes. - VMOV ZR, V1.B16 - - // Check that it's safe to load 16 bytes of input. If cap(input)<16, jump - // to a check that determines whether a tail load is necessary (to avoid a - // page fault). - CMP $16, R4 - BLO safeload - -load: - // Load the input key (V0) and pad with zero bytes (V1). To blend the two - // vectors, we load a mask for the particular key length and then use TBL - // to select bytes from either V0 or V1. - VLD1 (R2), [V0.B16] - MOVD $blend_masks<>(SB), R10 - ADD R3<<4, R10, R10 - VLD1 (R10), [V2.B16] - VTBL V2.B16, [V0.B16, V1.B16], V3.B16 - -loop: - // Loop through each 16 byte key in the keyset. - CMP R0, R5 - BEQ notfound - - // Load and compare the next key. - VLD1.P 16(R0), [V4.B16] - VCMEQ V3.B16, V4.B16, V5.B16 - VMOV V5.D[0], R8 - VMOV V5.D[1], R9 - AND R8, R9, R9 - - // If the masks match, we found the key. - CMP R9, R7 - BEQ found - JMP loop - -found: - // If the key was found, take the position in the keyset and convert it - // to an index. The keyset pointer (R0) will be 1 key past the match, so - // subtract the starting pointer (R6), divide by 16 to convert from byte - // length to an index, and then subtract one. - SUB R6, R0, R0 - ADD R0>>4, ZR, R0 - SUB $1, R0, R0 - MOVD R0, ret+48(FP) - RET - -notfound: - // Return the number of keys in the keyset, which is the byte length (R1) - // divided by 16. - ADD R1>>4, ZR, R1 - MOVD R1, ret+48(FP) - RET - -safeload: - // Check if the input crosses a page boundary. If not, jump back. - AND $4095, R2, R12 - CMP $4080, R12 - BLS load - - // If it does cross a page boundary, we must assume that loading 16 bytes - // will cause a fault. Instead, we load the 16 bytes up to and including the - // key and then shuffle the key forward in the register. We can shuffle and - // pad with zeroes at the same time to avoid having to also blend (as load - // does). - MOVD $16, R12 - SUB R3, R12, R12 - SUB R12, R2, R2 - VLD1 (R2), [V0.B16] - MOVD $shuffle_masks<>(SB), R10 - ADD R12, R10, R10 - VLD1 (R10), [V2.B16] - VTBL V2.B16, [V0.B16, V1.B16], V3.B16 - JMP loop - -DATA blend_masks<>+0(SB)/8, $0x1010101010101010 -DATA blend_masks<>+8(SB)/8, $0x1010101010101010 -DATA blend_masks<>+16(SB)/8, $0x1010101010101000 -DATA blend_masks<>+24(SB)/8, $0x1010101010101010 -DATA blend_masks<>+32(SB)/8, $0x1010101010100100 -DATA blend_masks<>+40(SB)/8, $0x1010101010101010 -DATA blend_masks<>+48(SB)/8, $0x1010101010020100 -DATA blend_masks<>+56(SB)/8, $0x1010101010101010 -DATA blend_masks<>+64(SB)/8, $0x1010101003020100 -DATA blend_masks<>+72(SB)/8, $0x1010101010101010 -DATA blend_masks<>+80(SB)/8, $0x1010100403020100 -DATA blend_masks<>+88(SB)/8, $0x1010101010101010 -DATA blend_masks<>+96(SB)/8, $0x1010050403020100 -DATA blend_masks<>+104(SB)/8, $0x1010101010101010 -DATA blend_masks<>+112(SB)/8, $0x1006050403020100 -DATA blend_masks<>+120(SB)/8, $0x1010101010101010 -DATA blend_masks<>+128(SB)/8, $0x0706050403020100 -DATA blend_masks<>+136(SB)/8, $0x1010101010101010 -DATA blend_masks<>+144(SB)/8, $0x0706050403020100 -DATA blend_masks<>+152(SB)/8, $0x1010101010101008 -DATA blend_masks<>+160(SB)/8, $0x0706050403020100 -DATA blend_masks<>+168(SB)/8, $0x1010101010100908 -DATA blend_masks<>+176(SB)/8, $0x0706050403020100 -DATA blend_masks<>+184(SB)/8, $0x10101010100A0908 -DATA blend_masks<>+192(SB)/8, $0x0706050403020100 -DATA blend_masks<>+200(SB)/8, $0x101010100B0A0908 -DATA blend_masks<>+208(SB)/8, $0x0706050403020100 -DATA blend_masks<>+216(SB)/8, $0x1010100C0B0A0908 -DATA blend_masks<>+224(SB)/8, $0x0706050403020100 -DATA blend_masks<>+232(SB)/8, $0x10100D0C0B0A0908 -DATA blend_masks<>+240(SB)/8, $0x0706050403020100 -DATA blend_masks<>+248(SB)/8, $0x100E0D0C0B0A0908 -DATA blend_masks<>+256(SB)/8, $0x0706050403020100 -DATA blend_masks<>+264(SB)/8, $0x0F0E0D0C0B0A0908 -GLOBL blend_masks<>(SB), RODATA|NOPTR, $272 - -DATA shuffle_masks<>+0(SB)/8, $0x0706050403020100 -DATA shuffle_masks<>+8(SB)/8, $0x0F0E0D0C0B0A0908 -DATA shuffle_masks<>+16(SB)/8, $0x1010101010101010 -DATA shuffle_masks<>+24(SB)/8, $0x1010101010101010 -GLOBL shuffle_masks<>(SB), RODATA|NOPTR, $32 diff --git a/go/sdk/vendor/github.com/segmentio/asm/keyset/keyset_default.go b/go/sdk/vendor/github.com/segmentio/asm/keyset/keyset_default.go deleted file mode 100644 index 1fa7d3f..0000000 --- a/go/sdk/vendor/github.com/segmentio/asm/keyset/keyset_default.go +++ /dev/null @@ -1,19 +0,0 @@ -//go:build purego || !(amd64 || arm64) -// +build purego !amd64,!arm64 - -package keyset - -func Lookup(keyset []byte, key []byte) int { - if len(key) > 16 { - return len(keyset) / 16 - } - var padded [16]byte - copy(padded[:], key) - - for i := 0; i < len(keyset); i += 16 { - if string(padded[:]) == string(keyset[i:i+16]) { - return i / 16 - } - } - return len(keyset) / 16 -} diff --git a/go/sdk/vendor/github.com/segmentio/encoding/LICENSE b/go/sdk/vendor/github.com/segmentio/encoding/LICENSE deleted file mode 100644 index 1fbffdf..0000000 --- a/go/sdk/vendor/github.com/segmentio/encoding/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019 Segment.io, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/go/sdk/vendor/github.com/segmentio/encoding/ascii/equal_fold.go b/go/sdk/vendor/github.com/segmentio/encoding/ascii/equal_fold.go deleted file mode 100644 index 4207f17..0000000 --- a/go/sdk/vendor/github.com/segmentio/encoding/ascii/equal_fold.go +++ /dev/null @@ -1,40 +0,0 @@ -//go:generate go run equal_fold_asm.go -out equal_fold_amd64.s -stubs equal_fold_amd64.go -package ascii - -import ( - "github.com/segmentio/asm/ascii" -) - -// EqualFold is a version of bytes.EqualFold designed to work on ASCII input -// instead of UTF-8. -// -// When the program has guarantees that the input is composed of ASCII -// characters only, it allows for greater optimizations. -func EqualFold(a, b []byte) bool { - return ascii.EqualFold(a, b) -} - -func HasPrefixFold(s, prefix []byte) bool { - return ascii.HasPrefixFold(s, prefix) -} - -func HasSuffixFold(s, suffix []byte) bool { - return ascii.HasSuffixFold(s, suffix) -} - -// EqualFoldString is a version of strings.EqualFold designed to work on ASCII -// input instead of UTF-8. -// -// When the program has guarantees that the input is composed of ASCII -// characters only, it allows for greater optimizations. -func EqualFoldString(a, b string) bool { - return ascii.EqualFoldString(a, b) -} - -func HasPrefixFoldString(s, prefix string) bool { - return ascii.HasPrefixFoldString(s, prefix) -} - -func HasSuffixFoldString(s, suffix string) bool { - return ascii.HasSuffixFoldString(s, suffix) -} diff --git a/go/sdk/vendor/github.com/segmentio/encoding/ascii/valid.go b/go/sdk/vendor/github.com/segmentio/encoding/ascii/valid.go deleted file mode 100644 index 68b7c6c..0000000 --- a/go/sdk/vendor/github.com/segmentio/encoding/ascii/valid.go +++ /dev/null @@ -1,26 +0,0 @@ -//go:generate go run valid_asm.go -out valid_amd64.s -stubs valid_amd64.go -package ascii - -import ( - "github.com/segmentio/asm/ascii" -) - -// Valid returns true if b contains only ASCII characters. -func Valid(b []byte) bool { - return ascii.Valid(b) -} - -// ValidBytes returns true if b is an ASCII character. -func ValidByte(b byte) bool { - return ascii.ValidByte(b) -} - -// ValidBytes returns true if b is an ASCII character. -func ValidRune(r rune) bool { - return ascii.ValidRune(r) -} - -// ValidString returns true if s contains only ASCII characters. -func ValidString(s string) bool { - return ascii.ValidString(s) -} diff --git a/go/sdk/vendor/github.com/segmentio/encoding/ascii/valid_print.go b/go/sdk/vendor/github.com/segmentio/encoding/ascii/valid_print.go deleted file mode 100644 index 241f584..0000000 --- a/go/sdk/vendor/github.com/segmentio/encoding/ascii/valid_print.go +++ /dev/null @@ -1,26 +0,0 @@ -//go:generate go run valid_print_asm.go -out valid_print_amd64.s -stubs valid_print_amd64.go -package ascii - -import ( - "github.com/segmentio/asm/ascii" -) - -// Valid returns true if b contains only printable ASCII characters. -func ValidPrint(b []byte) bool { - return ascii.ValidPrint(b) -} - -// ValidBytes returns true if b is an ASCII character. -func ValidPrintByte(b byte) bool { - return ascii.ValidPrintByte(b) -} - -// ValidBytes returns true if b is an ASCII character. -func ValidPrintRune(r rune) bool { - return ascii.ValidPrintRune(r) -} - -// ValidString returns true if s contains only printable ASCII characters. -func ValidPrintString(s string) bool { - return ascii.ValidPrintString(s) -} diff --git a/go/sdk/vendor/github.com/segmentio/encoding/iso8601/parse.go b/go/sdk/vendor/github.com/segmentio/encoding/iso8601/parse.go deleted file mode 100644 index 6fbe5dc..0000000 --- a/go/sdk/vendor/github.com/segmentio/encoding/iso8601/parse.go +++ /dev/null @@ -1,185 +0,0 @@ -package iso8601 - -import ( - "encoding/binary" - "errors" - "time" - "unsafe" -) - -var ( - errInvalidTimestamp = errors.New("invalid ISO8601 timestamp") - errMonthOutOfRange = errors.New("month out of range") - errDayOutOfRange = errors.New("day out of range") - errHourOutOfRange = errors.New("hour out of range") - errMinuteOutOfRange = errors.New("minute out of range") - errSecondOutOfRange = errors.New("second out of range") -) - -// Parse parses an ISO8601 timestamp, e.g. "2021-03-25T21:36:12Z". -func Parse(input string) (time.Time, error) { - b := unsafeStringToBytes(input) - if len(b) >= 20 && len(b) <= 30 && b[len(b)-1] == 'Z' { - if len(b) == 21 || (len(b) > 21 && b[19] != '.') { - return time.Time{}, errInvalidTimestamp - } - - t1 := binary.LittleEndian.Uint64(b) - t2 := binary.LittleEndian.Uint64(b[8:16]) - t3 := uint64(b[16]) | uint64(b[17])<<8 | uint64(b[18])<<16 | uint64('Z')<<24 - - // Check for valid separators by masking input with " - - T : : Z". - // If separators are all valid, replace them with a '0' (0x30) byte and - // check all bytes are now numeric. - if !match(t1, mask1) || !match(t2, mask2) || !match(t3, mask3) { - return time.Time{}, errInvalidTimestamp - } - t1 ^= replace1 - t2 ^= replace2 - t3 ^= replace3 - if (nonNumeric(t1) | nonNumeric(t2) | nonNumeric(t3)) != 0 { - return time.Time{}, errInvalidTimestamp - } - - t1 -= zero - t2 -= zero - t3 -= zero - year := (t1&0xF)*1000 + (t1>>8&0xF)*100 + (t1>>16&0xF)*10 + (t1 >> 24 & 0xF) - month := (t1>>40&0xF)*10 + (t1 >> 48 & 0xF) - day := (t2&0xF)*10 + (t2 >> 8 & 0xF) - hour := (t2>>24&0xF)*10 + (t2 >> 32 & 0xF) - minute := (t2>>48&0xF)*10 + (t2 >> 56) - second := (t3>>8&0xF)*10 + (t3 >> 16) - - nanos := int64(0) - if len(b) > 20 { - for _, c := range b[20 : len(b)-1] { - if c < '0' || c > '9' { - return time.Time{}, errInvalidTimestamp - } - nanos = (nanos * 10) + int64(c-'0') - } - nanos *= pow10[30-len(b)] - } - - if err := validate(year, month, day, hour, minute, second); err != nil { - return time.Time{}, err - } - - unixSeconds := int64(daysSinceEpoch(year, month, day))*86400 + int64(hour*3600+minute*60+second) - return time.Unix(unixSeconds, nanos).UTC(), nil - } - - // Fallback to using time.Parse(). - t, err := time.Parse(time.RFC3339Nano, input) - if err != nil { - // Override (and don't wrap) the error here. The error returned by - // time.Parse() is dynamic, and includes a reference to the input - // string. By overriding the error, we guarantee that the input string - // doesn't escape. - return time.Time{}, errInvalidTimestamp - } - return t, nil -} - -var pow10 = []int64{1, 10, 100, 1000, 1e4, 1e5, 1e6, 1e7, 1e8} - -const ( - mask1 = 0x2d00002d00000000 // YYYY-MM- - mask2 = 0x00003a0000540000 // DDTHH:MM - mask3 = 0x000000005a00003a // :SSZ____ - - // Generate masks that replace the separators with a numeric byte. - // The input must have valid separators. XOR with the separator bytes - // to zero them out and then XOR with 0x30 to replace them with '0'. - replace1 = mask1 ^ 0x3000003000000000 - replace2 = mask2 ^ 0x0000300000300000 - replace3 = mask3 ^ 0x3030303030000030 - - lsb = ^uint64(0) / 255 - msb = lsb * 0x80 - - zero = lsb * '0' - nine = lsb * '9' -) - -func validate(year, month, day, hour, minute, second uint64) error { - if day == 0 || day > 31 { - return errDayOutOfRange - } - if month == 0 || month > 12 { - return errMonthOutOfRange - } - if hour >= 24 { - return errHourOutOfRange - } - if minute >= 60 { - return errMinuteOutOfRange - } - if second >= 60 { - return errSecondOutOfRange - } - if month == 2 && (day > 29 || (day == 29 && !isLeapYear(year))) { - return errDayOutOfRange - } - if day == 31 { - switch month { - case 4, 6, 9, 11: - return errDayOutOfRange - } - } - return nil -} - -func match(u, mask uint64) bool { - return (u & mask) == mask -} - -func nonNumeric(u uint64) uint64 { - // Derived from https://graphics.stanford.edu/~seander/bithacks.html#HasLessInWord. - // Subtract '0' (0x30) from each byte so that the MSB is set in each byte - // if there's a byte less than '0' (0x30). Add 0x46 (0x7F-'9') so that the - // MSB is set if there's a byte greater than '9' (0x39). To handle overflow - // when adding 0x46, include the MSB from the input bytes in the final mask. - // Remove all but the MSBs and then you're left with a mask where each - // non-numeric byte from the input has its MSB set in the output. - return ((u - zero) | (u + (^msb - nine)) | u) & msb -} - -func daysSinceEpoch(year, month, day uint64) uint64 { - // Derived from https://blog.reverberate.org/2020/05/12/optimizing-date-algorithms.html. - monthAdjusted := month - 3 - var carry uint64 - if monthAdjusted > month { - carry = 1 - } - var adjust uint64 - if carry == 1 { - adjust = 12 - } - yearAdjusted := year + 4800 - carry - monthDays := ((monthAdjusted+adjust)*62719 + 769) / 2048 - leapDays := yearAdjusted/4 - yearAdjusted/100 + yearAdjusted/400 - return yearAdjusted*365 + leapDays + monthDays + (day - 1) - 2472632 -} - -func isLeapYear(y uint64) bool { - return (y%4) == 0 && ((y%100) != 0 || (y%400) == 0) -} - -func unsafeStringToBytes(s string) []byte { - return *(*[]byte)(unsafe.Pointer(&sliceHeader{ - Data: *(*unsafe.Pointer)(unsafe.Pointer(&s)), - Len: len(s), - Cap: len(s), - })) -} - -// sliceHeader is like reflect.SliceHeader but the Data field is a -// unsafe.Pointer instead of being a uintptr to avoid invalid -// conversions from uintptr to unsafe.Pointer. -type sliceHeader struct { - Data unsafe.Pointer - Len int - Cap int -} diff --git a/go/sdk/vendor/github.com/segmentio/encoding/iso8601/valid.go b/go/sdk/vendor/github.com/segmentio/encoding/iso8601/valid.go deleted file mode 100644 index 187b4ef..0000000 --- a/go/sdk/vendor/github.com/segmentio/encoding/iso8601/valid.go +++ /dev/null @@ -1,179 +0,0 @@ -package iso8601 - -// ValidFlags is a bitset type used to configure the behavior of the Valid -// function. -type ValidFlags int - -const ( - // Strict is a validation flag used to represent a string iso8601 validation - // (this is the default). - Strict ValidFlags = 0 - - // AllowSpaceSeparator allows the presence of a space instead of a 'T' as - // separator between the date and time. - AllowSpaceSeparator ValidFlags = 1 << iota - - // AllowMissingTime allows the value to contain only a date. - AllowMissingTime - - // AllowMissingSubsecond allows the value to contain only a date and time. - AllowMissingSubsecond - - // AllowMissingTimezone allows the value to be missing the timezone - // information. - AllowMissingTimezone - - // AllowNumericTimezone allows the value to represent timezones in their - // numeric form. - AllowNumericTimezone - - // Flexible is a combination of all validation flag that allow for - // non-strict checking of the input value. - Flexible = AllowSpaceSeparator | AllowMissingTime | AllowMissingSubsecond | AllowMissingTimezone | AllowNumericTimezone -) - -// Valid check value to verify whether or not it is a valid iso8601 time -// representation. -func Valid(value string, flags ValidFlags) bool { - var ok bool - - // year - if value, ok = readDigits(value, 4, 4); !ok { - return false - } - - if value, ok = readByte(value, '-'); !ok { - return false - } - - // month - if value, ok = readDigits(value, 2, 2); !ok { - return false - } - - if value, ok = readByte(value, '-'); !ok { - return false - } - - // day - if value, ok = readDigits(value, 2, 2); !ok { - return false - } - - if len(value) == 0 && (flags&AllowMissingTime) != 0 { - return true // date only - } - - // separator - if value, ok = readByte(value, 'T'); !ok { - if (flags & AllowSpaceSeparator) == 0 { - return false - } - if value, ok = readByte(value, ' '); !ok { - return false - } - } - - // hour - if value, ok = readDigits(value, 2, 2); !ok { - return false - } - - if value, ok = readByte(value, ':'); !ok { - return false - } - - // minute - if value, ok = readDigits(value, 2, 2); !ok { - return false - } - - if value, ok = readByte(value, ':'); !ok { - return false - } - - // second - if value, ok = readDigits(value, 2, 2); !ok { - return false - } - - // microsecond - if value, ok = readByte(value, '.'); !ok { - if (flags & AllowMissingSubsecond) == 0 { - return false - } - } else { - if value, ok = readDigits(value, 1, 9); !ok { - return false - } - } - - if len(value) == 0 && (flags&AllowMissingTimezone) != 0 { - return true // date and time - } - - // timezone - if value, ok = readByte(value, 'Z'); ok { - return len(value) == 0 - } - - if (flags & AllowSpaceSeparator) != 0 { - value, _ = readByte(value, ' ') - } - - if value, ok = readByte(value, '+'); !ok { - if value, ok = readByte(value, '-'); !ok { - return false - } - } - - // timezone hour - if value, ok = readDigits(value, 2, 2); !ok { - return false - } - - if value, ok = readByte(value, ':'); !ok { - if (flags & AllowNumericTimezone) == 0 { - return false - } - } - - // timezone minute - if value, ok = readDigits(value, 2, 2); !ok { - return false - } - - return len(value) == 0 -} - -func readDigits(value string, min, max int) (string, bool) { - if len(value) < min { - return value, false - } - - i := 0 - - for i < max && i < len(value) && isDigit(value[i]) { - i++ - } - - if i < max && i < min { - return value, false - } - - return value[i:], true -} - -func readByte(value string, c byte) (string, bool) { - if len(value) == 0 { - return value, false - } - if value[0] != c { - return value, false - } - return value[1:], true -} - -func isDigit(c byte) bool { - return '0' <= c && c <= '9' -} diff --git a/go/sdk/vendor/github.com/segmentio/encoding/json/README.md b/go/sdk/vendor/github.com/segmentio/encoding/json/README.md deleted file mode 100644 index c5ed94b..0000000 --- a/go/sdk/vendor/github.com/segmentio/encoding/json/README.md +++ /dev/null @@ -1,76 +0,0 @@ -# encoding/json [![GoDoc](https://godoc.org/github.com/segmentio/encoding/json?status.svg)](https://godoc.org/github.com/segmentio/encoding/json) - -Go package offering a replacement implementation of the standard library's -[`encoding/json`](https://golang.org/pkg/encoding/json/) package, with much -better performance. - -## Usage - -The exported API of this package mirrors the standard library's -[`encoding/json`](https://golang.org/pkg/encoding/json/) package, the only -change needed to take advantage of the performance improvements is the import -path of the `json` package, from: -```go -import ( - "encoding/json" -) -``` -to -```go -import ( - "github.com/segmentio/encoding/json" -) -``` - -One way to gain higher encoding throughput is to disable HTML escaping. -It allows the string encoding to use a much more efficient code path which -does not require parsing UTF-8 runes most of the time. - -## Performance Improvements - -The internal implementation uses a fair amount of unsafe operations (untyped -code, pointer arithmetic, etc...) to avoid using reflection as much as possible, -which is often the reason why serialization code has a large CPU and memory -footprint. - -The package aims for zero unnecessary dynamic memory allocations and hot code -paths that are mostly free from calls into the reflect package. - -## Compatibility with encoding/json - -This package aims to be a drop-in replacement, therefore it is tested to behave -exactly like the standard library's package. However, there are still a few -missing features that have not been ported yet: - -- Streaming decoder, currently the `Decoder` implementation offered by the -package does not support progressively reading values from a JSON array (unlike -the standard library). In our experience this is a very rare use-case, if you -need it you're better off sticking to the standard library, or spend a bit of -time implementing it in here ;) - -Note that none of those features should result in performance degradations if -they were implemented in the package, and we welcome contributions! - -## Trade-offs - -As one would expect, we had to make a couple of trade-offs to achieve greater -performance than the standard library, but there were also features that we -did not want to give away. - -Other open-source packages offering a reduced CPU and memory footprint usually -do so by designing a different API, or require code generation (therefore adding -complexity to the build process). These were not acceptable conditions for us, -as we were not willing to trade off developer productivity for better runtime -performance. To achieve this, we chose to exactly replicate the standard -library interfaces and behavior, which meant the package implementation was the -only area that we were able to work with. The internals of this package make -heavy use of unsafe pointer arithmetics and other performance optimizations, -and therefore are not as approachable as typical Go programs. Basically, we put -a bigger burden on maintainers to achieve better runtime cost without -sacrificing developer productivity. - -For these reasons, we also don't believe that this code should be ported upstream -to the standard `encoding/json` package. The standard library has to remain -readable and approachable to maximize stability and maintainability, and make -projects like this one possible because a high quality reference implementation -already exists. diff --git a/go/sdk/vendor/github.com/segmentio/encoding/json/codec.go b/go/sdk/vendor/github.com/segmentio/encoding/json/codec.go deleted file mode 100644 index 77fe264..0000000 --- a/go/sdk/vendor/github.com/segmentio/encoding/json/codec.go +++ /dev/null @@ -1,1240 +0,0 @@ -package json - -import ( - "encoding" - "encoding/json" - "fmt" - "maps" - "math/big" - "reflect" - "sort" - "strconv" - "strings" - "sync/atomic" - "time" - "unicode" - "unsafe" - - "github.com/segmentio/asm/keyset" -) - -const ( - // 1000 is the value used by the standard encoding/json package. - // - // https://cs.opensource.google/go/go/+/refs/tags/go1.17.3:src/encoding/json/encode.go;drc=refs%2Ftags%2Fgo1.17.3;l=300 - startDetectingCyclesAfter = 1000 -) - -type codec struct { - encode encodeFunc - decode decodeFunc -} - -type encoder struct { - flags AppendFlags - // ptrDepth tracks the depth of pointer cycles, when it reaches the value - // of startDetectingCyclesAfter, the ptrSeen map is allocated and the - // encoder starts tracking pointers it has seen as an attempt to detect - // whether it has entered a pointer cycle and needs to error before the - // goroutine runs out of stack space. - ptrDepth uint32 - ptrSeen map[unsafe.Pointer]struct{} -} - -type decoder struct { - flags ParseFlags -} - -type ( - encodeFunc func(encoder, []byte, unsafe.Pointer) ([]byte, error) - decodeFunc func(decoder, []byte, unsafe.Pointer) ([]byte, error) -) - -type ( - emptyFunc func(unsafe.Pointer) bool - sortFunc func([]reflect.Value) -) - -// Eventually consistent cache mapping go types to dynamically generated -// codecs. -// -// Note: using a uintptr as key instead of reflect.Type shaved ~15ns off of -// the ~30ns Marhsal/Unmarshal functions which were dominated by the map -// lookup time for simple types like bool, int, etc.. -var cache atomic.Pointer[map[unsafe.Pointer]codec] - -func cacheLoad() map[unsafe.Pointer]codec { - p := cache.Load() - if p == nil { - return nil - } - - return *p -} - -func cacheStore(typ reflect.Type, cod codec, oldCodecs map[unsafe.Pointer]codec) { - newCodecs := make(map[unsafe.Pointer]codec, len(oldCodecs)+1) - maps.Copy(newCodecs, oldCodecs) - newCodecs[typeid(typ)] = cod - - cache.Store(&newCodecs) -} - -func typeid(t reflect.Type) unsafe.Pointer { - return (*iface)(unsafe.Pointer(&t)).ptr -} - -func constructCachedCodec(t reflect.Type, cache map[unsafe.Pointer]codec) codec { - c := constructCodec(t, map[reflect.Type]*structType{}, t.Kind() == reflect.Ptr) - - if inlined(t) { - c.encode = constructInlineValueEncodeFunc(c.encode) - } - - cacheStore(t, c, cache) - return c -} - -func constructCodec(t reflect.Type, seen map[reflect.Type]*structType, canAddr bool) (c codec) { - switch t { - case nullType, nil: - c = codec{encode: encoder.encodeNull, decode: decoder.decodeNull} - - case numberType: - c = codec{encode: encoder.encodeNumber, decode: decoder.decodeNumber} - - case bytesType: - c = codec{encode: encoder.encodeBytes, decode: decoder.decodeBytes} - - case durationType: - c = codec{encode: encoder.encodeDuration, decode: decoder.decodeDuration} - - case timeType: - c = codec{encode: encoder.encodeTime, decode: decoder.decodeTime} - - case interfaceType: - c = codec{encode: encoder.encodeInterface, decode: decoder.decodeInterface} - - case rawMessageType: - c = codec{encode: encoder.encodeRawMessage, decode: decoder.decodeRawMessage} - - case numberPtrType: - c = constructPointerCodec(numberPtrType, nil) - - case durationPtrType: - c = constructPointerCodec(durationPtrType, nil) - - case timePtrType: - c = constructPointerCodec(timePtrType, nil) - - case rawMessagePtrType: - c = constructPointerCodec(rawMessagePtrType, nil) - } - - if c.encode != nil { - return - } - - switch t.Kind() { - case reflect.Bool: - c = codec{encode: encoder.encodeBool, decode: decoder.decodeBool} - - case reflect.Int: - c = codec{encode: encoder.encodeInt, decode: decoder.decodeInt} - - case reflect.Int8: - c = codec{encode: encoder.encodeInt8, decode: decoder.decodeInt8} - - case reflect.Int16: - c = codec{encode: encoder.encodeInt16, decode: decoder.decodeInt16} - - case reflect.Int32: - c = codec{encode: encoder.encodeInt32, decode: decoder.decodeInt32} - - case reflect.Int64: - c = codec{encode: encoder.encodeInt64, decode: decoder.decodeInt64} - - case reflect.Uint: - c = codec{encode: encoder.encodeUint, decode: decoder.decodeUint} - - case reflect.Uintptr: - c = codec{encode: encoder.encodeUintptr, decode: decoder.decodeUintptr} - - case reflect.Uint8: - c = codec{encode: encoder.encodeUint8, decode: decoder.decodeUint8} - - case reflect.Uint16: - c = codec{encode: encoder.encodeUint16, decode: decoder.decodeUint16} - - case reflect.Uint32: - c = codec{encode: encoder.encodeUint32, decode: decoder.decodeUint32} - - case reflect.Uint64: - c = codec{encode: encoder.encodeUint64, decode: decoder.decodeUint64} - - case reflect.Float32: - c = codec{encode: encoder.encodeFloat32, decode: decoder.decodeFloat32} - - case reflect.Float64: - c = codec{encode: encoder.encodeFloat64, decode: decoder.decodeFloat64} - - case reflect.String: - c = codec{encode: encoder.encodeString, decode: decoder.decodeString} - - case reflect.Interface: - c = constructInterfaceCodec(t) - - case reflect.Array: - c = constructArrayCodec(t, seen, canAddr) - - case reflect.Slice: - c = constructSliceCodec(t, seen) - - case reflect.Map: - c = constructMapCodec(t, seen) - - case reflect.Struct: - c = constructStructCodec(t, seen, canAddr) - - case reflect.Ptr: - c = constructPointerCodec(t, seen) - - default: - c = constructUnsupportedTypeCodec(t) - } - - p := reflect.PointerTo(t) - - if canAddr { - switch { - case p.Implements(jsonMarshalerType): - c.encode = constructJSONMarshalerEncodeFunc(t, true) - case p.Implements(textMarshalerType): - c.encode = constructTextMarshalerEncodeFunc(t, true) - } - } - - switch { - case t.Implements(jsonMarshalerType): - c.encode = constructJSONMarshalerEncodeFunc(t, false) - case t.Implements(textMarshalerType): - c.encode = constructTextMarshalerEncodeFunc(t, false) - } - - switch { - case p.Implements(jsonUnmarshalerType): - c.decode = constructJSONUnmarshalerDecodeFunc(t, true) - case p.Implements(textUnmarshalerType): - c.decode = constructTextUnmarshalerDecodeFunc(t, true) - } - - return -} - -func constructStringCodec(t reflect.Type, seen map[reflect.Type]*structType, canAddr bool) codec { - c := constructCodec(t, seen, canAddr) - return codec{ - encode: constructStringEncodeFunc(c.encode), - decode: constructStringDecodeFunc(c.decode), - } -} - -func constructStringEncodeFunc(encode encodeFunc) encodeFunc { - return func(e encoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return e.encodeToString(b, p, encode) - } -} - -func constructStringDecodeFunc(decode decodeFunc) decodeFunc { - return func(d decoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return d.decodeFromString(b, p, decode) - } -} - -func constructStringToIntDecodeFunc(t reflect.Type, decode decodeFunc) decodeFunc { - return func(d decoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return d.decodeFromStringToInt(b, p, t, decode) - } -} - -func constructArrayCodec(t reflect.Type, seen map[reflect.Type]*structType, canAddr bool) codec { - e := t.Elem() - c := constructCodec(e, seen, canAddr) - s := alignedSize(e) - return codec{ - encode: constructArrayEncodeFunc(s, t, c.encode), - decode: constructArrayDecodeFunc(s, t, c.decode), - } -} - -func constructArrayEncodeFunc(size uintptr, t reflect.Type, encode encodeFunc) encodeFunc { - n := t.Len() - return func(e encoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return e.encodeArray(b, p, n, size, t, encode) - } -} - -func constructArrayDecodeFunc(size uintptr, t reflect.Type, decode decodeFunc) decodeFunc { - n := t.Len() - return func(d decoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return d.decodeArray(b, p, n, size, t, decode) - } -} - -func constructSliceCodec(t reflect.Type, seen map[reflect.Type]*structType) codec { - e := t.Elem() - s := alignedSize(e) - - if e.Kind() == reflect.Uint8 { - // Go 1.7+ behavior: slices of byte types (and aliases) may override the - // default encoding and decoding behaviors by implementing marshaler and - // unmarshaler interfaces. - p := reflect.PointerTo(e) - c := codec{} - - switch { - case e.Implements(jsonMarshalerType): - c.encode = constructJSONMarshalerEncodeFunc(e, false) - case e.Implements(textMarshalerType): - c.encode = constructTextMarshalerEncodeFunc(e, false) - case p.Implements(jsonMarshalerType): - c.encode = constructJSONMarshalerEncodeFunc(e, true) - case p.Implements(textMarshalerType): - c.encode = constructTextMarshalerEncodeFunc(e, true) - } - - switch { - case e.Implements(jsonUnmarshalerType): - c.decode = constructJSONUnmarshalerDecodeFunc(e, false) - case e.Implements(textUnmarshalerType): - c.decode = constructTextUnmarshalerDecodeFunc(e, false) - case p.Implements(jsonUnmarshalerType): - c.decode = constructJSONUnmarshalerDecodeFunc(e, true) - case p.Implements(textUnmarshalerType): - c.decode = constructTextUnmarshalerDecodeFunc(e, true) - } - - if c.encode != nil { - c.encode = constructSliceEncodeFunc(s, t, c.encode) - } else { - c.encode = encoder.encodeBytes - } - - if c.decode != nil { - c.decode = constructSliceDecodeFunc(s, t, c.decode) - } else { - c.decode = decoder.decodeBytes - } - - return c - } - - c := constructCodec(e, seen, true) - return codec{ - encode: constructSliceEncodeFunc(s, t, c.encode), - decode: constructSliceDecodeFunc(s, t, c.decode), - } -} - -func constructSliceEncodeFunc(size uintptr, t reflect.Type, encode encodeFunc) encodeFunc { - return func(e encoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return e.encodeSlice(b, p, size, t, encode) - } -} - -func constructSliceDecodeFunc(size uintptr, t reflect.Type, decode decodeFunc) decodeFunc { - return func(d decoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return d.decodeSlice(b, p, size, t, decode) - } -} - -func constructMapCodec(t reflect.Type, seen map[reflect.Type]*structType) codec { - var sortKeys sortFunc - k := t.Key() - v := t.Elem() - - // Faster implementations for some common cases. - switch { - case k == stringType && v == interfaceType: - return codec{ - encode: encoder.encodeMapStringInterface, - decode: decoder.decodeMapStringInterface, - } - - case k == stringType && v == rawMessageType: - return codec{ - encode: encoder.encodeMapStringRawMessage, - decode: decoder.decodeMapStringRawMessage, - } - - case k == stringType && v == stringType: - return codec{ - encode: encoder.encodeMapStringString, - decode: decoder.decodeMapStringString, - } - - case k == stringType && v == stringsType: - return codec{ - encode: encoder.encodeMapStringStringSlice, - decode: decoder.decodeMapStringStringSlice, - } - - case k == stringType && v == boolType: - return codec{ - encode: encoder.encodeMapStringBool, - decode: decoder.decodeMapStringBool, - } - } - - kc := codec{} - vc := constructCodec(v, seen, false) - - if k.Implements(textMarshalerType) || reflect.PointerTo(k).Implements(textUnmarshalerType) { - kc.encode = constructTextMarshalerEncodeFunc(k, false) - kc.decode = constructTextUnmarshalerDecodeFunc(k, true) - - sortKeys = func(keys []reflect.Value) { - sort.Slice(keys, func(i, j int) bool { - // This is a performance abomination but the use case is rare - // enough that it shouldn't be a problem in practice. - k1, _ := keys[i].Interface().(encoding.TextMarshaler).MarshalText() - k2, _ := keys[j].Interface().(encoding.TextMarshaler).MarshalText() - return string(k1) < string(k2) - }) - } - } else { - switch k.Kind() { - case reflect.String: - kc.encode = encoder.encodeString - kc.decode = decoder.decodeString - - sortKeys = func(keys []reflect.Value) { - sort.Slice(keys, func(i, j int) bool { return keys[i].String() < keys[j].String() }) - } - - case reflect.Int, - reflect.Int8, - reflect.Int16, - reflect.Int32, - reflect.Int64: - kc = constructStringCodec(k, seen, false) - - sortKeys = func(keys []reflect.Value) { - sort.Slice(keys, func(i, j int) bool { return intStringsAreSorted(keys[i].Int(), keys[j].Int()) }) - } - - case reflect.Uint, - reflect.Uintptr, - reflect.Uint8, - reflect.Uint16, - reflect.Uint32, - reflect.Uint64: - kc = constructStringCodec(k, seen, false) - - sortKeys = func(keys []reflect.Value) { - sort.Slice(keys, func(i, j int) bool { return uintStringsAreSorted(keys[i].Uint(), keys[j].Uint()) }) - } - - default: - return constructUnsupportedTypeCodec(t) - } - } - - if inlined(v) { - vc.encode = constructInlineValueEncodeFunc(vc.encode) - } - - return codec{ - encode: constructMapEncodeFunc(t, kc.encode, vc.encode, sortKeys), - decode: constructMapDecodeFunc(t, kc.decode, vc.decode), - } -} - -func constructMapEncodeFunc(t reflect.Type, encodeKey, encodeValue encodeFunc, sortKeys sortFunc) encodeFunc { - return func(e encoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return e.encodeMap(b, p, t, encodeKey, encodeValue, sortKeys) - } -} - -func constructMapDecodeFunc(t reflect.Type, decodeKey, decodeValue decodeFunc) decodeFunc { - kt := t.Key() - vt := t.Elem() - kz := reflect.Zero(kt) - vz := reflect.Zero(vt) - return func(d decoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return d.decodeMap(b, p, t, kt, vt, kz, vz, decodeKey, decodeValue) - } -} - -func constructStructCodec(t reflect.Type, seen map[reflect.Type]*structType, canAddr bool) codec { - st := constructStructType(t, seen, canAddr) - return codec{ - encode: constructStructEncodeFunc(st), - decode: constructStructDecodeFunc(st), - } -} - -func constructStructType(t reflect.Type, seen map[reflect.Type]*structType, canAddr bool) *structType { - // Used for preventing infinite recursion on types that have pointers to - // themselves. - st := seen[t] - - if st == nil { - st = &structType{ - fields: make([]structField, 0, t.NumField()), - fieldsIndex: make(map[string]*structField), - ficaseIndex: make(map[string]*structField), - typ: t, - } - - seen[t] = st - st.fields = appendStructFields(st.fields, t, 0, seen, canAddr) - - for i := range st.fields { - f := &st.fields[i] - s := strings.ToLower(f.name) - st.fieldsIndex[f.name] = f - // When there is ambiguity because multiple fields have the same - // case-insensitive representation, the first field must win. - if _, exists := st.ficaseIndex[s]; !exists { - st.ficaseIndex[s] = f - } - } - - // At a certain point the linear scan provided by keyset is less - // efficient than a map. The 32 was chosen based on benchmarks in the - // segmentio/asm repo run with an Intel Kaby Lake processor and go1.17. - if len(st.fields) <= 32 { - keys := make([][]byte, len(st.fields)) - for i, f := range st.fields { - keys[i] = []byte(f.name) - } - st.keyset = keyset.New(keys) - } - } - - return st -} - -func constructStructEncodeFunc(st *structType) encodeFunc { - return func(e encoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return e.encodeStruct(b, p, st) - } -} - -func constructStructDecodeFunc(st *structType) decodeFunc { - return func(d decoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return d.decodeStruct(b, p, st) - } -} - -func constructEmbeddedStructPointerCodec(t reflect.Type, unexported bool, offset uintptr, field codec) codec { - return codec{ - encode: constructEmbeddedStructPointerEncodeFunc(t, unexported, offset, field.encode), - decode: constructEmbeddedStructPointerDecodeFunc(t, unexported, offset, field.decode), - } -} - -func constructEmbeddedStructPointerEncodeFunc(t reflect.Type, unexported bool, offset uintptr, encode encodeFunc) encodeFunc { - return func(e encoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return e.encodeEmbeddedStructPointer(b, p, t, unexported, offset, encode) - } -} - -func constructEmbeddedStructPointerDecodeFunc(t reflect.Type, unexported bool, offset uintptr, decode decodeFunc) decodeFunc { - return func(d decoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return d.decodeEmbeddedStructPointer(b, p, t, unexported, offset, decode) - } -} - -func appendStructFields(fields []structField, t reflect.Type, offset uintptr, seen map[reflect.Type]*structType, canAddr bool) []structField { - type embeddedField struct { - index int - offset uintptr - pointer bool - unexported bool - subtype *structType - subfield *structField - } - - names := make(map[string]struct{}) - embedded := make([]embeddedField, 0, 10) - - for i := range t.NumField() { - f := t.Field(i) - - var ( - name = f.Name - anonymous = f.Anonymous - tag = false - omitempty = false - stringify = false - unexported = len(f.PkgPath) != 0 - ) - - if unexported && !anonymous { // unexported - continue - } - - if parts := strings.Split(f.Tag.Get("json"), ","); len(parts) != 0 { - if len(parts[0]) != 0 { - name, tag = parts[0], true - } - - if name == "-" && len(parts) == 1 { // ignored - continue - } - - if !isValidTag(name) { - name = f.Name - } - - for _, tag := range parts[1:] { - switch tag { - case "omitempty": - omitempty = true - case "string": - stringify = true - } - } - } - - if anonymous && !tag { // embedded - typ := f.Type - ptr := f.Type.Kind() == reflect.Ptr - - if ptr { - typ = f.Type.Elem() - } - - if typ.Kind() == reflect.Struct { - // When the embedded fields is inlined the fields can be looked - // up by offset from the address of the wrapping object, so we - // simply add the embedded struct fields to the list of fields - // of the current struct type. - subtype := constructStructType(typ, seen, canAddr) - - for j := range subtype.fields { - embedded = append(embedded, embeddedField{ - index: i<<32 | j, - offset: offset + f.Offset, - pointer: ptr, - unexported: unexported, - subtype: subtype, - subfield: &subtype.fields[j], - }) - } - - continue - } - - if unexported { // ignore unexported non-struct types - continue - } - } - - codec := constructCodec(f.Type, seen, canAddr) - - if stringify { - // https://golang.org/pkg/encoding/json/#Marshal - // - // The "string" option signals that a field is stored as JSON inside - // a JSON-encoded string. It applies only to fields of string, - // floating point, integer, or boolean types. This extra level of - // encoding is sometimes used when communicating with JavaScript - // programs: - typ := f.Type - - if typ.Kind() == reflect.Ptr { - typ = typ.Elem() - } - - switch typ.Kind() { - case reflect.Int, - reflect.Int8, - reflect.Int16, - reflect.Int32, - reflect.Int64, - reflect.Uint, - reflect.Uintptr, - reflect.Uint8, - reflect.Uint16, - reflect.Uint32, - reflect.Uint64: - codec.encode = constructStringEncodeFunc(codec.encode) - codec.decode = constructStringToIntDecodeFunc(typ, codec.decode) - case reflect.Bool, - reflect.Float32, - reflect.Float64, - reflect.String: - codec.encode = constructStringEncodeFunc(codec.encode) - codec.decode = constructStringDecodeFunc(codec.decode) - } - } - - fields = append(fields, structField{ - codec: codec, - offset: offset + f.Offset, - empty: emptyFuncOf(f.Type), - tag: tag, - omitempty: omitempty, - name: name, - index: i << 32, - typ: f.Type, - zero: reflect.Zero(f.Type), - }) - - names[name] = struct{}{} - } - - // Only unambiguous embedded fields must be serialized. - ambiguousNames := make(map[string]int) - ambiguousTags := make(map[string]int) - - // Embedded types can never override a field that was already present at - // the top-level. - for name := range names { - ambiguousNames[name]++ - ambiguousTags[name]++ - } - - for _, embfield := range embedded { - ambiguousNames[embfield.subfield.name]++ - if embfield.subfield.tag { - ambiguousTags[embfield.subfield.name]++ - } - } - - for _, embfield := range embedded { - subfield := *embfield.subfield - - if ambiguousNames[subfield.name] > 1 && (!subfield.tag || ambiguousTags[subfield.name] != 1) { - continue // ambiguous embedded field - } - - if embfield.pointer { - subfield.codec = constructEmbeddedStructPointerCodec(embfield.subtype.typ, embfield.unexported, subfield.offset, subfield.codec) - subfield.offset = embfield.offset - } else { - subfield.offset += embfield.offset - } - - // To prevent dominant flags more than one level below the embedded one. - subfield.tag = false - - // To ensure the order of the fields in the output is the same is in the - // struct type. - subfield.index = embfield.index - - fields = append(fields, subfield) - } - - for i := range fields { - name := fields[i].name - fields[i].json = encodeKeyFragment(name, 0) - fields[i].html = encodeKeyFragment(name, EscapeHTML) - } - - sort.Slice(fields, func(i, j int) bool { return fields[i].index < fields[j].index }) - return fields -} - -func encodeKeyFragment(s string, flags AppendFlags) string { - b := make([]byte, 1, len(s)+4) - b[0] = ',' - e := encoder{flags: flags} - b, _ = e.encodeString(b, unsafe.Pointer(&s)) - b = append(b, ':') - return *(*string)(unsafe.Pointer(&b)) -} - -func constructPointerCodec(t reflect.Type, seen map[reflect.Type]*structType) codec { - e := t.Elem() - c := constructCodec(e, seen, true) - return codec{ - encode: constructPointerEncodeFunc(e, c.encode), - decode: constructPointerDecodeFunc(e, c.decode), - } -} - -func constructPointerEncodeFunc(t reflect.Type, encode encodeFunc) encodeFunc { - return func(e encoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return e.encodePointer(b, p, t, encode) - } -} - -func constructPointerDecodeFunc(t reflect.Type, decode decodeFunc) decodeFunc { - return func(d decoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return d.decodePointer(b, p, t, decode) - } -} - -func constructInterfaceCodec(t reflect.Type) codec { - return codec{ - encode: constructMaybeEmptyInterfaceEncoderFunc(t), - decode: constructMaybeEmptyInterfaceDecoderFunc(t), - } -} - -func constructMaybeEmptyInterfaceEncoderFunc(t reflect.Type) encodeFunc { - return func(e encoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return e.encodeMaybeEmptyInterface(b, p, t) - } -} - -func constructMaybeEmptyInterfaceDecoderFunc(t reflect.Type) decodeFunc { - return func(d decoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return d.decodeMaybeEmptyInterface(b, p, t) - } -} - -func constructUnsupportedTypeCodec(t reflect.Type) codec { - return codec{ - encode: constructUnsupportedTypeEncodeFunc(t), - decode: constructUnsupportedTypeDecodeFunc(t), - } -} - -func constructUnsupportedTypeEncodeFunc(t reflect.Type) encodeFunc { - return func(e encoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return e.encodeUnsupportedTypeError(b, p, t) - } -} - -func constructUnsupportedTypeDecodeFunc(t reflect.Type) decodeFunc { - return func(d decoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return d.decodeUnmarshalTypeError(b, p, t) - } -} - -func constructJSONMarshalerEncodeFunc(t reflect.Type, pointer bool) encodeFunc { - return func(e encoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return e.encodeJSONMarshaler(b, p, t, pointer) - } -} - -func constructJSONUnmarshalerDecodeFunc(t reflect.Type, pointer bool) decodeFunc { - return func(d decoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return d.decodeJSONUnmarshaler(b, p, t, pointer) - } -} - -func constructTextMarshalerEncodeFunc(t reflect.Type, pointer bool) encodeFunc { - return func(e encoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return e.encodeTextMarshaler(b, p, t, pointer) - } -} - -func constructTextUnmarshalerDecodeFunc(t reflect.Type, pointer bool) decodeFunc { - return func(d decoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return d.decodeTextUnmarshaler(b, p, t, pointer) - } -} - -func constructInlineValueEncodeFunc(encode encodeFunc) encodeFunc { - return func(e encoder, b []byte, p unsafe.Pointer) ([]byte, error) { - return encode(e, b, noescape(unsafe.Pointer(&p))) - } -} - -// noescape hides a pointer from escape analysis. noescape is -// the identity function but escape analysis doesn't think the -// output depends on the input. noescape is inlined and currently -// compiles down to zero instructions. -// USE CAREFULLY! -// This was copied from the runtime; see issues 23382 and 7921. -// -//go:nosplit -func noescape(p unsafe.Pointer) unsafe.Pointer { - x := uintptr(p) - return unsafe.Pointer(x ^ 0) -} - -func alignedSize(t reflect.Type) uintptr { - a := t.Align() - s := t.Size() - return align(uintptr(a), uintptr(s)) -} - -func align(align, size uintptr) uintptr { - if align != 0 && (size%align) != 0 { - size = ((size / align) + 1) * align - } - return size -} - -func inlined(t reflect.Type) bool { - switch t.Kind() { - case reflect.Ptr: - return true - case reflect.Map: - return true - case reflect.Struct: - return t.NumField() == 1 && inlined(t.Field(0).Type) - default: - return false - } -} - -func isValidTag(s string) bool { - if s == "" { - return false - } - for _, c := range s { - switch { - case strings.ContainsRune("!#$%&()*+-./:;<=>?@[]^_{|}~ ", c): - // Backslash and quote chars are reserved, but - // otherwise any punctuation chars are allowed - // in a tag name. - default: - if !unicode.IsLetter(c) && !unicode.IsDigit(c) { - return false - } - } - } - return true -} - -func emptyFuncOf(t reflect.Type) emptyFunc { - switch t { - case bytesType, rawMessageType: - return func(p unsafe.Pointer) bool { return (*slice)(p).len == 0 } - } - - switch t.Kind() { - case reflect.Array: - if t.Len() == 0 { - return func(unsafe.Pointer) bool { return true } - } - - case reflect.Map: - return func(p unsafe.Pointer) bool { return reflect.NewAt(t, p).Elem().Len() == 0 } - - case reflect.Slice: - return func(p unsafe.Pointer) bool { return (*slice)(p).len == 0 } - - case reflect.String: - return func(p unsafe.Pointer) bool { return len(*(*string)(p)) == 0 } - - case reflect.Bool: - return func(p unsafe.Pointer) bool { return !*(*bool)(p) } - - case reflect.Int, reflect.Uint: - return func(p unsafe.Pointer) bool { return *(*uint)(p) == 0 } - - case reflect.Uintptr: - return func(p unsafe.Pointer) bool { return *(*uintptr)(p) == 0 } - - case reflect.Int8, reflect.Uint8: - return func(p unsafe.Pointer) bool { return *(*uint8)(p) == 0 } - - case reflect.Int16, reflect.Uint16: - return func(p unsafe.Pointer) bool { return *(*uint16)(p) == 0 } - - case reflect.Int32, reflect.Uint32: - return func(p unsafe.Pointer) bool { return *(*uint32)(p) == 0 } - - case reflect.Int64, reflect.Uint64: - return func(p unsafe.Pointer) bool { return *(*uint64)(p) == 0 } - - case reflect.Float32: - return func(p unsafe.Pointer) bool { return *(*float32)(p) == 0 } - - case reflect.Float64: - return func(p unsafe.Pointer) bool { return *(*float64)(p) == 0 } - - case reflect.Ptr: - return func(p unsafe.Pointer) bool { return *(*unsafe.Pointer)(p) == nil } - - case reflect.Interface: - return func(p unsafe.Pointer) bool { return (*iface)(p).ptr == nil } - } - - return func(unsafe.Pointer) bool { return false } -} - -type iface struct { - typ unsafe.Pointer - ptr unsafe.Pointer -} - -type slice struct { - data unsafe.Pointer - len int - cap int -} - -type structType struct { - fields []structField - fieldsIndex map[string]*structField - ficaseIndex map[string]*structField - keyset []byte - typ reflect.Type -} - -type structField struct { - codec codec - offset uintptr - empty emptyFunc - tag bool - omitempty bool - json string - html string - name string - typ reflect.Type - zero reflect.Value - index int -} - -func unmarshalTypeError(b []byte, t reflect.Type) error { - return &UnmarshalTypeError{Value: strconv.Quote(prefix(b)), Type: t} -} - -func unmarshalOverflow(b []byte, t reflect.Type) error { - return &UnmarshalTypeError{Value: "number " + prefix(b) + " overflows", Type: t} -} - -func unexpectedEOF(b []byte) error { - return syntaxError(b, "unexpected end of JSON input") -} - -var syntaxErrorMsgOffset = ^uintptr(0) - -func init() { - t := reflect.TypeOf(SyntaxError{}) - for i := range t.NumField() { - if f := t.Field(i); f.Type.Kind() == reflect.String { - syntaxErrorMsgOffset = f.Offset - } - } -} - -func syntaxError(b []byte, msg string, args ...any) error { - e := new(SyntaxError) - i := syntaxErrorMsgOffset - if i != ^uintptr(0) { - s := "json: " + fmt.Sprintf(msg, args...) + ": " + prefix(b) - p := unsafe.Pointer(e) - // Hack to set the unexported `msg` field. - *(*string)(unsafe.Pointer(uintptr(p) + i)) = s - } - return e -} - -func objectKeyError(b []byte, err error) ([]byte, error) { - if len(b) == 0 { - return nil, unexpectedEOF(b) - } - switch err.(type) { - case *UnmarshalTypeError: - err = syntaxError(b, "invalid character '%c' looking for beginning of object key", b[0]) - } - return b, err -} - -func prefix(b []byte) string { - if len(b) < 32 { - return string(b) - } - return string(b[:32]) + "..." -} - -func intStringsAreSorted(i0, i1 int64) bool { - var b0, b1 [32]byte - return string(strconv.AppendInt(b0[:0], i0, 10)) < string(strconv.AppendInt(b1[:0], i1, 10)) -} - -func uintStringsAreSorted(u0, u1 uint64) bool { - var b0, b1 [32]byte - return string(strconv.AppendUint(b0[:0], u0, 10)) < string(strconv.AppendUint(b1[:0], u1, 10)) -} - -func stringToBytes(s string) []byte { - return *(*[]byte)(unsafe.Pointer(&sliceHeader{ - Data: *(*unsafe.Pointer)(unsafe.Pointer(&s)), - Len: len(s), - Cap: len(s), - })) -} - -type sliceHeader struct { - Data unsafe.Pointer - Len int - Cap int -} - -var ( - nullType = reflect.TypeOf(nil) - boolType = reflect.TypeOf(false) - - intType = reflect.TypeOf(int(0)) - int8Type = reflect.TypeOf(int8(0)) - int16Type = reflect.TypeOf(int16(0)) - int32Type = reflect.TypeOf(int32(0)) - int64Type = reflect.TypeOf(int64(0)) - - uintType = reflect.TypeOf(uint(0)) - uint8Type = reflect.TypeOf(uint8(0)) - uint16Type = reflect.TypeOf(uint16(0)) - uint32Type = reflect.TypeOf(uint32(0)) - uint64Type = reflect.TypeOf(uint64(0)) - uintptrType = reflect.TypeOf(uintptr(0)) - - float32Type = reflect.TypeOf(float32(0)) - float64Type = reflect.TypeOf(float64(0)) - - bigIntType = reflect.TypeOf(new(big.Int)) - numberType = reflect.TypeOf(json.Number("")) - stringType = reflect.TypeOf("") - stringsType = reflect.TypeOf([]string(nil)) - bytesType = reflect.TypeOf(([]byte)(nil)) - durationType = reflect.TypeOf(time.Duration(0)) - timeType = reflect.TypeOf(time.Time{}) - rawMessageType = reflect.TypeOf(RawMessage(nil)) - - numberPtrType = reflect.PointerTo(numberType) - durationPtrType = reflect.PointerTo(durationType) - timePtrType = reflect.PointerTo(timeType) - rawMessagePtrType = reflect.PointerTo(rawMessageType) - - sliceInterfaceType = reflect.TypeOf(([]any)(nil)) - sliceStringType = reflect.TypeOf(([]any)(nil)) - mapStringInterfaceType = reflect.TypeOf((map[string]any)(nil)) - mapStringRawMessageType = reflect.TypeOf((map[string]RawMessage)(nil)) - mapStringStringType = reflect.TypeOf((map[string]string)(nil)) - mapStringStringSliceType = reflect.TypeOf((map[string][]string)(nil)) - mapStringBoolType = reflect.TypeOf((map[string]bool)(nil)) - - interfaceType = reflect.TypeOf((*any)(nil)).Elem() - jsonMarshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem() - jsonUnmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem() - textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem() - textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() - - bigIntDecoder = constructJSONUnmarshalerDecodeFunc(bigIntType, false) -) - -// ============================================================================= -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// appendDuration appends a human-readable representation of d to b. -// -// The function copies the implementation of time.Duration.String but prevents -// Go from making a dynamic memory allocation on the returned value. -func appendDuration(b []byte, d time.Duration) []byte { - // Largest time is 2540400h10m10.000000000s - var buf [32]byte - w := len(buf) - - u := uint64(d) - neg := d < 0 - if neg { - u = -u - } - - if u < uint64(time.Second) { - // Special case: if duration is smaller than a second, - // use smaller units, like 1.2ms - var prec int - w-- - buf[w] = 's' - w-- - switch { - case u == 0: - return append(b, '0', 's') - case u < uint64(time.Microsecond): - // print nanoseconds - prec = 0 - buf[w] = 'n' - case u < uint64(time.Millisecond): - // print microseconds - prec = 3 - // U+00B5 'µ' micro sign == 0xC2 0xB5 - w-- // Need room for two bytes. - copy(buf[w:], "µ") - default: - // print milliseconds - prec = 6 - buf[w] = 'm' - } - w, u = fmtFrac(buf[:w], u, prec) - w = fmtInt(buf[:w], u) - } else { - w-- - buf[w] = 's' - - w, u = fmtFrac(buf[:w], u, 9) - - // u is now integer seconds - w = fmtInt(buf[:w], u%60) - u /= 60 - - // u is now integer minutes - if u > 0 { - w-- - buf[w] = 'm' - w = fmtInt(buf[:w], u%60) - u /= 60 - - // u is now integer hours - // Stop at hours because days can be different lengths. - if u > 0 { - w-- - buf[w] = 'h' - w = fmtInt(buf[:w], u) - } - } - } - - if neg { - w-- - buf[w] = '-' - } - - return append(b, buf[w:]...) -} - -// fmtFrac formats the fraction of v/10**prec (e.g., ".12345") into the -// tail of buf, omitting trailing zeros. it omits the decimal -// point too when the fraction is 0. It returns the index where the -// output bytes begin and the value v/10**prec. -func fmtFrac(buf []byte, v uint64, prec int) (nw int, nv uint64) { - // Omit trailing zeros up to and including decimal point. - w := len(buf) - print := false - for range prec { - digit := v % 10 - print = print || digit != 0 - if print { - w-- - buf[w] = byte(digit) + '0' - } - v /= 10 - } - if print { - w-- - buf[w] = '.' - } - return w, v -} - -// fmtInt formats v into the tail of buf. -// It returns the index where the output begins. -func fmtInt(buf []byte, v uint64) int { - w := len(buf) - if v == 0 { - w-- - buf[w] = '0' - } else { - for v > 0 { - w-- - buf[w] = byte(v%10) + '0' - v /= 10 - } - } - return w -} - -// ============================================================================= diff --git a/go/sdk/vendor/github.com/segmentio/encoding/json/decode.go b/go/sdk/vendor/github.com/segmentio/encoding/json/decode.go deleted file mode 100644 index c87f01e..0000000 --- a/go/sdk/vendor/github.com/segmentio/encoding/json/decode.go +++ /dev/null @@ -1,1532 +0,0 @@ -package json - -import ( - "bytes" - "encoding" - "encoding/json" - "fmt" - "math" - "math/big" - "reflect" - "strconv" - "time" - "unsafe" - - "github.com/segmentio/asm/base64" - "github.com/segmentio/asm/keyset" - "github.com/segmentio/encoding/iso8601" -) - -func (d decoder) anyFlagsSet(flags ParseFlags) bool { - return d.flags&flags != 0 -} - -func (d decoder) decodeNull(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - return b[4:], nil - } - return d.inputError(b, nullType) -} - -func (d decoder) decodeBool(b []byte, p unsafe.Pointer) ([]byte, error) { - switch { - case hasTruePrefix(b): - *(*bool)(p) = true - return b[4:], nil - - case hasFalsePrefix(b): - *(*bool)(p) = false - return b[5:], nil - - case hasNullPrefix(b): - return b[4:], nil - - default: - return d.inputError(b, boolType) - } -} - -func (d decoder) decodeInt(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - return b[4:], nil - } - - v, r, err := d.parseInt(b, intType) - if err != nil { - return r, err - } - - *(*int)(p) = int(v) - return r, nil -} - -func (d decoder) decodeInt8(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - return b[4:], nil - } - - v, r, err := d.parseInt(b, int8Type) - if err != nil { - return r, err - } - - if v < math.MinInt8 || v > math.MaxInt8 { - return r, unmarshalOverflow(b[:len(b)-len(r)], int8Type) - } - - *(*int8)(p) = int8(v) - return r, nil -} - -func (d decoder) decodeInt16(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - return b[4:], nil - } - - v, r, err := d.parseInt(b, int16Type) - if err != nil { - return r, err - } - - if v < math.MinInt16 || v > math.MaxInt16 { - return r, unmarshalOverflow(b[:len(b)-len(r)], int16Type) - } - - *(*int16)(p) = int16(v) - return r, nil -} - -func (d decoder) decodeInt32(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - return b[4:], nil - } - - v, r, err := d.parseInt(b, int32Type) - if err != nil { - return r, err - } - - if v < math.MinInt32 || v > math.MaxInt32 { - return r, unmarshalOverflow(b[:len(b)-len(r)], int32Type) - } - - *(*int32)(p) = int32(v) - return r, nil -} - -func (d decoder) decodeInt64(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - return b[4:], nil - } - - v, r, err := d.parseInt(b, int64Type) - if err != nil { - return r, err - } - - *(*int64)(p) = v - return r, nil -} - -func (d decoder) decodeUint(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - return b[4:], nil - } - - v, r, err := d.parseUint(b, uintType) - if err != nil { - return r, err - } - - *(*uint)(p) = uint(v) - return r, nil -} - -func (d decoder) decodeUintptr(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - return b[4:], nil - } - - v, r, err := d.parseUint(b, uintptrType) - if err != nil { - return r, err - } - - *(*uintptr)(p) = uintptr(v) - return r, nil -} - -func (d decoder) decodeUint8(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - return b[4:], nil - } - - v, r, err := d.parseUint(b, uint8Type) - if err != nil { - return r, err - } - - if v > math.MaxUint8 { - return r, unmarshalOverflow(b[:len(b)-len(r)], uint8Type) - } - - *(*uint8)(p) = uint8(v) - return r, nil -} - -func (d decoder) decodeUint16(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - return b[4:], nil - } - - v, r, err := d.parseUint(b, uint16Type) - if err != nil { - return r, err - } - - if v > math.MaxUint16 { - return r, unmarshalOverflow(b[:len(b)-len(r)], uint16Type) - } - - *(*uint16)(p) = uint16(v) - return r, nil -} - -func (d decoder) decodeUint32(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - return b[4:], nil - } - - v, r, err := d.parseUint(b, uint32Type) - if err != nil { - return r, err - } - - if v > math.MaxUint32 { - return r, unmarshalOverflow(b[:len(b)-len(r)], uint32Type) - } - - *(*uint32)(p) = uint32(v) - return r, nil -} - -func (d decoder) decodeUint64(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - return b[4:], nil - } - - v, r, err := d.parseUint(b, uint64Type) - if err != nil { - return r, err - } - - *(*uint64)(p) = v - return r, nil -} - -func (d decoder) decodeFloat32(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - return b[4:], nil - } - - v, r, _, err := d.parseNumber(b) - if err != nil { - return d.inputError(b, float32Type) - } - - f, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&v)), 32) - if err != nil { - return d.inputError(b, float32Type) - } - - *(*float32)(p) = float32(f) - return r, nil -} - -func (d decoder) decodeFloat64(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - return b[4:], nil - } - - v, r, _, err := d.parseNumber(b) - if err != nil { - return d.inputError(b, float64Type) - } - - f, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&v)), 64) - if err != nil { - return d.inputError(b, float64Type) - } - - *(*float64)(p) = f - return r, nil -} - -func (d decoder) decodeNumber(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - return b[4:], nil - } - - v, r, _, err := d.parseNumber(b) - if err != nil { - return d.inputError(b, numberType) - } - - if (d.flags & DontCopyNumber) != 0 { - *(*Number)(p) = *(*Number)(unsafe.Pointer(&v)) - } else { - *(*Number)(p) = Number(v) - } - - return r, nil -} - -func (d decoder) decodeString(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - return b[4:], nil - } - - s, r, new, err := d.parseStringUnquote(b, nil) - if err != nil { - if len(b) == 0 || b[0] != '"' { - return d.inputError(b, stringType) - } - return r, err - } - - if new || (d.flags&DontCopyString) != 0 { - *(*string)(p) = *(*string)(unsafe.Pointer(&s)) - } else { - *(*string)(p) = string(s) - } - - return r, nil -} - -func (d decoder) decodeFromString(b []byte, p unsafe.Pointer, decode decodeFunc) ([]byte, error) { - if hasNullPrefix(b) { - return decode(d, b, p) - } - - v, b, _, err := d.parseStringUnquote(b, nil) - if err != nil { - return d.inputError(v, stringType) - } - - if v, err = decode(d, v, p); err != nil { - return b, err - } - - if v = skipSpaces(v); len(v) != 0 { - return b, syntaxError(v, "unexpected trailing tokens after string value") - } - - return b, nil -} - -func (d decoder) decodeFromStringToInt(b []byte, p unsafe.Pointer, t reflect.Type, decode decodeFunc) ([]byte, error) { - if hasNullPrefix(b) { - return decode(d, b, p) - } - - if len(b) > 0 && b[0] != '"' { - v, r, k, err := d.parseNumber(b) - if err == nil { - // The encoding/json package will return a *json.UnmarshalTypeError if - // the input was a floating point number representation, even tho a - // string is expected here. - if k == Float { - _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&v)), 64) - if err != nil { - return r, unmarshalTypeError(v, t) - } - } - } - return r, fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into int") - } - - if len(b) > 1 && b[0] == '"' && b[1] == '"' { - return b, fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal \"\" into int") - } - - v, b, _, err := d.parseStringUnquote(b, nil) - if err != nil { - return d.inputError(v, t) - } - - if hasLeadingZeroes(v) { - // In this context the encoding/json package accepts leading zeroes because - // it is not constrained by the JSON syntax, remove them so the parsing - // functions don't return syntax errors. - u := make([]byte, 0, len(v)) - i := 0 - - if i < len(v) && v[i] == '-' || v[i] == '+' { - u = append(u, v[i]) - i++ - } - - for (i+1) < len(v) && v[i] == '0' && '0' <= v[i+1] && v[i+1] <= '9' { - i++ - } - - v = append(u, v[i:]...) - } - - if r, err := decode(d, v, p); err != nil { - if _, isSyntaxError := err.(*SyntaxError); isSyntaxError { - if hasPrefix(v, "-") { - // The standard library interprets sequences of '-' characters - // as numbers but still returns type errors in this case... - return b, unmarshalTypeError(v, t) - } - return b, fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into int", prefix(v)) - } - // When the input value was a valid number representation we retain the - // error returned by the decoder. - if _, _, _, err := d.parseNumber(v); err != nil { - // When the input value valid JSON we mirror the behavior of the - // encoding/json package and return a generic error. - if _, _, _, err := d.parseValue(v); err == nil { - return b, fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into int", prefix(v)) - } - } - return b, err - } else if len(r) != 0 { - return r, unmarshalTypeError(v, t) - } - - return b, nil -} - -func (d decoder) decodeBytes(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - *(*[]byte)(p) = nil - return b[4:], nil - } - - if len(b) < 2 { - return d.inputError(b, bytesType) - } - - if b[0] != '"' { - // Go 1.7- behavior: bytes slices may be decoded from array of integers. - if len(b) > 0 && b[0] == '[' { - return d.decodeSlice(b, p, 1, bytesType, decoder.decodeUint8) - } - return d.inputError(b, bytesType) - } - - // The input string contains escaped sequences, we need to parse it before - // decoding it to match the encoding/json package behvaior. - src, r, _, err := d.parseStringUnquote(b, nil) - if err != nil { - return d.inputError(b, bytesType) - } - - dst := make([]byte, base64.StdEncoding.DecodedLen(len(src))) - - n, err := base64.StdEncoding.Decode(dst, src) - if err != nil { - return r, err - } - - *(*[]byte)(p) = dst[:n] - return r, nil -} - -func (d decoder) decodeDuration(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - return b[4:], nil - } - - // in order to inter-operate with the stdlib, we must be able to interpret - // durations passed as integer values. there's some discussion about being - // flexible on how durations are formatted, but for the time being, it's - // been punted to go2 at the earliest: https://github.com/golang/go/issues/4712 - if len(b) > 0 && b[0] != '"' { - v, r, err := d.parseInt(b, durationType) - if err != nil { - return d.inputError(b, int32Type) - } - - if v < math.MinInt64 || v > math.MaxInt64 { - return r, unmarshalOverflow(b[:len(b)-len(r)], int32Type) - } - - *(*time.Duration)(p) = time.Duration(v) - return r, nil - } - - if len(b) < 2 || b[0] != '"' { - return d.inputError(b, durationType) - } - - i := bytes.IndexByte(b[1:], '"') + 1 - if i <= 0 { - return d.inputError(b, durationType) - } - - s := b[1:i] // trim quotes - - v, err := time.ParseDuration(*(*string)(unsafe.Pointer(&s))) - if err != nil { - return d.inputError(b, durationType) - } - - *(*time.Duration)(p) = v - return b[i+1:], nil -} - -func (d decoder) decodeTime(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - return b[4:], nil - } - - if len(b) < 2 || b[0] != '"' { - return d.inputError(b, timeType) - } - - i := bytes.IndexByte(b[1:], '"') + 1 - if i <= 0 { - return d.inputError(b, timeType) - } - - s := b[1:i] // trim quotes - - v, err := iso8601.Parse(*(*string)(unsafe.Pointer(&s))) - if err != nil { - return d.inputError(b, timeType) - } - - *(*time.Time)(p) = v - return b[i+1:], nil -} - -func (d decoder) decodeArray(b []byte, p unsafe.Pointer, n int, size uintptr, t reflect.Type, decode decodeFunc) ([]byte, error) { - if hasNullPrefix(b) { - return b[4:], nil - } - - if len(b) < 2 || b[0] != '[' { - return d.inputError(b, t) - } - b = b[1:] - - var err error - for i := range n { - b = skipSpaces(b) - - if i != 0 { - if len(b) == 0 { - return b, syntaxError(b, "unexpected EOF after array element") - } - switch b[0] { - case ',': - b = skipSpaces(b[1:]) - case ']': - return b[1:], nil - default: - return b, syntaxError(b, "expected ',' after array element but found '%c'", b[0]) - } - } - - b, err = decode(d, b, unsafe.Pointer(uintptr(p)+(uintptr(i)*size))) - if err != nil { - if e, ok := err.(*UnmarshalTypeError); ok { - e.Struct = t.String() + e.Struct - e.Field = d.prependField(strconv.Itoa(i), e.Field) - } - return b, err - } - } - - // The encoding/json package ignores extra elements found when decoding into - // array types (which have a fixed size). - for { - b = skipSpaces(b) - - if len(b) == 0 { - return b, syntaxError(b, "missing closing ']' in array value") - } - - switch b[0] { - case ',': - b = skipSpaces(b[1:]) - case ']': - return b[1:], nil - } - - _, b, _, err = d.parseValue(b) - if err != nil { - return b, err - } - } -} - -// This is a placeholder used to consturct non-nil empty slices. -var empty struct{} - -func (d decoder) decodeSlice(b []byte, p unsafe.Pointer, size uintptr, t reflect.Type, decode decodeFunc) ([]byte, error) { - if hasNullPrefix(b) { - *(*slice)(p) = slice{} - return b[4:], nil - } - - if len(b) < 2 { - return d.inputError(b, t) - } - - if b[0] != '[' { - // Go 1.7- behavior: fallback to decoding as a []byte if the element - // type is byte; allow conversions from JSON strings even tho the - // underlying type implemented unmarshaler interfaces. - if t.Elem().Kind() == reflect.Uint8 { - return d.decodeBytes(b, p) - } - return d.inputError(b, t) - } - - input := b - b = b[1:] - - s := (*slice)(p) - s.len = 0 - - var err error - for { - b = skipSpaces(b) - - if len(b) != 0 && b[0] == ']' { - if s.data == nil { - s.data = unsafe.Pointer(&empty) - } - return b[1:], nil - } - - if s.len != 0 { - if len(b) == 0 { - return b, syntaxError(b, "unexpected EOF after array element") - } - if b[0] != ',' { - return b, syntaxError(b, "expected ',' after array element but found '%c'", b[0]) - } - b = skipSpaces(b[1:]) - } - - if s.len == s.cap { - c := s.cap - - if c == 0 { - c = 10 - } else { - c *= 2 - } - - *s = extendSlice(t, s, c) - } - - b, err = decode(d, b, unsafe.Pointer(uintptr(s.data)+(uintptr(s.len)*size))) - if err != nil { - if _, r, _, err := d.parseValue(input); err != nil { - return r, err - } else { - b = r - } - if e, ok := err.(*UnmarshalTypeError); ok { - e.Struct = t.String() + e.Struct - e.Field = d.prependField(strconv.Itoa(s.len), e.Field) - } - return b, err - } - - s.len++ - } -} - -func (d decoder) decodeMap(b []byte, p unsafe.Pointer, t, kt, vt reflect.Type, kz, vz reflect.Value, decodeKey, decodeValue decodeFunc) ([]byte, error) { - if hasNullPrefix(b) { - *(*unsafe.Pointer)(p) = nil - return b[4:], nil - } - - if len(b) < 2 || b[0] != '{' { - return d.inputError(b, t) - } - i := 0 - m := reflect.NewAt(t, p).Elem() - - k := reflect.New(kt).Elem() - v := reflect.New(vt).Elem() - - kptr := (*iface)(unsafe.Pointer(&k)).ptr - vptr := (*iface)(unsafe.Pointer(&v)).ptr - input := b - - if m.IsNil() { - m = reflect.MakeMap(t) - } - - var err error - b = b[1:] - for { - k.Set(kz) - v.Set(vz) - b = skipSpaces(b) - - if len(b) != 0 && b[0] == '}' { - *(*unsafe.Pointer)(p) = unsafe.Pointer(m.Pointer()) - return b[1:], nil - } - - if i != 0 { - if len(b) == 0 { - return b, syntaxError(b, "unexpected end of JSON input after object field value") - } - if b[0] != ',' { - return b, syntaxError(b, "expected ',' after object field value but found '%c'", b[0]) - } - b = skipSpaces(b[1:]) - } - - if hasNullPrefix(b) { - return b, syntaxError(b, "cannot decode object key string from 'null' value") - } - - if b, err = decodeKey(d, b, kptr); err != nil { - return objectKeyError(b, err) - } - b = skipSpaces(b) - - if len(b) == 0 { - return b, syntaxError(b, "unexpected end of JSON input after object field key") - } - if b[0] != ':' { - return b, syntaxError(b, "expected ':' after object field key but found '%c'", b[0]) - } - b = skipSpaces(b[1:]) - - if b, err = decodeValue(d, b, vptr); err != nil { - if _, r, _, err := d.parseValue(input); err != nil { - return r, err - } else { - b = r - } - if e, ok := err.(*UnmarshalTypeError); ok { - e.Struct = "map[" + kt.String() + "]" + vt.String() + "{" + e.Struct + "}" - e.Field = d.prependField(fmt.Sprint(k.Interface()), e.Field) - } - return b, err - } - - m.SetMapIndex(k, v) - i++ - } -} - -func (d decoder) decodeMapStringInterface(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - *(*unsafe.Pointer)(p) = nil - return b[4:], nil - } - - if len(b) < 2 || b[0] != '{' { - return d.inputError(b, mapStringInterfaceType) - } - - i := 0 - m := *(*map[string]any)(p) - - if m == nil { - m = make(map[string]any, 64) - } - - var ( - input = b - key string - val any - err error - ) - - b = b[1:] - for { - key = "" - val = nil - - b = skipSpaces(b) - - if len(b) != 0 && b[0] == '}' { - *(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(unsafe.Pointer(&m)) - return b[1:], nil - } - - if i != 0 { - if len(b) == 0 { - return b, syntaxError(b, "unexpected end of JSON input after object field value") - } - if b[0] != ',' { - return b, syntaxError(b, "expected ',' after object field value but found '%c'", b[0]) - } - b = skipSpaces(b[1:]) - } - - if hasNullPrefix(b) { - return b, syntaxError(b, "cannot decode object key string from 'null' value") - } - - b, err = d.decodeString(b, unsafe.Pointer(&key)) - if err != nil { - return objectKeyError(b, err) - } - b = skipSpaces(b) - - if len(b) == 0 { - return b, syntaxError(b, "unexpected end of JSON input after object field key") - } - if b[0] != ':' { - return b, syntaxError(b, "expected ':' after object field key but found '%c'", b[0]) - } - b = skipSpaces(b[1:]) - - b, err = d.decodeInterface(b, unsafe.Pointer(&val)) - if err != nil { - if _, r, _, err := d.parseValue(input); err != nil { - return r, err - } else { - b = r - } - if e, ok := err.(*UnmarshalTypeError); ok { - e.Struct = mapStringInterfaceType.String() + e.Struct - e.Field = d.prependField(key, e.Field) - } - return b, err - } - - m[key] = val - i++ - } -} - -func (d decoder) decodeMapStringRawMessage(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - *(*unsafe.Pointer)(p) = nil - return b[4:], nil - } - - if len(b) < 2 || b[0] != '{' { - return d.inputError(b, mapStringRawMessageType) - } - - i := 0 - m := *(*map[string]RawMessage)(p) - - if m == nil { - m = make(map[string]RawMessage, 64) - } - - var err error - var key string - var val RawMessage - input := b - - b = b[1:] - for { - key = "" - val = nil - - b = skipSpaces(b) - - if len(b) != 0 && b[0] == '}' { - *(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(unsafe.Pointer(&m)) - return b[1:], nil - } - - if i != 0 { - if len(b) == 0 { - return b, syntaxError(b, "unexpected end of JSON input after object field value") - } - if b[0] != ',' { - return b, syntaxError(b, "expected ',' after object field value but found '%c'", b[0]) - } - b = skipSpaces(b[1:]) - } - - if hasNullPrefix(b) { - return b, syntaxError(b, "cannot decode object key string from 'null' value") - } - - b, err = d.decodeString(b, unsafe.Pointer(&key)) - if err != nil { - return objectKeyError(b, err) - } - b = skipSpaces(b) - - if len(b) == 0 { - return b, syntaxError(b, "unexpected end of JSON input after object field key") - } - if b[0] != ':' { - return b, syntaxError(b, "expected ':' after object field key but found '%c'", b[0]) - } - b = skipSpaces(b[1:]) - - b, err = d.decodeRawMessage(b, unsafe.Pointer(&val)) - if err != nil { - if _, r, _, err := d.parseValue(input); err != nil { - return r, err - } else { - b = r - } - if e, ok := err.(*UnmarshalTypeError); ok { - e.Struct = mapStringRawMessageType.String() + e.Struct - e.Field = d.prependField(key, e.Field) - } - return b, err - } - - m[key] = val - i++ - } -} - -func (d decoder) decodeMapStringString(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - *(*unsafe.Pointer)(p) = nil - return b[4:], nil - } - - if len(b) < 2 || b[0] != '{' { - return d.inputError(b, mapStringStringType) - } - - i := 0 - m := *(*map[string]string)(p) - - if m == nil { - m = make(map[string]string, 64) - } - - var err error - var key string - var val string - input := b - - b = b[1:] - for { - key = "" - val = "" - - b = skipSpaces(b) - - if len(b) != 0 && b[0] == '}' { - *(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(unsafe.Pointer(&m)) - return b[1:], nil - } - - if i != 0 { - if len(b) == 0 { - return b, syntaxError(b, "unexpected end of JSON input after object field value") - } - if b[0] != ',' { - return b, syntaxError(b, "expected ',' after object field value but found '%c'", b[0]) - } - b = skipSpaces(b[1:]) - } - - if hasNullPrefix(b) { - return b, syntaxError(b, "cannot decode object key string from 'null' value") - } - - b, err = d.decodeString(b, unsafe.Pointer(&key)) - if err != nil { - return objectKeyError(b, err) - } - b = skipSpaces(b) - - if len(b) == 0 { - return b, syntaxError(b, "unexpected end of JSON input after object field key") - } - if b[0] != ':' { - return b, syntaxError(b, "expected ':' after object field key but found '%c'", b[0]) - } - b = skipSpaces(b[1:]) - - b, err = d.decodeString(b, unsafe.Pointer(&val)) - if err != nil { - if _, r, _, err := d.parseValue(input); err != nil { - return r, err - } else { - b = r - } - if e, ok := err.(*UnmarshalTypeError); ok { - e.Struct = mapStringStringType.String() + e.Struct - e.Field = d.prependField(key, e.Field) - } - return b, err - } - - m[key] = val - i++ - } -} - -func (d decoder) decodeMapStringStringSlice(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - *(*unsafe.Pointer)(p) = nil - return b[4:], nil - } - - if len(b) < 2 || b[0] != '{' { - return d.inputError(b, mapStringStringSliceType) - } - - i := 0 - m := *(*map[string][]string)(p) - - if m == nil { - m = make(map[string][]string, 64) - } - - var err error - var key string - var buf []string - input := b - stringSize := unsafe.Sizeof("") - - b = b[1:] - for { - key = "" - buf = buf[:0] - - b = skipSpaces(b) - - if len(b) != 0 && b[0] == '}' { - *(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(unsafe.Pointer(&m)) - return b[1:], nil - } - - if i != 0 { - if len(b) == 0 { - return b, syntaxError(b, "unexpected end of JSON input after object field value") - } - if b[0] != ',' { - return b, syntaxError(b, "expected ',' after object field value but found '%c'", b[0]) - } - b = skipSpaces(b[1:]) - } - - if hasNullPrefix(b) { - return b, syntaxError(b, "cannot decode object key string from 'null' value") - } - - b, err = d.decodeString(b, unsafe.Pointer(&key)) - if err != nil { - return objectKeyError(b, err) - } - b = skipSpaces(b) - - if len(b) == 0 { - return b, syntaxError(b, "unexpected end of JSON input after object field key") - } - if b[0] != ':' { - return b, syntaxError(b, "expected ':' after object field key but found '%c'", b[0]) - } - b = skipSpaces(b[1:]) - - b, err = d.decodeSlice(b, unsafe.Pointer(&buf), stringSize, sliceStringType, decoder.decodeString) - if err != nil { - if _, r, _, err := d.parseValue(input); err != nil { - return r, err - } else { - b = r - } - if e, ok := err.(*UnmarshalTypeError); ok { - e.Struct = mapStringStringType.String() + e.Struct - e.Field = d.prependField(key, e.Field) - } - return b, err - } - - val := make([]string, len(buf)) - copy(val, buf) - - m[key] = val - i++ - } -} - -func (d decoder) decodeMapStringBool(b []byte, p unsafe.Pointer) ([]byte, error) { - if hasNullPrefix(b) { - *(*unsafe.Pointer)(p) = nil - return b[4:], nil - } - - if len(b) < 2 || b[0] != '{' { - return d.inputError(b, mapStringBoolType) - } - - i := 0 - m := *(*map[string]bool)(p) - - if m == nil { - m = make(map[string]bool, 64) - } - - var err error - var key string - var val bool - input := b - - b = b[1:] - for { - key = "" - val = false - - b = skipSpaces(b) - - if len(b) != 0 && b[0] == '}' { - *(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(unsafe.Pointer(&m)) - return b[1:], nil - } - - if i != 0 { - if len(b) == 0 { - return b, syntaxError(b, "unexpected end of JSON input after object field value") - } - if b[0] != ',' { - return b, syntaxError(b, "expected ',' after object field value but found '%c'", b[0]) - } - b = skipSpaces(b[1:]) - } - - if hasNullPrefix(b) { - return b, syntaxError(b, "cannot decode object key string from 'null' value") - } - - b, err = d.decodeString(b, unsafe.Pointer(&key)) - if err != nil { - return objectKeyError(b, err) - } - b = skipSpaces(b) - - if len(b) == 0 { - return b, syntaxError(b, "unexpected end of JSON input after object field key") - } - if b[0] != ':' { - return b, syntaxError(b, "expected ':' after object field key but found '%c'", b[0]) - } - b = skipSpaces(b[1:]) - - b, err = d.decodeBool(b, unsafe.Pointer(&val)) - if err != nil { - if _, r, _, err := d.parseValue(input); err != nil { - return r, err - } else { - b = r - } - if e, ok := err.(*UnmarshalTypeError); ok { - e.Struct = mapStringStringType.String() + e.Struct - e.Field = d.prependField(key, e.Field) - } - return b, err - } - - m[key] = val - i++ - } -} - -func (d decoder) decodeStruct(b []byte, p unsafe.Pointer, st *structType) ([]byte, error) { - if hasNullPrefix(b) { - return b[4:], nil - } - - if len(b) < 2 || b[0] != '{' { - return d.inputError(b, st.typ) - } - - var err error - var k []byte - var i int - - // memory buffer used to convert short field names to lowercase - var buf [64]byte - var key []byte - input := b - - b = b[1:] - for { - b = skipSpaces(b) - - if len(b) != 0 && b[0] == '}' { - return b[1:], nil - } - - if i != 0 { - if len(b) == 0 { - return b, syntaxError(b, "unexpected end of JSON input after object field value") - } - if b[0] != ',' { - return b, syntaxError(b, "expected ',' after object field value but found '%c'", b[0]) - } - b = skipSpaces(b[1:]) - } - i++ - - if hasNullPrefix(b) { - return b, syntaxError(b, "cannot decode object key string from 'null' value") - } - - k, b, _, err = d.parseStringUnquote(b, nil) - if err != nil { - return objectKeyError(b, err) - } - b = skipSpaces(b) - - if len(b) == 0 { - return b, syntaxError(b, "unexpected end of JSON input after object field key") - } - if b[0] != ':' { - return b, syntaxError(b, "expected ':' after object field key but found '%c'", b[0]) - } - b = skipSpaces(b[1:]) - - var f *structField - if len(st.keyset) != 0 { - if n := keyset.Lookup(st.keyset, k); n < len(st.fields) { - f = &st.fields[n] - } - } else { - f = st.fieldsIndex[string(k)] - } - - if f == nil && (d.flags&DontMatchCaseInsensitiveStructFields) == 0 { - key = appendToLower(buf[:0], k) - f = st.ficaseIndex[string(key)] - } - - if f == nil { - if (d.flags & DisallowUnknownFields) != 0 { - return b, fmt.Errorf("json: unknown field %q", k) - } - if _, b, _, err = d.parseValue(b); err != nil { - return b, err - } - continue - } - - if b, err = f.codec.decode(d, b, unsafe.Pointer(uintptr(p)+f.offset)); err != nil { - if _, r, _, err := d.parseValue(input); err != nil { - return r, err - } else { - b = r - } - if e, ok := err.(*UnmarshalTypeError); ok { - e.Struct = st.typ.String() + e.Struct - e.Field = d.prependField(string(k), e.Field) - } - return b, err - } - } -} - -func (d decoder) decodeEmbeddedStructPointer(b []byte, p unsafe.Pointer, t reflect.Type, unexported bool, offset uintptr, decode decodeFunc) ([]byte, error) { - v := *(*unsafe.Pointer)(p) - - if v == nil { - if unexported { - return nil, fmt.Errorf("json: cannot set embedded pointer to unexported struct: %s", t) - } - v = unsafe.Pointer(reflect.New(t).Pointer()) - *(*unsafe.Pointer)(p) = v - } - - return decode(d, b, unsafe.Pointer(uintptr(v)+offset)) -} - -func (d decoder) decodePointer(b []byte, p unsafe.Pointer, t reflect.Type, decode decodeFunc) ([]byte, error) { - if hasNullPrefix(b) { - pp := *(*unsafe.Pointer)(p) - if pp != nil && t.Kind() == reflect.Ptr { - return decode(d, b, pp) - } - *(*unsafe.Pointer)(p) = nil - return b[4:], nil - } - - v := *(*unsafe.Pointer)(p) - if v == nil { - v = unsafe.Pointer(reflect.New(t).Pointer()) - *(*unsafe.Pointer)(p) = v - } - - return decode(d, b, v) -} - -func (d decoder) decodeInterface(b []byte, p unsafe.Pointer) ([]byte, error) { - val := *(*any)(p) - *(*any)(p) = nil - - if t := reflect.TypeOf(val); t != nil && t.Kind() == reflect.Ptr { - if v := reflect.ValueOf(val); v.IsNil() || t.Elem().Kind() != reflect.Ptr { - // If the destination is nil the only value that is OK to decode is - // `null`, and the encoding/json package always nils the destination - // interface value in this case. - if hasNullPrefix(b) { - *(*any)(p) = nil - return b[4:], nil - } - } - - b, err := Parse(b, val, d.flags) - if err == nil { - *(*any)(p) = val - } - - return b, err - } - - v, b, k, err := d.parseValue(b) - if err != nil { - return b, err - } - - switch k.Class() { - case Object: - m := make(map[string]interface{}) - v, err = d.decodeMapStringInterface(v, unsafe.Pointer(&m)) - val = m - - case Array: - a := make([]interface{}, 0, 10) - v, err = d.decodeSlice(v, unsafe.Pointer(&a), unsafe.Sizeof(a[0]), sliceInterfaceType, decoder.decodeInterface) - val = a - - case String: - s := "" - v, err = d.decodeString(v, unsafe.Pointer(&s)) - val = s - - case Null: - v, val = nil, nil - - case Bool: - v, val = nil, k == True - - case Num: - v, err = d.decodeDynamicNumber(v, unsafe.Pointer(&val)) - - default: - return b, syntaxError(v, "expected token but found '%c'", v[0]) - } - - if err != nil { - return b, err - } - - if v = skipSpaces(v); len(v) != 0 { - return b, syntaxError(v, "unexpected trailing trailing tokens after json value") - } - - *(*any)(p) = val - return b, nil -} - -func (d decoder) decodeDynamicNumber(b []byte, p unsafe.Pointer) ([]byte, error) { - kind := Float - var err error - - // Only pre-parse for numeric kind if a conditional decode - // has been requested. - if d.anyFlagsSet(UseBigInt | UseInt64 | UseUint64) { - _, _, kind, err = d.parseNumber(b) - if err != nil { - return b, err - } - } - - var rem []byte - anyPtr := (*any)(p) - - // Mutually exclusive integer handling cases. - switch { - // If requested, attempt decode of positive integers as uint64. - case kind == Uint && d.anyFlagsSet(UseUint64): - rem, err = decodeInto[uint64](anyPtr, b, d, decoder.decodeUint64) - if err == nil { - return rem, err - } - - // If uint64 decode was not requested but int64 decode was requested, - // then attempt decode of positive integers as int64. - case kind == Uint && d.anyFlagsSet(UseInt64): - fallthrough - - // If int64 decode was requested, - // attempt decode of negative integers as int64. - case kind == Int && d.anyFlagsSet(UseInt64): - rem, err = decodeInto[int64](anyPtr, b, d, decoder.decodeInt64) - if err == nil { - return rem, err - } - } - - // Fallback numeric handling cases: - // these cannot be combined into the above switch, - // since these cases also handle overflow - // from the above cases, if decode was already attempted. - switch { - // If *big.Int decode was requested, handle that case for any integer. - case kind == Uint && d.anyFlagsSet(UseBigInt): - fallthrough - case kind == Int && d.anyFlagsSet(UseBigInt): - rem, err = decodeInto[*big.Int](anyPtr, b, d, bigIntDecoder) - - // If json.Number decode was requested, handle that for any number. - case d.anyFlagsSet(UseNumber): - rem, err = decodeInto[Number](anyPtr, b, d, decoder.decodeNumber) - - // Fall back to float64 decode when no special decoding has been requested. - default: - rem, err = decodeInto[float64](anyPtr, b, d, decoder.decodeFloat64) - } - - return rem, err -} - -func (d decoder) decodeMaybeEmptyInterface(b []byte, p unsafe.Pointer, t reflect.Type) ([]byte, error) { - if hasNullPrefix(b) { - *(*any)(p) = nil - return b[4:], nil - } - - if x := reflect.NewAt(t, p).Elem(); !x.IsNil() { - if e := x.Elem(); e.Kind() == reflect.Ptr { - return Parse(b, e.Interface(), d.flags) - } - } else if t.NumMethod() == 0 { // empty interface - return Parse(b, (*any)(p), d.flags) - } - - return d.decodeUnmarshalTypeError(b, p, t) -} - -func (d decoder) decodeUnmarshalTypeError(b []byte, _ unsafe.Pointer, t reflect.Type) ([]byte, error) { - v, b, _, err := d.parseValue(b) - if err != nil { - return b, err - } - return b, &UnmarshalTypeError{ - Value: string(v), - Type: t, - } -} - -func (d decoder) decodeRawMessage(b []byte, p unsafe.Pointer) ([]byte, error) { - v, r, _, err := d.parseValue(b) - if err != nil { - return d.inputError(b, rawMessageType) - } - - if (d.flags & DontCopyRawMessage) == 0 { - v = append(make([]byte, 0, len(v)), v...) - } - - *(*RawMessage)(p) = json.RawMessage(v) - return r, err -} - -func (d decoder) decodeJSONUnmarshaler(b []byte, p unsafe.Pointer, t reflect.Type, pointer bool) ([]byte, error) { - v, b, _, err := d.parseValue(b) - if err != nil { - return b, err - } - - u := reflect.NewAt(t, p) - if !pointer { - u = u.Elem() - t = t.Elem() - } - if u.IsNil() { - u.Set(reflect.New(t)) - } - - return b, u.Interface().(Unmarshaler).UnmarshalJSON(v) -} - -func (d decoder) decodeTextUnmarshaler(b []byte, p unsafe.Pointer, t reflect.Type, pointer bool) ([]byte, error) { - var value string - - v, b, k, err := d.parseValue(b) - if err != nil { - return b, err - } - if len(v) == 0 { - return d.inputError(v, t) - } - - switch k.Class() { - case Null: - return b, err - - case String: - s, _, _, err := d.parseStringUnquote(v, nil) - if err != nil { - return b, err - } - u := reflect.NewAt(t, p) - if !pointer { - u = u.Elem() - t = t.Elem() - } - if u.IsNil() { - u.Set(reflect.New(t)) - } - return b, u.Interface().(encoding.TextUnmarshaler).UnmarshalText(s) - - case Bool: - if k == True { - value = "true" - } else { - value = "false" - } - - case Num: - value = "number" - - case Object: - value = "object" - - case Array: - value = "array" - } - - return b, &UnmarshalTypeError{Value: value, Type: reflect.PointerTo(t)} -} - -func (d decoder) prependField(key, field string) string { - if field != "" { - return key + "." + field - } - return key -} - -func (d decoder) inputError(b []byte, t reflect.Type) ([]byte, error) { - if len(b) == 0 { - return nil, unexpectedEOF(b) - } - _, r, _, err := d.parseValue(b) - if err != nil { - return r, err - } - return skipSpaces(r), unmarshalTypeError(b, t) -} - -func decodeInto[T any](dest *any, b []byte, d decoder, fn decodeFunc) ([]byte, error) { - var v T - rem, err := fn(d, b, unsafe.Pointer(&v)) - if err == nil { - *dest = v - } - - return rem, err -} diff --git a/go/sdk/vendor/github.com/segmentio/encoding/json/encode.go b/go/sdk/vendor/github.com/segmentio/encoding/json/encode.go deleted file mode 100644 index 2a6da07..0000000 --- a/go/sdk/vendor/github.com/segmentio/encoding/json/encode.go +++ /dev/null @@ -1,970 +0,0 @@ -package json - -import ( - "encoding" - "fmt" - "math" - "reflect" - "sort" - "strconv" - "sync" - "time" - "unicode/utf8" - "unsafe" - - "github.com/segmentio/asm/base64" -) - -const hex = "0123456789abcdef" - -func (e encoder) encodeNull(b []byte, p unsafe.Pointer) ([]byte, error) { - return append(b, "null"...), nil -} - -func (e encoder) encodeBool(b []byte, p unsafe.Pointer) ([]byte, error) { - if *(*bool)(p) { - return append(b, "true"...), nil - } - return append(b, "false"...), nil -} - -func (e encoder) encodeInt(b []byte, p unsafe.Pointer) ([]byte, error) { - return appendInt(b, int64(*(*int)(p))), nil -} - -func (e encoder) encodeInt8(b []byte, p unsafe.Pointer) ([]byte, error) { - return appendInt(b, int64(*(*int8)(p))), nil -} - -func (e encoder) encodeInt16(b []byte, p unsafe.Pointer) ([]byte, error) { - return appendInt(b, int64(*(*int16)(p))), nil -} - -func (e encoder) encodeInt32(b []byte, p unsafe.Pointer) ([]byte, error) { - return appendInt(b, int64(*(*int32)(p))), nil -} - -func (e encoder) encodeInt64(b []byte, p unsafe.Pointer) ([]byte, error) { - return appendInt(b, *(*int64)(p)), nil -} - -func (e encoder) encodeUint(b []byte, p unsafe.Pointer) ([]byte, error) { - return appendUint(b, uint64(*(*uint)(p))), nil -} - -func (e encoder) encodeUintptr(b []byte, p unsafe.Pointer) ([]byte, error) { - return appendUint(b, uint64(*(*uintptr)(p))), nil -} - -func (e encoder) encodeUint8(b []byte, p unsafe.Pointer) ([]byte, error) { - return appendUint(b, uint64(*(*uint8)(p))), nil -} - -func (e encoder) encodeUint16(b []byte, p unsafe.Pointer) ([]byte, error) { - return appendUint(b, uint64(*(*uint16)(p))), nil -} - -func (e encoder) encodeUint32(b []byte, p unsafe.Pointer) ([]byte, error) { - return appendUint(b, uint64(*(*uint32)(p))), nil -} - -func (e encoder) encodeUint64(b []byte, p unsafe.Pointer) ([]byte, error) { - return appendUint(b, *(*uint64)(p)), nil -} - -func (e encoder) encodeFloat32(b []byte, p unsafe.Pointer) ([]byte, error) { - return e.encodeFloat(b, float64(*(*float32)(p)), 32) -} - -func (e encoder) encodeFloat64(b []byte, p unsafe.Pointer) ([]byte, error) { - return e.encodeFloat(b, *(*float64)(p), 64) -} - -func (e encoder) encodeFloat(b []byte, f float64, bits int) ([]byte, error) { - switch { - case math.IsNaN(f): - return b, &UnsupportedValueError{Value: reflect.ValueOf(f), Str: "NaN"} - case math.IsInf(f, 0): - return b, &UnsupportedValueError{Value: reflect.ValueOf(f), Str: "inf"} - } - - // Convert as if by ES6 number to string conversion. - // This matches most other JSON generators. - // See golang.org/issue/6384 and golang.org/issue/14135. - // Like fmt %g, but the exponent cutoffs are different - // and exponents themselves are not padded to two digits. - abs := math.Abs(f) - fmt := byte('f') - // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right. - if abs != 0 { - if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) { - fmt = 'e' - } - } - - b = strconv.AppendFloat(b, f, fmt, -1, int(bits)) - - if fmt == 'e' { - // clean up e-09 to e-9 - n := len(b) - if n >= 4 && b[n-4] == 'e' && b[n-3] == '-' && b[n-2] == '0' { - b[n-2] = b[n-1] - b = b[:n-1] - } - } - - return b, nil -} - -func (e encoder) encodeNumber(b []byte, p unsafe.Pointer) ([]byte, error) { - n := *(*Number)(p) - if n == "" { - n = "0" - } - - d := decoder{} - _, _, _, err := d.parseNumber(stringToBytes(string(n))) - if err != nil { - return b, err - } - - return append(b, n...), nil -} - -func (e encoder) encodeString(b []byte, p unsafe.Pointer) ([]byte, error) { - s := *(*string)(p) - if len(s) == 0 { - return append(b, `""`...), nil - } - i := 0 - j := 0 - escapeHTML := (e.flags & EscapeHTML) != 0 - - b = append(b, '"') - - if len(s) >= 8 { - if j = escapeIndex(s, escapeHTML); j < 0 { - return append(append(b, s...), '"'), nil - } - } - - for j < len(s) { - c := s[j] - - if c >= 0x20 && c <= 0x7f && c != '\\' && c != '"' && (!escapeHTML || (c != '<' && c != '>' && c != '&')) { - // fast path: most of the time, printable ascii characters are used - j++ - continue - } - - switch c { - case '\\', '"', '\b', '\f', '\n', '\r', '\t': - b = append(b, s[i:j]...) - b = append(b, '\\', escapeByteRepr(c)) - i = j + 1 - j = j + 1 - continue - - case '<', '>', '&': - b = append(b, s[i:j]...) - b = append(b, `\u00`...) - b = append(b, hex[c>>4], hex[c&0xF]) - i = j + 1 - j = j + 1 - continue - } - - // This encodes bytes < 0x20 except for \t, \n and \r. - if c < 0x20 { - b = append(b, s[i:j]...) - b = append(b, `\u00`...) - b = append(b, hex[c>>4], hex[c&0xF]) - i = j + 1 - j = j + 1 - continue - } - - r, size := utf8.DecodeRuneInString(s[j:]) - - if r == utf8.RuneError && size == 1 { - b = append(b, s[i:j]...) - b = append(b, `\ufffd`...) - i = j + size - j = j + size - continue - } - - switch r { - case '\u2028', '\u2029': - // U+2028 is LINE SEPARATOR. - // U+2029 is PARAGRAPH SEPARATOR. - // They are both technically valid characters in JSON strings, - // but don't work in JSONP, which has to be evaluated as JavaScript, - // and can lead to security holes there. It is valid JSON to - // escape them, so we do so unconditionally. - // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. - b = append(b, s[i:j]...) - b = append(b, `\u202`...) - b = append(b, hex[r&0xF]) - i = j + size - j = j + size - continue - } - - j += size - } - - b = append(b, s[i:]...) - b = append(b, '"') - return b, nil -} - -func (e encoder) encodeToString(b []byte, p unsafe.Pointer, encode encodeFunc) ([]byte, error) { - i := len(b) - - b, err := encode(e, b, p) - if err != nil { - return b, err - } - - j := len(b) - s := b[i:] - - if b, err = e.encodeString(b, unsafe.Pointer(&s)); err != nil { - return b, err - } - - n := copy(b[i:], b[j:]) - return b[:i+n], nil -} - -func (e encoder) encodeBytes(b []byte, p unsafe.Pointer) ([]byte, error) { - v := *(*[]byte)(p) - if v == nil { - return append(b, "null"...), nil - } - - n := base64.StdEncoding.EncodedLen(len(v)) + 2 - - if avail := cap(b) - len(b); avail < n { - newB := make([]byte, cap(b)+(n-avail)) - copy(newB, b) - b = newB[:len(b)] - } - - i := len(b) - j := len(b) + n - - b = b[:j] - b[i] = '"' - base64.StdEncoding.Encode(b[i+1:j-1], v) - b[j-1] = '"' - return b, nil -} - -func (e encoder) encodeDuration(b []byte, p unsafe.Pointer) ([]byte, error) { - b = append(b, '"') - b = appendDuration(b, *(*time.Duration)(p)) - b = append(b, '"') - return b, nil -} - -func (e encoder) encodeTime(b []byte, p unsafe.Pointer) ([]byte, error) { - t := *(*time.Time)(p) - b = append(b, '"') - b = t.AppendFormat(b, time.RFC3339Nano) - b = append(b, '"') - return b, nil -} - -func (e encoder) encodeArray(b []byte, p unsafe.Pointer, n int, size uintptr, t reflect.Type, encode encodeFunc) ([]byte, error) { - start := len(b) - var err error - b = append(b, '[') - - for i := range n { - if i != 0 { - b = append(b, ',') - } - if b, err = encode(e, b, unsafe.Pointer(uintptr(p)+(uintptr(i)*size))); err != nil { - return b[:start], err - } - } - - b = append(b, ']') - return b, nil -} - -func (e encoder) encodeSlice(b []byte, p unsafe.Pointer, size uintptr, t reflect.Type, encode encodeFunc) ([]byte, error) { - s := (*slice)(p) - - if s.data == nil && s.len == 0 && s.cap == 0 { - return append(b, "null"...), nil - } - - return e.encodeArray(b, s.data, s.len, size, t, encode) -} - -func (e encoder) encodeMap(b []byte, p unsafe.Pointer, t reflect.Type, encodeKey, encodeValue encodeFunc, sortKeys sortFunc) ([]byte, error) { - m := reflect.NewAt(t, p).Elem() - if m.IsNil() { - return append(b, "null"...), nil - } - - keys := m.MapKeys() - if sortKeys != nil && (e.flags&SortMapKeys) != 0 { - sortKeys(keys) - } - - start := len(b) - var err error - b = append(b, '{') - - for i, k := range keys { - v := m.MapIndex(k) - - if i != 0 { - b = append(b, ',') - } - - if b, err = encodeKey(e, b, (*iface)(unsafe.Pointer(&k)).ptr); err != nil { - return b[:start], err - } - - b = append(b, ':') - - if b, err = encodeValue(e, b, (*iface)(unsafe.Pointer(&v)).ptr); err != nil { - return b[:start], err - } - } - - b = append(b, '}') - return b, nil -} - -type element struct { - key string - val any - raw RawMessage -} - -type mapslice struct { - elements []element -} - -func (m *mapslice) Len() int { return len(m.elements) } -func (m *mapslice) Less(i, j int) bool { return m.elements[i].key < m.elements[j].key } -func (m *mapslice) Swap(i, j int) { m.elements[i], m.elements[j] = m.elements[j], m.elements[i] } - -var mapslicePool = sync.Pool{ - New: func() any { return new(mapslice) }, -} - -func (e encoder) encodeMapStringInterface(b []byte, p unsafe.Pointer) ([]byte, error) { - m := *(*map[string]any)(p) - if m == nil { - return append(b, "null"...), nil - } - - if (e.flags & SortMapKeys) == 0 { - // Optimized code path when the program does not need the map keys to be - // sorted. - b = append(b, '{') - - if len(m) != 0 { - var err error - i := 0 - - for k, v := range m { - if i != 0 { - b = append(b, ',') - } - - b, _ = e.encodeString(b, unsafe.Pointer(&k)) - b = append(b, ':') - - b, err = Append(b, v, e.flags) - if err != nil { - return b, err - } - - i++ - } - } - - b = append(b, '}') - return b, nil - } - - s := mapslicePool.Get().(*mapslice) - if cap(s.elements) < len(m) { - s.elements = make([]element, 0, align(10, uintptr(len(m)))) - } - for key, val := range m { - s.elements = append(s.elements, element{key: key, val: val}) - } - sort.Sort(s) - - start := len(b) - var err error - b = append(b, '{') - - for i, elem := range s.elements { - if i != 0 { - b = append(b, ',') - } - - b, _ = e.encodeString(b, unsafe.Pointer(&elem.key)) - b = append(b, ':') - - b, err = Append(b, elem.val, e.flags) - if err != nil { - break - } - } - - for i := range s.elements { - s.elements[i] = element{} - } - - s.elements = s.elements[:0] - mapslicePool.Put(s) - - if err != nil { - return b[:start], err - } - - b = append(b, '}') - return b, nil -} - -func (e encoder) encodeMapStringRawMessage(b []byte, p unsafe.Pointer) ([]byte, error) { - m := *(*map[string]RawMessage)(p) - if m == nil { - return append(b, "null"...), nil - } - - if (e.flags & SortMapKeys) == 0 { - // Optimized code path when the program does not need the map keys to be - // sorted. - b = append(b, '{') - - if len(m) != 0 { - var err error - i := 0 - - for k, v := range m { - if i != 0 { - b = append(b, ',') - } - - // encodeString doesn't return errors so we ignore it here - b, _ = e.encodeString(b, unsafe.Pointer(&k)) - b = append(b, ':') - - b, err = e.encodeRawMessage(b, unsafe.Pointer(&v)) - if err != nil { - break - } - - i++ - } - } - - b = append(b, '}') - return b, nil - } - - s := mapslicePool.Get().(*mapslice) - if cap(s.elements) < len(m) { - s.elements = make([]element, 0, align(10, uintptr(len(m)))) - } - for key, raw := range m { - s.elements = append(s.elements, element{key: key, raw: raw}) - } - sort.Sort(s) - - start := len(b) - var err error - b = append(b, '{') - - for i, elem := range s.elements { - if i != 0 { - b = append(b, ',') - } - - b, _ = e.encodeString(b, unsafe.Pointer(&elem.key)) - b = append(b, ':') - - b, err = e.encodeRawMessage(b, unsafe.Pointer(&elem.raw)) - if err != nil { - break - } - } - - for i := range s.elements { - s.elements[i] = element{} - } - - s.elements = s.elements[:0] - mapslicePool.Put(s) - - if err != nil { - return b[:start], err - } - - b = append(b, '}') - return b, nil -} - -func (e encoder) encodeMapStringString(b []byte, p unsafe.Pointer) ([]byte, error) { - m := *(*map[string]string)(p) - if m == nil { - return append(b, "null"...), nil - } - - if (e.flags & SortMapKeys) == 0 { - // Optimized code path when the program does not need the map keys to be - // sorted. - b = append(b, '{') - - if len(m) != 0 { - i := 0 - - for k, v := range m { - if i != 0 { - b = append(b, ',') - } - - // encodeString never returns an error so we ignore it here - b, _ = e.encodeString(b, unsafe.Pointer(&k)) - b = append(b, ':') - b, _ = e.encodeString(b, unsafe.Pointer(&v)) - - i++ - } - } - - b = append(b, '}') - return b, nil - } - - s := mapslicePool.Get().(*mapslice) - if cap(s.elements) < len(m) { - s.elements = make([]element, 0, align(10, uintptr(len(m)))) - } - for key, val := range m { - v := val - s.elements = append(s.elements, element{key: key, val: &v}) - } - sort.Sort(s) - - b = append(b, '{') - - for i, elem := range s.elements { - if i != 0 { - b = append(b, ',') - } - - // encodeString never returns an error so we ignore it here - b, _ = e.encodeString(b, unsafe.Pointer(&elem.key)) - b = append(b, ':') - b, _ = e.encodeString(b, unsafe.Pointer(elem.val.(*string))) - } - - for i := range s.elements { - s.elements[i] = element{} - } - - s.elements = s.elements[:0] - mapslicePool.Put(s) - - b = append(b, '}') - return b, nil -} - -func (e encoder) encodeMapStringStringSlice(b []byte, p unsafe.Pointer) ([]byte, error) { - m := *(*map[string][]string)(p) - if m == nil { - return append(b, "null"...), nil - } - - stringSize := unsafe.Sizeof("") - - if (e.flags & SortMapKeys) == 0 { - // Optimized code path when the program does not need the map keys to be - // sorted. - b = append(b, '{') - - if len(m) != 0 { - var err error - i := 0 - - for k, v := range m { - if i != 0 { - b = append(b, ',') - } - - b, _ = e.encodeString(b, unsafe.Pointer(&k)) - b = append(b, ':') - - b, err = e.encodeSlice(b, unsafe.Pointer(&v), stringSize, sliceStringType, encoder.encodeString) - if err != nil { - return b, err - } - - i++ - } - } - - b = append(b, '}') - return b, nil - } - - s := mapslicePool.Get().(*mapslice) - if cap(s.elements) < len(m) { - s.elements = make([]element, 0, align(10, uintptr(len(m)))) - } - for key, val := range m { - v := val - s.elements = append(s.elements, element{key: key, val: &v}) - } - sort.Sort(s) - - start := len(b) - var err error - b = append(b, '{') - - for i, elem := range s.elements { - if i != 0 { - b = append(b, ',') - } - - b, _ = e.encodeString(b, unsafe.Pointer(&elem.key)) - b = append(b, ':') - - b, err = e.encodeSlice(b, unsafe.Pointer(elem.val.(*[]string)), stringSize, sliceStringType, encoder.encodeString) - if err != nil { - break - } - } - - for i := range s.elements { - s.elements[i] = element{} - } - - s.elements = s.elements[:0] - mapslicePool.Put(s) - - if err != nil { - return b[:start], err - } - - b = append(b, '}') - return b, nil -} - -func (e encoder) encodeMapStringBool(b []byte, p unsafe.Pointer) ([]byte, error) { - m := *(*map[string]bool)(p) - if m == nil { - return append(b, "null"...), nil - } - - if (e.flags & SortMapKeys) == 0 { - // Optimized code path when the program does not need the map keys to be - // sorted. - b = append(b, '{') - - if len(m) != 0 { - i := 0 - - for k, v := range m { - if i != 0 { - b = append(b, ',') - } - - // encodeString never returns an error so we ignore it here - b, _ = e.encodeString(b, unsafe.Pointer(&k)) - if v { - b = append(b, ":true"...) - } else { - b = append(b, ":false"...) - } - - i++ - } - } - - b = append(b, '}') - return b, nil - } - - s := mapslicePool.Get().(*mapslice) - if cap(s.elements) < len(m) { - s.elements = make([]element, 0, align(10, uintptr(len(m)))) - } - for key, val := range m { - s.elements = append(s.elements, element{key: key, val: val}) - } - sort.Sort(s) - - b = append(b, '{') - - for i, elem := range s.elements { - if i != 0 { - b = append(b, ',') - } - - // encodeString never returns an error so we ignore it here - b, _ = e.encodeString(b, unsafe.Pointer(&elem.key)) - if elem.val.(bool) { - b = append(b, ":true"...) - } else { - b = append(b, ":false"...) - } - } - - for i := range s.elements { - s.elements[i] = element{} - } - - s.elements = s.elements[:0] - mapslicePool.Put(s) - - b = append(b, '}') - return b, nil -} - -func (e encoder) encodeStruct(b []byte, p unsafe.Pointer, st *structType) ([]byte, error) { - start := len(b) - var err error - var k string - var n int - b = append(b, '{') - - escapeHTML := (e.flags & EscapeHTML) != 0 - - for i := range st.fields { - f := &st.fields[i] - v := unsafe.Pointer(uintptr(p) + f.offset) - - if f.omitempty && f.empty(v) { - continue - } - - if escapeHTML { - k = f.html - } else { - k = f.json - } - - lengthBeforeKey := len(b) - - if n != 0 { - b = append(b, k...) - } else { - b = append(b, k[1:]...) - } - - if b, err = f.codec.encode(e, b, v); err != nil { - if err == (rollback{}) { - b = b[:lengthBeforeKey] - continue - } - return b[:start], err - } - - n++ - } - - b = append(b, '}') - return b, nil -} - -type rollback struct{} - -func (rollback) Error() string { return "rollback" } - -func (e encoder) encodeEmbeddedStructPointer(b []byte, p unsafe.Pointer, t reflect.Type, unexported bool, offset uintptr, encode encodeFunc) ([]byte, error) { - p = *(*unsafe.Pointer)(p) - if p == nil { - return b, rollback{} - } - return encode(e, b, unsafe.Pointer(uintptr(p)+offset)) -} - -func (e encoder) encodePointer(b []byte, p unsafe.Pointer, t reflect.Type, encode encodeFunc) ([]byte, error) { - if p = *(*unsafe.Pointer)(p); p != nil { - if e.ptrDepth++; e.ptrDepth >= startDetectingCyclesAfter { - if _, seen := e.ptrSeen[p]; seen { - // TODO: reconstruct the reflect.Value from p + t so we can set - // the erorr's Value field? - return b, &UnsupportedValueError{Str: fmt.Sprintf("encountered a cycle via %s", t)} - } - if e.ptrSeen == nil { - e.ptrSeen = make(map[unsafe.Pointer]struct{}) - } - e.ptrSeen[p] = struct{}{} - defer delete(e.ptrSeen, p) - } - return encode(e, b, p) - } - return e.encodeNull(b, nil) -} - -func (e encoder) encodeInterface(b []byte, p unsafe.Pointer) ([]byte, error) { - return Append(b, *(*any)(p), e.flags) -} - -func (e encoder) encodeMaybeEmptyInterface(b []byte, p unsafe.Pointer, t reflect.Type) ([]byte, error) { - return Append(b, reflect.NewAt(t, p).Elem().Interface(), e.flags) -} - -func (e encoder) encodeUnsupportedTypeError(b []byte, p unsafe.Pointer, t reflect.Type) ([]byte, error) { - return b, &UnsupportedTypeError{Type: t} -} - -func (e encoder) encodeRawMessage(b []byte, p unsafe.Pointer) ([]byte, error) { - v := *(*RawMessage)(p) - - if v == nil { - return append(b, "null"...), nil - } - - var s []byte - - if (e.flags & TrustRawMessage) != 0 { - s = v - } else { - var err error - v = skipSpaces(v) // don't assume that a RawMessage starts with a token. - d := decoder{} - s, _, _, err = d.parseValue(v) - if err != nil { - return b, &UnsupportedValueError{Value: reflect.ValueOf(v), Str: err.Error()} - } - } - - if (e.flags & EscapeHTML) != 0 { - return appendCompactEscapeHTML(b, s), nil - } - - return append(b, s...), nil -} - -func (e encoder) encodeJSONMarshaler(b []byte, p unsafe.Pointer, t reflect.Type, pointer bool) ([]byte, error) { - v := reflect.NewAt(t, p) - - if !pointer { - v = v.Elem() - } - - switch v.Kind() { - case reflect.Ptr, reflect.Interface: - if v.IsNil() { - return append(b, "null"...), nil - } - } - - j, err := v.Interface().(Marshaler).MarshalJSON() - if err != nil { - return b, err - } - - d := decoder{} - s, _, _, err := d.parseValue(j) - if err != nil { - return b, &MarshalerError{Type: t, Err: err} - } - - if (e.flags & EscapeHTML) != 0 { - return appendCompactEscapeHTML(b, s), nil - } - - return append(b, s...), nil -} - -func (e encoder) encodeTextMarshaler(b []byte, p unsafe.Pointer, t reflect.Type, pointer bool) ([]byte, error) { - v := reflect.NewAt(t, p) - - if !pointer { - v = v.Elem() - } - - switch v.Kind() { - case reflect.Ptr, reflect.Interface: - if v.IsNil() { - return append(b, `null`...), nil - } - } - - s, err := v.Interface().(encoding.TextMarshaler).MarshalText() - if err != nil { - return b, err - } - - return e.encodeString(b, unsafe.Pointer(&s)) -} - -func appendCompactEscapeHTML(dst []byte, src []byte) []byte { - start := 0 - escape := false - inString := false - - for i, c := range src { - if !inString { - switch c { - case '"': // enter string - inString = true - case ' ', '\n', '\r', '\t': // skip space - if start < i { - dst = append(dst, src[start:i]...) - } - start = i + 1 - } - continue - } - - if escape { - escape = false - continue - } - - if c == '\\' { - escape = true - continue - } - - if c == '"' { - inString = false - continue - } - - if c == '<' || c == '>' || c == '&' { - if start < i { - dst = append(dst, src[start:i]...) - } - dst = append(dst, `\u00`...) - dst = append(dst, hex[c>>4], hex[c&0xF]) - start = i + 1 - continue - } - - // Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9). - if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 { - if start < i { - dst = append(dst, src[start:i]...) - } - dst = append(dst, `\u202`...) - dst = append(dst, hex[src[i+2]&0xF]) - start = i + 3 - continue - } - } - - if start < len(src) { - dst = append(dst, src[start:]...) - } - - return dst -} diff --git a/go/sdk/vendor/github.com/segmentio/encoding/json/int.go b/go/sdk/vendor/github.com/segmentio/encoding/json/int.go deleted file mode 100644 index b53149c..0000000 --- a/go/sdk/vendor/github.com/segmentio/encoding/json/int.go +++ /dev/null @@ -1,98 +0,0 @@ -package json - -import ( - "unsafe" -) - -var endianness int - -func init() { - var b [2]byte - *(*uint16)(unsafe.Pointer(&b)) = uint16(0xABCD) - - switch b[0] { - case 0xCD: - endianness = 0 // LE - case 0xAB: - endianness = 1 // BE - default: - panic("could not determine endianness") - } -} - -// "00010203...96979899" cast to []uint16 -var intLELookup = [100]uint16{ - 0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, 0x3630, 0x3730, 0x3830, 0x3930, - 0x3031, 0x3131, 0x3231, 0x3331, 0x3431, 0x3531, 0x3631, 0x3731, 0x3831, 0x3931, - 0x3032, 0x3132, 0x3232, 0x3332, 0x3432, 0x3532, 0x3632, 0x3732, 0x3832, 0x3932, - 0x3033, 0x3133, 0x3233, 0x3333, 0x3433, 0x3533, 0x3633, 0x3733, 0x3833, 0x3933, - 0x3034, 0x3134, 0x3234, 0x3334, 0x3434, 0x3534, 0x3634, 0x3734, 0x3834, 0x3934, - 0x3035, 0x3135, 0x3235, 0x3335, 0x3435, 0x3535, 0x3635, 0x3735, 0x3835, 0x3935, - 0x3036, 0x3136, 0x3236, 0x3336, 0x3436, 0x3536, 0x3636, 0x3736, 0x3836, 0x3936, - 0x3037, 0x3137, 0x3237, 0x3337, 0x3437, 0x3537, 0x3637, 0x3737, 0x3837, 0x3937, - 0x3038, 0x3138, 0x3238, 0x3338, 0x3438, 0x3538, 0x3638, 0x3738, 0x3838, 0x3938, - 0x3039, 0x3139, 0x3239, 0x3339, 0x3439, 0x3539, 0x3639, 0x3739, 0x3839, 0x3939, -} - -var intBELookup = [100]uint16{ - 0x3030, 0x3031, 0x3032, 0x3033, 0x3034, 0x3035, 0x3036, 0x3037, 0x3038, 0x3039, - 0x3130, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137, 0x3138, 0x3139, - 0x3230, 0x3231, 0x3232, 0x3233, 0x3234, 0x3235, 0x3236, 0x3237, 0x3238, 0x3239, - 0x3330, 0x3331, 0x3332, 0x3333, 0x3334, 0x3335, 0x3336, 0x3337, 0x3338, 0x3339, - 0x3430, 0x3431, 0x3432, 0x3433, 0x3434, 0x3435, 0x3436, 0x3437, 0x3438, 0x3439, - 0x3530, 0x3531, 0x3532, 0x3533, 0x3534, 0x3535, 0x3536, 0x3537, 0x3538, 0x3539, - 0x3630, 0x3631, 0x3632, 0x3633, 0x3634, 0x3635, 0x3636, 0x3637, 0x3638, 0x3639, - 0x3730, 0x3731, 0x3732, 0x3733, 0x3734, 0x3735, 0x3736, 0x3737, 0x3738, 0x3739, - 0x3830, 0x3831, 0x3832, 0x3833, 0x3834, 0x3835, 0x3836, 0x3837, 0x3838, 0x3839, - 0x3930, 0x3931, 0x3932, 0x3933, 0x3934, 0x3935, 0x3936, 0x3937, 0x3938, 0x3939, -} - -var intLookup = [2]*[100]uint16{&intLELookup, &intBELookup} - -func appendInt(b []byte, n int64) []byte { - return formatInteger(b, uint64(n), n < 0) -} - -func appendUint(b []byte, n uint64) []byte { - return formatInteger(b, n, false) -} - -func formatInteger(out []byte, n uint64, negative bool) []byte { - if !negative { - if n < 10 { - return append(out, byte(n+'0')) - } else if n < 100 { - u := intLELookup[n] - return append(out, byte(u), byte(u>>8)) - } - } else { - n = -n - } - - lookup := intLookup[endianness] - - var b [22]byte - u := (*[11]uint16)(unsafe.Pointer(&b)) - i := 11 - - for n >= 100 { - j := n % 100 - n /= 100 - i-- - u[i] = lookup[j] - } - - i-- - u[i] = lookup[n] - - i *= 2 // convert to byte index - if n < 10 { - i++ // remove leading zero - } - if negative { - i-- - b[i] = '-' - } - - return append(out, b[i:]...) -} diff --git a/go/sdk/vendor/github.com/segmentio/encoding/json/json.go b/go/sdk/vendor/github.com/segmentio/encoding/json/json.go deleted file mode 100644 index 028fd1f..0000000 --- a/go/sdk/vendor/github.com/segmentio/encoding/json/json.go +++ /dev/null @@ -1,594 +0,0 @@ -package json - -import ( - "bytes" - "encoding/json" - "io" - "math/bits" - "reflect" - "runtime" - "sync" - "unsafe" -) - -// Delim is documented at https://golang.org/pkg/encoding/json/#Delim -type Delim = json.Delim - -// InvalidUTF8Error is documented at https://golang.org/pkg/encoding/json/#InvalidUTF8Error -type InvalidUTF8Error = json.InvalidUTF8Error //nolint:staticcheck // compat. - -// InvalidUnmarshalError is documented at https://golang.org/pkg/encoding/json/#InvalidUnmarshalError -type InvalidUnmarshalError = json.InvalidUnmarshalError - -// Marshaler is documented at https://golang.org/pkg/encoding/json/#Marshaler -type Marshaler = json.Marshaler - -// MarshalerError is documented at https://golang.org/pkg/encoding/json/#MarshalerError -type MarshalerError = json.MarshalerError - -// Number is documented at https://golang.org/pkg/encoding/json/#Number -type Number = json.Number - -// RawMessage is documented at https://golang.org/pkg/encoding/json/#RawMessage -type RawMessage = json.RawMessage - -// A SyntaxError is a description of a JSON syntax error. -type SyntaxError = json.SyntaxError - -// Token is documented at https://golang.org/pkg/encoding/json/#Token -type Token = json.Token - -// UnmarshalFieldError is documented at https://golang.org/pkg/encoding/json/#UnmarshalFieldError -type UnmarshalFieldError = json.UnmarshalFieldError //nolint:staticcheck // compat. - -// UnmarshalTypeError is documented at https://golang.org/pkg/encoding/json/#UnmarshalTypeError -type UnmarshalTypeError = json.UnmarshalTypeError - -// Unmarshaler is documented at https://golang.org/pkg/encoding/json/#Unmarshaler -type Unmarshaler = json.Unmarshaler - -// UnsupportedTypeError is documented at https://golang.org/pkg/encoding/json/#UnsupportedTypeError -type UnsupportedTypeError = json.UnsupportedTypeError - -// UnsupportedValueError is documented at https://golang.org/pkg/encoding/json/#UnsupportedValueError -type UnsupportedValueError = json.UnsupportedValueError - -// AppendFlags is a type used to represent configuration options that can be -// applied when formatting json output. -type AppendFlags uint32 - -const ( - // EscapeHTML is a formatting flag used to to escape HTML in json strings. - EscapeHTML AppendFlags = 1 << iota - - // SortMapKeys is formatting flag used to enable sorting of map keys when - // encoding JSON (this matches the behavior of the standard encoding/json - // package). - SortMapKeys - - // TrustRawMessage is a performance optimization flag to skip value - // checking of raw messages. It should only be used if the values are - // known to be valid json (e.g., they were created by json.Unmarshal). - TrustRawMessage - - // appendNewline is a formatting flag to enable the addition of a newline - // in Encode (this matches the behavior of the standard encoding/json - // package). - appendNewline -) - -// ParseFlags is a type used to represent configuration options that can be -// applied when parsing json input. -type ParseFlags uint32 - -func (flags ParseFlags) has(f ParseFlags) bool { - return (flags & f) != 0 -} - -func (f ParseFlags) kind() Kind { - return Kind((f >> kindOffset) & 0xFF) -} - -func (f ParseFlags) withKind(kind Kind) ParseFlags { - return (f & ^(ParseFlags(0xFF) << kindOffset)) | (ParseFlags(kind) << kindOffset) -} - -const ( - // DisallowUnknownFields is a parsing flag used to prevent decoding of - // objects to Go struct values when a field of the input does not match - // with any of the struct fields. - DisallowUnknownFields ParseFlags = 1 << iota - - // UseNumber is a parsing flag used to load numeric values as Number - // instead of float64. - UseNumber - - // DontCopyString is a parsing flag used to provide zero-copy support when - // loading string values from a json payload. It is not always possible to - // avoid dynamic memory allocations, for example when a string is escaped in - // the json data a new buffer has to be allocated, but when the `wire` value - // can be used as content of a Go value the decoder will simply point into - // the input buffer. - DontCopyString - - // DontCopyNumber is a parsing flag used to provide zero-copy support when - // loading Number values (see DontCopyString and DontCopyRawMessage). - DontCopyNumber - - // DontCopyRawMessage is a parsing flag used to provide zero-copy support - // when loading RawMessage values from a json payload. When used, the - // RawMessage values will not be allocated into new memory buffers and - // will instead point directly to the area of the input buffer where the - // value was found. - DontCopyRawMessage - - // DontMatchCaseInsensitiveStructFields is a parsing flag used to prevent - // matching fields in a case-insensitive way. This can prevent degrading - // performance on case conversions, and can also act as a stricter decoding - // mode. - DontMatchCaseInsensitiveStructFields - - // Decode integers into *big.Int. - // Takes precedence over UseNumber for integers. - UseBigInt - - // Decode in-range integers to int64. - // Takes precedence over UseNumber and UseBigInt for in-range integers. - UseInt64 - - // Decode in-range positive integers to uint64. - // Takes precedence over UseNumber, UseBigInt, and UseInt64 - // for positive, in-range integers. - UseUint64 - - // ZeroCopy is a parsing flag that combines all the copy optimizations - // available in the package. - // - // The zero-copy optimizations are better used in request-handler style - // code where none of the values are retained after the handler returns. - ZeroCopy = DontCopyString | DontCopyNumber | DontCopyRawMessage - - // validAsciiPrint is an internal flag indicating that the input contains - // only valid ASCII print chars (0x20 <= c <= 0x7E). If the flag is unset, - // it's unknown whether the input is valid ASCII print. - validAsciiPrint ParseFlags = 1 << 28 - - // noBackslach is an internal flag indicating that the input does not - // contain a backslash. If the flag is unset, it's unknown whether the - // input contains a backslash. - noBackslash ParseFlags = 1 << 29 - - // Bit offset where the kind of the json value is stored. - // - // See Kind in token.go for the enum. - kindOffset ParseFlags = 16 -) - -// Kind represents the different kinds of value that exist in JSON. -type Kind uint - -const ( - Undefined Kind = 0 - - Null Kind = 1 // Null is not zero, so we keep zero for "undefined". - - Bool Kind = 2 // Bit two is set to 1, means it's a boolean. - False Kind = 2 // Bool + 0 - True Kind = 3 // Bool + 1 - - Num Kind = 4 // Bit three is set to 1, means it's a number. - Uint Kind = 5 // Num + 1 - Int Kind = 6 // Num + 2 - Float Kind = 7 // Num + 3 - - String Kind = 8 // Bit four is set to 1, means it's a string. - Unescaped Kind = 9 // String + 1 - - Array Kind = 16 // Equivalent to Delim == '[' - Object Kind = 32 // Equivalent to Delim == '{' -) - -// Class returns the class of k. -func (k Kind) Class() Kind { return Kind(1 << uint(bits.Len(uint(k))-1)) } - -// Append acts like Marshal but appends the json representation to b instead of -// always reallocating a new slice. -func Append(b []byte, x any, flags AppendFlags) ([]byte, error) { - if x == nil { - // Special case for nil values because it makes the rest of the code - // simpler to assume that it won't be seeing nil pointers. - return append(b, "null"...), nil - } - - t := reflect.TypeOf(x) - p := (*iface)(unsafe.Pointer(&x)).ptr - - cache := cacheLoad() - c, found := cache[typeid(t)] - - if !found { - c = constructCachedCodec(t, cache) - } - - b, err := c.encode(encoder{flags: flags}, b, p) - runtime.KeepAlive(x) - return b, err -} - -// Escape is a convenience helper to construct an escaped JSON string from s. -// The function escales HTML characters, for more control over the escape -// behavior and to write to a pre-allocated buffer, use AppendEscape. -func Escape(s string) []byte { - // +10 for extra escape characters, maybe not enough and the buffer will - // be reallocated. - b := make([]byte, 0, len(s)+10) - return AppendEscape(b, s, EscapeHTML) -} - -// AppendEscape appends s to b with the string escaped as a JSON value. -// This will include the starting and ending quote characters, and the -// appropriate characters will be escaped correctly for JSON encoding. -func AppendEscape(b []byte, s string, flags AppendFlags) []byte { - e := encoder{flags: flags} - b, _ = e.encodeString(b, unsafe.Pointer(&s)) - return b -} - -// Unescape is a convenience helper to unescape a JSON value. -// For more control over the unescape behavior and -// to write to a pre-allocated buffer, use AppendUnescape. -func Unescape(s []byte) []byte { - b := make([]byte, 0, len(s)) - return AppendUnescape(b, s, ParseFlags(0)) -} - -// AppendUnescape appends s to b with the string unescaped as a JSON value. -// This will remove starting and ending quote characters, and the -// appropriate characters will be escaped correctly as if JSON decoded. -// New space will be reallocated if more space is needed. -func AppendUnescape(b []byte, s []byte, flags ParseFlags) []byte { - d := decoder{flags: flags} - buf := new(string) - d.decodeString(s, unsafe.Pointer(buf)) - return append(b, *buf...) -} - -// Compact is documented at https://golang.org/pkg/encoding/json/#Compact -func Compact(dst *bytes.Buffer, src []byte) error { - return json.Compact(dst, src) -} - -// HTMLEscape is documented at https://golang.org/pkg/encoding/json/#HTMLEscape -func HTMLEscape(dst *bytes.Buffer, src []byte) { - json.HTMLEscape(dst, src) -} - -// Indent is documented at https://golang.org/pkg/encoding/json/#Indent -func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error { - return json.Indent(dst, src, prefix, indent) -} - -// Marshal is documented at https://golang.org/pkg/encoding/json/#Marshal -func Marshal(x any) ([]byte, error) { - var err error - buf := encoderBufferPool.Get().(*encoderBuffer) - - if buf.data, err = Append(buf.data[:0], x, EscapeHTML|SortMapKeys); err != nil { - return nil, err - } - - b := make([]byte, len(buf.data)) - copy(b, buf.data) - encoderBufferPool.Put(buf) - return b, nil -} - -// MarshalIndent is documented at https://golang.org/pkg/encoding/json/#MarshalIndent -func MarshalIndent(x any, prefix, indent string) ([]byte, error) { - b, err := Marshal(x) - - if err == nil { - tmp := &bytes.Buffer{} - tmp.Grow(2 * len(b)) - - Indent(tmp, b, prefix, indent) - b = tmp.Bytes() - } - - return b, err -} - -// Unmarshal is documented at https://golang.org/pkg/encoding/json/#Unmarshal -func Unmarshal(b []byte, x any) error { - r, err := Parse(b, x, 0) - if len(r) != 0 { - if _, ok := err.(*SyntaxError); !ok { - // The encoding/json package prioritizes reporting errors caused by - // unexpected trailing bytes over other issues; here we emulate this - // behavior by overriding the error. - err = syntaxError(r, "invalid character '%c' after top-level value", r[0]) - } - } - return err -} - -// Parse behaves like Unmarshal but the caller can pass a set of flags to -// configure the parsing behavior. -func Parse(b []byte, x any, flags ParseFlags) ([]byte, error) { - t := reflect.TypeOf(x) - p := (*iface)(unsafe.Pointer(&x)).ptr - - d := decoder{flags: flags | internalParseFlags(b)} - - b = skipSpaces(b) - - if t == nil || p == nil || t.Kind() != reflect.Ptr { - _, r, _, err := d.parseValue(b) - r = skipSpaces(r) - if err != nil { - return r, err - } - return r, &InvalidUnmarshalError{Type: t} - } - t = t.Elem() - - cache := cacheLoad() - c, found := cache[typeid(t)] - - if !found { - c = constructCachedCodec(t, cache) - } - - r, err := c.decode(d, b, p) - return skipSpaces(r), err -} - -// Valid is documented at https://golang.org/pkg/encoding/json/#Valid -func Valid(data []byte) bool { - data = skipSpaces(data) - d := decoder{flags: internalParseFlags(data)} - _, data, _, err := d.parseValue(data) - if err != nil { - return false - } - return len(skipSpaces(data)) == 0 -} - -// Decoder is documented at https://golang.org/pkg/encoding/json/#Decoder -type Decoder struct { - reader io.Reader - buffer []byte - remain []byte - inputOffset int64 - err error - flags ParseFlags -} - -// NewDecoder is documented at https://golang.org/pkg/encoding/json/#NewDecoder -func NewDecoder(r io.Reader) *Decoder { return &Decoder{reader: r} } - -// Buffered is documented at https://golang.org/pkg/encoding/json/#Decoder.Buffered -func (dec *Decoder) Buffered() io.Reader { - return bytes.NewReader(dec.remain) -} - -// Decode is documented at https://golang.org/pkg/encoding/json/#Decoder.Decode -func (dec *Decoder) Decode(v any) error { - raw, err := dec.readValue() - if err != nil { - return err - } - _, err = Parse(raw, v, dec.flags) - return err -} - -const ( - minBufferSize = 32768 - minReadSize = 4096 -) - -// readValue reads one JSON value from the buffer and returns its raw bytes. It -// is optimized for the "one JSON value per line" case. -func (dec *Decoder) readValue() (v []byte, err error) { - var n int - var r []byte - d := decoder{flags: dec.flags} - - for { - if len(dec.remain) != 0 { - v, r, _, err = d.parseValue(dec.remain) - if err == nil { - dec.remain, n = skipSpacesN(r) - dec.inputOffset += int64(len(v) + n) - return - } - if len(r) != 0 { - // Parsing of the next JSON value stopped at a position other - // than the end of the input buffer, which indicaates that a - // syntax error was encountered. - return - } - } - - if err = dec.err; err != nil { - if len(dec.remain) != 0 && err == io.EOF { - err = io.ErrUnexpectedEOF - } - return - } - - if dec.buffer == nil { - dec.buffer = make([]byte, 0, minBufferSize) - } else { - dec.buffer = dec.buffer[:copy(dec.buffer[:cap(dec.buffer)], dec.remain)] - dec.remain = nil - } - - if (cap(dec.buffer) - len(dec.buffer)) < minReadSize { - buf := make([]byte, len(dec.buffer), 2*cap(dec.buffer)) - copy(buf, dec.buffer) - dec.buffer = buf - } - - n, err = io.ReadFull(dec.reader, dec.buffer[len(dec.buffer):cap(dec.buffer)]) - if n > 0 { - dec.buffer = dec.buffer[:len(dec.buffer)+n] - if err != nil { - err = nil - } - } else if err == io.ErrUnexpectedEOF { - err = io.EOF - } - dec.remain, n = skipSpacesN(dec.buffer) - d.flags = dec.flags | internalParseFlags(dec.remain) - dec.inputOffset += int64(n) - dec.err = err - } -} - -// DisallowUnknownFields is documented at https://golang.org/pkg/encoding/json/#Decoder.DisallowUnknownFields -func (dec *Decoder) DisallowUnknownFields() { dec.flags |= DisallowUnknownFields } - -// UseNumber is documented at https://golang.org/pkg/encoding/json/#Decoder.UseNumber -func (dec *Decoder) UseNumber() { dec.flags |= UseNumber } - -// DontCopyString is an extension to the standard encoding/json package -// which instructs the decoder to not copy strings loaded from the json -// payloads when possible. -func (dec *Decoder) DontCopyString() { dec.flags |= DontCopyString } - -// DontCopyNumber is an extension to the standard encoding/json package -// which instructs the decoder to not copy numbers loaded from the json -// payloads. -func (dec *Decoder) DontCopyNumber() { dec.flags |= DontCopyNumber } - -// DontCopyRawMessage is an extension to the standard encoding/json package -// which instructs the decoder to not allocate RawMessage values in separate -// memory buffers (see the documentation of the DontcopyRawMessage flag for -// more detais). -func (dec *Decoder) DontCopyRawMessage() { dec.flags |= DontCopyRawMessage } - -// DontMatchCaseInsensitiveStructFields is an extension to the standard -// encoding/json package which instructs the decoder to not match object fields -// against struct fields in a case-insensitive way, the field names have to -// match exactly to be decoded into the struct field values. -func (dec *Decoder) DontMatchCaseInsensitiveStructFields() { - dec.flags |= DontMatchCaseInsensitiveStructFields -} - -// ZeroCopy is an extension to the standard encoding/json package which enables -// all the copy optimizations of the decoder. -func (dec *Decoder) ZeroCopy() { dec.flags |= ZeroCopy } - -// InputOffset returns the input stream byte offset of the current decoder position. -// The offset gives the location of the end of the most recently returned token -// and the beginning of the next token. -func (dec *Decoder) InputOffset() int64 { - return dec.inputOffset -} - -// Encoder is documented at https://golang.org/pkg/encoding/json/#Encoder -type Encoder struct { - writer io.Writer - prefix string - indent string - buffer *bytes.Buffer - err error - flags AppendFlags -} - -// NewEncoder is documented at https://golang.org/pkg/encoding/json/#NewEncoder -func NewEncoder(w io.Writer) *Encoder { - return &Encoder{writer: w, flags: EscapeHTML | SortMapKeys | appendNewline} -} - -// Encode is documented at https://golang.org/pkg/encoding/json/#Encoder.Encode -func (enc *Encoder) Encode(v any) error { - if enc.err != nil { - return enc.err - } - - var err error - buf := encoderBufferPool.Get().(*encoderBuffer) - - buf.data, err = Append(buf.data[:0], v, enc.flags) - if err != nil { - encoderBufferPool.Put(buf) - return err - } - - if (enc.flags & appendNewline) != 0 { - buf.data = append(buf.data, '\n') - } - b := buf.data - - if enc.prefix != "" || enc.indent != "" { - if enc.buffer == nil { - enc.buffer = new(bytes.Buffer) - enc.buffer.Grow(2 * len(buf.data)) - } else { - enc.buffer.Reset() - } - Indent(enc.buffer, buf.data, enc.prefix, enc.indent) - b = enc.buffer.Bytes() - } - - if _, err := enc.writer.Write(b); err != nil { - enc.err = err - } - - encoderBufferPool.Put(buf) - return err -} - -// SetEscapeHTML is documented at https://golang.org/pkg/encoding/json/#Encoder.SetEscapeHTML -func (enc *Encoder) SetEscapeHTML(on bool) { - if on { - enc.flags |= EscapeHTML - } else { - enc.flags &= ^EscapeHTML - } -} - -// SetIndent is documented at https://golang.org/pkg/encoding/json/#Encoder.SetIndent -func (enc *Encoder) SetIndent(prefix, indent string) { - enc.prefix = prefix - enc.indent = indent -} - -// SetSortMapKeys is an extension to the standard encoding/json package which -// allows the program to toggle sorting of map keys on and off. -func (enc *Encoder) SetSortMapKeys(on bool) { - if on { - enc.flags |= SortMapKeys - } else { - enc.flags &= ^SortMapKeys - } -} - -// SetTrustRawMessage skips value checking when encoding a raw json message. It should only -// be used if the values are known to be valid json, e.g. because they were originally created -// by json.Unmarshal. -func (enc *Encoder) SetTrustRawMessage(on bool) { - if on { - enc.flags |= TrustRawMessage - } else { - enc.flags &= ^TrustRawMessage - } -} - -// SetAppendNewline is an extension to the standard encoding/json package which -// allows the program to toggle the addition of a newline in Encode on or off. -func (enc *Encoder) SetAppendNewline(on bool) { - if on { - enc.flags |= appendNewline - } else { - enc.flags &= ^appendNewline - } -} - -var encoderBufferPool = sync.Pool{ - New: func() any { return &encoderBuffer{data: make([]byte, 0, 4096)} }, -} - -type encoderBuffer struct{ data []byte } diff --git a/go/sdk/vendor/github.com/segmentio/encoding/json/parse.go b/go/sdk/vendor/github.com/segmentio/encoding/json/parse.go deleted file mode 100644 index d0ee221..0000000 --- a/go/sdk/vendor/github.com/segmentio/encoding/json/parse.go +++ /dev/null @@ -1,781 +0,0 @@ -package json - -import ( - "bytes" - "encoding/binary" - "math" - "math/bits" - "reflect" - "unicode" - "unicode/utf16" - "unicode/utf8" - - "github.com/segmentio/encoding/ascii" -) - -// All spaces characters defined in the json specification. -const ( - sp = ' ' - ht = '\t' - nl = '\n' - cr = '\r' -) - -func internalParseFlags(b []byte) (flags ParseFlags) { - // Don't consider surrounding whitespace - b = skipSpaces(b) - b = trimTrailingSpaces(b) - if ascii.ValidPrint(b) { - flags |= validAsciiPrint - } - if bytes.IndexByte(b, '\\') == -1 { - flags |= noBackslash - } - return -} - -func skipSpaces(b []byte) []byte { - if len(b) > 0 && b[0] <= 0x20 { - b, _ = skipSpacesN(b) - } - return b -} - -func skipSpacesN(b []byte) ([]byte, int) { - for i := range b { - switch b[i] { - case sp, ht, nl, cr: - default: - return b[i:], i - } - } - return nil, 0 -} - -func trimTrailingSpaces(b []byte) []byte { - if len(b) > 0 && b[len(b)-1] <= 0x20 { - b = trimTrailingSpacesN(b) - } - return b -} - -func trimTrailingSpacesN(b []byte) []byte { - i := len(b) - 1 -loop: - for ; i >= 0; i-- { - switch b[i] { - case sp, ht, nl, cr: - default: - break loop - } - } - return b[:i+1] -} - -// parseInt parses a decimal representation of an int64 from b. -// -// The function is equivalent to calling strconv.ParseInt(string(b), 10, 64) but -// it prevents Go from making a memory allocation for converting a byte slice to -// a string (escape analysis fails due to the error returned by strconv.ParseInt). -// -// Because it only works with base 10 the function is also significantly faster -// than strconv.ParseInt. -func (d decoder) parseInt(b []byte, t reflect.Type) (int64, []byte, error) { - var value int64 - var count int - - if len(b) == 0 { - return 0, b, syntaxError(b, "cannot decode integer from an empty input") - } - - if b[0] == '-' { - const max = math.MinInt64 - const lim = max / 10 - - if len(b) == 1 { - return 0, b, syntaxError(b, "cannot decode integer from '-'") - } - - if len(b) > 2 && b[1] == '0' && '0' <= b[2] && b[2] <= '9' { - return 0, b, syntaxError(b, "invalid leading character '0' in integer") - } - - for _, c := range b[1:] { - if c < '0' || c > '9' { - if count == 0 { - b, err := d.inputError(b, t) - return 0, b, err - } - break - } - - if value < lim { - return 0, b, unmarshalOverflow(b, t) - } - - value *= 10 - x := int64(c - '0') - - if value < (max + x) { - return 0, b, unmarshalOverflow(b, t) - } - - value -= x - count++ - } - - count++ - } else { - if len(b) > 1 && b[0] == '0' && '0' <= b[1] && b[1] <= '9' { - return 0, b, syntaxError(b, "invalid leading character '0' in integer") - } - - for ; count < len(b) && b[count] >= '0' && b[count] <= '9'; count++ { - x := int64(b[count] - '0') - next := value*10 + x - if next < value { - return 0, b, unmarshalOverflow(b, t) - } - value = next - } - - if count == 0 { - b, err := d.inputError(b, t) - return 0, b, err - } - } - - if count < len(b) { - switch b[count] { - case '.', 'e', 'E': // was this actually a float? - v, r, _, err := d.parseNumber(b) - if err != nil { - v, r = b[:count+1], b[count+1:] - } - return 0, r, unmarshalTypeError(v, t) - } - } - - return value, b[count:], nil -} - -// parseUint is like parseInt but for unsigned integers. -func (d decoder) parseUint(b []byte, t reflect.Type) (uint64, []byte, error) { - var value uint64 - var count int - - if len(b) == 0 { - return 0, b, syntaxError(b, "cannot decode integer value from an empty input") - } - - if len(b) > 1 && b[0] == '0' && '0' <= b[1] && b[1] <= '9' { - return 0, b, syntaxError(b, "invalid leading character '0' in integer") - } - - for ; count < len(b) && b[count] >= '0' && b[count] <= '9'; count++ { - x := uint64(b[count] - '0') - next := value*10 + x - if next < value { - return 0, b, unmarshalOverflow(b, t) - } - value = next - } - - if count == 0 { - b, err := d.inputError(b, t) - return 0, b, err - } - - if count < len(b) { - switch b[count] { - case '.', 'e', 'E': // was this actually a float? - v, r, _, err := d.parseNumber(b) - if err != nil { - v, r = b[:count+1], b[count+1:] - } - return 0, r, unmarshalTypeError(v, t) - } - } - - return value, b[count:], nil -} - -// parseUintHex parses a hexadecimanl representation of a uint64 from b. -// -// The function is equivalent to calling strconv.ParseUint(string(b), 16, 64) but -// it prevents Go from making a memory allocation for converting a byte slice to -// a string (escape analysis fails due to the error returned by strconv.ParseUint). -// -// Because it only works with base 16 the function is also significantly faster -// than strconv.ParseUint. -func (d decoder) parseUintHex(b []byte) (uint64, []byte, error) { - const max = math.MaxUint64 - const lim = max / 0x10 - - var value uint64 - var count int - - if len(b) == 0 { - return 0, b, syntaxError(b, "cannot decode hexadecimal value from an empty input") - } - -parseLoop: - for i, c := range b { - var x uint64 - - switch { - case c >= '0' && c <= '9': - x = uint64(c - '0') - - case c >= 'A' && c <= 'F': - x = uint64(c-'A') + 0xA - - case c >= 'a' && c <= 'f': - x = uint64(c-'a') + 0xA - - default: - if i == 0 { - return 0, b, syntaxError(b, "expected hexadecimal digit but found '%c'", c) - } - break parseLoop - } - - if value > lim { - return 0, b, syntaxError(b, "hexadecimal value out of range") - } - - if value *= 0x10; value > (max - x) { - return 0, b, syntaxError(b, "hexadecimal value out of range") - } - - value += x - count++ - } - - return value, b[count:], nil -} - -func (d decoder) parseNull(b []byte) ([]byte, []byte, Kind, error) { - if hasNullPrefix(b) { - return b[:4], b[4:], Null, nil - } - if len(b) < 4 { - return nil, b[len(b):], Undefined, unexpectedEOF(b) - } - return nil, b, Undefined, syntaxError(b, "expected 'null' but found invalid token") -} - -func (d decoder) parseTrue(b []byte) ([]byte, []byte, Kind, error) { - if hasTruePrefix(b) { - return b[:4], b[4:], True, nil - } - if len(b) < 4 { - return nil, b[len(b):], Undefined, unexpectedEOF(b) - } - return nil, b, Undefined, syntaxError(b, "expected 'true' but found invalid token") -} - -func (d decoder) parseFalse(b []byte) ([]byte, []byte, Kind, error) { - if hasFalsePrefix(b) { - return b[:5], b[5:], False, nil - } - if len(b) < 5 { - return nil, b[len(b):], Undefined, unexpectedEOF(b) - } - return nil, b, Undefined, syntaxError(b, "expected 'false' but found invalid token") -} - -func (d decoder) parseNumber(b []byte) (v, r []byte, kind Kind, err error) { - if len(b) == 0 { - r, err = b, unexpectedEOF(b) - return - } - - // Assume it's an unsigned integer at first. - kind = Uint - - i := 0 - // sign - if b[i] == '-' { - kind = Int - i++ - } - - if i == len(b) { - r, err = b[i:], syntaxError(b, "missing number value after sign") - return - } - - if b[i] < '0' || b[i] > '9' { - r, err = b[i:], syntaxError(b, "expected digit but got '%c'", b[i]) - return - } - - // integer part - if b[i] == '0' { - i++ - if i == len(b) || (b[i] != '.' && b[i] != 'e' && b[i] != 'E') { - v, r = b[:i], b[i:] - return - } - if '0' <= b[i] && b[i] <= '9' { - r, err = b[i:], syntaxError(b, "cannot decode number with leading '0' character") - return - } - } - - for i < len(b) && '0' <= b[i] && b[i] <= '9' { - i++ - } - - // decimal part - if i < len(b) && b[i] == '.' { - kind = Float - i++ - decimalStart := i - - for i < len(b) { - if c := b[i]; '0' > c || c > '9' { - if i == decimalStart { - r, err = b[i:], syntaxError(b, "expected digit but found '%c'", c) - return - } - break - } - i++ - } - - if i == decimalStart { - r, err = b[i:], syntaxError(b, "expected decimal part after '.'") - return - } - } - - // exponent part - if i < len(b) && (b[i] == 'e' || b[i] == 'E') { - kind = Float - i++ - - if i < len(b) { - if c := b[i]; c == '+' || c == '-' { - i++ - } - } - - if i == len(b) { - r, err = b[i:], syntaxError(b, "missing exponent in number") - return - } - - exponentStart := i - - for i < len(b) { - if c := b[i]; '0' > c || c > '9' { - if i == exponentStart { - err = syntaxError(b, "expected digit but found '%c'", c) - return - } - break - } - i++ - } - } - - v, r = b[:i], b[i:] - return -} - -func (d decoder) parseUnicode(b []byte) (rune, int, error) { - if len(b) < 4 { - return 0, len(b), syntaxError(b, "unicode code point must have at least 4 characters") - } - - u, r, err := d.parseUintHex(b[:4]) - if err != nil { - return 0, 4, syntaxError(b, "parsing unicode code point: %s", err) - } - - if len(r) != 0 { - return 0, 4, syntaxError(b, "invalid unicode code point") - } - - return rune(u), 4, nil -} - -func (d decoder) parseString(b []byte) ([]byte, []byte, Kind, error) { - if len(b) < 2 { - return nil, b[len(b):], Undefined, unexpectedEOF(b) - } - if b[0] != '"' { - return nil, b, Undefined, syntaxError(b, "expected '\"' at the beginning of a string value") - } - - var n int - if len(b) >= 9 { - // This is an optimization for short strings. We read 8/16 bytes, - // and XOR each with 0x22 (") so that these bytes (and only - // these bytes) are now zero. We use the hasless(u,1) trick - // from https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord - // to determine whether any bytes are zero. Finally, we CTZ - // to find the index of that byte. - const mask1 = 0x2222222222222222 - const mask2 = 0x0101010101010101 - const mask3 = 0x8080808080808080 - u := binary.LittleEndian.Uint64(b[1:]) ^ mask1 - if mask := (u - mask2) & ^u & mask3; mask != 0 { - n = bits.TrailingZeros64(mask)/8 + 2 - goto found - } - if len(b) >= 17 { - u = binary.LittleEndian.Uint64(b[9:]) ^ mask1 - if mask := (u - mask2) & ^u & mask3; mask != 0 { - n = bits.TrailingZeros64(mask)/8 + 10 - goto found - } - } - } - n = bytes.IndexByte(b[1:], '"') + 2 - if n <= 1 { - return nil, b[len(b):], Undefined, syntaxError(b, "missing '\"' at the end of a string value") - } -found: - if (d.flags.has(noBackslash) || bytes.IndexByte(b[1:n], '\\') < 0) && - (d.flags.has(validAsciiPrint) || ascii.ValidPrint(b[1:n])) { - return b[:n], b[n:], Unescaped, nil - } - - for i := 1; i < len(b); i++ { - switch b[i] { - case '\\': - if i++; i < len(b) { - switch b[i] { - case '"', '\\', '/', 'n', 'r', 't', 'f', 'b': - case 'u': - _, n, err := d.parseUnicode(b[i+1:]) - if err != nil { - return nil, b[i+1+n:], Undefined, err - } - i += n - default: - return nil, b, Undefined, syntaxError(b, "invalid character '%c' in string escape code", b[i]) - } - } - - case '"': - return b[:i+1], b[i+1:], String, nil - - default: - if b[i] < 0x20 { - return nil, b, Undefined, syntaxError(b, "invalid character '%c' in string escape code", b[i]) - } - } - } - - return nil, b[len(b):], Undefined, syntaxError(b, "missing '\"' at the end of a string value") -} - -func (d decoder) parseStringUnquote(b []byte, r []byte) ([]byte, []byte, bool, error) { - s, b, k, err := d.parseString(b) - if err != nil { - return s, b, false, err - } - - s = s[1 : len(s)-1] // trim the quotes - - if k == Unescaped { - return s, b, false, nil - } - - if r == nil { - r = make([]byte, 0, len(s)) - } - - for len(s) != 0 { - i := bytes.IndexByte(s, '\\') - - if i < 0 { - r = appendCoerceInvalidUTF8(r, s) - break - } - - r = appendCoerceInvalidUTF8(r, s[:i]) - s = s[i+1:] - - c := s[0] - switch c { - case '"', '\\', '/': - // simple escaped character - case 'n': - c = '\n' - - case 'r': - c = '\r' - - case 't': - c = '\t' - - case 'b': - c = '\b' - - case 'f': - c = '\f' - - case 'u': - s = s[1:] - - r1, n1, err := d.parseUnicode(s) - if err != nil { - return r, b, true, err - } - s = s[n1:] - - if utf16.IsSurrogate(r1) { - if !hasPrefix(s, `\u`) { - r1 = unicode.ReplacementChar - } else { - r2, n2, err := d.parseUnicode(s[2:]) - if err != nil { - return r, b, true, err - } - if r1 = utf16.DecodeRune(r1, r2); r1 != unicode.ReplacementChar { - s = s[2+n2:] - } - } - } - - r = appendRune(r, r1) - continue - - default: // not sure what this escape sequence is - return r, b, false, syntaxError(s, "invalid character '%c' in string escape code", c) - } - - r = append(r, c) - s = s[1:] - } - - return r, b, true, nil -} - -func appendRune(b []byte, r rune) []byte { - n := len(b) - b = append(b, 0, 0, 0, 0) - return b[:n+utf8.EncodeRune(b[n:], r)] -} - -func appendCoerceInvalidUTF8(b []byte, s []byte) []byte { - c := [4]byte{} - - for _, r := range string(s) { - b = append(b, c[:utf8.EncodeRune(c[:], r)]...) - } - - return b -} - -func (d decoder) parseObject(b []byte) ([]byte, []byte, Kind, error) { - if len(b) < 2 { - return nil, b[len(b):], Undefined, unexpectedEOF(b) - } - - if b[0] != '{' { - return nil, b, Undefined, syntaxError(b, "expected '{' at the beginning of an object value") - } - - var err error - a := b - n := len(b) - i := 0 - - b = b[1:] - for { - b = skipSpaces(b) - - if len(b) == 0 { - return nil, b, Undefined, syntaxError(b, "cannot decode object from empty input") - } - - if b[0] == '}' { - j := (n - len(b)) + 1 - return a[:j], a[j:], Object, nil - } - - if i != 0 { - if len(b) == 0 { - return nil, b, Undefined, syntaxError(b, "unexpected EOF after object field value") - } - if b[0] != ',' { - return nil, b, Undefined, syntaxError(b, "expected ',' after object field value but found '%c'", b[0]) - } - b = skipSpaces(b[1:]) - if len(b) == 0 { - return nil, b, Undefined, unexpectedEOF(b) - } - if b[0] == '}' { - return nil, b, Undefined, syntaxError(b, "unexpected trailing comma after object field") - } - } - - _, b, _, err = d.parseString(b) - if err != nil { - return nil, b, Undefined, err - } - b = skipSpaces(b) - - if len(b) == 0 { - return nil, b, Undefined, syntaxError(b, "unexpected EOF after object field key") - } - if b[0] != ':' { - return nil, b, Undefined, syntaxError(b, "expected ':' after object field key but found '%c'", b[0]) - } - b = skipSpaces(b[1:]) - - _, b, _, err = d.parseValue(b) - if err != nil { - return nil, b, Undefined, err - } - - i++ - } -} - -func (d decoder) parseArray(b []byte) ([]byte, []byte, Kind, error) { - if len(b) < 2 { - return nil, b[len(b):], Undefined, unexpectedEOF(b) - } - - if b[0] != '[' { - return nil, b, Undefined, syntaxError(b, "expected '[' at the beginning of array value") - } - - var err error - a := b - n := len(b) - i := 0 - - b = b[1:] - for { - b = skipSpaces(b) - - if len(b) == 0 { - return nil, b, Undefined, syntaxError(b, "missing closing ']' after array value") - } - - if b[0] == ']' { - j := (n - len(b)) + 1 - return a[:j], a[j:], Array, nil - } - - if i != 0 { - if len(b) == 0 { - return nil, b, Undefined, syntaxError(b, "unexpected EOF after array element") - } - if b[0] != ',' { - return nil, b, Undefined, syntaxError(b, "expected ',' after array element but found '%c'", b[0]) - } - b = skipSpaces(b[1:]) - if len(b) == 0 { - return nil, b, Undefined, unexpectedEOF(b) - } - if b[0] == ']' { - return nil, b, Undefined, syntaxError(b, "unexpected trailing comma after object field") - } - } - - _, b, _, err = d.parseValue(b) - if err != nil { - return nil, b, Undefined, err - } - - i++ - } -} - -func (d decoder) parseValue(b []byte) ([]byte, []byte, Kind, error) { - if len(b) == 0 { - return nil, b, Undefined, syntaxError(b, "unexpected end of JSON input") - } - - var v []byte - var k Kind - var err error - - switch b[0] { - case '{': - v, b, k, err = d.parseObject(b) - case '[': - v, b, k, err = d.parseArray(b) - case '"': - v, b, k, err = d.parseString(b) - case 'n': - v, b, k, err = d.parseNull(b) - case 't': - v, b, k, err = d.parseTrue(b) - case 'f': - v, b, k, err = d.parseFalse(b) - case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - v, b, k, err = d.parseNumber(b) - default: - err = syntaxError(b, "invalid character '%c' looking for beginning of value", b[0]) - } - - return v, b, k, err -} - -func hasNullPrefix(b []byte) bool { - return len(b) >= 4 && string(b[:4]) == "null" -} - -func hasTruePrefix(b []byte) bool { - return len(b) >= 4 && string(b[:4]) == "true" -} - -func hasFalsePrefix(b []byte) bool { - return len(b) >= 5 && string(b[:5]) == "false" -} - -func hasPrefix(b []byte, s string) bool { - return len(b) >= len(s) && s == string(b[:len(s)]) -} - -func hasLeadingSign(b []byte) bool { - return len(b) > 0 && (b[0] == '+' || b[0] == '-') -} - -func hasLeadingZeroes(b []byte) bool { - if hasLeadingSign(b) { - b = b[1:] - } - return len(b) > 1 && b[0] == '0' && '0' <= b[1] && b[1] <= '9' -} - -func appendToLower(b, s []byte) []byte { - if ascii.Valid(s) { // fast path for ascii strings - i := 0 - - for j := range s { - c := s[j] - - if 'A' <= c && c <= 'Z' { - b = append(b, s[i:j]...) - b = append(b, c+('a'-'A')) - i = j + 1 - } - } - - return append(b, s[i:]...) - } - - for _, r := range string(s) { - b = appendRune(b, foldRune(r)) - } - - return b -} - -func foldRune(r rune) rune { - if r = unicode.SimpleFold(r); 'A' <= r && r <= 'Z' { - r = r + ('a' - 'A') - } - return r -} diff --git a/go/sdk/vendor/github.com/segmentio/encoding/json/reflect.go b/go/sdk/vendor/github.com/segmentio/encoding/json/reflect.go deleted file mode 100644 index 6edd80e..0000000 --- a/go/sdk/vendor/github.com/segmentio/encoding/json/reflect.go +++ /dev/null @@ -1,20 +0,0 @@ -//go:build go1.20 -// +build go1.20 - -package json - -import ( - "reflect" - "unsafe" -) - -func extendSlice(t reflect.Type, s *slice, n int) slice { - arrayType := reflect.ArrayOf(n, t.Elem()) - arrayData := reflect.New(arrayType) - reflect.Copy(arrayData.Elem(), reflect.NewAt(t, unsafe.Pointer(s)).Elem()) - return slice{ - data: unsafe.Pointer(arrayData.Pointer()), - len: s.len, - cap: n, - } -} diff --git a/go/sdk/vendor/github.com/segmentio/encoding/json/reflect_optimize.go b/go/sdk/vendor/github.com/segmentio/encoding/json/reflect_optimize.go deleted file mode 100644 index 6588433..0000000 --- a/go/sdk/vendor/github.com/segmentio/encoding/json/reflect_optimize.go +++ /dev/null @@ -1,30 +0,0 @@ -//go:build !go1.20 -// +build !go1.20 - -package json - -import ( - "reflect" - "unsafe" -) - -//go:linkname unsafe_NewArray reflect.unsafe_NewArray -func unsafe_NewArray(rtype unsafe.Pointer, length int) unsafe.Pointer - -//go:linkname typedslicecopy reflect.typedslicecopy -//go:noescape -func typedslicecopy(elemType unsafe.Pointer, dst, src slice) int - -func extendSlice(t reflect.Type, s *slice, n int) slice { - elemTypeRef := t.Elem() - elemTypePtr := ((*iface)(unsafe.Pointer(&elemTypeRef))).ptr - - d := slice{ - data: unsafe_NewArray(elemTypePtr, n), - len: s.len, - cap: n, - } - - typedslicecopy(elemTypePtr, d, *s) - return d -} diff --git a/go/sdk/vendor/github.com/segmentio/encoding/json/string.go b/go/sdk/vendor/github.com/segmentio/encoding/json/string.go deleted file mode 100644 index a9a972b..0000000 --- a/go/sdk/vendor/github.com/segmentio/encoding/json/string.go +++ /dev/null @@ -1,89 +0,0 @@ -package json - -import ( - "math/bits" - "unsafe" -) - -const ( - lsb = 0x0101010101010101 - msb = 0x8080808080808080 -) - -// escapeIndex finds the index of the first char in `s` that requires escaping. -// A char requires escaping if it's outside of the range of [0x20, 0x7F] or if -// it includes a double quote or backslash. If the escapeHTML mode is enabled, -// the chars <, > and & also require escaping. If no chars in `s` require -// escaping, the return value is -1. -func escapeIndex(s string, escapeHTML bool) int { - chunks := stringToUint64(s) - for _, n := range chunks { - // combine masks before checking for the MSB of each byte. We include - // `n` in the mask to check whether any of the *input* byte MSBs were - // set (i.e. the byte was outside the ASCII range). - mask := n | below(n, 0x20) | contains(n, '"') | contains(n, '\\') - if escapeHTML { - mask |= contains(n, '<') | contains(n, '>') | contains(n, '&') - } - if (mask & msb) != 0 { - return bits.TrailingZeros64(mask&msb) / 8 - } - } - - for i := len(chunks) * 8; i < len(s); i++ { - c := s[i] - if c < 0x20 || c > 0x7f || c == '"' || c == '\\' || (escapeHTML && (c == '<' || c == '>' || c == '&')) { - return i - } - } - - return -1 -} - -func escapeByteRepr(b byte) byte { - switch b { - case '\\', '"': - return b - case '\b': - return 'b' - case '\f': - return 'f' - case '\n': - return 'n' - case '\r': - return 'r' - case '\t': - return 't' - } - - return 0 -} - -// below return a mask that can be used to determine if any of the bytes -// in `n` are below `b`. If a byte's MSB is set in the mask then that byte was -// below `b`. The result is only valid if `b`, and each byte in `n`, is below -// 0x80. -func below(n uint64, b byte) uint64 { - return n - expand(b) -} - -// contains returns a mask that can be used to determine if any of the -// bytes in `n` are equal to `b`. If a byte's MSB is set in the mask then -// that byte is equal to `b`. The result is only valid if `b`, and each -// byte in `n`, is below 0x80. -func contains(n uint64, b byte) uint64 { - return (n ^ expand(b)) - lsb -} - -// expand puts the specified byte into each of the 8 bytes of a uint64. -func expand(b byte) uint64 { - return lsb * uint64(b) -} - -func stringToUint64(s string) []uint64 { - return *(*[]uint64)(unsafe.Pointer(&sliceHeader{ - Data: *(*unsafe.Pointer)(unsafe.Pointer(&s)), - Len: len(s) / 8, - Cap: len(s) / 8, - })) -} diff --git a/go/sdk/vendor/github.com/segmentio/encoding/json/token.go b/go/sdk/vendor/github.com/segmentio/encoding/json/token.go deleted file mode 100644 index ddcd05d..0000000 --- a/go/sdk/vendor/github.com/segmentio/encoding/json/token.go +++ /dev/null @@ -1,426 +0,0 @@ -package json - -import ( - "strconv" - "sync" - "unsafe" -) - -// Tokenizer is an iterator-style type which can be used to progressively parse -// through a json input. -// -// Tokenizing json is useful to build highly efficient parsing operations, for -// example when doing tranformations on-the-fly where as the program reads the -// input and produces the transformed json to an output buffer. -// -// Here is a common pattern to use a tokenizer: -// -// for t := json.NewTokenizer(b); t.Next(); { -// switch k := t.Kind(); k.Class() { -// case json.Null: -// ... -// case json.Bool: -// ... -// case json.Num: -// ... -// case json.String: -// ... -// case json.Array: -// ... -// case json.Object: -// ... -// } -// } -type Tokenizer struct { - // When the tokenizer is positioned on a json delimiter this field is not - // zero. In this case the possible values are '{', '}', '[', ']', ':', and - // ','. - Delim Delim - - // This field contains the raw json token that the tokenizer is pointing at. - // When Delim is not zero, this field is a single-element byte slice - // continaing the delimiter value. Otherwise, this field holds values like - // null, true, false, numbers, or quoted strings. - Value RawValue - - // When the tokenizer has encountered invalid content this field is not nil. - Err error - - // When the value is in an array or an object, this field contains the depth - // at which it was found. - Depth int - - // When the value is in an array or an object, this field contains the - // position at which it was found. - Index int - - // This field is true when the value is the key of an object. - IsKey bool - - // Tells whether the next value read from the tokenizer is a key. - isKey bool - - // json input for the tokenizer, pointing at data right after the last token - // that was parsed. - json []byte - - // Stack used to track entering and leaving arrays, objects, and keys. - stack *stack - - // Decoder used for parsing. - decoder -} - -// NewTokenizer constructs a new Tokenizer which reads its json input from b. -func NewTokenizer(b []byte) *Tokenizer { - return &Tokenizer{ - json: b, - decoder: decoder{flags: internalParseFlags(b)}, - } -} - -// Reset erases the state of t and re-initializes it with the json input from b. -func (t *Tokenizer) Reset(b []byte) { - if t.stack != nil { - releaseStack(t.stack) - } - // This code is similar to: - // - // *t = Tokenizer{json: b} - // - // However, it does not compile down to an invocation of duff-copy. - t.Delim = 0 - t.Value = nil - t.Err = nil - t.Depth = 0 - t.Index = 0 - t.IsKey = false - t.isKey = false - t.json = b - t.stack = nil - t.decoder = decoder{flags: internalParseFlags(b)} -} - -// Next returns a new tokenizer pointing at the next token, or the zero-value of -// Tokenizer if the end of the json input has been reached. -// -// If the tokenizer encounters malformed json while reading the input the method -// sets t.Err to an error describing the issue, and returns false. Once an error -// has been encountered, the tokenizer will always fail until its input is -// cleared by a call to its Reset method. -func (t *Tokenizer) Next() bool { - if t.Err != nil { - return false - } - - // Inlined code of the skipSpaces function, this give a ~15% speed boost. - i := 0 -skipLoop: - for _, c := range t.json { - switch c { - case sp, ht, nl, cr: - i++ - default: - break skipLoop - } - } - - if i > 0 { - t.json = t.json[i:] - } - - if len(t.json) == 0 { - t.Reset(nil) - return false - } - - var kind Kind - switch t.json[0] { - case '"': - t.Delim = 0 - t.Value, t.json, kind, t.Err = t.parseString(t.json) - case 'n': - t.Delim = 0 - t.Value, t.json, kind, t.Err = t.parseNull(t.json) - case 't': - t.Delim = 0 - t.Value, t.json, kind, t.Err = t.parseTrue(t.json) - case 'f': - t.Delim = 0 - t.Value, t.json, kind, t.Err = t.parseFalse(t.json) - case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - t.Delim = 0 - t.Value, t.json, kind, t.Err = t.parseNumber(t.json) - case '{', '}', '[', ']', ':', ',': - t.Delim, t.Value, t.json = Delim(t.json[0]), t.json[:1], t.json[1:] - switch t.Delim { - case '{': - kind = Object - case '[': - kind = Array - } - default: - t.Delim = 0 - t.Value, t.json, t.Err = t.json[:1], t.json[1:], syntaxError(t.json, "expected token but found '%c'", t.json[0]) - } - - t.Depth = t.depth() - t.Index = t.index() - t.flags = t.flags.withKind(kind) - - if t.Delim == 0 { - t.IsKey = t.isKey - } else { - t.IsKey = false - - switch t.Delim { - case '{': - t.isKey = true - t.push(inObject) - case '[': - t.push(inArray) - case '}': - t.Err = t.pop(inObject) - t.Depth-- - t.Index = t.index() - case ']': - t.Err = t.pop(inArray) - t.Depth-- - t.Index = t.index() - case ':': - t.isKey = false - case ',': - if t.stack == nil || len(t.stack.state) == 0 { - t.Err = syntaxError(t.json, "found unexpected comma") - return false - } - if t.stack.is(inObject) { - t.isKey = true - } - t.stack.state[len(t.stack.state)-1].len++ - } - } - - return (t.Delim != 0 || len(t.Value) != 0) && t.Err == nil -} - -func (t *Tokenizer) depth() int { - if t.stack == nil { - return 0 - } - return t.stack.depth() -} - -func (t *Tokenizer) index() int { - if t.stack == nil { - return 0 - } - return t.stack.index() -} - -func (t *Tokenizer) push(typ scope) { - if t.stack == nil { - t.stack = acquireStack() - } - t.stack.push(typ) -} - -func (t *Tokenizer) pop(expect scope) error { - if t.stack == nil || !t.stack.pop(expect) { - return syntaxError(t.json, "found unexpected character while tokenizing json input") - } - return nil -} - -// Kind returns the kind of the value that the tokenizer is currently positioned -// on. -func (t *Tokenizer) Kind() Kind { return t.flags.kind() } - -// Bool returns a bool containing the value of the json boolean that the -// tokenizer is currently pointing at. -// -// This method must only be called after checking the kind of the token via a -// call to Kind. -// -// If the tokenizer is not positioned on a boolean, the behavior is undefined. -func (t *Tokenizer) Bool() bool { return t.flags.kind() == True } - -// Int returns a byte slice containing the value of the json number that the -// tokenizer is currently pointing at. -// -// This method must only be called after checking the kind of the token via a -// call to Kind. -// -// If the tokenizer is not positioned on an integer, the behavior is undefined. -func (t *Tokenizer) Int() int64 { - i, _, _ := t.parseInt(t.Value, int64Type) - return i -} - -// Uint returns a byte slice containing the value of the json number that the -// tokenizer is currently pointing at. -// -// This method must only be called after checking the kind of the token via a -// call to Kind. -// -// If the tokenizer is not positioned on a positive integer, the behavior is -// undefined. -func (t *Tokenizer) Uint() uint64 { - u, _, _ := t.parseUint(t.Value, uint64Type) - return u -} - -// Float returns a byte slice containing the value of the json number that the -// tokenizer is currently pointing at. -// -// This method must only be called after checking the kind of the token via a -// call to Kind. -// -// If the tokenizer is not positioned on a number, the behavior is undefined. -func (t *Tokenizer) Float() float64 { - f, _ := strconv.ParseFloat(*(*string)(unsafe.Pointer(&t.Value)), 64) - return f -} - -// String returns a byte slice containing the value of the json string that the -// tokenizer is currently pointing at. -// -// This method must only be called after checking the kind of the token via a -// call to Kind. -// -// When possible, the returned byte slice references the backing array of the -// tokenizer. A new slice is only allocated if the tokenizer needed to unescape -// the json string. -// -// If the tokenizer is not positioned on a string, the behavior is undefined. -func (t *Tokenizer) String() []byte { - if t.flags.kind() == Unescaped && len(t.Value) > 1 { - return t.Value[1 : len(t.Value)-1] // unquote - } - s, _, _, _ := t.parseStringUnquote(t.Value, nil) - return s -} - -// Remaining returns the number of bytes left to parse. -// -// The position of the tokenizer's current Value within the original byte slice -// can be calculated like so: -// -// end := len(b) - tok.Remaining() -// start := end - len(tok.Value) -// -// And slicing b[start:end] will yield the tokenizer's current Value. -func (t *Tokenizer) Remaining() int { - return len(t.json) -} - -// RawValue represents a raw json value, it is intended to carry null, true, -// false, number, and string values only. -type RawValue []byte - -// String returns true if v contains a string value. -func (v RawValue) String() bool { return len(v) != 0 && v[0] == '"' } - -// Null returns true if v contains a null value. -func (v RawValue) Null() bool { return len(v) != 0 && v[0] == 'n' } - -// True returns true if v contains a true value. -func (v RawValue) True() bool { return len(v) != 0 && v[0] == 't' } - -// False returns true if v contains a false value. -func (v RawValue) False() bool { return len(v) != 0 && v[0] == 'f' } - -// Number returns true if v contains a number value. -func (v RawValue) Number() bool { - if len(v) != 0 { - switch v[0] { - case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - return true - } - } - return false -} - -// AppendUnquote writes the unquoted version of the string value in v into b. -func (v RawValue) AppendUnquote(b []byte) []byte { - d := decoder{} - s, r, _, err := d.parseStringUnquote(v, b) - if err != nil { - panic(err) - } - if len(r) != 0 { - panic(syntaxError(r, "unexpected trailing tokens after json value")) - } - return append(b, s...) -} - -// Unquote returns the unquoted version of the string value in v. -func (v RawValue) Unquote() []byte { - return v.AppendUnquote(nil) -} - -type scope int - -const ( - inArray scope = iota - inObject -) - -type state struct { - typ scope - len int -} - -type stack struct { - state []state -} - -func (s *stack) push(typ scope) { - s.state = append(s.state, state{typ: typ, len: 1}) -} - -func (s *stack) pop(expect scope) bool { - i := len(s.state) - 1 - - if i < 0 { - return false - } - - if found := s.state[i]; expect != found.typ { - return false - } - - s.state = s.state[:i] - return true -} - -func (s *stack) is(typ scope) bool { - return len(s.state) != 0 && s.state[len(s.state)-1].typ == typ -} - -func (s *stack) depth() int { - return len(s.state) -} - -func (s *stack) index() int { - if len(s.state) == 0 { - return 0 - } - return s.state[len(s.state)-1].len - 1 -} - -func acquireStack() *stack { - s, _ := stackPool.Get().(*stack) - if s == nil { - s = &stack{state: make([]state, 0, 4)} - } else { - s.state = s.state[:0] - } - return s -} - -func releaseStack(s *stack) { - stackPool.Put(s) -} - -var stackPool sync.Pool // *stack diff --git a/go/sdk/vendor/github.com/stretchr/testify/LICENSE b/go/sdk/vendor/github.com/stretchr/testify/LICENSE deleted file mode 100644 index 4b0421c..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2012-2020 Mat Ryer, Tyler Bunnell and contributors. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/go/sdk/vendor/github.com/stretchr/testify/assert/assertion_compare.go b/go/sdk/vendor/github.com/stretchr/testify/assert/assertion_compare.go deleted file mode 100644 index ffb24e8..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/assert/assertion_compare.go +++ /dev/null @@ -1,495 +0,0 @@ -package assert - -import ( - "bytes" - "fmt" - "reflect" - "time" -) - -// Deprecated: CompareType has only ever been for internal use and has accidentally been published since v1.6.0. Do not use it. -type CompareType = compareResult - -type compareResult int - -const ( - compareLess compareResult = iota - 1 - compareEqual - compareGreater -) - -var ( - intType = reflect.TypeOf(int(1)) - int8Type = reflect.TypeOf(int8(1)) - int16Type = reflect.TypeOf(int16(1)) - int32Type = reflect.TypeOf(int32(1)) - int64Type = reflect.TypeOf(int64(1)) - - uintType = reflect.TypeOf(uint(1)) - uint8Type = reflect.TypeOf(uint8(1)) - uint16Type = reflect.TypeOf(uint16(1)) - uint32Type = reflect.TypeOf(uint32(1)) - uint64Type = reflect.TypeOf(uint64(1)) - - uintptrType = reflect.TypeOf(uintptr(1)) - - float32Type = reflect.TypeOf(float32(1)) - float64Type = reflect.TypeOf(float64(1)) - - stringType = reflect.TypeOf("") - - timeType = reflect.TypeOf(time.Time{}) - bytesType = reflect.TypeOf([]byte{}) -) - -func compare(obj1, obj2 interface{}, kind reflect.Kind) (compareResult, bool) { - obj1Value := reflect.ValueOf(obj1) - obj2Value := reflect.ValueOf(obj2) - - // throughout this switch we try and avoid calling .Convert() if possible, - // as this has a pretty big performance impact - switch kind { - case reflect.Int: - { - intobj1, ok := obj1.(int) - if !ok { - intobj1 = obj1Value.Convert(intType).Interface().(int) - } - intobj2, ok := obj2.(int) - if !ok { - intobj2 = obj2Value.Convert(intType).Interface().(int) - } - if intobj1 > intobj2 { - return compareGreater, true - } - if intobj1 == intobj2 { - return compareEqual, true - } - if intobj1 < intobj2 { - return compareLess, true - } - } - case reflect.Int8: - { - int8obj1, ok := obj1.(int8) - if !ok { - int8obj1 = obj1Value.Convert(int8Type).Interface().(int8) - } - int8obj2, ok := obj2.(int8) - if !ok { - int8obj2 = obj2Value.Convert(int8Type).Interface().(int8) - } - if int8obj1 > int8obj2 { - return compareGreater, true - } - if int8obj1 == int8obj2 { - return compareEqual, true - } - if int8obj1 < int8obj2 { - return compareLess, true - } - } - case reflect.Int16: - { - int16obj1, ok := obj1.(int16) - if !ok { - int16obj1 = obj1Value.Convert(int16Type).Interface().(int16) - } - int16obj2, ok := obj2.(int16) - if !ok { - int16obj2 = obj2Value.Convert(int16Type).Interface().(int16) - } - if int16obj1 > int16obj2 { - return compareGreater, true - } - if int16obj1 == int16obj2 { - return compareEqual, true - } - if int16obj1 < int16obj2 { - return compareLess, true - } - } - case reflect.Int32: - { - int32obj1, ok := obj1.(int32) - if !ok { - int32obj1 = obj1Value.Convert(int32Type).Interface().(int32) - } - int32obj2, ok := obj2.(int32) - if !ok { - int32obj2 = obj2Value.Convert(int32Type).Interface().(int32) - } - if int32obj1 > int32obj2 { - return compareGreater, true - } - if int32obj1 == int32obj2 { - return compareEqual, true - } - if int32obj1 < int32obj2 { - return compareLess, true - } - } - case reflect.Int64: - { - int64obj1, ok := obj1.(int64) - if !ok { - int64obj1 = obj1Value.Convert(int64Type).Interface().(int64) - } - int64obj2, ok := obj2.(int64) - if !ok { - int64obj2 = obj2Value.Convert(int64Type).Interface().(int64) - } - if int64obj1 > int64obj2 { - return compareGreater, true - } - if int64obj1 == int64obj2 { - return compareEqual, true - } - if int64obj1 < int64obj2 { - return compareLess, true - } - } - case reflect.Uint: - { - uintobj1, ok := obj1.(uint) - if !ok { - uintobj1 = obj1Value.Convert(uintType).Interface().(uint) - } - uintobj2, ok := obj2.(uint) - if !ok { - uintobj2 = obj2Value.Convert(uintType).Interface().(uint) - } - if uintobj1 > uintobj2 { - return compareGreater, true - } - if uintobj1 == uintobj2 { - return compareEqual, true - } - if uintobj1 < uintobj2 { - return compareLess, true - } - } - case reflect.Uint8: - { - uint8obj1, ok := obj1.(uint8) - if !ok { - uint8obj1 = obj1Value.Convert(uint8Type).Interface().(uint8) - } - uint8obj2, ok := obj2.(uint8) - if !ok { - uint8obj2 = obj2Value.Convert(uint8Type).Interface().(uint8) - } - if uint8obj1 > uint8obj2 { - return compareGreater, true - } - if uint8obj1 == uint8obj2 { - return compareEqual, true - } - if uint8obj1 < uint8obj2 { - return compareLess, true - } - } - case reflect.Uint16: - { - uint16obj1, ok := obj1.(uint16) - if !ok { - uint16obj1 = obj1Value.Convert(uint16Type).Interface().(uint16) - } - uint16obj2, ok := obj2.(uint16) - if !ok { - uint16obj2 = obj2Value.Convert(uint16Type).Interface().(uint16) - } - if uint16obj1 > uint16obj2 { - return compareGreater, true - } - if uint16obj1 == uint16obj2 { - return compareEqual, true - } - if uint16obj1 < uint16obj2 { - return compareLess, true - } - } - case reflect.Uint32: - { - uint32obj1, ok := obj1.(uint32) - if !ok { - uint32obj1 = obj1Value.Convert(uint32Type).Interface().(uint32) - } - uint32obj2, ok := obj2.(uint32) - if !ok { - uint32obj2 = obj2Value.Convert(uint32Type).Interface().(uint32) - } - if uint32obj1 > uint32obj2 { - return compareGreater, true - } - if uint32obj1 == uint32obj2 { - return compareEqual, true - } - if uint32obj1 < uint32obj2 { - return compareLess, true - } - } - case reflect.Uint64: - { - uint64obj1, ok := obj1.(uint64) - if !ok { - uint64obj1 = obj1Value.Convert(uint64Type).Interface().(uint64) - } - uint64obj2, ok := obj2.(uint64) - if !ok { - uint64obj2 = obj2Value.Convert(uint64Type).Interface().(uint64) - } - if uint64obj1 > uint64obj2 { - return compareGreater, true - } - if uint64obj1 == uint64obj2 { - return compareEqual, true - } - if uint64obj1 < uint64obj2 { - return compareLess, true - } - } - case reflect.Float32: - { - float32obj1, ok := obj1.(float32) - if !ok { - float32obj1 = obj1Value.Convert(float32Type).Interface().(float32) - } - float32obj2, ok := obj2.(float32) - if !ok { - float32obj2 = obj2Value.Convert(float32Type).Interface().(float32) - } - if float32obj1 > float32obj2 { - return compareGreater, true - } - if float32obj1 == float32obj2 { - return compareEqual, true - } - if float32obj1 < float32obj2 { - return compareLess, true - } - } - case reflect.Float64: - { - float64obj1, ok := obj1.(float64) - if !ok { - float64obj1 = obj1Value.Convert(float64Type).Interface().(float64) - } - float64obj2, ok := obj2.(float64) - if !ok { - float64obj2 = obj2Value.Convert(float64Type).Interface().(float64) - } - if float64obj1 > float64obj2 { - return compareGreater, true - } - if float64obj1 == float64obj2 { - return compareEqual, true - } - if float64obj1 < float64obj2 { - return compareLess, true - } - } - case reflect.String: - { - stringobj1, ok := obj1.(string) - if !ok { - stringobj1 = obj1Value.Convert(stringType).Interface().(string) - } - stringobj2, ok := obj2.(string) - if !ok { - stringobj2 = obj2Value.Convert(stringType).Interface().(string) - } - if stringobj1 > stringobj2 { - return compareGreater, true - } - if stringobj1 == stringobj2 { - return compareEqual, true - } - if stringobj1 < stringobj2 { - return compareLess, true - } - } - // Check for known struct types we can check for compare results. - case reflect.Struct: - { - // All structs enter here. We're not interested in most types. - if !obj1Value.CanConvert(timeType) { - break - } - - // time.Time can be compared! - timeObj1, ok := obj1.(time.Time) - if !ok { - timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time) - } - - timeObj2, ok := obj2.(time.Time) - if !ok { - timeObj2 = obj2Value.Convert(timeType).Interface().(time.Time) - } - - if timeObj1.Before(timeObj2) { - return compareLess, true - } - if timeObj1.Equal(timeObj2) { - return compareEqual, true - } - return compareGreater, true - } - case reflect.Slice: - { - // We only care about the []byte type. - if !obj1Value.CanConvert(bytesType) { - break - } - - // []byte can be compared! - bytesObj1, ok := obj1.([]byte) - if !ok { - bytesObj1 = obj1Value.Convert(bytesType).Interface().([]byte) - - } - bytesObj2, ok := obj2.([]byte) - if !ok { - bytesObj2 = obj2Value.Convert(bytesType).Interface().([]byte) - } - - return compareResult(bytes.Compare(bytesObj1, bytesObj2)), true - } - case reflect.Uintptr: - { - uintptrObj1, ok := obj1.(uintptr) - if !ok { - uintptrObj1 = obj1Value.Convert(uintptrType).Interface().(uintptr) - } - uintptrObj2, ok := obj2.(uintptr) - if !ok { - uintptrObj2 = obj2Value.Convert(uintptrType).Interface().(uintptr) - } - if uintptrObj1 > uintptrObj2 { - return compareGreater, true - } - if uintptrObj1 == uintptrObj2 { - return compareEqual, true - } - if uintptrObj1 < uintptrObj2 { - return compareLess, true - } - } - } - - return compareEqual, false -} - -// Greater asserts that the first element is greater than the second -// -// assert.Greater(t, 2, 1) -// assert.Greater(t, float64(2), float64(1)) -// assert.Greater(t, "b", "a") -func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - failMessage := fmt.Sprintf("\"%v\" is not greater than \"%v\"", e1, e2) - return compareTwoValues(t, e1, e2, []compareResult{compareGreater}, failMessage, msgAndArgs...) -} - -// GreaterOrEqual asserts that the first element is greater than or equal to the second -// -// assert.GreaterOrEqual(t, 2, 1) -// assert.GreaterOrEqual(t, 2, 2) -// assert.GreaterOrEqual(t, "b", "a") -// assert.GreaterOrEqual(t, "b", "b") -func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - failMessage := fmt.Sprintf("\"%v\" is not greater than or equal to \"%v\"", e1, e2) - return compareTwoValues(t, e1, e2, []compareResult{compareGreater, compareEqual}, failMessage, msgAndArgs...) -} - -// Less asserts that the first element is less than the second -// -// assert.Less(t, 1, 2) -// assert.Less(t, float64(1), float64(2)) -// assert.Less(t, "a", "b") -func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - failMessage := fmt.Sprintf("\"%v\" is not less than \"%v\"", e1, e2) - return compareTwoValues(t, e1, e2, []compareResult{compareLess}, failMessage, msgAndArgs...) -} - -// LessOrEqual asserts that the first element is less than or equal to the second -// -// assert.LessOrEqual(t, 1, 2) -// assert.LessOrEqual(t, 2, 2) -// assert.LessOrEqual(t, "a", "b") -// assert.LessOrEqual(t, "b", "b") -func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - failMessage := fmt.Sprintf("\"%v\" is not less than or equal to \"%v\"", e1, e2) - return compareTwoValues(t, e1, e2, []compareResult{compareLess, compareEqual}, failMessage, msgAndArgs...) -} - -// Positive asserts that the specified element is positive -// -// assert.Positive(t, 1) -// assert.Positive(t, 1.23) -func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - zero := reflect.Zero(reflect.TypeOf(e)) - failMessage := fmt.Sprintf("\"%v\" is not positive", e) - return compareTwoValues(t, e, zero.Interface(), []compareResult{compareGreater}, failMessage, msgAndArgs...) -} - -// Negative asserts that the specified element is negative -// -// assert.Negative(t, -1) -// assert.Negative(t, -1.23) -func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - zero := reflect.Zero(reflect.TypeOf(e)) - failMessage := fmt.Sprintf("\"%v\" is not negative", e) - return compareTwoValues(t, e, zero.Interface(), []compareResult{compareLess}, failMessage, msgAndArgs...) -} - -func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []compareResult, failMessage string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - e1Kind := reflect.ValueOf(e1).Kind() - e2Kind := reflect.ValueOf(e2).Kind() - if e1Kind != e2Kind { - return Fail(t, "Elements should be the same type", msgAndArgs...) - } - - compareResult, isComparable := compare(e1, e2, e1Kind) - if !isComparable { - return Fail(t, fmt.Sprintf(`Can not compare type "%T"`, e1), msgAndArgs...) - } - - if !containsValue(allowedComparesResults, compareResult) { - return Fail(t, failMessage, msgAndArgs...) - } - - return true -} - -func containsValue(values []compareResult, value compareResult) bool { - for _, v := range values { - if v == value { - return true - } - } - - return false -} diff --git a/go/sdk/vendor/github.com/stretchr/testify/assert/assertion_format.go b/go/sdk/vendor/github.com/stretchr/testify/assert/assertion_format.go deleted file mode 100644 index c592f6a..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/assert/assertion_format.go +++ /dev/null @@ -1,866 +0,0 @@ -// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. - -package assert - -import ( - http "net/http" - url "net/url" - time "time" -) - -// Conditionf uses a Comparison to assert a complex condition. -func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Condition(t, comp, append([]interface{}{msg}, args...)...) -} - -// Containsf asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted") -// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") -// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") -func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Contains(t, s, contains, append([]interface{}{msg}, args...)...) -} - -// DirExistsf checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return DirExists(t, path, append([]interface{}{msg}, args...)...) -} - -// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") -func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return ElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...) -} - -// Emptyf asserts that the given value is "empty". -// -// [Zero values] are "empty". -// -// Arrays are "empty" if every element is the zero value of the type (stricter than "empty"). -// -// Slices, maps and channels with zero length are "empty". -// -// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty". -// -// assert.Emptyf(t, obj, "error message %s", "formatted") -// -// [Zero values]: https://go.dev/ref/spec#The_zero_value -func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Empty(t, object, append([]interface{}{msg}, args...)...) -} - -// Equalf asserts that two objects are equal. -// -// assert.Equalf(t, 123, 123, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Equal(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// EqualErrorf asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") -func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...) -} - -// EqualExportedValuesf asserts that the types of two objects are equal and their public -// fields are also equal. This is useful for comparing structs that have private fields -// that could potentially differ. -// -// type S struct { -// Exported int -// notExported int -// } -// assert.EqualExportedValuesf(t, S{1, 2}, S{1, 3}, "error message %s", "formatted") => true -// assert.EqualExportedValuesf(t, S{1, 2}, S{2, 3}, "error message %s", "formatted") => false -func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return EqualExportedValues(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// EqualValuesf asserts that two objects are equal or convertible to the larger -// type and equal. -// -// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted") -func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return EqualValues(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// Errorf asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// assert.Errorf(t, err, "error message %s", "formatted") -func Errorf(t TestingT, err error, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Error(t, err, append([]interface{}{msg}, args...)...) -} - -// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return ErrorAs(t, err, target, append([]interface{}{msg}, args...)...) -} - -// ErrorContainsf asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted") -func ErrorContainsf(t TestingT, theError error, contains string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return ErrorContains(t, theError, contains, append([]interface{}{msg}, args...)...) -} - -// ErrorIsf asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return ErrorIs(t, err, target, append([]interface{}{msg}, args...)...) -} - -// Eventuallyf asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Eventually(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...) -} - -// EventuallyWithTf asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. In contrast to Eventually, -// it supplies a CollectT to the condition function, so that the condition -// function can use the CollectT to call other assertions. -// The condition is considered "met" if no errors are raised in a tick. -// The supplied CollectT collects all errors from one tick (if there are any). -// If the condition is not met before waitFor, the collected errors of -// the last tick are copied to t. -// -// externalValue := false -// go func() { -// time.Sleep(8*time.Second) -// externalValue = true -// }() -// assert.EventuallyWithTf(t, func(c *assert.CollectT, "error message %s", "formatted") { -// // add assertions as needed; any assertion failure will fail the current tick -// assert.True(c, externalValue, "expected 'externalValue' to be true") -// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false") -func EventuallyWithTf(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return EventuallyWithT(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...) -} - -// Exactlyf asserts that two objects are equal in value and type. -// -// assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted") -func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Exactly(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// Failf reports a failure through -func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, failureMessage, append([]interface{}{msg}, args...)...) -} - -// FailNowf fails test -func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return FailNow(t, failureMessage, append([]interface{}{msg}, args...)...) -} - -// Falsef asserts that the specified value is false. -// -// assert.Falsef(t, myBool, "error message %s", "formatted") -func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return False(t, value, append([]interface{}{msg}, args...)...) -} - -// FileExistsf checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return FileExists(t, path, append([]interface{}{msg}, args...)...) -} - -// Greaterf asserts that the first element is greater than the second -// -// assert.Greaterf(t, 2, 1, "error message %s", "formatted") -// assert.Greaterf(t, float64(2), float64(1), "error message %s", "formatted") -// assert.Greaterf(t, "b", "a", "error message %s", "formatted") -func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Greater(t, e1, e2, append([]interface{}{msg}, args...)...) -} - -// GreaterOrEqualf asserts that the first element is greater than or equal to the second -// -// assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted") -// assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted") -// assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted") -// assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted") -func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return GreaterOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...) -} - -// HTTPBodyContainsf asserts that a specified handler returns a -// body that contains a string. -// -// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return HTTPBodyContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) -} - -// HTTPBodyNotContainsf asserts that a specified handler returns a -// body that does not contain a string. -// -// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return HTTPBodyNotContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) -} - -// HTTPErrorf asserts that a specified handler returns an error status code. -// -// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return HTTPError(t, handler, method, url, values, append([]interface{}{msg}, args...)...) -} - -// HTTPRedirectf asserts that a specified handler returns a redirect status code. -// -// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return HTTPRedirect(t, handler, method, url, values, append([]interface{}{msg}, args...)...) -} - -// HTTPStatusCodef asserts that a specified handler returns a specified status code. -// -// assert.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return HTTPStatusCode(t, handler, method, url, values, statuscode, append([]interface{}{msg}, args...)...) -} - -// HTTPSuccessf asserts that a specified handler returns a success status code. -// -// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return HTTPSuccess(t, handler, method, url, values, append([]interface{}{msg}, args...)...) -} - -// Implementsf asserts that an object is implemented by the specified interface. -// -// assert.Implementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") -func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Implements(t, interfaceObject, object, append([]interface{}{msg}, args...)...) -} - -// InDeltaf asserts that the two numerals are within delta of each other. -// -// assert.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted") -func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return InDelta(t, expected, actual, delta, append([]interface{}{msg}, args...)...) -} - -// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return InDeltaMapValues(t, expected, actual, delta, append([]interface{}{msg}, args...)...) -} - -// InDeltaSlicef is the same as InDelta, except it compares two slices. -func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return InDeltaSlice(t, expected, actual, delta, append([]interface{}{msg}, args...)...) -} - -// InEpsilonf asserts that expected and actual have a relative error less than epsilon -func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return InEpsilon(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) -} - -// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. -func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) -} - -// IsDecreasingf asserts that the collection is decreasing -// -// assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted") -// assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted") -// assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted") -func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return IsDecreasing(t, object, append([]interface{}{msg}, args...)...) -} - -// IsIncreasingf asserts that the collection is increasing -// -// assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted") -// assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted") -// assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted") -func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return IsIncreasing(t, object, append([]interface{}{msg}, args...)...) -} - -// IsNonDecreasingf asserts that the collection is not decreasing -// -// assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted") -// assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted") -// assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted") -func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return IsNonDecreasing(t, object, append([]interface{}{msg}, args...)...) -} - -// IsNonIncreasingf asserts that the collection is not increasing -// -// assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted") -// assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted") -// assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted") -func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return IsNonIncreasing(t, object, append([]interface{}{msg}, args...)...) -} - -// IsNotTypef asserts that the specified objects are not of the same type. -// -// assert.IsNotTypef(t, &NotMyStruct{}, &MyStruct{}, "error message %s", "formatted") -func IsNotTypef(t TestingT, theType interface{}, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return IsNotType(t, theType, object, append([]interface{}{msg}, args...)...) -} - -// IsTypef asserts that the specified objects are of the same type. -// -// assert.IsTypef(t, &MyStruct{}, &MyStruct{}, "error message %s", "formatted") -func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return IsType(t, expectedType, object, append([]interface{}{msg}, args...)...) -} - -// JSONEqf asserts that two JSON strings are equivalent. -// -// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") -func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// Lenf asserts that the specified object has specific length. -// Lenf also fails if the object has a type that len() not accept. -// -// assert.Lenf(t, mySlice, 3, "error message %s", "formatted") -func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Len(t, object, length, append([]interface{}{msg}, args...)...) -} - -// Lessf asserts that the first element is less than the second -// -// assert.Lessf(t, 1, 2, "error message %s", "formatted") -// assert.Lessf(t, float64(1), float64(2), "error message %s", "formatted") -// assert.Lessf(t, "a", "b", "error message %s", "formatted") -func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Less(t, e1, e2, append([]interface{}{msg}, args...)...) -} - -// LessOrEqualf asserts that the first element is less than or equal to the second -// -// assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted") -// assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted") -// assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted") -// assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted") -func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return LessOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...) -} - -// Negativef asserts that the specified element is negative -// -// assert.Negativef(t, -1, "error message %s", "formatted") -// assert.Negativef(t, -1.23, "error message %s", "formatted") -func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Negative(t, e, append([]interface{}{msg}, args...)...) -} - -// Neverf asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// assert.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Never(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...) -} - -// Nilf asserts that the specified object is nil. -// -// assert.Nilf(t, err, "error message %s", "formatted") -func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Nil(t, object, append([]interface{}{msg}, args...)...) -} - -// NoDirExistsf checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func NoDirExistsf(t TestingT, path string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NoDirExists(t, path, append([]interface{}{msg}, args...)...) -} - -// NoErrorf asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if assert.NoErrorf(t, err, "error message %s", "formatted") { -// assert.Equal(t, expectedObj, actualObj) -// } -func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NoError(t, err, append([]interface{}{msg}, args...)...) -} - -// NoFileExistsf checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func NoFileExistsf(t TestingT, path string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NoFileExists(t, path, append([]interface{}{msg}, args...)...) -} - -// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") -// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") -// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") -func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotContains(t, s, contains, append([]interface{}{msg}, args...)...) -} - -// NotElementsMatchf asserts that the specified listA(array, slice...) is NOT equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should not match. -// This is an inverse of ElementsMatch. -// -// assert.NotElementsMatchf(t, [1, 1, 2, 3], [1, 1, 2, 3], "error message %s", "formatted") -> false -// -// assert.NotElementsMatchf(t, [1, 1, 2, 3], [1, 2, 3], "error message %s", "formatted") -> true -// -// assert.NotElementsMatchf(t, [1, 2, 3], [1, 2, 4], "error message %s", "formatted") -> true -func NotElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...) -} - -// NotEmptyf asserts that the specified object is NOT [Empty]. -// -// if assert.NotEmptyf(t, obj, "error message %s", "formatted") { -// assert.Equal(t, "two", obj[1]) -// } -func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotEmpty(t, object, append([]interface{}{msg}, args...)...) -} - -// NotEqualf asserts that the specified values are NOT equal. -// -// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// NotEqualValuesf asserts that two objects are not equal even when converted to the same type -// -// assert.NotEqualValuesf(t, obj1, obj2, "error message %s", "formatted") -func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotEqualValues(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// NotErrorAsf asserts that none of the errors in err's chain matches target, -// but if so, sets target to that error value. -func NotErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotErrorAs(t, err, target, append([]interface{}{msg}, args...)...) -} - -// NotErrorIsf asserts that none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...) -} - -// NotImplementsf asserts that an object does not implement the specified interface. -// -// assert.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") -func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotImplements(t, interfaceObject, object, append([]interface{}{msg}, args...)...) -} - -// NotNilf asserts that the specified object is not nil. -// -// assert.NotNilf(t, err, "error message %s", "formatted") -func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotNil(t, object, append([]interface{}{msg}, args...)...) -} - -// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") -func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotPanics(t, f, append([]interface{}{msg}, args...)...) -} - -// NotRegexpf asserts that a specified regexp does not match a string. -// -// assert.NotRegexpf(t, regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") -// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") -func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotRegexp(t, rx, str, append([]interface{}{msg}, args...)...) -} - -// NotSamef asserts that two pointers do not reference the same object. -// -// assert.NotSamef(t, ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// NotSubsetf asserts that the list (array, slice, or map) does NOT contain all -// elements given in the subset (array, slice, or map). -// Map elements are key-value pairs unless compared with an array or slice where -// only the map key is evaluated. -// -// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted") -// assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") -// assert.NotSubsetf(t, [1, 3, 4], {1: "one", 2: "two"}, "error message %s", "formatted") -// assert.NotSubsetf(t, {"x": 1, "y": 2}, ["z"], "error message %s", "formatted") -func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotSubset(t, list, subset, append([]interface{}{msg}, args...)...) -} - -// NotZerof asserts that i is not the zero value for its type. -func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotZero(t, i, append([]interface{}{msg}, args...)...) -} - -// Panicsf asserts that the code inside the specified PanicTestFunc panics. -// -// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") -func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Panics(t, f, append([]interface{}{msg}, args...)...) -} - -// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// assert.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func PanicsWithErrorf(t TestingT, errString string, f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return PanicsWithError(t, errString, f, append([]interface{}{msg}, args...)...) -} - -// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...) -} - -// Positivef asserts that the specified element is positive -// -// assert.Positivef(t, 1, "error message %s", "formatted") -// assert.Positivef(t, 1.23, "error message %s", "formatted") -func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Positive(t, e, append([]interface{}{msg}, args...)...) -} - -// Regexpf asserts that a specified regexp matches a string. -// -// assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") -// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") -func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Regexp(t, rx, str, append([]interface{}{msg}, args...)...) -} - -// Samef asserts that two pointers reference the same object. -// -// assert.Samef(t, ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func Samef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Same(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// Subsetf asserts that the list (array, slice, or map) contains all elements -// given in the subset (array, slice, or map). -// Map elements are key-value pairs unless compared with an array or slice where -// only the map key is evaluated. -// -// assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted") -// assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") -// assert.Subsetf(t, [1, 2, 3], {1: "one", 2: "two"}, "error message %s", "formatted") -// assert.Subsetf(t, {"x": 1, "y": 2}, ["x"], "error message %s", "formatted") -func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Subset(t, list, subset, append([]interface{}{msg}, args...)...) -} - -// Truef asserts that the specified value is true. -// -// assert.Truef(t, myBool, "error message %s", "formatted") -func Truef(t TestingT, value bool, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return True(t, value, append([]interface{}{msg}, args...)...) -} - -// WithinDurationf asserts that the two times are within duration delta of each other. -// -// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") -func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...) -} - -// WithinRangef asserts that a time is within a time range (inclusive). -// -// assert.WithinRangef(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") -func WithinRangef(t TestingT, actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return WithinRange(t, actual, start, end, append([]interface{}{msg}, args...)...) -} - -// YAMLEqf asserts that two YAML strings are equivalent. -func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return YAMLEq(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// Zerof asserts that i is the zero value for its type. -func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Zero(t, i, append([]interface{}{msg}, args...)...) -} diff --git a/go/sdk/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl b/go/sdk/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl deleted file mode 100644 index d2bb0b8..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl +++ /dev/null @@ -1,5 +0,0 @@ -{{.CommentFormat}} -func {{.DocInfo.Name}}f(t TestingT, {{.ParamsFormat}}) bool { - if h, ok := t.(tHelper); ok { h.Helper() } - return {{.DocInfo.Name}}(t, {{.ForwardedParamsFormat}}) -} diff --git a/go/sdk/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/go/sdk/vendor/github.com/stretchr/testify/assert/assertion_forward.go deleted file mode 100644 index 58db928..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/assert/assertion_forward.go +++ /dev/null @@ -1,1723 +0,0 @@ -// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. - -package assert - -import ( - http "net/http" - url "net/url" - time "time" -) - -// Condition uses a Comparison to assert a complex condition. -func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Condition(a.t, comp, msgAndArgs...) -} - -// Conditionf uses a Comparison to assert a complex condition. -func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Conditionf(a.t, comp, msg, args...) -} - -// Contains asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// a.Contains("Hello World", "World") -// a.Contains(["Hello", "World"], "World") -// a.Contains({"Hello": "World"}, "Hello") -func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Contains(a.t, s, contains, msgAndArgs...) -} - -// Containsf asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// a.Containsf("Hello World", "World", "error message %s", "formatted") -// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") -// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") -func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Containsf(a.t, s, contains, msg, args...) -} - -// DirExists checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return DirExists(a.t, path, msgAndArgs...) -} - -// DirExistsf checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return DirExistsf(a.t, path, msg, args...) -} - -// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2]) -func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ElementsMatch(a.t, listA, listB, msgAndArgs...) -} - -// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") -func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ElementsMatchf(a.t, listA, listB, msg, args...) -} - -// Empty asserts that the given value is "empty". -// -// [Zero values] are "empty". -// -// Arrays are "empty" if every element is the zero value of the type (stricter than "empty"). -// -// Slices, maps and channels with zero length are "empty". -// -// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty". -// -// a.Empty(obj) -// -// [Zero values]: https://go.dev/ref/spec#The_zero_value -func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Empty(a.t, object, msgAndArgs...) -} - -// Emptyf asserts that the given value is "empty". -// -// [Zero values] are "empty". -// -// Arrays are "empty" if every element is the zero value of the type (stricter than "empty"). -// -// Slices, maps and channels with zero length are "empty". -// -// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty". -// -// a.Emptyf(obj, "error message %s", "formatted") -// -// [Zero values]: https://go.dev/ref/spec#The_zero_value -func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Emptyf(a.t, object, msg, args...) -} - -// Equal asserts that two objects are equal. -// -// a.Equal(123, 123) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Equal(a.t, expected, actual, msgAndArgs...) -} - -// EqualError asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// a.EqualError(err, expectedErrorString) -func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return EqualError(a.t, theError, errString, msgAndArgs...) -} - -// EqualErrorf asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") -func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return EqualErrorf(a.t, theError, errString, msg, args...) -} - -// EqualExportedValues asserts that the types of two objects are equal and their public -// fields are also equal. This is useful for comparing structs that have private fields -// that could potentially differ. -// -// type S struct { -// Exported int -// notExported int -// } -// a.EqualExportedValues(S{1, 2}, S{1, 3}) => true -// a.EqualExportedValues(S{1, 2}, S{2, 3}) => false -func (a *Assertions) EqualExportedValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return EqualExportedValues(a.t, expected, actual, msgAndArgs...) -} - -// EqualExportedValuesf asserts that the types of two objects are equal and their public -// fields are also equal. This is useful for comparing structs that have private fields -// that could potentially differ. -// -// type S struct { -// Exported int -// notExported int -// } -// a.EqualExportedValuesf(S{1, 2}, S{1, 3}, "error message %s", "formatted") => true -// a.EqualExportedValuesf(S{1, 2}, S{2, 3}, "error message %s", "formatted") => false -func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return EqualExportedValuesf(a.t, expected, actual, msg, args...) -} - -// EqualValues asserts that two objects are equal or convertible to the larger -// type and equal. -// -// a.EqualValues(uint32(123), int32(123)) -func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return EqualValues(a.t, expected, actual, msgAndArgs...) -} - -// EqualValuesf asserts that two objects are equal or convertible to the larger -// type and equal. -// -// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted") -func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return EqualValuesf(a.t, expected, actual, msg, args...) -} - -// Equalf asserts that two objects are equal. -// -// a.Equalf(123, 123, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Equalf(a.t, expected, actual, msg, args...) -} - -// Error asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// a.Error(err) -func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Error(a.t, err, msgAndArgs...) -} - -// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func (a *Assertions) ErrorAs(err error, target interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ErrorAs(a.t, err, target, msgAndArgs...) -} - -// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ErrorAsf(a.t, err, target, msg, args...) -} - -// ErrorContains asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// a.ErrorContains(err, expectedErrorSubString) -func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ErrorContains(a.t, theError, contains, msgAndArgs...) -} - -// ErrorContainsf asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted") -func (a *Assertions) ErrorContainsf(theError error, contains string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ErrorContainsf(a.t, theError, contains, msg, args...) -} - -// ErrorIs asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ErrorIs(a.t, err, target, msgAndArgs...) -} - -// ErrorIsf asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ErrorIsf(a.t, err, target, msg, args...) -} - -// Errorf asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// a.Errorf(err, "error message %s", "formatted") -func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Errorf(a.t, err, msg, args...) -} - -// Eventually asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond) -func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Eventually(a.t, condition, waitFor, tick, msgAndArgs...) -} - -// EventuallyWithT asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. In contrast to Eventually, -// it supplies a CollectT to the condition function, so that the condition -// function can use the CollectT to call other assertions. -// The condition is considered "met" if no errors are raised in a tick. -// The supplied CollectT collects all errors from one tick (if there are any). -// If the condition is not met before waitFor, the collected errors of -// the last tick are copied to t. -// -// externalValue := false -// go func() { -// time.Sleep(8*time.Second) -// externalValue = true -// }() -// a.EventuallyWithT(func(c *assert.CollectT) { -// // add assertions as needed; any assertion failure will fail the current tick -// assert.True(c, externalValue, "expected 'externalValue' to be true") -// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false") -func (a *Assertions) EventuallyWithT(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return EventuallyWithT(a.t, condition, waitFor, tick, msgAndArgs...) -} - -// EventuallyWithTf asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. In contrast to Eventually, -// it supplies a CollectT to the condition function, so that the condition -// function can use the CollectT to call other assertions. -// The condition is considered "met" if no errors are raised in a tick. -// The supplied CollectT collects all errors from one tick (if there are any). -// If the condition is not met before waitFor, the collected errors of -// the last tick are copied to t. -// -// externalValue := false -// go func() { -// time.Sleep(8*time.Second) -// externalValue = true -// }() -// a.EventuallyWithTf(func(c *assert.CollectT, "error message %s", "formatted") { -// // add assertions as needed; any assertion failure will fail the current tick -// assert.True(c, externalValue, "expected 'externalValue' to be true") -// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false") -func (a *Assertions) EventuallyWithTf(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return EventuallyWithTf(a.t, condition, waitFor, tick, msg, args...) -} - -// Eventuallyf asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Eventuallyf(a.t, condition, waitFor, tick, msg, args...) -} - -// Exactly asserts that two objects are equal in value and type. -// -// a.Exactly(int32(123), int64(123)) -func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Exactly(a.t, expected, actual, msgAndArgs...) -} - -// Exactlyf asserts that two objects are equal in value and type. -// -// a.Exactlyf(int32(123), int64(123), "error message %s", "formatted") -func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Exactlyf(a.t, expected, actual, msg, args...) -} - -// Fail reports a failure through -func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Fail(a.t, failureMessage, msgAndArgs...) -} - -// FailNow fails test -func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return FailNow(a.t, failureMessage, msgAndArgs...) -} - -// FailNowf fails test -func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return FailNowf(a.t, failureMessage, msg, args...) -} - -// Failf reports a failure through -func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Failf(a.t, failureMessage, msg, args...) -} - -// False asserts that the specified value is false. -// -// a.False(myBool) -func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return False(a.t, value, msgAndArgs...) -} - -// Falsef asserts that the specified value is false. -// -// a.Falsef(myBool, "error message %s", "formatted") -func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Falsef(a.t, value, msg, args...) -} - -// FileExists checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return FileExists(a.t, path, msgAndArgs...) -} - -// FileExistsf checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return FileExistsf(a.t, path, msg, args...) -} - -// Greater asserts that the first element is greater than the second -// -// a.Greater(2, 1) -// a.Greater(float64(2), float64(1)) -// a.Greater("b", "a") -func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Greater(a.t, e1, e2, msgAndArgs...) -} - -// GreaterOrEqual asserts that the first element is greater than or equal to the second -// -// a.GreaterOrEqual(2, 1) -// a.GreaterOrEqual(2, 2) -// a.GreaterOrEqual("b", "a") -// a.GreaterOrEqual("b", "b") -func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return GreaterOrEqual(a.t, e1, e2, msgAndArgs...) -} - -// GreaterOrEqualf asserts that the first element is greater than or equal to the second -// -// a.GreaterOrEqualf(2, 1, "error message %s", "formatted") -// a.GreaterOrEqualf(2, 2, "error message %s", "formatted") -// a.GreaterOrEqualf("b", "a", "error message %s", "formatted") -// a.GreaterOrEqualf("b", "b", "error message %s", "formatted") -func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return GreaterOrEqualf(a.t, e1, e2, msg, args...) -} - -// Greaterf asserts that the first element is greater than the second -// -// a.Greaterf(2, 1, "error message %s", "formatted") -// a.Greaterf(float64(2), float64(1), "error message %s", "formatted") -// a.Greaterf("b", "a", "error message %s", "formatted") -func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Greaterf(a.t, e1, e2, msg, args...) -} - -// HTTPBodyContains asserts that a specified handler returns a -// body that contains a string. -// -// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...) -} - -// HTTPBodyContainsf asserts that a specified handler returns a -// body that contains a string. -// -// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...) -} - -// HTTPBodyNotContains asserts that a specified handler returns a -// body that does not contain a string. -// -// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...) -} - -// HTTPBodyNotContainsf asserts that a specified handler returns a -// body that does not contain a string. -// -// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...) -} - -// HTTPError asserts that a specified handler returns an error status code. -// -// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPError(a.t, handler, method, url, values, msgAndArgs...) -} - -// HTTPErrorf asserts that a specified handler returns an error status code. -// -// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPErrorf(a.t, handler, method, url, values, msg, args...) -} - -// HTTPRedirect asserts that a specified handler returns a redirect status code. -// -// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...) -} - -// HTTPRedirectf asserts that a specified handler returns a redirect status code. -// -// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPRedirectf(a.t, handler, method, url, values, msg, args...) -} - -// HTTPStatusCode asserts that a specified handler returns a specified status code. -// -// a.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501) -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPStatusCode(a.t, handler, method, url, values, statuscode, msgAndArgs...) -} - -// HTTPStatusCodef asserts that a specified handler returns a specified status code. -// -// a.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPStatusCodef(a.t, handler, method, url, values, statuscode, msg, args...) -} - -// HTTPSuccess asserts that a specified handler returns a success status code. -// -// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...) -} - -// HTTPSuccessf asserts that a specified handler returns a success status code. -// -// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPSuccessf(a.t, handler, method, url, values, msg, args...) -} - -// Implements asserts that an object is implemented by the specified interface. -// -// a.Implements((*MyInterface)(nil), new(MyObject)) -func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Implements(a.t, interfaceObject, object, msgAndArgs...) -} - -// Implementsf asserts that an object is implemented by the specified interface. -// -// a.Implementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") -func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Implementsf(a.t, interfaceObject, object, msg, args...) -} - -// InDelta asserts that the two numerals are within delta of each other. -// -// a.InDelta(math.Pi, 22/7.0, 0.01) -func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InDelta(a.t, expected, actual, delta, msgAndArgs...) -} - -// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...) -} - -// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...) -} - -// InDeltaSlice is the same as InDelta, except it compares two slices. -func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) -} - -// InDeltaSlicef is the same as InDelta, except it compares two slices. -func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InDeltaSlicef(a.t, expected, actual, delta, msg, args...) -} - -// InDeltaf asserts that the two numerals are within delta of each other. -// -// a.InDeltaf(math.Pi, 22/7.0, 0.01, "error message %s", "formatted") -func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InDeltaf(a.t, expected, actual, delta, msg, args...) -} - -// InEpsilon asserts that expected and actual have a relative error less than epsilon -func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) -} - -// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. -func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...) -} - -// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. -func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...) -} - -// InEpsilonf asserts that expected and actual have a relative error less than epsilon -func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InEpsilonf(a.t, expected, actual, epsilon, msg, args...) -} - -// IsDecreasing asserts that the collection is decreasing -// -// a.IsDecreasing([]int{2, 1, 0}) -// a.IsDecreasing([]float{2, 1}) -// a.IsDecreasing([]string{"b", "a"}) -func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsDecreasing(a.t, object, msgAndArgs...) -} - -// IsDecreasingf asserts that the collection is decreasing -// -// a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted") -// a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted") -// a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted") -func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsDecreasingf(a.t, object, msg, args...) -} - -// IsIncreasing asserts that the collection is increasing -// -// a.IsIncreasing([]int{1, 2, 3}) -// a.IsIncreasing([]float{1, 2}) -// a.IsIncreasing([]string{"a", "b"}) -func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsIncreasing(a.t, object, msgAndArgs...) -} - -// IsIncreasingf asserts that the collection is increasing -// -// a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted") -// a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted") -// a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted") -func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsIncreasingf(a.t, object, msg, args...) -} - -// IsNonDecreasing asserts that the collection is not decreasing -// -// a.IsNonDecreasing([]int{1, 1, 2}) -// a.IsNonDecreasing([]float{1, 2}) -// a.IsNonDecreasing([]string{"a", "b"}) -func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsNonDecreasing(a.t, object, msgAndArgs...) -} - -// IsNonDecreasingf asserts that the collection is not decreasing -// -// a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted") -// a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted") -// a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted") -func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsNonDecreasingf(a.t, object, msg, args...) -} - -// IsNonIncreasing asserts that the collection is not increasing -// -// a.IsNonIncreasing([]int{2, 1, 1}) -// a.IsNonIncreasing([]float{2, 1}) -// a.IsNonIncreasing([]string{"b", "a"}) -func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsNonIncreasing(a.t, object, msgAndArgs...) -} - -// IsNonIncreasingf asserts that the collection is not increasing -// -// a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted") -// a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted") -// a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted") -func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsNonIncreasingf(a.t, object, msg, args...) -} - -// IsNotType asserts that the specified objects are not of the same type. -// -// a.IsNotType(&NotMyStruct{}, &MyStruct{}) -func (a *Assertions) IsNotType(theType interface{}, object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsNotType(a.t, theType, object, msgAndArgs...) -} - -// IsNotTypef asserts that the specified objects are not of the same type. -// -// a.IsNotTypef(&NotMyStruct{}, &MyStruct{}, "error message %s", "formatted") -func (a *Assertions) IsNotTypef(theType interface{}, object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsNotTypef(a.t, theType, object, msg, args...) -} - -// IsType asserts that the specified objects are of the same type. -// -// a.IsType(&MyStruct{}, &MyStruct{}) -func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsType(a.t, expectedType, object, msgAndArgs...) -} - -// IsTypef asserts that the specified objects are of the same type. -// -// a.IsTypef(&MyStruct{}, &MyStruct{}, "error message %s", "formatted") -func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsTypef(a.t, expectedType, object, msg, args...) -} - -// JSONEq asserts that two JSON strings are equivalent. -// -// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) -func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return JSONEq(a.t, expected, actual, msgAndArgs...) -} - -// JSONEqf asserts that two JSON strings are equivalent. -// -// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") -func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return JSONEqf(a.t, expected, actual, msg, args...) -} - -// Len asserts that the specified object has specific length. -// Len also fails if the object has a type that len() not accept. -// -// a.Len(mySlice, 3) -func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Len(a.t, object, length, msgAndArgs...) -} - -// Lenf asserts that the specified object has specific length. -// Lenf also fails if the object has a type that len() not accept. -// -// a.Lenf(mySlice, 3, "error message %s", "formatted") -func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Lenf(a.t, object, length, msg, args...) -} - -// Less asserts that the first element is less than the second -// -// a.Less(1, 2) -// a.Less(float64(1), float64(2)) -// a.Less("a", "b") -func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Less(a.t, e1, e2, msgAndArgs...) -} - -// LessOrEqual asserts that the first element is less than or equal to the second -// -// a.LessOrEqual(1, 2) -// a.LessOrEqual(2, 2) -// a.LessOrEqual("a", "b") -// a.LessOrEqual("b", "b") -func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return LessOrEqual(a.t, e1, e2, msgAndArgs...) -} - -// LessOrEqualf asserts that the first element is less than or equal to the second -// -// a.LessOrEqualf(1, 2, "error message %s", "formatted") -// a.LessOrEqualf(2, 2, "error message %s", "formatted") -// a.LessOrEqualf("a", "b", "error message %s", "formatted") -// a.LessOrEqualf("b", "b", "error message %s", "formatted") -func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return LessOrEqualf(a.t, e1, e2, msg, args...) -} - -// Lessf asserts that the first element is less than the second -// -// a.Lessf(1, 2, "error message %s", "formatted") -// a.Lessf(float64(1), float64(2), "error message %s", "formatted") -// a.Lessf("a", "b", "error message %s", "formatted") -func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Lessf(a.t, e1, e2, msg, args...) -} - -// Negative asserts that the specified element is negative -// -// a.Negative(-1) -// a.Negative(-1.23) -func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Negative(a.t, e, msgAndArgs...) -} - -// Negativef asserts that the specified element is negative -// -// a.Negativef(-1, "error message %s", "formatted") -// a.Negativef(-1.23, "error message %s", "formatted") -func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Negativef(a.t, e, msg, args...) -} - -// Never asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// a.Never(func() bool { return false; }, time.Second, 10*time.Millisecond) -func (a *Assertions) Never(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Never(a.t, condition, waitFor, tick, msgAndArgs...) -} - -// Neverf asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// a.Neverf(func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func (a *Assertions) Neverf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Neverf(a.t, condition, waitFor, tick, msg, args...) -} - -// Nil asserts that the specified object is nil. -// -// a.Nil(err) -func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Nil(a.t, object, msgAndArgs...) -} - -// Nilf asserts that the specified object is nil. -// -// a.Nilf(err, "error message %s", "formatted") -func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Nilf(a.t, object, msg, args...) -} - -// NoDirExists checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func (a *Assertions) NoDirExists(path string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NoDirExists(a.t, path, msgAndArgs...) -} - -// NoDirExistsf checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func (a *Assertions) NoDirExistsf(path string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NoDirExistsf(a.t, path, msg, args...) -} - -// NoError asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if a.NoError(err) { -// assert.Equal(t, expectedObj, actualObj) -// } -func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NoError(a.t, err, msgAndArgs...) -} - -// NoErrorf asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if a.NoErrorf(err, "error message %s", "formatted") { -// assert.Equal(t, expectedObj, actualObj) -// } -func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NoErrorf(a.t, err, msg, args...) -} - -// NoFileExists checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func (a *Assertions) NoFileExists(path string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NoFileExists(a.t, path, msgAndArgs...) -} - -// NoFileExistsf checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func (a *Assertions) NoFileExistsf(path string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NoFileExistsf(a.t, path, msg, args...) -} - -// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// a.NotContains("Hello World", "Earth") -// a.NotContains(["Hello", "World"], "Earth") -// a.NotContains({"Hello": "World"}, "Earth") -func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotContains(a.t, s, contains, msgAndArgs...) -} - -// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") -// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") -// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") -func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotContainsf(a.t, s, contains, msg, args...) -} - -// NotElementsMatch asserts that the specified listA(array, slice...) is NOT equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should not match. -// This is an inverse of ElementsMatch. -// -// a.NotElementsMatch([1, 1, 2, 3], [1, 1, 2, 3]) -> false -// -// a.NotElementsMatch([1, 1, 2, 3], [1, 2, 3]) -> true -// -// a.NotElementsMatch([1, 2, 3], [1, 2, 4]) -> true -func (a *Assertions) NotElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotElementsMatch(a.t, listA, listB, msgAndArgs...) -} - -// NotElementsMatchf asserts that the specified listA(array, slice...) is NOT equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should not match. -// This is an inverse of ElementsMatch. -// -// a.NotElementsMatchf([1, 1, 2, 3], [1, 1, 2, 3], "error message %s", "formatted") -> false -// -// a.NotElementsMatchf([1, 1, 2, 3], [1, 2, 3], "error message %s", "formatted") -> true -// -// a.NotElementsMatchf([1, 2, 3], [1, 2, 4], "error message %s", "formatted") -> true -func (a *Assertions) NotElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotElementsMatchf(a.t, listA, listB, msg, args...) -} - -// NotEmpty asserts that the specified object is NOT [Empty]. -// -// if a.NotEmpty(obj) { -// assert.Equal(t, "two", obj[1]) -// } -func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotEmpty(a.t, object, msgAndArgs...) -} - -// NotEmptyf asserts that the specified object is NOT [Empty]. -// -// if a.NotEmptyf(obj, "error message %s", "formatted") { -// assert.Equal(t, "two", obj[1]) -// } -func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotEmptyf(a.t, object, msg, args...) -} - -// NotEqual asserts that the specified values are NOT equal. -// -// a.NotEqual(obj1, obj2) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotEqual(a.t, expected, actual, msgAndArgs...) -} - -// NotEqualValues asserts that two objects are not equal even when converted to the same type -// -// a.NotEqualValues(obj1, obj2) -func (a *Assertions) NotEqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotEqualValues(a.t, expected, actual, msgAndArgs...) -} - -// NotEqualValuesf asserts that two objects are not equal even when converted to the same type -// -// a.NotEqualValuesf(obj1, obj2, "error message %s", "formatted") -func (a *Assertions) NotEqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotEqualValuesf(a.t, expected, actual, msg, args...) -} - -// NotEqualf asserts that the specified values are NOT equal. -// -// a.NotEqualf(obj1, obj2, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotEqualf(a.t, expected, actual, msg, args...) -} - -// NotErrorAs asserts that none of the errors in err's chain matches target, -// but if so, sets target to that error value. -func (a *Assertions) NotErrorAs(err error, target interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotErrorAs(a.t, err, target, msgAndArgs...) -} - -// NotErrorAsf asserts that none of the errors in err's chain matches target, -// but if so, sets target to that error value. -func (a *Assertions) NotErrorAsf(err error, target interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotErrorAsf(a.t, err, target, msg, args...) -} - -// NotErrorIs asserts that none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotErrorIs(a.t, err, target, msgAndArgs...) -} - -// NotErrorIsf asserts that none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotErrorIsf(a.t, err, target, msg, args...) -} - -// NotImplements asserts that an object does not implement the specified interface. -// -// a.NotImplements((*MyInterface)(nil), new(MyObject)) -func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotImplements(a.t, interfaceObject, object, msgAndArgs...) -} - -// NotImplementsf asserts that an object does not implement the specified interface. -// -// a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") -func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotImplementsf(a.t, interfaceObject, object, msg, args...) -} - -// NotNil asserts that the specified object is not nil. -// -// a.NotNil(err) -func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotNil(a.t, object, msgAndArgs...) -} - -// NotNilf asserts that the specified object is not nil. -// -// a.NotNilf(err, "error message %s", "formatted") -func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotNilf(a.t, object, msg, args...) -} - -// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// a.NotPanics(func(){ RemainCalm() }) -func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotPanics(a.t, f, msgAndArgs...) -} - -// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") -func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotPanicsf(a.t, f, msg, args...) -} - -// NotRegexp asserts that a specified regexp does not match a string. -// -// a.NotRegexp(regexp.MustCompile("starts"), "it's starting") -// a.NotRegexp("^start", "it's not starting") -func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotRegexp(a.t, rx, str, msgAndArgs...) -} - -// NotRegexpf asserts that a specified regexp does not match a string. -// -// a.NotRegexpf(regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") -// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") -func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotRegexpf(a.t, rx, str, msg, args...) -} - -// NotSame asserts that two pointers do not reference the same object. -// -// a.NotSame(ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) NotSame(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotSame(a.t, expected, actual, msgAndArgs...) -} - -// NotSamef asserts that two pointers do not reference the same object. -// -// a.NotSamef(ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotSamef(a.t, expected, actual, msg, args...) -} - -// NotSubset asserts that the list (array, slice, or map) does NOT contain all -// elements given in the subset (array, slice, or map). -// Map elements are key-value pairs unless compared with an array or slice where -// only the map key is evaluated. -// -// a.NotSubset([1, 3, 4], [1, 2]) -// a.NotSubset({"x": 1, "y": 2}, {"z": 3}) -// a.NotSubset([1, 3, 4], {1: "one", 2: "two"}) -// a.NotSubset({"x": 1, "y": 2}, ["z"]) -func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotSubset(a.t, list, subset, msgAndArgs...) -} - -// NotSubsetf asserts that the list (array, slice, or map) does NOT contain all -// elements given in the subset (array, slice, or map). -// Map elements are key-value pairs unless compared with an array or slice where -// only the map key is evaluated. -// -// a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted") -// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") -// a.NotSubsetf([1, 3, 4], {1: "one", 2: "two"}, "error message %s", "formatted") -// a.NotSubsetf({"x": 1, "y": 2}, ["z"], "error message %s", "formatted") -func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotSubsetf(a.t, list, subset, msg, args...) -} - -// NotZero asserts that i is not the zero value for its type. -func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotZero(a.t, i, msgAndArgs...) -} - -// NotZerof asserts that i is not the zero value for its type. -func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotZerof(a.t, i, msg, args...) -} - -// Panics asserts that the code inside the specified PanicTestFunc panics. -// -// a.Panics(func(){ GoCrazy() }) -func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Panics(a.t, f, msgAndArgs...) -} - -// PanicsWithError asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// a.PanicsWithError("crazy error", func(){ GoCrazy() }) -func (a *Assertions) PanicsWithError(errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return PanicsWithError(a.t, errString, f, msgAndArgs...) -} - -// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// a.PanicsWithErrorf("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func (a *Assertions) PanicsWithErrorf(errString string, f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return PanicsWithErrorf(a.t, errString, f, msg, args...) -} - -// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// a.PanicsWithValue("crazy error", func(){ GoCrazy() }) -func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return PanicsWithValue(a.t, expected, f, msgAndArgs...) -} - -// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return PanicsWithValuef(a.t, expected, f, msg, args...) -} - -// Panicsf asserts that the code inside the specified PanicTestFunc panics. -// -// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") -func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Panicsf(a.t, f, msg, args...) -} - -// Positive asserts that the specified element is positive -// -// a.Positive(1) -// a.Positive(1.23) -func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Positive(a.t, e, msgAndArgs...) -} - -// Positivef asserts that the specified element is positive -// -// a.Positivef(1, "error message %s", "formatted") -// a.Positivef(1.23, "error message %s", "formatted") -func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Positivef(a.t, e, msg, args...) -} - -// Regexp asserts that a specified regexp matches a string. -// -// a.Regexp(regexp.MustCompile("start"), "it's starting") -// a.Regexp("start...$", "it's not starting") -func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Regexp(a.t, rx, str, msgAndArgs...) -} - -// Regexpf asserts that a specified regexp matches a string. -// -// a.Regexpf(regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") -// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") -func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Regexpf(a.t, rx, str, msg, args...) -} - -// Same asserts that two pointers reference the same object. -// -// a.Same(ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) Same(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Same(a.t, expected, actual, msgAndArgs...) -} - -// Samef asserts that two pointers reference the same object. -// -// a.Samef(ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Samef(a.t, expected, actual, msg, args...) -} - -// Subset asserts that the list (array, slice, or map) contains all elements -// given in the subset (array, slice, or map). -// Map elements are key-value pairs unless compared with an array or slice where -// only the map key is evaluated. -// -// a.Subset([1, 2, 3], [1, 2]) -// a.Subset({"x": 1, "y": 2}, {"x": 1}) -// a.Subset([1, 2, 3], {1: "one", 2: "two"}) -// a.Subset({"x": 1, "y": 2}, ["x"]) -func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Subset(a.t, list, subset, msgAndArgs...) -} - -// Subsetf asserts that the list (array, slice, or map) contains all elements -// given in the subset (array, slice, or map). -// Map elements are key-value pairs unless compared with an array or slice where -// only the map key is evaluated. -// -// a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted") -// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") -// a.Subsetf([1, 2, 3], {1: "one", 2: "two"}, "error message %s", "formatted") -// a.Subsetf({"x": 1, "y": 2}, ["x"], "error message %s", "formatted") -func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Subsetf(a.t, list, subset, msg, args...) -} - -// True asserts that the specified value is true. -// -// a.True(myBool) -func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return True(a.t, value, msgAndArgs...) -} - -// Truef asserts that the specified value is true. -// -// a.Truef(myBool, "error message %s", "formatted") -func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Truef(a.t, value, msg, args...) -} - -// WithinDuration asserts that the two times are within duration delta of each other. -// -// a.WithinDuration(time.Now(), time.Now(), 10*time.Second) -func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return WithinDuration(a.t, expected, actual, delta, msgAndArgs...) -} - -// WithinDurationf asserts that the two times are within duration delta of each other. -// -// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") -func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return WithinDurationf(a.t, expected, actual, delta, msg, args...) -} - -// WithinRange asserts that a time is within a time range (inclusive). -// -// a.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) -func (a *Assertions) WithinRange(actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return WithinRange(a.t, actual, start, end, msgAndArgs...) -} - -// WithinRangef asserts that a time is within a time range (inclusive). -// -// a.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") -func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return WithinRangef(a.t, actual, start, end, msg, args...) -} - -// YAMLEq asserts that two YAML strings are equivalent. -func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return YAMLEq(a.t, expected, actual, msgAndArgs...) -} - -// YAMLEqf asserts that two YAML strings are equivalent. -func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return YAMLEqf(a.t, expected, actual, msg, args...) -} - -// Zero asserts that i is the zero value for its type. -func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Zero(a.t, i, msgAndArgs...) -} - -// Zerof asserts that i is the zero value for its type. -func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Zerof(a.t, i, msg, args...) -} diff --git a/go/sdk/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl b/go/sdk/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl deleted file mode 100644 index 188bb9e..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl +++ /dev/null @@ -1,5 +0,0 @@ -{{.CommentWithoutT "a"}} -func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool { - if h, ok := a.t.(tHelper); ok { h.Helper() } - return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) -} diff --git a/go/sdk/vendor/github.com/stretchr/testify/assert/assertion_order.go b/go/sdk/vendor/github.com/stretchr/testify/assert/assertion_order.go deleted file mode 100644 index 2fdf80f..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/assert/assertion_order.go +++ /dev/null @@ -1,81 +0,0 @@ -package assert - -import ( - "fmt" - "reflect" -) - -// isOrdered checks that collection contains orderable elements. -func isOrdered(t TestingT, object interface{}, allowedComparesResults []compareResult, failMessage string, msgAndArgs ...interface{}) bool { - objKind := reflect.TypeOf(object).Kind() - if objKind != reflect.Slice && objKind != reflect.Array { - return false - } - - objValue := reflect.ValueOf(object) - objLen := objValue.Len() - - if objLen <= 1 { - return true - } - - value := objValue.Index(0) - valueInterface := value.Interface() - firstValueKind := value.Kind() - - for i := 1; i < objLen; i++ { - prevValue := value - prevValueInterface := valueInterface - - value = objValue.Index(i) - valueInterface = value.Interface() - - compareResult, isComparable := compare(prevValueInterface, valueInterface, firstValueKind) - - if !isComparable { - return Fail(t, fmt.Sprintf(`Can not compare type "%T" and "%T"`, value, prevValue), msgAndArgs...) - } - - if !containsValue(allowedComparesResults, compareResult) { - return Fail(t, fmt.Sprintf(failMessage, prevValue, value), msgAndArgs...) - } - } - - return true -} - -// IsIncreasing asserts that the collection is increasing -// -// assert.IsIncreasing(t, []int{1, 2, 3}) -// assert.IsIncreasing(t, []float{1, 2}) -// assert.IsIncreasing(t, []string{"a", "b"}) -func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - return isOrdered(t, object, []compareResult{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...) -} - -// IsNonIncreasing asserts that the collection is not increasing -// -// assert.IsNonIncreasing(t, []int{2, 1, 1}) -// assert.IsNonIncreasing(t, []float{2, 1}) -// assert.IsNonIncreasing(t, []string{"b", "a"}) -func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - return isOrdered(t, object, []compareResult{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...) -} - -// IsDecreasing asserts that the collection is decreasing -// -// assert.IsDecreasing(t, []int{2, 1, 0}) -// assert.IsDecreasing(t, []float{2, 1}) -// assert.IsDecreasing(t, []string{"b", "a"}) -func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - return isOrdered(t, object, []compareResult{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...) -} - -// IsNonDecreasing asserts that the collection is not decreasing -// -// assert.IsNonDecreasing(t, []int{1, 1, 2}) -// assert.IsNonDecreasing(t, []float{1, 2}) -// assert.IsNonDecreasing(t, []string{"a", "b"}) -func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - return isOrdered(t, object, []compareResult{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...) -} diff --git a/go/sdk/vendor/github.com/stretchr/testify/assert/assertions.go b/go/sdk/vendor/github.com/stretchr/testify/assert/assertions.go deleted file mode 100644 index de8de0c..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/assert/assertions.go +++ /dev/null @@ -1,2295 +0,0 @@ -package assert - -import ( - "bufio" - "bytes" - "encoding/json" - "errors" - "fmt" - "math" - "os" - "reflect" - "regexp" - "runtime" - "runtime/debug" - "strings" - "time" - "unicode" - "unicode/utf8" - - "github.com/davecgh/go-spew/spew" - "github.com/pmezard/go-difflib/difflib" - - // Wrapper around gopkg.in/yaml.v3 - "github.com/stretchr/testify/assert/yaml" -) - -//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl" - -// TestingT is an interface wrapper around *testing.T -type TestingT interface { - Errorf(format string, args ...interface{}) -} - -// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful -// for table driven tests. -type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) bool - -// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful -// for table driven tests. -type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) bool - -// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful -// for table driven tests. -type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool - -// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful -// for table driven tests. -type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool - -// PanicAssertionFunc is a common function prototype when validating a panic value. Can be useful -// for table driven tests. -type PanicAssertionFunc = func(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool - -// Comparison is a custom function that returns true on success and false on failure -type Comparison func() (success bool) - -/* - Helper functions -*/ - -// ObjectsAreEqual determines if two objects are considered equal. -// -// This function does no assertion of any kind. -func ObjectsAreEqual(expected, actual interface{}) bool { - if expected == nil || actual == nil { - return expected == actual - } - - exp, ok := expected.([]byte) - if !ok { - return reflect.DeepEqual(expected, actual) - } - - act, ok := actual.([]byte) - if !ok { - return false - } - if exp == nil || act == nil { - return exp == nil && act == nil - } - return bytes.Equal(exp, act) -} - -// copyExportedFields iterates downward through nested data structures and creates a copy -// that only contains the exported struct fields. -func copyExportedFields(expected interface{}) interface{} { - if isNil(expected) { - return expected - } - - expectedType := reflect.TypeOf(expected) - expectedKind := expectedType.Kind() - expectedValue := reflect.ValueOf(expected) - - switch expectedKind { - case reflect.Struct: - result := reflect.New(expectedType).Elem() - for i := 0; i < expectedType.NumField(); i++ { - field := expectedType.Field(i) - isExported := field.IsExported() - if isExported { - fieldValue := expectedValue.Field(i) - if isNil(fieldValue) || isNil(fieldValue.Interface()) { - continue - } - newValue := copyExportedFields(fieldValue.Interface()) - result.Field(i).Set(reflect.ValueOf(newValue)) - } - } - return result.Interface() - - case reflect.Ptr: - result := reflect.New(expectedType.Elem()) - unexportedRemoved := copyExportedFields(expectedValue.Elem().Interface()) - result.Elem().Set(reflect.ValueOf(unexportedRemoved)) - return result.Interface() - - case reflect.Array, reflect.Slice: - var result reflect.Value - if expectedKind == reflect.Array { - result = reflect.New(reflect.ArrayOf(expectedValue.Len(), expectedType.Elem())).Elem() - } else { - result = reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len()) - } - for i := 0; i < expectedValue.Len(); i++ { - index := expectedValue.Index(i) - if isNil(index) { - continue - } - unexportedRemoved := copyExportedFields(index.Interface()) - result.Index(i).Set(reflect.ValueOf(unexportedRemoved)) - } - return result.Interface() - - case reflect.Map: - result := reflect.MakeMap(expectedType) - for _, k := range expectedValue.MapKeys() { - index := expectedValue.MapIndex(k) - unexportedRemoved := copyExportedFields(index.Interface()) - result.SetMapIndex(k, reflect.ValueOf(unexportedRemoved)) - } - return result.Interface() - - default: - return expected - } -} - -// ObjectsExportedFieldsAreEqual determines if the exported (public) fields of two objects are -// considered equal. This comparison of only exported fields is applied recursively to nested data -// structures. -// -// This function does no assertion of any kind. -// -// Deprecated: Use [EqualExportedValues] instead. -func ObjectsExportedFieldsAreEqual(expected, actual interface{}) bool { - expectedCleaned := copyExportedFields(expected) - actualCleaned := copyExportedFields(actual) - return ObjectsAreEqualValues(expectedCleaned, actualCleaned) -} - -// ObjectsAreEqualValues gets whether two objects are equal, or if their -// values are equal. -func ObjectsAreEqualValues(expected, actual interface{}) bool { - if ObjectsAreEqual(expected, actual) { - return true - } - - expectedValue := reflect.ValueOf(expected) - actualValue := reflect.ValueOf(actual) - if !expectedValue.IsValid() || !actualValue.IsValid() { - return false - } - - expectedType := expectedValue.Type() - actualType := actualValue.Type() - if !expectedType.ConvertibleTo(actualType) { - return false - } - - if !isNumericType(expectedType) || !isNumericType(actualType) { - // Attempt comparison after type conversion - return reflect.DeepEqual( - expectedValue.Convert(actualType).Interface(), actual, - ) - } - - // If BOTH values are numeric, there are chances of false positives due - // to overflow or underflow. So, we need to make sure to always convert - // the smaller type to a larger type before comparing. - if expectedType.Size() >= actualType.Size() { - return actualValue.Convert(expectedType).Interface() == expected - } - - return expectedValue.Convert(actualType).Interface() == actual -} - -// isNumericType returns true if the type is one of: -// int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, -// float32, float64, complex64, complex128 -func isNumericType(t reflect.Type) bool { - return t.Kind() >= reflect.Int && t.Kind() <= reflect.Complex128 -} - -/* CallerInfo is necessary because the assert functions use the testing object -internally, causing it to print the file:line of the assert method, rather than where -the problem actually occurred in calling code.*/ - -// CallerInfo returns an array of strings containing the file and line number -// of each stack frame leading from the current test to the assert call that -// failed. -func CallerInfo() []string { - var pc uintptr - var file string - var line int - var name string - - const stackFrameBufferSize = 10 - pcs := make([]uintptr, stackFrameBufferSize) - - callers := []string{} - offset := 1 - - for { - n := runtime.Callers(offset, pcs) - - if n == 0 { - break - } - - frames := runtime.CallersFrames(pcs[:n]) - - for { - frame, more := frames.Next() - pc = frame.PC - file = frame.File - line = frame.Line - - // This is a huge edge case, but it will panic if this is the case, see #180 - if file == "" { - break - } - - f := runtime.FuncForPC(pc) - if f == nil { - break - } - name = f.Name() - - // testing.tRunner is the standard library function that calls - // tests. Subtests are called directly by tRunner, without going through - // the Test/Benchmark/Example function that contains the t.Run calls, so - // with subtests we should break when we hit tRunner, without adding it - // to the list of callers. - if name == "testing.tRunner" { - break - } - - parts := strings.Split(file, "/") - if len(parts) > 1 { - filename := parts[len(parts)-1] - dir := parts[len(parts)-2] - if (dir != "assert" && dir != "mock" && dir != "require") || filename == "mock_test.go" { - callers = append(callers, fmt.Sprintf("%s:%d", file, line)) - } - } - - // Drop the package - dotPos := strings.LastIndexByte(name, '.') - name = name[dotPos+1:] - if isTest(name, "Test") || - isTest(name, "Benchmark") || - isTest(name, "Example") { - break - } - - if !more { - break - } - } - - // Next batch - offset += cap(pcs) - } - - return callers -} - -// Stolen from the `go test` tool. -// isTest tells whether name looks like a test (or benchmark, according to prefix). -// It is a Test (say) if there is a character after Test that is not a lower-case letter. -// We don't want TesticularCancer. -func isTest(name, prefix string) bool { - if !strings.HasPrefix(name, prefix) { - return false - } - if len(name) == len(prefix) { // "Test" is ok - return true - } - r, _ := utf8.DecodeRuneInString(name[len(prefix):]) - return !unicode.IsLower(r) -} - -func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { - if len(msgAndArgs) == 0 || msgAndArgs == nil { - return "" - } - if len(msgAndArgs) == 1 { - msg := msgAndArgs[0] - if msgAsStr, ok := msg.(string); ok { - return msgAsStr - } - return fmt.Sprintf("%+v", msg) - } - if len(msgAndArgs) > 1 { - return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) - } - return "" -} - -// Aligns the provided message so that all lines after the first line start at the same location as the first line. -// Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab). -// The longestLabelLen parameter specifies the length of the longest label in the output (required because this is the -// basis on which the alignment occurs). -func indentMessageLines(message string, longestLabelLen int) string { - outBuf := new(bytes.Buffer) - - for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ { - // no need to align first line because it starts at the correct location (after the label) - if i != 0 { - // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab - outBuf.WriteString("\n\t" + strings.Repeat(" ", longestLabelLen+1) + "\t") - } - outBuf.WriteString(scanner.Text()) - } - - return outBuf.String() -} - -type failNower interface { - FailNow() -} - -// FailNow fails test -func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - Fail(t, failureMessage, msgAndArgs...) - - // We cannot extend TestingT with FailNow() and - // maintain backwards compatibility, so we fallback - // to panicking when FailNow is not available in - // TestingT. - // See issue #263 - - if t, ok := t.(failNower); ok { - t.FailNow() - } else { - panic("test failed and t is missing `FailNow()`") - } - return false -} - -// Fail reports a failure through -func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - content := []labeledContent{ - {"Error Trace", strings.Join(CallerInfo(), "\n\t\t\t")}, - {"Error", failureMessage}, - } - - // Add test name if the Go version supports it - if n, ok := t.(interface { - Name() string - }); ok { - content = append(content, labeledContent{"Test", n.Name()}) - } - - message := messageFromMsgAndArgs(msgAndArgs...) - if len(message) > 0 { - content = append(content, labeledContent{"Messages", message}) - } - - t.Errorf("\n%s", ""+labeledOutput(content...)) - - return false -} - -type labeledContent struct { - label string - content string -} - -// labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner: -// -// \t{{label}}:{{align_spaces}}\t{{content}}\n -// -// The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label. -// If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this -// alignment is achieved, "\t{{content}}\n" is added for the output. -// -// If the content of the labeledOutput contains line breaks, the subsequent lines are aligned so that they start at the same location as the first line. -func labeledOutput(content ...labeledContent) string { - longestLabel := 0 - for _, v := range content { - if len(v.label) > longestLabel { - longestLabel = len(v.label) - } - } - var output string - for _, v := range content { - output += "\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n" - } - return output -} - -// Implements asserts that an object is implemented by the specified interface. -// -// assert.Implements(t, (*MyInterface)(nil), new(MyObject)) -func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - interfaceType := reflect.TypeOf(interfaceObject).Elem() - - if object == nil { - return Fail(t, fmt.Sprintf("Cannot check if nil implements %v", interfaceType), msgAndArgs...) - } - if !reflect.TypeOf(object).Implements(interfaceType) { - return Fail(t, fmt.Sprintf("%T must implement %v", object, interfaceType), msgAndArgs...) - } - - return true -} - -// NotImplements asserts that an object does not implement the specified interface. -// -// assert.NotImplements(t, (*MyInterface)(nil), new(MyObject)) -func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - interfaceType := reflect.TypeOf(interfaceObject).Elem() - - if object == nil { - return Fail(t, fmt.Sprintf("Cannot check if nil does not implement %v", interfaceType), msgAndArgs...) - } - if reflect.TypeOf(object).Implements(interfaceType) { - return Fail(t, fmt.Sprintf("%T implements %v", object, interfaceType), msgAndArgs...) - } - - return true -} - -func isType(expectedType, object interface{}) bool { - return ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) -} - -// IsType asserts that the specified objects are of the same type. -// -// assert.IsType(t, &MyStruct{}, &MyStruct{}) -func IsType(t TestingT, expectedType, object interface{}, msgAndArgs ...interface{}) bool { - if isType(expectedType, object) { - return true - } - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, fmt.Sprintf("Object expected to be of type %T, but was %T", expectedType, object), msgAndArgs...) -} - -// IsNotType asserts that the specified objects are not of the same type. -// -// assert.IsNotType(t, &NotMyStruct{}, &MyStruct{}) -func IsNotType(t TestingT, theType, object interface{}, msgAndArgs ...interface{}) bool { - if !isType(theType, object) { - return true - } - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, fmt.Sprintf("Object type expected to be different than %T", theType), msgAndArgs...) -} - -// Equal asserts that two objects are equal. -// -// assert.Equal(t, 123, 123) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if err := validateEqualArgs(expected, actual); err != nil { - return Fail(t, fmt.Sprintf("Invalid operation: %#v == %#v (%s)", - expected, actual, err), msgAndArgs...) - } - - if !ObjectsAreEqual(expected, actual) { - diff := diff(expected, actual) - expected, actual = formatUnequalValues(expected, actual) - return Fail(t, fmt.Sprintf("Not equal: \n"+ - "expected: %s\n"+ - "actual : %s%s", expected, actual, diff), msgAndArgs...) - } - - return true -} - -// validateEqualArgs checks whether provided arguments can be safely used in the -// Equal/NotEqual functions. -func validateEqualArgs(expected, actual interface{}) error { - if expected == nil && actual == nil { - return nil - } - - if isFunction(expected) || isFunction(actual) { - return errors.New("cannot take func type as argument") - } - return nil -} - -// Same asserts that two pointers reference the same object. -// -// assert.Same(t, ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - same, ok := samePointers(expected, actual) - if !ok { - return Fail(t, "Both arguments must be pointers", msgAndArgs...) - } - - if !same { - // both are pointers but not the same type & pointing to the same address - return Fail(t, fmt.Sprintf("Not same: \n"+ - "expected: %p %#[1]v\n"+ - "actual : %p %#[2]v", - expected, actual), msgAndArgs...) - } - - return true -} - -// NotSame asserts that two pointers do not reference the same object. -// -// assert.NotSame(t, ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - same, ok := samePointers(expected, actual) - if !ok { - // fails when the arguments are not pointers - return !(Fail(t, "Both arguments must be pointers", msgAndArgs...)) - } - - if same { - return Fail(t, fmt.Sprintf( - "Expected and actual point to the same object: %p %#[1]v", - expected), msgAndArgs...) - } - return true -} - -// samePointers checks if two generic interface objects are pointers of the same -// type pointing to the same object. It returns two values: same indicating if -// they are the same type and point to the same object, and ok indicating that -// both inputs are pointers. -func samePointers(first, second interface{}) (same bool, ok bool) { - firstPtr, secondPtr := reflect.ValueOf(first), reflect.ValueOf(second) - if firstPtr.Kind() != reflect.Ptr || secondPtr.Kind() != reflect.Ptr { - return false, false // not both are pointers - } - - firstType, secondType := reflect.TypeOf(first), reflect.TypeOf(second) - if firstType != secondType { - return false, true // both are pointers, but of different types - } - - // compare pointer addresses - return first == second, true -} - -// formatUnequalValues takes two values of arbitrary types and returns string -// representations appropriate to be presented to the user. -// -// If the values are not of like type, the returned strings will be prefixed -// with the type name, and the value will be enclosed in parentheses similar -// to a type conversion in the Go grammar. -func formatUnequalValues(expected, actual interface{}) (e string, a string) { - if reflect.TypeOf(expected) != reflect.TypeOf(actual) { - return fmt.Sprintf("%T(%s)", expected, truncatingFormat(expected)), - fmt.Sprintf("%T(%s)", actual, truncatingFormat(actual)) - } - switch expected.(type) { - case time.Duration: - return fmt.Sprintf("%v", expected), fmt.Sprintf("%v", actual) - } - return truncatingFormat(expected), truncatingFormat(actual) -} - -// truncatingFormat formats the data and truncates it if it's too long. -// -// This helps keep formatted error messages lines from exceeding the -// bufio.MaxScanTokenSize max line length that the go testing framework imposes. -func truncatingFormat(data interface{}) string { - value := fmt.Sprintf("%#v", data) - max := bufio.MaxScanTokenSize - 100 // Give us some space the type info too if needed. - if len(value) > max { - value = value[0:max] + "<... truncated>" - } - return value -} - -// EqualValues asserts that two objects are equal or convertible to the larger -// type and equal. -// -// assert.EqualValues(t, uint32(123), int32(123)) -func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if !ObjectsAreEqualValues(expected, actual) { - diff := diff(expected, actual) - expected, actual = formatUnequalValues(expected, actual) - return Fail(t, fmt.Sprintf("Not equal: \n"+ - "expected: %s\n"+ - "actual : %s%s", expected, actual, diff), msgAndArgs...) - } - - return true -} - -// EqualExportedValues asserts that the types of two objects are equal and their public -// fields are also equal. This is useful for comparing structs that have private fields -// that could potentially differ. -// -// type S struct { -// Exported int -// notExported int -// } -// assert.EqualExportedValues(t, S{1, 2}, S{1, 3}) => true -// assert.EqualExportedValues(t, S{1, 2}, S{2, 3}) => false -func EqualExportedValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - aType := reflect.TypeOf(expected) - bType := reflect.TypeOf(actual) - - if aType != bType { - return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...) - } - - expected = copyExportedFields(expected) - actual = copyExportedFields(actual) - - if !ObjectsAreEqualValues(expected, actual) { - diff := diff(expected, actual) - expected, actual = formatUnequalValues(expected, actual) - return Fail(t, fmt.Sprintf("Not equal (comparing only exported fields): \n"+ - "expected: %s\n"+ - "actual : %s%s", expected, actual, diff), msgAndArgs...) - } - - return true -} - -// Exactly asserts that two objects are equal in value and type. -// -// assert.Exactly(t, int32(123), int64(123)) -func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - aType := reflect.TypeOf(expected) - bType := reflect.TypeOf(actual) - - if aType != bType { - return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...) - } - - return Equal(t, expected, actual, msgAndArgs...) -} - -// NotNil asserts that the specified object is not nil. -// -// assert.NotNil(t, err) -func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - if !isNil(object) { - return true - } - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, "Expected value not to be nil.", msgAndArgs...) -} - -// isNil checks if a specified object is nil or not, without Failing. -func isNil(object interface{}) bool { - if object == nil { - return true - } - - value := reflect.ValueOf(object) - switch value.Kind() { - case - reflect.Chan, reflect.Func, - reflect.Interface, reflect.Map, - reflect.Ptr, reflect.Slice, reflect.UnsafePointer: - - return value.IsNil() - } - - return false -} - -// Nil asserts that the specified object is nil. -// -// assert.Nil(t, err) -func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - if isNil(object) { - return true - } - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...) -} - -// isEmpty gets whether the specified object is considered empty or not. -func isEmpty(object interface{}) bool { - // get nil case out of the way - if object == nil { - return true - } - - return isEmptyValue(reflect.ValueOf(object)) -} - -// isEmptyValue gets whether the specified reflect.Value is considered empty or not. -func isEmptyValue(objValue reflect.Value) bool { - if objValue.IsZero() { - return true - } - // Special cases of non-zero values that we consider empty - switch objValue.Kind() { - // collection types are empty when they have no element - // Note: array types are empty when they match their zero-initialized state. - case reflect.Chan, reflect.Map, reflect.Slice: - return objValue.Len() == 0 - // non-nil pointers are empty if the value they point to is empty - case reflect.Ptr: - return isEmptyValue(objValue.Elem()) - } - return false -} - -// Empty asserts that the given value is "empty". -// -// [Zero values] are "empty". -// -// Arrays are "empty" if every element is the zero value of the type (stricter than "empty"). -// -// Slices, maps and channels with zero length are "empty". -// -// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty". -// -// assert.Empty(t, obj) -// -// [Zero values]: https://go.dev/ref/spec#The_zero_value -func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - pass := isEmpty(object) - if !pass { - if h, ok := t.(tHelper); ok { - h.Helper() - } - Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...) - } - - return pass -} - -// NotEmpty asserts that the specified object is NOT [Empty]. -// -// if assert.NotEmpty(t, obj) { -// assert.Equal(t, "two", obj[1]) -// } -func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - pass := !isEmpty(object) - if !pass { - if h, ok := t.(tHelper); ok { - h.Helper() - } - Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...) - } - - return pass -} - -// getLen tries to get the length of an object. -// It returns (0, false) if impossible. -func getLen(x interface{}) (length int, ok bool) { - v := reflect.ValueOf(x) - defer func() { - ok = recover() == nil - }() - return v.Len(), true -} - -// Len asserts that the specified object has specific length. -// Len also fails if the object has a type that len() not accept. -// -// assert.Len(t, mySlice, 3) -func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - l, ok := getLen(object) - if !ok { - return Fail(t, fmt.Sprintf("\"%v\" could not be applied builtin len()", object), msgAndArgs...) - } - - if l != length { - return Fail(t, fmt.Sprintf("\"%v\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) - } - return true -} - -// True asserts that the specified value is true. -// -// assert.True(t, myBool) -func True(t TestingT, value bool, msgAndArgs ...interface{}) bool { - if !value { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, "Should be true", msgAndArgs...) - } - - return true -} - -// False asserts that the specified value is false. -// -// assert.False(t, myBool) -func False(t TestingT, value bool, msgAndArgs ...interface{}) bool { - if value { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, "Should be false", msgAndArgs...) - } - - return true -} - -// NotEqual asserts that the specified values are NOT equal. -// -// assert.NotEqual(t, obj1, obj2) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if err := validateEqualArgs(expected, actual); err != nil { - return Fail(t, fmt.Sprintf("Invalid operation: %#v != %#v (%s)", - expected, actual, err), msgAndArgs...) - } - - if ObjectsAreEqual(expected, actual) { - return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...) - } - - return true -} - -// NotEqualValues asserts that two objects are not equal even when converted to the same type -// -// assert.NotEqualValues(t, obj1, obj2) -func NotEqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if ObjectsAreEqualValues(expected, actual) { - return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...) - } - - return true -} - -// containsElement try loop over the list check if the list includes the element. -// return (false, false) if impossible. -// return (true, false) if element was not found. -// return (true, true) if element was found. -func containsElement(list interface{}, element interface{}) (ok, found bool) { - listValue := reflect.ValueOf(list) - listType := reflect.TypeOf(list) - if listType == nil { - return false, false - } - listKind := listType.Kind() - defer func() { - if e := recover(); e != nil { - ok = false - found = false - } - }() - - if listKind == reflect.String { - elementValue := reflect.ValueOf(element) - return true, strings.Contains(listValue.String(), elementValue.String()) - } - - if listKind == reflect.Map { - mapKeys := listValue.MapKeys() - for i := 0; i < len(mapKeys); i++ { - if ObjectsAreEqual(mapKeys[i].Interface(), element) { - return true, true - } - } - return true, false - } - - for i := 0; i < listValue.Len(); i++ { - if ObjectsAreEqual(listValue.Index(i).Interface(), element) { - return true, true - } - } - return true, false -} - -// Contains asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// assert.Contains(t, "Hello World", "World") -// assert.Contains(t, ["Hello", "World"], "World") -// assert.Contains(t, {"Hello": "World"}, "Hello") -func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - ok, found := containsElement(s, contains) - if !ok { - return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...) - } - if !found { - return Fail(t, fmt.Sprintf("%#v does not contain %#v", s, contains), msgAndArgs...) - } - - return true -} - -// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// assert.NotContains(t, "Hello World", "Earth") -// assert.NotContains(t, ["Hello", "World"], "Earth") -// assert.NotContains(t, {"Hello": "World"}, "Earth") -func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - ok, found := containsElement(s, contains) - if !ok { - return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...) - } - if found { - return Fail(t, fmt.Sprintf("%#v should not contain %#v", s, contains), msgAndArgs...) - } - - return true -} - -// Subset asserts that the list (array, slice, or map) contains all elements -// given in the subset (array, slice, or map). -// Map elements are key-value pairs unless compared with an array or slice where -// only the map key is evaluated. -// -// assert.Subset(t, [1, 2, 3], [1, 2]) -// assert.Subset(t, {"x": 1, "y": 2}, {"x": 1}) -// assert.Subset(t, [1, 2, 3], {1: "one", 2: "two"}) -// assert.Subset(t, {"x": 1, "y": 2}, ["x"]) -func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if subset == nil { - return true // we consider nil to be equal to the nil set - } - - listKind := reflect.TypeOf(list).Kind() - if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map { - return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) - } - - subsetKind := reflect.TypeOf(subset).Kind() - if subsetKind != reflect.Array && subsetKind != reflect.Slice && subsetKind != reflect.Map { - return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) - } - - if subsetKind == reflect.Map && listKind == reflect.Map { - subsetMap := reflect.ValueOf(subset) - actualMap := reflect.ValueOf(list) - - for _, k := range subsetMap.MapKeys() { - ev := subsetMap.MapIndex(k) - av := actualMap.MapIndex(k) - - if !av.IsValid() { - return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...) - } - if !ObjectsAreEqual(ev.Interface(), av.Interface()) { - return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...) - } - } - - return true - } - - subsetList := reflect.ValueOf(subset) - if subsetKind == reflect.Map { - keys := make([]interface{}, subsetList.Len()) - for idx, key := range subsetList.MapKeys() { - keys[idx] = key.Interface() - } - subsetList = reflect.ValueOf(keys) - } - for i := 0; i < subsetList.Len(); i++ { - element := subsetList.Index(i).Interface() - ok, found := containsElement(list, element) - if !ok { - return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", list), msgAndArgs...) - } - if !found { - return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, element), msgAndArgs...) - } - } - - return true -} - -// NotSubset asserts that the list (array, slice, or map) does NOT contain all -// elements given in the subset (array, slice, or map). -// Map elements are key-value pairs unless compared with an array or slice where -// only the map key is evaluated. -// -// assert.NotSubset(t, [1, 3, 4], [1, 2]) -// assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3}) -// assert.NotSubset(t, [1, 3, 4], {1: "one", 2: "two"}) -// assert.NotSubset(t, {"x": 1, "y": 2}, ["z"]) -func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if subset == nil { - return Fail(t, "nil is the empty set which is a subset of every set", msgAndArgs...) - } - - listKind := reflect.TypeOf(list).Kind() - if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map { - return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) - } - - subsetKind := reflect.TypeOf(subset).Kind() - if subsetKind != reflect.Array && subsetKind != reflect.Slice && subsetKind != reflect.Map { - return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) - } - - if subsetKind == reflect.Map && listKind == reflect.Map { - subsetMap := reflect.ValueOf(subset) - actualMap := reflect.ValueOf(list) - - for _, k := range subsetMap.MapKeys() { - ev := subsetMap.MapIndex(k) - av := actualMap.MapIndex(k) - - if !av.IsValid() { - return true - } - if !ObjectsAreEqual(ev.Interface(), av.Interface()) { - return true - } - } - - return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...) - } - - subsetList := reflect.ValueOf(subset) - if subsetKind == reflect.Map { - keys := make([]interface{}, subsetList.Len()) - for idx, key := range subsetList.MapKeys() { - keys[idx] = key.Interface() - } - subsetList = reflect.ValueOf(keys) - } - for i := 0; i < subsetList.Len(); i++ { - element := subsetList.Index(i).Interface() - ok, found := containsElement(list, element) - if !ok { - return Fail(t, fmt.Sprintf("%q could not be applied builtin len()", list), msgAndArgs...) - } - if !found { - return true - } - } - - return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...) -} - -// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]) -func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if isEmpty(listA) && isEmpty(listB) { - return true - } - - if !isList(t, listA, msgAndArgs...) || !isList(t, listB, msgAndArgs...) { - return false - } - - extraA, extraB := diffLists(listA, listB) - - if len(extraA) == 0 && len(extraB) == 0 { - return true - } - - return Fail(t, formatListDiff(listA, listB, extraA, extraB), msgAndArgs...) -} - -// isList checks that the provided value is array or slice. -func isList(t TestingT, list interface{}, msgAndArgs ...interface{}) (ok bool) { - kind := reflect.TypeOf(list).Kind() - if kind != reflect.Array && kind != reflect.Slice { - return Fail(t, fmt.Sprintf("%q has an unsupported type %s, expecting array or slice", list, kind), - msgAndArgs...) - } - return true -} - -// diffLists diffs two arrays/slices and returns slices of elements that are only in A and only in B. -// If some element is present multiple times, each instance is counted separately (e.g. if something is 2x in A and -// 5x in B, it will be 0x in extraA and 3x in extraB). The order of items in both lists is ignored. -func diffLists(listA, listB interface{}) (extraA, extraB []interface{}) { - aValue := reflect.ValueOf(listA) - bValue := reflect.ValueOf(listB) - - aLen := aValue.Len() - bLen := bValue.Len() - - // Mark indexes in bValue that we already used - visited := make([]bool, bLen) - for i := 0; i < aLen; i++ { - element := aValue.Index(i).Interface() - found := false - for j := 0; j < bLen; j++ { - if visited[j] { - continue - } - if ObjectsAreEqual(bValue.Index(j).Interface(), element) { - visited[j] = true - found = true - break - } - } - if !found { - extraA = append(extraA, element) - } - } - - for j := 0; j < bLen; j++ { - if visited[j] { - continue - } - extraB = append(extraB, bValue.Index(j).Interface()) - } - - return -} - -func formatListDiff(listA, listB interface{}, extraA, extraB []interface{}) string { - var msg bytes.Buffer - - msg.WriteString("elements differ") - if len(extraA) > 0 { - msg.WriteString("\n\nextra elements in list A:\n") - msg.WriteString(spewConfig.Sdump(extraA)) - } - if len(extraB) > 0 { - msg.WriteString("\n\nextra elements in list B:\n") - msg.WriteString(spewConfig.Sdump(extraB)) - } - msg.WriteString("\n\nlistA:\n") - msg.WriteString(spewConfig.Sdump(listA)) - msg.WriteString("\n\nlistB:\n") - msg.WriteString(spewConfig.Sdump(listB)) - - return msg.String() -} - -// NotElementsMatch asserts that the specified listA(array, slice...) is NOT equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should not match. -// This is an inverse of ElementsMatch. -// -// assert.NotElementsMatch(t, [1, 1, 2, 3], [1, 1, 2, 3]) -> false -// -// assert.NotElementsMatch(t, [1, 1, 2, 3], [1, 2, 3]) -> true -// -// assert.NotElementsMatch(t, [1, 2, 3], [1, 2, 4]) -> true -func NotElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if isEmpty(listA) && isEmpty(listB) { - return Fail(t, "listA and listB contain the same elements", msgAndArgs) - } - - if !isList(t, listA, msgAndArgs...) { - return Fail(t, "listA is not a list type", msgAndArgs...) - } - if !isList(t, listB, msgAndArgs...) { - return Fail(t, "listB is not a list type", msgAndArgs...) - } - - extraA, extraB := diffLists(listA, listB) - if len(extraA) == 0 && len(extraB) == 0 { - return Fail(t, "listA and listB contain the same elements", msgAndArgs) - } - - return true -} - -// Condition uses a Comparison to assert a complex condition. -func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - result := comp() - if !result { - Fail(t, "Condition failed!", msgAndArgs...) - } - return result -} - -// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics -// methods, and represents a simple func that takes no arguments, and returns nothing. -type PanicTestFunc func() - -// didPanic returns true if the function passed to it panics. Otherwise, it returns false. -func didPanic(f PanicTestFunc) (didPanic bool, message interface{}, stack string) { - didPanic = true - - defer func() { - message = recover() - if didPanic { - stack = string(debug.Stack()) - } - }() - - // call the target function - f() - didPanic = false - - return -} - -// Panics asserts that the code inside the specified PanicTestFunc panics. -// -// assert.Panics(t, func(){ GoCrazy() }) -func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if funcDidPanic, panicValue, _ := didPanic(f); !funcDidPanic { - return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) - } - - return true -} - -// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) -func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - funcDidPanic, panicValue, panickedStack := didPanic(f) - if !funcDidPanic { - return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) - } - if panicValue != expected { - return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, expected, panicValue, panickedStack), msgAndArgs...) - } - - return true -} - -// PanicsWithError asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// assert.PanicsWithError(t, "crazy error", func(){ GoCrazy() }) -func PanicsWithError(t TestingT, errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - funcDidPanic, panicValue, panickedStack := didPanic(f) - if !funcDidPanic { - return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) - } - panicErr, ok := panicValue.(error) - if !ok || panicErr.Error() != errString { - return Fail(t, fmt.Sprintf("func %#v should panic with error message:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, errString, panicValue, panickedStack), msgAndArgs...) - } - - return true -} - -// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// assert.NotPanics(t, func(){ RemainCalm() }) -func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if funcDidPanic, panicValue, panickedStack := didPanic(f); funcDidPanic { - return Fail(t, fmt.Sprintf("func %#v should not panic\n\tPanic value:\t%v\n\tPanic stack:\t%s", f, panicValue, panickedStack), msgAndArgs...) - } - - return true -} - -// WithinDuration asserts that the two times are within duration delta of each other. -// -// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) -func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - dt := expected.Sub(actual) - if dt < -delta || dt > delta { - return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) - } - - return true -} - -// WithinRange asserts that a time is within a time range (inclusive). -// -// assert.WithinRange(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) -func WithinRange(t TestingT, actual, start, end time.Time, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if end.Before(start) { - return Fail(t, "Start should be before end", msgAndArgs...) - } - - if actual.Before(start) { - return Fail(t, fmt.Sprintf("Time %v expected to be in time range %v to %v, but is before the range", actual, start, end), msgAndArgs...) - } else if actual.After(end) { - return Fail(t, fmt.Sprintf("Time %v expected to be in time range %v to %v, but is after the range", actual, start, end), msgAndArgs...) - } - - return true -} - -func toFloat(x interface{}) (float64, bool) { - var xf float64 - xok := true - - switch xn := x.(type) { - case uint: - xf = float64(xn) - case uint8: - xf = float64(xn) - case uint16: - xf = float64(xn) - case uint32: - xf = float64(xn) - case uint64: - xf = float64(xn) - case int: - xf = float64(xn) - case int8: - xf = float64(xn) - case int16: - xf = float64(xn) - case int32: - xf = float64(xn) - case int64: - xf = float64(xn) - case float32: - xf = float64(xn) - case float64: - xf = xn - case time.Duration: - xf = float64(xn) - default: - xok = false - } - - return xf, xok -} - -// InDelta asserts that the two numerals are within delta of each other. -// -// assert.InDelta(t, math.Pi, 22/7.0, 0.01) -func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - af, aok := toFloat(expected) - bf, bok := toFloat(actual) - - if !aok || !bok { - return Fail(t, "Parameters must be numerical", msgAndArgs...) - } - - if math.IsNaN(af) && math.IsNaN(bf) { - return true - } - - if math.IsNaN(af) { - return Fail(t, "Expected must not be NaN", msgAndArgs...) - } - - if math.IsNaN(bf) { - return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...) - } - - dt := af - bf - if dt < -delta || dt > delta { - return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) - } - - return true -} - -// InDeltaSlice is the same as InDelta, except it compares two slices. -func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if expected == nil || actual == nil || - reflect.TypeOf(actual).Kind() != reflect.Slice || - reflect.TypeOf(expected).Kind() != reflect.Slice { - return Fail(t, "Parameters must be slice", msgAndArgs...) - } - - actualSlice := reflect.ValueOf(actual) - expectedSlice := reflect.ValueOf(expected) - - for i := 0; i < actualSlice.Len(); i++ { - result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta, msgAndArgs...) - if !result { - return result - } - } - - return true -} - -// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if expected == nil || actual == nil || - reflect.TypeOf(actual).Kind() != reflect.Map || - reflect.TypeOf(expected).Kind() != reflect.Map { - return Fail(t, "Arguments must be maps", msgAndArgs...) - } - - expectedMap := reflect.ValueOf(expected) - actualMap := reflect.ValueOf(actual) - - if expectedMap.Len() != actualMap.Len() { - return Fail(t, "Arguments must have the same number of keys", msgAndArgs...) - } - - for _, k := range expectedMap.MapKeys() { - ev := expectedMap.MapIndex(k) - av := actualMap.MapIndex(k) - - if !ev.IsValid() { - return Fail(t, fmt.Sprintf("missing key %q in expected map", k), msgAndArgs...) - } - - if !av.IsValid() { - return Fail(t, fmt.Sprintf("missing key %q in actual map", k), msgAndArgs...) - } - - if !InDelta( - t, - ev.Interface(), - av.Interface(), - delta, - msgAndArgs..., - ) { - return false - } - } - - return true -} - -func calcRelativeError(expected, actual interface{}) (float64, error) { - af, aok := toFloat(expected) - bf, bok := toFloat(actual) - if !aok || !bok { - return 0, fmt.Errorf("Parameters must be numerical") - } - if math.IsNaN(af) && math.IsNaN(bf) { - return 0, nil - } - if math.IsNaN(af) { - return 0, errors.New("expected value must not be NaN") - } - if af == 0 { - return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error") - } - if math.IsNaN(bf) { - return 0, errors.New("actual value must not be NaN") - } - - return math.Abs(af-bf) / math.Abs(af), nil -} - -// InEpsilon asserts that expected and actual have a relative error less than epsilon -func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if math.IsNaN(epsilon) { - return Fail(t, "epsilon must not be NaN", msgAndArgs...) - } - actualEpsilon, err := calcRelativeError(expected, actual) - if err != nil { - return Fail(t, err.Error(), msgAndArgs...) - } - if math.IsNaN(actualEpsilon) { - return Fail(t, "relative error is NaN", msgAndArgs...) - } - if actualEpsilon > epsilon { - return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+ - " < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...) - } - - return true -} - -// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. -func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if expected == nil || actual == nil { - return Fail(t, "Parameters must be slice", msgAndArgs...) - } - - expectedSlice := reflect.ValueOf(expected) - actualSlice := reflect.ValueOf(actual) - - if expectedSlice.Type().Kind() != reflect.Slice { - return Fail(t, "Expected value must be slice", msgAndArgs...) - } - - expectedLen := expectedSlice.Len() - if !IsType(t, expected, actual) || !Len(t, actual, expectedLen) { - return false - } - - for i := 0; i < expectedLen; i++ { - if !InEpsilon(t, expectedSlice.Index(i).Interface(), actualSlice.Index(i).Interface(), epsilon, "at index %d", i) { - return false - } - } - - return true -} - -/* - Errors -*/ - -// NoError asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if assert.NoError(t, err) { -// assert.Equal(t, expectedObj, actualObj) -// } -func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { - if err != nil { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...) - } - - return true -} - -// Error asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// assert.Error(t, err) -func Error(t TestingT, err error, msgAndArgs ...interface{}) bool { - if err == nil { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, "An error is expected but got nil.", msgAndArgs...) - } - - return true -} - -// EqualError asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// assert.EqualError(t, err, expectedErrorString) -func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if !Error(t, theError, msgAndArgs...) { - return false - } - expected := errString - actual := theError.Error() - // don't need to use deep equals here, we know they are both strings - if expected != actual { - return Fail(t, fmt.Sprintf("Error message not equal:\n"+ - "expected: %q\n"+ - "actual : %q", expected, actual), msgAndArgs...) - } - return true -} - -// ErrorContains asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// assert.ErrorContains(t, err, expectedErrorSubString) -func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if !Error(t, theError, msgAndArgs...) { - return false - } - - actual := theError.Error() - if !strings.Contains(actual, contains) { - return Fail(t, fmt.Sprintf("Error %#v does not contain %#v", actual, contains), msgAndArgs...) - } - - return true -} - -// matchRegexp return true if a specified regexp matches a string. -func matchRegexp(rx interface{}, str interface{}) bool { - var r *regexp.Regexp - if rr, ok := rx.(*regexp.Regexp); ok { - r = rr - } else { - r = regexp.MustCompile(fmt.Sprint(rx)) - } - - switch v := str.(type) { - case []byte: - return r.Match(v) - case string: - return r.MatchString(v) - default: - return r.MatchString(fmt.Sprint(v)) - } -} - -// Regexp asserts that a specified regexp matches a string. -// -// assert.Regexp(t, regexp.MustCompile("start"), "it's starting") -// assert.Regexp(t, "start...$", "it's not starting") -func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - match := matchRegexp(rx, str) - - if !match { - Fail(t, fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...) - } - - return match -} - -// NotRegexp asserts that a specified regexp does not match a string. -// -// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") -// assert.NotRegexp(t, "^start", "it's not starting") -func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - match := matchRegexp(rx, str) - - if match { - Fail(t, fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...) - } - - return !match -} - -// Zero asserts that i is the zero value for its type. -func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { - return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...) - } - return true -} - -// NotZero asserts that i is not the zero value for its type. -func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { - return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...) - } - return true -} - -// FileExists checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - info, err := os.Lstat(path) - if err != nil { - if os.IsNotExist(err) { - return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) - } - return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) - } - if info.IsDir() { - return Fail(t, fmt.Sprintf("%q is a directory", path), msgAndArgs...) - } - return true -} - -// NoFileExists checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func NoFileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - info, err := os.Lstat(path) - if err != nil { - return true - } - if info.IsDir() { - return true - } - return Fail(t, fmt.Sprintf("file %q exists", path), msgAndArgs...) -} - -// DirExists checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - info, err := os.Lstat(path) - if err != nil { - if os.IsNotExist(err) { - return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) - } - return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) - } - if !info.IsDir() { - return Fail(t, fmt.Sprintf("%q is a file", path), msgAndArgs...) - } - return true -} - -// NoDirExists checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func NoDirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - info, err := os.Lstat(path) - if err != nil { - if os.IsNotExist(err) { - return true - } - return true - } - if !info.IsDir() { - return true - } - return Fail(t, fmt.Sprintf("directory %q exists", path), msgAndArgs...) -} - -// JSONEq asserts that two JSON strings are equivalent. -// -// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) -func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - var expectedJSONAsInterface, actualJSONAsInterface interface{} - - if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil { - return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...) - } - - // Shortcut if same bytes - if actual == expected { - return true - } - - if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil { - return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...) - } - - return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...) -} - -// YAMLEq asserts that two YAML strings are equivalent. -func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - var expectedYAMLAsInterface, actualYAMLAsInterface interface{} - - if err := yaml.Unmarshal([]byte(expected), &expectedYAMLAsInterface); err != nil { - return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid yaml.\nYAML parsing error: '%s'", expected, err.Error()), msgAndArgs...) - } - - // Shortcut if same bytes - if actual == expected { - return true - } - - if err := yaml.Unmarshal([]byte(actual), &actualYAMLAsInterface); err != nil { - return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid yaml.\nYAML error: '%s'", actual, err.Error()), msgAndArgs...) - } - - return Equal(t, expectedYAMLAsInterface, actualYAMLAsInterface, msgAndArgs...) -} - -func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { - t := reflect.TypeOf(v) - k := t.Kind() - - if k == reflect.Ptr { - t = t.Elem() - k = t.Kind() - } - return t, k -} - -// diff returns a diff of both values as long as both are of the same type and -// are a struct, map, slice, array or string. Otherwise it returns an empty string. -func diff(expected interface{}, actual interface{}) string { - if expected == nil || actual == nil { - return "" - } - - et, ek := typeAndKind(expected) - at, _ := typeAndKind(actual) - - if et != at { - return "" - } - - if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array && ek != reflect.String { - return "" - } - - var e, a string - - switch et { - case reflect.TypeOf(""): - e = reflect.ValueOf(expected).String() - a = reflect.ValueOf(actual).String() - case reflect.TypeOf(time.Time{}): - e = spewConfigStringerEnabled.Sdump(expected) - a = spewConfigStringerEnabled.Sdump(actual) - default: - e = spewConfig.Sdump(expected) - a = spewConfig.Sdump(actual) - } - - diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ - A: difflib.SplitLines(e), - B: difflib.SplitLines(a), - FromFile: "Expected", - FromDate: "", - ToFile: "Actual", - ToDate: "", - Context: 1, - }) - - return "\n\nDiff:\n" + diff -} - -func isFunction(arg interface{}) bool { - if arg == nil { - return false - } - return reflect.TypeOf(arg).Kind() == reflect.Func -} - -var spewConfig = spew.ConfigState{ - Indent: " ", - DisablePointerAddresses: true, - DisableCapacities: true, - SortKeys: true, - DisableMethods: true, - MaxDepth: 10, -} - -var spewConfigStringerEnabled = spew.ConfigState{ - Indent: " ", - DisablePointerAddresses: true, - DisableCapacities: true, - SortKeys: true, - MaxDepth: 10, -} - -type tHelper = interface { - Helper() -} - -// Eventually asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond) -func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - ch := make(chan bool, 1) - checkCond := func() { ch <- condition() } - - timer := time.NewTimer(waitFor) - defer timer.Stop() - - ticker := time.NewTicker(tick) - defer ticker.Stop() - - var tickC <-chan time.Time - - // Check the condition once first on the initial call. - go checkCond() - - for { - select { - case <-timer.C: - return Fail(t, "Condition never satisfied", msgAndArgs...) - case <-tickC: - tickC = nil - go checkCond() - case v := <-ch: - if v { - return true - } - tickC = ticker.C - } - } -} - -// CollectT implements the TestingT interface and collects all errors. -type CollectT struct { - // A slice of errors. Non-nil slice denotes a failure. - // If it's non-nil but len(c.errors) == 0, this is also a failure - // obtained by direct c.FailNow() call. - errors []error -} - -// Helper is like [testing.T.Helper] but does nothing. -func (CollectT) Helper() {} - -// Errorf collects the error. -func (c *CollectT) Errorf(format string, args ...interface{}) { - c.errors = append(c.errors, fmt.Errorf(format, args...)) -} - -// FailNow stops execution by calling runtime.Goexit. -func (c *CollectT) FailNow() { - c.fail() - runtime.Goexit() -} - -// Deprecated: That was a method for internal usage that should not have been published. Now just panics. -func (*CollectT) Reset() { - panic("Reset() is deprecated") -} - -// Deprecated: That was a method for internal usage that should not have been published. Now just panics. -func (*CollectT) Copy(TestingT) { - panic("Copy() is deprecated") -} - -func (c *CollectT) fail() { - if !c.failed() { - c.errors = []error{} // Make it non-nil to mark a failure. - } -} - -func (c *CollectT) failed() bool { - return c.errors != nil -} - -// EventuallyWithT asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. In contrast to Eventually, -// it supplies a CollectT to the condition function, so that the condition -// function can use the CollectT to call other assertions. -// The condition is considered "met" if no errors are raised in a tick. -// The supplied CollectT collects all errors from one tick (if there are any). -// If the condition is not met before waitFor, the collected errors of -// the last tick are copied to t. -// -// externalValue := false -// go func() { -// time.Sleep(8*time.Second) -// externalValue = true -// }() -// assert.EventuallyWithT(t, func(c *assert.CollectT) { -// // add assertions as needed; any assertion failure will fail the current tick -// assert.True(c, externalValue, "expected 'externalValue' to be true") -// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false") -func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - var lastFinishedTickErrs []error - ch := make(chan *CollectT, 1) - - checkCond := func() { - collect := new(CollectT) - defer func() { - ch <- collect - }() - condition(collect) - } - - timer := time.NewTimer(waitFor) - defer timer.Stop() - - ticker := time.NewTicker(tick) - defer ticker.Stop() - - var tickC <-chan time.Time - - // Check the condition once first on the initial call. - go checkCond() - - for { - select { - case <-timer.C: - for _, err := range lastFinishedTickErrs { - t.Errorf("%v", err) - } - return Fail(t, "Condition never satisfied", msgAndArgs...) - case <-tickC: - tickC = nil - go checkCond() - case collect := <-ch: - if !collect.failed() { - return true - } - // Keep the errors from the last ended condition, so that they can be copied to t if timeout is reached. - lastFinishedTickErrs = collect.errors - tickC = ticker.C - } - } -} - -// Never asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// assert.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond) -func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - ch := make(chan bool, 1) - checkCond := func() { ch <- condition() } - - timer := time.NewTimer(waitFor) - defer timer.Stop() - - ticker := time.NewTicker(tick) - defer ticker.Stop() - - var tickC <-chan time.Time - - // Check the condition once first on the initial call. - go checkCond() - - for { - select { - case <-timer.C: - return true - case <-tickC: - tickC = nil - go checkCond() - case v := <-ch: - if v { - return Fail(t, "Condition satisfied", msgAndArgs...) - } - tickC = ticker.C - } - } -} - -// ErrorIs asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func ErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if errors.Is(err, target) { - return true - } - - var expectedText string - if target != nil { - expectedText = target.Error() - if err == nil { - return Fail(t, fmt.Sprintf("Expected error with %q in chain but got nil.", expectedText), msgAndArgs...) - } - } - - chain := buildErrorChainString(err, false) - - return Fail(t, fmt.Sprintf("Target error should be in err chain:\n"+ - "expected: %q\n"+ - "in chain: %s", expectedText, chain, - ), msgAndArgs...) -} - -// NotErrorIs asserts that none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func NotErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if !errors.Is(err, target) { - return true - } - - var expectedText string - if target != nil { - expectedText = target.Error() - } - - chain := buildErrorChainString(err, false) - - return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+ - "found: %q\n"+ - "in chain: %s", expectedText, chain, - ), msgAndArgs...) -} - -// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if errors.As(err, target) { - return true - } - - expectedType := reflect.TypeOf(target).Elem().String() - if err == nil { - return Fail(t, fmt.Sprintf("An error is expected but got nil.\n"+ - "expected: %s", expectedType), msgAndArgs...) - } - - chain := buildErrorChainString(err, true) - - return Fail(t, fmt.Sprintf("Should be in error chain:\n"+ - "expected: %s\n"+ - "in chain: %s", expectedType, chain, - ), msgAndArgs...) -} - -// NotErrorAs asserts that none of the errors in err's chain matches target, -// but if so, sets target to that error value. -func NotErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if !errors.As(err, target) { - return true - } - - chain := buildErrorChainString(err, true) - - return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+ - "found: %s\n"+ - "in chain: %s", reflect.TypeOf(target).Elem().String(), chain, - ), msgAndArgs...) -} - -func unwrapAll(err error) (errs []error) { - errs = append(errs, err) - switch x := err.(type) { - case interface{ Unwrap() error }: - err = x.Unwrap() - if err == nil { - return - } - errs = append(errs, unwrapAll(err)...) - case interface{ Unwrap() []error }: - for _, err := range x.Unwrap() { - errs = append(errs, unwrapAll(err)...) - } - } - return -} - -func buildErrorChainString(err error, withType bool) string { - if err == nil { - return "" - } - - var chain string - errs := unwrapAll(err) - for i := range errs { - if i != 0 { - chain += "\n\t" - } - chain += fmt.Sprintf("%q", errs[i].Error()) - if withType { - chain += fmt.Sprintf(" (%T)", errs[i]) - } - } - return chain -} diff --git a/go/sdk/vendor/github.com/stretchr/testify/assert/doc.go b/go/sdk/vendor/github.com/stretchr/testify/assert/doc.go deleted file mode 100644 index a0b953a..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/assert/doc.go +++ /dev/null @@ -1,50 +0,0 @@ -// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. -// -// # Note -// -// All functions in this package return a bool value indicating whether the assertion has passed. -// -// # Example Usage -// -// The following is a complete example using assert in a standard test function: -// -// import ( -// "testing" -// "github.com/stretchr/testify/assert" -// ) -// -// func TestSomething(t *testing.T) { -// -// var a string = "Hello" -// var b string = "Hello" -// -// assert.Equal(t, a, b, "The two words should be the same.") -// -// } -// -// if you assert many times, use the format below: -// -// import ( -// "testing" -// "github.com/stretchr/testify/assert" -// ) -// -// func TestSomething(t *testing.T) { -// assert := assert.New(t) -// -// var a string = "Hello" -// var b string = "Hello" -// -// assert.Equal(a, b, "The two words should be the same.") -// } -// -// # Assertions -// -// Assertions allow you to easily write test code, and are global funcs in the `assert` package. -// All assertion functions take, as the first argument, the `*testing.T` object provided by the -// testing framework. This allows the assertion funcs to write the failings and other details to -// the correct place. -// -// Every assertion function also takes an optional string message as the final argument, -// allowing custom error messages to be appended to the message the assertion method outputs. -package assert diff --git a/go/sdk/vendor/github.com/stretchr/testify/assert/errors.go b/go/sdk/vendor/github.com/stretchr/testify/assert/errors.go deleted file mode 100644 index ac9dc9d..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/assert/errors.go +++ /dev/null @@ -1,10 +0,0 @@ -package assert - -import ( - "errors" -) - -// AnError is an error instance useful for testing. If the code does not care -// about error specifics, and only needs to return the error for example, this -// error should be used to make the test code more readable. -var AnError = errors.New("assert.AnError general error for testing") diff --git a/go/sdk/vendor/github.com/stretchr/testify/assert/forward_assertions.go b/go/sdk/vendor/github.com/stretchr/testify/assert/forward_assertions.go deleted file mode 100644 index df189d2..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/assert/forward_assertions.go +++ /dev/null @@ -1,16 +0,0 @@ -package assert - -// Assertions provides assertion methods around the -// TestingT interface. -type Assertions struct { - t TestingT -} - -// New makes a new Assertions object for the specified TestingT. -func New(t TestingT) *Assertions { - return &Assertions{ - t: t, - } -} - -//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_forward.go.tmpl -include-format-funcs" diff --git a/go/sdk/vendor/github.com/stretchr/testify/assert/http_assertions.go b/go/sdk/vendor/github.com/stretchr/testify/assert/http_assertions.go deleted file mode 100644 index 5a6bb75..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/assert/http_assertions.go +++ /dev/null @@ -1,165 +0,0 @@ -package assert - -import ( - "fmt" - "net/http" - "net/http/httptest" - "net/url" - "strings" -) - -// httpCode is a helper that returns HTTP code of the response. It returns -1 and -// an error if building a new request fails. -func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) { - w := httptest.NewRecorder() - req, err := http.NewRequest(method, url, http.NoBody) - if err != nil { - return -1, err - } - req.URL.RawQuery = values.Encode() - handler(w, req) - return w.Code, nil -} - -// HTTPSuccess asserts that a specified handler returns a success status code. -// -// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - code, err := httpCode(handler, method, url, values) - if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) - } - - isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent - if !isSuccessCode { - Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) - } - - return isSuccessCode -} - -// HTTPRedirect asserts that a specified handler returns a redirect status code. -// -// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - code, err := httpCode(handler, method, url, values) - if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) - } - - isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect - if !isRedirectCode { - Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) - } - - return isRedirectCode -} - -// HTTPError asserts that a specified handler returns an error status code. -// -// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - code, err := httpCode(handler, method, url, values) - if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) - } - - isErrorCode := code >= http.StatusBadRequest - if !isErrorCode { - Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) - } - - return isErrorCode -} - -// HTTPStatusCode asserts that a specified handler returns a specified status code. -// -// assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501) -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - code, err := httpCode(handler, method, url, values) - if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) - } - - successful := code == statuscode - if !successful { - Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code), msgAndArgs...) - } - - return successful -} - -// HTTPBody is a helper that returns HTTP body of the response. It returns -// empty string if building a new request fails. -func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string { - w := httptest.NewRecorder() - if len(values) > 0 { - url += "?" + values.Encode() - } - req, err := http.NewRequest(method, url, http.NoBody) - if err != nil { - return "" - } - handler(w, req) - return w.Body.String() -} - -// HTTPBodyContains asserts that a specified handler returns a -// body that contains a string. -// -// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - body := HTTPBody(handler, method, url, values) - - contains := strings.Contains(body, fmt.Sprint(str)) - if !contains { - Fail(t, fmt.Sprintf("Expected response body for %q to contain %q but found %q", url+"?"+values.Encode(), str, body), msgAndArgs...) - } - - return contains -} - -// HTTPBodyNotContains asserts that a specified handler returns a -// body that does not contain a string. -// -// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - body := HTTPBody(handler, method, url, values) - - contains := strings.Contains(body, fmt.Sprint(str)) - if contains { - Fail(t, fmt.Sprintf("Expected response body for %q to NOT contain %q but found %q", url+"?"+values.Encode(), str, body), msgAndArgs...) - } - - return !contains -} diff --git a/go/sdk/vendor/github.com/stretchr/testify/assert/yaml/yaml_custom.go b/go/sdk/vendor/github.com/stretchr/testify/assert/yaml/yaml_custom.go deleted file mode 100644 index 5a74c4f..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/assert/yaml/yaml_custom.go +++ /dev/null @@ -1,24 +0,0 @@ -//go:build testify_yaml_custom && !testify_yaml_fail && !testify_yaml_default - -// Package yaml is an implementation of YAML functions that calls a pluggable implementation. -// -// This implementation is selected with the testify_yaml_custom build tag. -// -// go test -tags testify_yaml_custom -// -// This implementation can be used at build time to replace the default implementation -// to avoid linking with [gopkg.in/yaml.v3]. -// -// In your test package: -// -// import assertYaml "github.com/stretchr/testify/assert/yaml" -// -// func init() { -// assertYaml.Unmarshal = func (in []byte, out interface{}) error { -// // ... -// return nil -// } -// } -package yaml - -var Unmarshal func(in []byte, out interface{}) error diff --git a/go/sdk/vendor/github.com/stretchr/testify/assert/yaml/yaml_default.go b/go/sdk/vendor/github.com/stretchr/testify/assert/yaml/yaml_default.go deleted file mode 100644 index 0bae80e..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/assert/yaml/yaml_default.go +++ /dev/null @@ -1,36 +0,0 @@ -//go:build !testify_yaml_fail && !testify_yaml_custom - -// Package yaml is just an indirection to handle YAML deserialization. -// -// This package is just an indirection that allows the builder to override the -// indirection with an alternative implementation of this package that uses -// another implementation of YAML deserialization. This allows to not either not -// use YAML deserialization at all, or to use another implementation than -// [gopkg.in/yaml.v3] (for example for license compatibility reasons, see [PR #1120]). -// -// Alternative implementations are selected using build tags: -// -// - testify_yaml_fail: [Unmarshal] always fails with an error -// - testify_yaml_custom: [Unmarshal] is a variable. Caller must initialize it -// before calling any of [github.com/stretchr/testify/assert.YAMLEq] or -// [github.com/stretchr/testify/assert.YAMLEqf]. -// -// Usage: -// -// go test -tags testify_yaml_fail -// -// You can check with "go list" which implementation is linked: -// -// go list -f '{{.Imports}}' github.com/stretchr/testify/assert/yaml -// go list -tags testify_yaml_fail -f '{{.Imports}}' github.com/stretchr/testify/assert/yaml -// go list -tags testify_yaml_custom -f '{{.Imports}}' github.com/stretchr/testify/assert/yaml -// -// [PR #1120]: https://github.com/stretchr/testify/pull/1120 -package yaml - -import goyaml "gopkg.in/yaml.v3" - -// Unmarshal is just a wrapper of [gopkg.in/yaml.v3.Unmarshal]. -func Unmarshal(in []byte, out interface{}) error { - return goyaml.Unmarshal(in, out) -} diff --git a/go/sdk/vendor/github.com/stretchr/testify/assert/yaml/yaml_fail.go b/go/sdk/vendor/github.com/stretchr/testify/assert/yaml/yaml_fail.go deleted file mode 100644 index 8041803..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/assert/yaml/yaml_fail.go +++ /dev/null @@ -1,17 +0,0 @@ -//go:build testify_yaml_fail && !testify_yaml_custom && !testify_yaml_default - -// Package yaml is an implementation of YAML functions that always fail. -// -// This implementation can be used at build time to replace the default implementation -// to avoid linking with [gopkg.in/yaml.v3]: -// -// go test -tags testify_yaml_fail -package yaml - -import "errors" - -var errNotImplemented = errors.New("YAML functions are not available (see https://pkg.go.dev/github.com/stretchr/testify/assert/yaml)") - -func Unmarshal([]byte, interface{}) error { - return errNotImplemented -} diff --git a/go/sdk/vendor/github.com/stretchr/testify/require/doc.go b/go/sdk/vendor/github.com/stretchr/testify/require/doc.go deleted file mode 100644 index c8e3f94..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/require/doc.go +++ /dev/null @@ -1,31 +0,0 @@ -// Package require implements the same assertions as the `assert` package but -// stops test execution when a test fails. -// -// # Example Usage -// -// The following is a complete example using require in a standard test function: -// -// import ( -// "testing" -// "github.com/stretchr/testify/require" -// ) -// -// func TestSomething(t *testing.T) { -// -// var a string = "Hello" -// var b string = "Hello" -// -// require.Equal(t, a, b, "The two words should be the same.") -// -// } -// -// # Assertions -// -// The `require` package have same global functions as in the `assert` package, -// but instead of returning a boolean result they call `t.FailNow()`. -// A consequence of this is that it must be called from the goroutine running -// the test function, not from other goroutines created during the test. -// -// Every assertion function also takes an optional string message as the final argument, -// allowing custom error messages to be appended to the message the assertion method outputs. -package require diff --git a/go/sdk/vendor/github.com/stretchr/testify/require/forward_requirements.go b/go/sdk/vendor/github.com/stretchr/testify/require/forward_requirements.go deleted file mode 100644 index 1dcb233..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/require/forward_requirements.go +++ /dev/null @@ -1,16 +0,0 @@ -package require - -// Assertions provides assertion methods around the -// TestingT interface. -type Assertions struct { - t TestingT -} - -// New makes a new Assertions object for the specified TestingT. -func New(t TestingT) *Assertions { - return &Assertions{ - t: t, - } -} - -//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=require -template=require_forward.go.tmpl -include-format-funcs" diff --git a/go/sdk/vendor/github.com/stretchr/testify/require/require.go b/go/sdk/vendor/github.com/stretchr/testify/require/require.go deleted file mode 100644 index 2d02f9b..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/require/require.go +++ /dev/null @@ -1,2180 +0,0 @@ -// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. - -package require - -import ( - assert "github.com/stretchr/testify/assert" - http "net/http" - url "net/url" - time "time" -) - -// Condition uses a Comparison to assert a complex condition. -func Condition(t TestingT, comp assert.Comparison, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Condition(t, comp, msgAndArgs...) { - return - } - t.FailNow() -} - -// Conditionf uses a Comparison to assert a complex condition. -func Conditionf(t TestingT, comp assert.Comparison, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Conditionf(t, comp, msg, args...) { - return - } - t.FailNow() -} - -// Contains asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// require.Contains(t, "Hello World", "World") -// require.Contains(t, ["Hello", "World"], "World") -// require.Contains(t, {"Hello": "World"}, "Hello") -func Contains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Contains(t, s, contains, msgAndArgs...) { - return - } - t.FailNow() -} - -// Containsf asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// require.Containsf(t, "Hello World", "World", "error message %s", "formatted") -// require.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") -// require.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") -func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Containsf(t, s, contains, msg, args...) { - return - } - t.FailNow() -} - -// DirExists checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func DirExists(t TestingT, path string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.DirExists(t, path, msgAndArgs...) { - return - } - t.FailNow() -} - -// DirExistsf checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func DirExistsf(t TestingT, path string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.DirExistsf(t, path, msg, args...) { - return - } - t.FailNow() -} - -// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// require.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]) -func ElementsMatch(t TestingT, listA interface{}, listB interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ElementsMatch(t, listA, listB, msgAndArgs...) { - return - } - t.FailNow() -} - -// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// require.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") -func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ElementsMatchf(t, listA, listB, msg, args...) { - return - } - t.FailNow() -} - -// Empty asserts that the given value is "empty". -// -// [Zero values] are "empty". -// -// Arrays are "empty" if every element is the zero value of the type (stricter than "empty"). -// -// Slices, maps and channels with zero length are "empty". -// -// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty". -// -// require.Empty(t, obj) -// -// [Zero values]: https://go.dev/ref/spec#The_zero_value -func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Empty(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// Emptyf asserts that the given value is "empty". -// -// [Zero values] are "empty". -// -// Arrays are "empty" if every element is the zero value of the type (stricter than "empty"). -// -// Slices, maps and channels with zero length are "empty". -// -// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty". -// -// require.Emptyf(t, obj, "error message %s", "formatted") -// -// [Zero values]: https://go.dev/ref/spec#The_zero_value -func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Emptyf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// Equal asserts that two objects are equal. -// -// require.Equal(t, 123, 123) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func Equal(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Equal(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// EqualError asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// require.EqualError(t, err, expectedErrorString) -func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.EqualError(t, theError, errString, msgAndArgs...) { - return - } - t.FailNow() -} - -// EqualErrorf asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// require.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") -func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.EqualErrorf(t, theError, errString, msg, args...) { - return - } - t.FailNow() -} - -// EqualExportedValues asserts that the types of two objects are equal and their public -// fields are also equal. This is useful for comparing structs that have private fields -// that could potentially differ. -// -// type S struct { -// Exported int -// notExported int -// } -// require.EqualExportedValues(t, S{1, 2}, S{1, 3}) => true -// require.EqualExportedValues(t, S{1, 2}, S{2, 3}) => false -func EqualExportedValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.EqualExportedValues(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// EqualExportedValuesf asserts that the types of two objects are equal and their public -// fields are also equal. This is useful for comparing structs that have private fields -// that could potentially differ. -// -// type S struct { -// Exported int -// notExported int -// } -// require.EqualExportedValuesf(t, S{1, 2}, S{1, 3}, "error message %s", "formatted") => true -// require.EqualExportedValuesf(t, S{1, 2}, S{2, 3}, "error message %s", "formatted") => false -func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.EqualExportedValuesf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// EqualValues asserts that two objects are equal or convertible to the larger -// type and equal. -// -// require.EqualValues(t, uint32(123), int32(123)) -func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.EqualValues(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// EqualValuesf asserts that two objects are equal or convertible to the larger -// type and equal. -// -// require.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted") -func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.EqualValuesf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// Equalf asserts that two objects are equal. -// -// require.Equalf(t, 123, 123, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Equalf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// Error asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// require.Error(t, err) -func Error(t TestingT, err error, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Error(t, err, msgAndArgs...) { - return - } - t.FailNow() -} - -// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ErrorAs(t, err, target, msgAndArgs...) { - return - } - t.FailNow() -} - -// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ErrorAsf(t, err, target, msg, args...) { - return - } - t.FailNow() -} - -// ErrorContains asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// require.ErrorContains(t, err, expectedErrorSubString) -func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ErrorContains(t, theError, contains, msgAndArgs...) { - return - } - t.FailNow() -} - -// ErrorContainsf asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// require.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted") -func ErrorContainsf(t TestingT, theError error, contains string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ErrorContainsf(t, theError, contains, msg, args...) { - return - } - t.FailNow() -} - -// ErrorIs asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func ErrorIs(t TestingT, err error, target error, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ErrorIs(t, err, target, msgAndArgs...) { - return - } - t.FailNow() -} - -// ErrorIsf asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ErrorIsf(t, err, target, msg, args...) { - return - } - t.FailNow() -} - -// Errorf asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// require.Errorf(t, err, "error message %s", "formatted") -func Errorf(t TestingT, err error, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Errorf(t, err, msg, args...) { - return - } - t.FailNow() -} - -// Eventually asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// require.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond) -func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Eventually(t, condition, waitFor, tick, msgAndArgs...) { - return - } - t.FailNow() -} - -// EventuallyWithT asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. In contrast to Eventually, -// it supplies a CollectT to the condition function, so that the condition -// function can use the CollectT to call other assertions. -// The condition is considered "met" if no errors are raised in a tick. -// The supplied CollectT collects all errors from one tick (if there are any). -// If the condition is not met before waitFor, the collected errors of -// the last tick are copied to t. -// -// externalValue := false -// go func() { -// time.Sleep(8*time.Second) -// externalValue = true -// }() -// require.EventuallyWithT(t, func(c *require.CollectT) { -// // add assertions as needed; any assertion failure will fail the current tick -// require.True(c, externalValue, "expected 'externalValue' to be true") -// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false") -func EventuallyWithT(t TestingT, condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.EventuallyWithT(t, condition, waitFor, tick, msgAndArgs...) { - return - } - t.FailNow() -} - -// EventuallyWithTf asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. In contrast to Eventually, -// it supplies a CollectT to the condition function, so that the condition -// function can use the CollectT to call other assertions. -// The condition is considered "met" if no errors are raised in a tick. -// The supplied CollectT collects all errors from one tick (if there are any). -// If the condition is not met before waitFor, the collected errors of -// the last tick are copied to t. -// -// externalValue := false -// go func() { -// time.Sleep(8*time.Second) -// externalValue = true -// }() -// require.EventuallyWithTf(t, func(c *require.CollectT, "error message %s", "formatted") { -// // add assertions as needed; any assertion failure will fail the current tick -// require.True(c, externalValue, "expected 'externalValue' to be true") -// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false") -func EventuallyWithTf(t TestingT, condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.EventuallyWithTf(t, condition, waitFor, tick, msg, args...) { - return - } - t.FailNow() -} - -// Eventuallyf asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// require.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Eventuallyf(t, condition, waitFor, tick, msg, args...) { - return - } - t.FailNow() -} - -// Exactly asserts that two objects are equal in value and type. -// -// require.Exactly(t, int32(123), int64(123)) -func Exactly(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Exactly(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// Exactlyf asserts that two objects are equal in value and type. -// -// require.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted") -func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Exactlyf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// Fail reports a failure through -func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Fail(t, failureMessage, msgAndArgs...) { - return - } - t.FailNow() -} - -// FailNow fails test -func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.FailNow(t, failureMessage, msgAndArgs...) { - return - } - t.FailNow() -} - -// FailNowf fails test -func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.FailNowf(t, failureMessage, msg, args...) { - return - } - t.FailNow() -} - -// Failf reports a failure through -func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Failf(t, failureMessage, msg, args...) { - return - } - t.FailNow() -} - -// False asserts that the specified value is false. -// -// require.False(t, myBool) -func False(t TestingT, value bool, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.False(t, value, msgAndArgs...) { - return - } - t.FailNow() -} - -// Falsef asserts that the specified value is false. -// -// require.Falsef(t, myBool, "error message %s", "formatted") -func Falsef(t TestingT, value bool, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Falsef(t, value, msg, args...) { - return - } - t.FailNow() -} - -// FileExists checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func FileExists(t TestingT, path string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.FileExists(t, path, msgAndArgs...) { - return - } - t.FailNow() -} - -// FileExistsf checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func FileExistsf(t TestingT, path string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.FileExistsf(t, path, msg, args...) { - return - } - t.FailNow() -} - -// Greater asserts that the first element is greater than the second -// -// require.Greater(t, 2, 1) -// require.Greater(t, float64(2), float64(1)) -// require.Greater(t, "b", "a") -func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Greater(t, e1, e2, msgAndArgs...) { - return - } - t.FailNow() -} - -// GreaterOrEqual asserts that the first element is greater than or equal to the second -// -// require.GreaterOrEqual(t, 2, 1) -// require.GreaterOrEqual(t, 2, 2) -// require.GreaterOrEqual(t, "b", "a") -// require.GreaterOrEqual(t, "b", "b") -func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.GreaterOrEqual(t, e1, e2, msgAndArgs...) { - return - } - t.FailNow() -} - -// GreaterOrEqualf asserts that the first element is greater than or equal to the second -// -// require.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted") -// require.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted") -// require.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted") -// require.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted") -func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.GreaterOrEqualf(t, e1, e2, msg, args...) { - return - } - t.FailNow() -} - -// Greaterf asserts that the first element is greater than the second -// -// require.Greaterf(t, 2, 1, "error message %s", "formatted") -// require.Greaterf(t, float64(2), float64(1), "error message %s", "formatted") -// require.Greaterf(t, "b", "a", "error message %s", "formatted") -func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Greaterf(t, e1, e2, msg, args...) { - return - } - t.FailNow() -} - -// HTTPBodyContains asserts that a specified handler returns a -// body that contains a string. -// -// require.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPBodyContains(t, handler, method, url, values, str, msgAndArgs...) { - return - } - t.FailNow() -} - -// HTTPBodyContainsf asserts that a specified handler returns a -// body that contains a string. -// -// require.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPBodyContainsf(t, handler, method, url, values, str, msg, args...) { - return - } - t.FailNow() -} - -// HTTPBodyNotContains asserts that a specified handler returns a -// body that does not contain a string. -// -// require.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPBodyNotContains(t, handler, method, url, values, str, msgAndArgs...) { - return - } - t.FailNow() -} - -// HTTPBodyNotContainsf asserts that a specified handler returns a -// body that does not contain a string. -// -// require.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPBodyNotContainsf(t, handler, method, url, values, str, msg, args...) { - return - } - t.FailNow() -} - -// HTTPError asserts that a specified handler returns an error status code. -// -// require.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPError(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPError(t, handler, method, url, values, msgAndArgs...) { - return - } - t.FailNow() -} - -// HTTPErrorf asserts that a specified handler returns an error status code. -// -// require.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPErrorf(t, handler, method, url, values, msg, args...) { - return - } - t.FailNow() -} - -// HTTPRedirect asserts that a specified handler returns a redirect status code. -// -// require.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPRedirect(t, handler, method, url, values, msgAndArgs...) { - return - } - t.FailNow() -} - -// HTTPRedirectf asserts that a specified handler returns a redirect status code. -// -// require.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPRedirectf(t, handler, method, url, values, msg, args...) { - return - } - t.FailNow() -} - -// HTTPStatusCode asserts that a specified handler returns a specified status code. -// -// require.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501) -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPStatusCode(t, handler, method, url, values, statuscode, msgAndArgs...) { - return - } - t.FailNow() -} - -// HTTPStatusCodef asserts that a specified handler returns a specified status code. -// -// require.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPStatusCodef(t, handler, method, url, values, statuscode, msg, args...) { - return - } - t.FailNow() -} - -// HTTPSuccess asserts that a specified handler returns a success status code. -// -// require.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPSuccess(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPSuccess(t, handler, method, url, values, msgAndArgs...) { - return - } - t.FailNow() -} - -// HTTPSuccessf asserts that a specified handler returns a success status code. -// -// require.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPSuccessf(t, handler, method, url, values, msg, args...) { - return - } - t.FailNow() -} - -// Implements asserts that an object is implemented by the specified interface. -// -// require.Implements(t, (*MyInterface)(nil), new(MyObject)) -func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Implements(t, interfaceObject, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// Implementsf asserts that an object is implemented by the specified interface. -// -// require.Implementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") -func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Implementsf(t, interfaceObject, object, msg, args...) { - return - } - t.FailNow() -} - -// InDelta asserts that the two numerals are within delta of each other. -// -// require.InDelta(t, math.Pi, 22/7.0, 0.01) -func InDelta(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InDelta(t, expected, actual, delta, msgAndArgs...) { - return - } - t.FailNow() -} - -// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func InDeltaMapValues(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InDeltaMapValues(t, expected, actual, delta, msgAndArgs...) { - return - } - t.FailNow() -} - -// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InDeltaMapValuesf(t, expected, actual, delta, msg, args...) { - return - } - t.FailNow() -} - -// InDeltaSlice is the same as InDelta, except it compares two slices. -func InDeltaSlice(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InDeltaSlice(t, expected, actual, delta, msgAndArgs...) { - return - } - t.FailNow() -} - -// InDeltaSlicef is the same as InDelta, except it compares two slices. -func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InDeltaSlicef(t, expected, actual, delta, msg, args...) { - return - } - t.FailNow() -} - -// InDeltaf asserts that the two numerals are within delta of each other. -// -// require.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted") -func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InDeltaf(t, expected, actual, delta, msg, args...) { - return - } - t.FailNow() -} - -// InEpsilon asserts that expected and actual have a relative error less than epsilon -func InEpsilon(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InEpsilon(t, expected, actual, epsilon, msgAndArgs...) { - return - } - t.FailNow() -} - -// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. -func InEpsilonSlice(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InEpsilonSlice(t, expected, actual, epsilon, msgAndArgs...) { - return - } - t.FailNow() -} - -// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. -func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InEpsilonSlicef(t, expected, actual, epsilon, msg, args...) { - return - } - t.FailNow() -} - -// InEpsilonf asserts that expected and actual have a relative error less than epsilon -func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InEpsilonf(t, expected, actual, epsilon, msg, args...) { - return - } - t.FailNow() -} - -// IsDecreasing asserts that the collection is decreasing -// -// require.IsDecreasing(t, []int{2, 1, 0}) -// require.IsDecreasing(t, []float{2, 1}) -// require.IsDecreasing(t, []string{"b", "a"}) -func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsDecreasing(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// IsDecreasingf asserts that the collection is decreasing -// -// require.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted") -// require.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted") -// require.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted") -func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsDecreasingf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// IsIncreasing asserts that the collection is increasing -// -// require.IsIncreasing(t, []int{1, 2, 3}) -// require.IsIncreasing(t, []float{1, 2}) -// require.IsIncreasing(t, []string{"a", "b"}) -func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsIncreasing(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// IsIncreasingf asserts that the collection is increasing -// -// require.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted") -// require.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted") -// require.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted") -func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsIncreasingf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// IsNonDecreasing asserts that the collection is not decreasing -// -// require.IsNonDecreasing(t, []int{1, 1, 2}) -// require.IsNonDecreasing(t, []float{1, 2}) -// require.IsNonDecreasing(t, []string{"a", "b"}) -func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsNonDecreasing(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// IsNonDecreasingf asserts that the collection is not decreasing -// -// require.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted") -// require.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted") -// require.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted") -func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsNonDecreasingf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// IsNonIncreasing asserts that the collection is not increasing -// -// require.IsNonIncreasing(t, []int{2, 1, 1}) -// require.IsNonIncreasing(t, []float{2, 1}) -// require.IsNonIncreasing(t, []string{"b", "a"}) -func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsNonIncreasing(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// IsNonIncreasingf asserts that the collection is not increasing -// -// require.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted") -// require.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted") -// require.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted") -func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsNonIncreasingf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// IsNotType asserts that the specified objects are not of the same type. -// -// require.IsNotType(t, &NotMyStruct{}, &MyStruct{}) -func IsNotType(t TestingT, theType interface{}, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsNotType(t, theType, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// IsNotTypef asserts that the specified objects are not of the same type. -// -// require.IsNotTypef(t, &NotMyStruct{}, &MyStruct{}, "error message %s", "formatted") -func IsNotTypef(t TestingT, theType interface{}, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsNotTypef(t, theType, object, msg, args...) { - return - } - t.FailNow() -} - -// IsType asserts that the specified objects are of the same type. -// -// require.IsType(t, &MyStruct{}, &MyStruct{}) -func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsType(t, expectedType, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// IsTypef asserts that the specified objects are of the same type. -// -// require.IsTypef(t, &MyStruct{}, &MyStruct{}, "error message %s", "formatted") -func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsTypef(t, expectedType, object, msg, args...) { - return - } - t.FailNow() -} - -// JSONEq asserts that two JSON strings are equivalent. -// -// require.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) -func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.JSONEq(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// JSONEqf asserts that two JSON strings are equivalent. -// -// require.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") -func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.JSONEqf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// Len asserts that the specified object has specific length. -// Len also fails if the object has a type that len() not accept. -// -// require.Len(t, mySlice, 3) -func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Len(t, object, length, msgAndArgs...) { - return - } - t.FailNow() -} - -// Lenf asserts that the specified object has specific length. -// Lenf also fails if the object has a type that len() not accept. -// -// require.Lenf(t, mySlice, 3, "error message %s", "formatted") -func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Lenf(t, object, length, msg, args...) { - return - } - t.FailNow() -} - -// Less asserts that the first element is less than the second -// -// require.Less(t, 1, 2) -// require.Less(t, float64(1), float64(2)) -// require.Less(t, "a", "b") -func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Less(t, e1, e2, msgAndArgs...) { - return - } - t.FailNow() -} - -// LessOrEqual asserts that the first element is less than or equal to the second -// -// require.LessOrEqual(t, 1, 2) -// require.LessOrEqual(t, 2, 2) -// require.LessOrEqual(t, "a", "b") -// require.LessOrEqual(t, "b", "b") -func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.LessOrEqual(t, e1, e2, msgAndArgs...) { - return - } - t.FailNow() -} - -// LessOrEqualf asserts that the first element is less than or equal to the second -// -// require.LessOrEqualf(t, 1, 2, "error message %s", "formatted") -// require.LessOrEqualf(t, 2, 2, "error message %s", "formatted") -// require.LessOrEqualf(t, "a", "b", "error message %s", "formatted") -// require.LessOrEqualf(t, "b", "b", "error message %s", "formatted") -func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.LessOrEqualf(t, e1, e2, msg, args...) { - return - } - t.FailNow() -} - -// Lessf asserts that the first element is less than the second -// -// require.Lessf(t, 1, 2, "error message %s", "formatted") -// require.Lessf(t, float64(1), float64(2), "error message %s", "formatted") -// require.Lessf(t, "a", "b", "error message %s", "formatted") -func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Lessf(t, e1, e2, msg, args...) { - return - } - t.FailNow() -} - -// Negative asserts that the specified element is negative -// -// require.Negative(t, -1) -// require.Negative(t, -1.23) -func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Negative(t, e, msgAndArgs...) { - return - } - t.FailNow() -} - -// Negativef asserts that the specified element is negative -// -// require.Negativef(t, -1, "error message %s", "formatted") -// require.Negativef(t, -1.23, "error message %s", "formatted") -func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Negativef(t, e, msg, args...) { - return - } - t.FailNow() -} - -// Never asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// require.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond) -func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Never(t, condition, waitFor, tick, msgAndArgs...) { - return - } - t.FailNow() -} - -// Neverf asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// require.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Neverf(t, condition, waitFor, tick, msg, args...) { - return - } - t.FailNow() -} - -// Nil asserts that the specified object is nil. -// -// require.Nil(t, err) -func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Nil(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// Nilf asserts that the specified object is nil. -// -// require.Nilf(t, err, "error message %s", "formatted") -func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Nilf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// NoDirExists checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func NoDirExists(t TestingT, path string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NoDirExists(t, path, msgAndArgs...) { - return - } - t.FailNow() -} - -// NoDirExistsf checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func NoDirExistsf(t TestingT, path string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NoDirExistsf(t, path, msg, args...) { - return - } - t.FailNow() -} - -// NoError asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if require.NoError(t, err) { -// require.Equal(t, expectedObj, actualObj) -// } -func NoError(t TestingT, err error, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NoError(t, err, msgAndArgs...) { - return - } - t.FailNow() -} - -// NoErrorf asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if require.NoErrorf(t, err, "error message %s", "formatted") { -// require.Equal(t, expectedObj, actualObj) -// } -func NoErrorf(t TestingT, err error, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NoErrorf(t, err, msg, args...) { - return - } - t.FailNow() -} - -// NoFileExists checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func NoFileExists(t TestingT, path string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NoFileExists(t, path, msgAndArgs...) { - return - } - t.FailNow() -} - -// NoFileExistsf checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func NoFileExistsf(t TestingT, path string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NoFileExistsf(t, path, msg, args...) { - return - } - t.FailNow() -} - -// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// require.NotContains(t, "Hello World", "Earth") -// require.NotContains(t, ["Hello", "World"], "Earth") -// require.NotContains(t, {"Hello": "World"}, "Earth") -func NotContains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotContains(t, s, contains, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// require.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") -// require.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") -// require.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") -func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotContainsf(t, s, contains, msg, args...) { - return - } - t.FailNow() -} - -// NotElementsMatch asserts that the specified listA(array, slice...) is NOT equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should not match. -// This is an inverse of ElementsMatch. -// -// require.NotElementsMatch(t, [1, 1, 2, 3], [1, 1, 2, 3]) -> false -// -// require.NotElementsMatch(t, [1, 1, 2, 3], [1, 2, 3]) -> true -// -// require.NotElementsMatch(t, [1, 2, 3], [1, 2, 4]) -> true -func NotElementsMatch(t TestingT, listA interface{}, listB interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotElementsMatch(t, listA, listB, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotElementsMatchf asserts that the specified listA(array, slice...) is NOT equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should not match. -// This is an inverse of ElementsMatch. -// -// require.NotElementsMatchf(t, [1, 1, 2, 3], [1, 1, 2, 3], "error message %s", "formatted") -> false -// -// require.NotElementsMatchf(t, [1, 1, 2, 3], [1, 2, 3], "error message %s", "formatted") -> true -// -// require.NotElementsMatchf(t, [1, 2, 3], [1, 2, 4], "error message %s", "formatted") -> true -func NotElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotElementsMatchf(t, listA, listB, msg, args...) { - return - } - t.FailNow() -} - -// NotEmpty asserts that the specified object is NOT [Empty]. -// -// if require.NotEmpty(t, obj) { -// require.Equal(t, "two", obj[1]) -// } -func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotEmpty(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotEmptyf asserts that the specified object is NOT [Empty]. -// -// if require.NotEmptyf(t, obj, "error message %s", "formatted") { -// require.Equal(t, "two", obj[1]) -// } -func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotEmptyf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// NotEqual asserts that the specified values are NOT equal. -// -// require.NotEqual(t, obj1, obj2) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func NotEqual(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotEqual(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotEqualValues asserts that two objects are not equal even when converted to the same type -// -// require.NotEqualValues(t, obj1, obj2) -func NotEqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotEqualValues(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotEqualValuesf asserts that two objects are not equal even when converted to the same type -// -// require.NotEqualValuesf(t, obj1, obj2, "error message %s", "formatted") -func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotEqualValuesf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// NotEqualf asserts that the specified values are NOT equal. -// -// require.NotEqualf(t, obj1, obj2, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotEqualf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// NotErrorAs asserts that none of the errors in err's chain matches target, -// but if so, sets target to that error value. -func NotErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotErrorAs(t, err, target, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotErrorAsf asserts that none of the errors in err's chain matches target, -// but if so, sets target to that error value. -func NotErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotErrorAsf(t, err, target, msg, args...) { - return - } - t.FailNow() -} - -// NotErrorIs asserts that none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func NotErrorIs(t TestingT, err error, target error, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotErrorIs(t, err, target, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotErrorIsf asserts that none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotErrorIsf(t, err, target, msg, args...) { - return - } - t.FailNow() -} - -// NotImplements asserts that an object does not implement the specified interface. -// -// require.NotImplements(t, (*MyInterface)(nil), new(MyObject)) -func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotImplements(t, interfaceObject, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotImplementsf asserts that an object does not implement the specified interface. -// -// require.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") -func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotImplementsf(t, interfaceObject, object, msg, args...) { - return - } - t.FailNow() -} - -// NotNil asserts that the specified object is not nil. -// -// require.NotNil(t, err) -func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotNil(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotNilf asserts that the specified object is not nil. -// -// require.NotNilf(t, err, "error message %s", "formatted") -func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotNilf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// require.NotPanics(t, func(){ RemainCalm() }) -func NotPanics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotPanics(t, f, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// require.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") -func NotPanicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotPanicsf(t, f, msg, args...) { - return - } - t.FailNow() -} - -// NotRegexp asserts that a specified regexp does not match a string. -// -// require.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") -// require.NotRegexp(t, "^start", "it's not starting") -func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotRegexp(t, rx, str, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotRegexpf asserts that a specified regexp does not match a string. -// -// require.NotRegexpf(t, regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") -// require.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") -func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotRegexpf(t, rx, str, msg, args...) { - return - } - t.FailNow() -} - -// NotSame asserts that two pointers do not reference the same object. -// -// require.NotSame(t, ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func NotSame(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotSame(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotSamef asserts that two pointers do not reference the same object. -// -// require.NotSamef(t, ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotSamef(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// NotSubset asserts that the list (array, slice, or map) does NOT contain all -// elements given in the subset (array, slice, or map). -// Map elements are key-value pairs unless compared with an array or slice where -// only the map key is evaluated. -// -// require.NotSubset(t, [1, 3, 4], [1, 2]) -// require.NotSubset(t, {"x": 1, "y": 2}, {"z": 3}) -// require.NotSubset(t, [1, 3, 4], {1: "one", 2: "two"}) -// require.NotSubset(t, {"x": 1, "y": 2}, ["z"]) -func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotSubset(t, list, subset, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotSubsetf asserts that the list (array, slice, or map) does NOT contain all -// elements given in the subset (array, slice, or map). -// Map elements are key-value pairs unless compared with an array or slice where -// only the map key is evaluated. -// -// require.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted") -// require.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") -// require.NotSubsetf(t, [1, 3, 4], {1: "one", 2: "two"}, "error message %s", "formatted") -// require.NotSubsetf(t, {"x": 1, "y": 2}, ["z"], "error message %s", "formatted") -func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotSubsetf(t, list, subset, msg, args...) { - return - } - t.FailNow() -} - -// NotZero asserts that i is not the zero value for its type. -func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotZero(t, i, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotZerof asserts that i is not the zero value for its type. -func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotZerof(t, i, msg, args...) { - return - } - t.FailNow() -} - -// Panics asserts that the code inside the specified PanicTestFunc panics. -// -// require.Panics(t, func(){ GoCrazy() }) -func Panics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Panics(t, f, msgAndArgs...) { - return - } - t.FailNow() -} - -// PanicsWithError asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// require.PanicsWithError(t, "crazy error", func(){ GoCrazy() }) -func PanicsWithError(t TestingT, errString string, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.PanicsWithError(t, errString, f, msgAndArgs...) { - return - } - t.FailNow() -} - -// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// require.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func PanicsWithErrorf(t TestingT, errString string, f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.PanicsWithErrorf(t, errString, f, msg, args...) { - return - } - t.FailNow() -} - -// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// require.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) -func PanicsWithValue(t TestingT, expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.PanicsWithValue(t, expected, f, msgAndArgs...) { - return - } - t.FailNow() -} - -// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// require.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func PanicsWithValuef(t TestingT, expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.PanicsWithValuef(t, expected, f, msg, args...) { - return - } - t.FailNow() -} - -// Panicsf asserts that the code inside the specified PanicTestFunc panics. -// -// require.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") -func Panicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Panicsf(t, f, msg, args...) { - return - } - t.FailNow() -} - -// Positive asserts that the specified element is positive -// -// require.Positive(t, 1) -// require.Positive(t, 1.23) -func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Positive(t, e, msgAndArgs...) { - return - } - t.FailNow() -} - -// Positivef asserts that the specified element is positive -// -// require.Positivef(t, 1, "error message %s", "formatted") -// require.Positivef(t, 1.23, "error message %s", "formatted") -func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Positivef(t, e, msg, args...) { - return - } - t.FailNow() -} - -// Regexp asserts that a specified regexp matches a string. -// -// require.Regexp(t, regexp.MustCompile("start"), "it's starting") -// require.Regexp(t, "start...$", "it's not starting") -func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Regexp(t, rx, str, msgAndArgs...) { - return - } - t.FailNow() -} - -// Regexpf asserts that a specified regexp matches a string. -// -// require.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") -// require.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") -func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Regexpf(t, rx, str, msg, args...) { - return - } - t.FailNow() -} - -// Same asserts that two pointers reference the same object. -// -// require.Same(t, ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func Same(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Same(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// Samef asserts that two pointers reference the same object. -// -// require.Samef(t, ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func Samef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Samef(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// Subset asserts that the list (array, slice, or map) contains all elements -// given in the subset (array, slice, or map). -// Map elements are key-value pairs unless compared with an array or slice where -// only the map key is evaluated. -// -// require.Subset(t, [1, 2, 3], [1, 2]) -// require.Subset(t, {"x": 1, "y": 2}, {"x": 1}) -// require.Subset(t, [1, 2, 3], {1: "one", 2: "two"}) -// require.Subset(t, {"x": 1, "y": 2}, ["x"]) -func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Subset(t, list, subset, msgAndArgs...) { - return - } - t.FailNow() -} - -// Subsetf asserts that the list (array, slice, or map) contains all elements -// given in the subset (array, slice, or map). -// Map elements are key-value pairs unless compared with an array or slice where -// only the map key is evaluated. -// -// require.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted") -// require.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") -// require.Subsetf(t, [1, 2, 3], {1: "one", 2: "two"}, "error message %s", "formatted") -// require.Subsetf(t, {"x": 1, "y": 2}, ["x"], "error message %s", "formatted") -func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Subsetf(t, list, subset, msg, args...) { - return - } - t.FailNow() -} - -// True asserts that the specified value is true. -// -// require.True(t, myBool) -func True(t TestingT, value bool, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.True(t, value, msgAndArgs...) { - return - } - t.FailNow() -} - -// Truef asserts that the specified value is true. -// -// require.Truef(t, myBool, "error message %s", "formatted") -func Truef(t TestingT, value bool, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Truef(t, value, msg, args...) { - return - } - t.FailNow() -} - -// WithinDuration asserts that the two times are within duration delta of each other. -// -// require.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) -func WithinDuration(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.WithinDuration(t, expected, actual, delta, msgAndArgs...) { - return - } - t.FailNow() -} - -// WithinDurationf asserts that the two times are within duration delta of each other. -// -// require.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") -func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.WithinDurationf(t, expected, actual, delta, msg, args...) { - return - } - t.FailNow() -} - -// WithinRange asserts that a time is within a time range (inclusive). -// -// require.WithinRange(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) -func WithinRange(t TestingT, actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.WithinRange(t, actual, start, end, msgAndArgs...) { - return - } - t.FailNow() -} - -// WithinRangef asserts that a time is within a time range (inclusive). -// -// require.WithinRangef(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") -func WithinRangef(t TestingT, actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.WithinRangef(t, actual, start, end, msg, args...) { - return - } - t.FailNow() -} - -// YAMLEq asserts that two YAML strings are equivalent. -func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.YAMLEq(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// YAMLEqf asserts that two YAML strings are equivalent. -func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.YAMLEqf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// Zero asserts that i is the zero value for its type. -func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Zero(t, i, msgAndArgs...) { - return - } - t.FailNow() -} - -// Zerof asserts that i is the zero value for its type. -func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Zerof(t, i, msg, args...) { - return - } - t.FailNow() -} diff --git a/go/sdk/vendor/github.com/stretchr/testify/require/require.go.tmpl b/go/sdk/vendor/github.com/stretchr/testify/require/require.go.tmpl deleted file mode 100644 index 8b32836..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/require/require.go.tmpl +++ /dev/null @@ -1,6 +0,0 @@ -{{ replace .Comment "assert." "require."}} -func {{.DocInfo.Name}}(t TestingT, {{.Params}}) { - if h, ok := t.(tHelper); ok { h.Helper() } - if assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { return } - t.FailNow() -} diff --git a/go/sdk/vendor/github.com/stretchr/testify/require/require_forward.go b/go/sdk/vendor/github.com/stretchr/testify/require/require_forward.go deleted file mode 100644 index e6f7e94..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/require/require_forward.go +++ /dev/null @@ -1,1724 +0,0 @@ -// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. - -package require - -import ( - assert "github.com/stretchr/testify/assert" - http "net/http" - url "net/url" - time "time" -) - -// Condition uses a Comparison to assert a complex condition. -func (a *Assertions) Condition(comp assert.Comparison, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Condition(a.t, comp, msgAndArgs...) -} - -// Conditionf uses a Comparison to assert a complex condition. -func (a *Assertions) Conditionf(comp assert.Comparison, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Conditionf(a.t, comp, msg, args...) -} - -// Contains asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// a.Contains("Hello World", "World") -// a.Contains(["Hello", "World"], "World") -// a.Contains({"Hello": "World"}, "Hello") -func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Contains(a.t, s, contains, msgAndArgs...) -} - -// Containsf asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// a.Containsf("Hello World", "World", "error message %s", "formatted") -// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") -// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") -func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Containsf(a.t, s, contains, msg, args...) -} - -// DirExists checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - DirExists(a.t, path, msgAndArgs...) -} - -// DirExistsf checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - DirExistsf(a.t, path, msg, args...) -} - -// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2]) -func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ElementsMatch(a.t, listA, listB, msgAndArgs...) -} - -// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") -func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ElementsMatchf(a.t, listA, listB, msg, args...) -} - -// Empty asserts that the given value is "empty". -// -// [Zero values] are "empty". -// -// Arrays are "empty" if every element is the zero value of the type (stricter than "empty"). -// -// Slices, maps and channels with zero length are "empty". -// -// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty". -// -// a.Empty(obj) -// -// [Zero values]: https://go.dev/ref/spec#The_zero_value -func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Empty(a.t, object, msgAndArgs...) -} - -// Emptyf asserts that the given value is "empty". -// -// [Zero values] are "empty". -// -// Arrays are "empty" if every element is the zero value of the type (stricter than "empty"). -// -// Slices, maps and channels with zero length are "empty". -// -// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty". -// -// a.Emptyf(obj, "error message %s", "formatted") -// -// [Zero values]: https://go.dev/ref/spec#The_zero_value -func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Emptyf(a.t, object, msg, args...) -} - -// Equal asserts that two objects are equal. -// -// a.Equal(123, 123) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Equal(a.t, expected, actual, msgAndArgs...) -} - -// EqualError asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// a.EqualError(err, expectedErrorString) -func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - EqualError(a.t, theError, errString, msgAndArgs...) -} - -// EqualErrorf asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") -func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - EqualErrorf(a.t, theError, errString, msg, args...) -} - -// EqualExportedValues asserts that the types of two objects are equal and their public -// fields are also equal. This is useful for comparing structs that have private fields -// that could potentially differ. -// -// type S struct { -// Exported int -// notExported int -// } -// a.EqualExportedValues(S{1, 2}, S{1, 3}) => true -// a.EqualExportedValues(S{1, 2}, S{2, 3}) => false -func (a *Assertions) EqualExportedValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - EqualExportedValues(a.t, expected, actual, msgAndArgs...) -} - -// EqualExportedValuesf asserts that the types of two objects are equal and their public -// fields are also equal. This is useful for comparing structs that have private fields -// that could potentially differ. -// -// type S struct { -// Exported int -// notExported int -// } -// a.EqualExportedValuesf(S{1, 2}, S{1, 3}, "error message %s", "formatted") => true -// a.EqualExportedValuesf(S{1, 2}, S{2, 3}, "error message %s", "formatted") => false -func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - EqualExportedValuesf(a.t, expected, actual, msg, args...) -} - -// EqualValues asserts that two objects are equal or convertible to the larger -// type and equal. -// -// a.EqualValues(uint32(123), int32(123)) -func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - EqualValues(a.t, expected, actual, msgAndArgs...) -} - -// EqualValuesf asserts that two objects are equal or convertible to the larger -// type and equal. -// -// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted") -func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - EqualValuesf(a.t, expected, actual, msg, args...) -} - -// Equalf asserts that two objects are equal. -// -// a.Equalf(123, 123, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Equalf(a.t, expected, actual, msg, args...) -} - -// Error asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// a.Error(err) -func (a *Assertions) Error(err error, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Error(a.t, err, msgAndArgs...) -} - -// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func (a *Assertions) ErrorAs(err error, target interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ErrorAs(a.t, err, target, msgAndArgs...) -} - -// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ErrorAsf(a.t, err, target, msg, args...) -} - -// ErrorContains asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// a.ErrorContains(err, expectedErrorSubString) -func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ErrorContains(a.t, theError, contains, msgAndArgs...) -} - -// ErrorContainsf asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted") -func (a *Assertions) ErrorContainsf(theError error, contains string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ErrorContainsf(a.t, theError, contains, msg, args...) -} - -// ErrorIs asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ErrorIs(a.t, err, target, msgAndArgs...) -} - -// ErrorIsf asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ErrorIsf(a.t, err, target, msg, args...) -} - -// Errorf asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// a.Errorf(err, "error message %s", "formatted") -func (a *Assertions) Errorf(err error, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Errorf(a.t, err, msg, args...) -} - -// Eventually asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond) -func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Eventually(a.t, condition, waitFor, tick, msgAndArgs...) -} - -// EventuallyWithT asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. In contrast to Eventually, -// it supplies a CollectT to the condition function, so that the condition -// function can use the CollectT to call other assertions. -// The condition is considered "met" if no errors are raised in a tick. -// The supplied CollectT collects all errors from one tick (if there are any). -// If the condition is not met before waitFor, the collected errors of -// the last tick are copied to t. -// -// externalValue := false -// go func() { -// time.Sleep(8*time.Second) -// externalValue = true -// }() -// a.EventuallyWithT(func(c *assert.CollectT) { -// // add assertions as needed; any assertion failure will fail the current tick -// assert.True(c, externalValue, "expected 'externalValue' to be true") -// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false") -func (a *Assertions) EventuallyWithT(condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - EventuallyWithT(a.t, condition, waitFor, tick, msgAndArgs...) -} - -// EventuallyWithTf asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. In contrast to Eventually, -// it supplies a CollectT to the condition function, so that the condition -// function can use the CollectT to call other assertions. -// The condition is considered "met" if no errors are raised in a tick. -// The supplied CollectT collects all errors from one tick (if there are any). -// If the condition is not met before waitFor, the collected errors of -// the last tick are copied to t. -// -// externalValue := false -// go func() { -// time.Sleep(8*time.Second) -// externalValue = true -// }() -// a.EventuallyWithTf(func(c *assert.CollectT, "error message %s", "formatted") { -// // add assertions as needed; any assertion failure will fail the current tick -// assert.True(c, externalValue, "expected 'externalValue' to be true") -// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false") -func (a *Assertions) EventuallyWithTf(condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - EventuallyWithTf(a.t, condition, waitFor, tick, msg, args...) -} - -// Eventuallyf asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Eventuallyf(a.t, condition, waitFor, tick, msg, args...) -} - -// Exactly asserts that two objects are equal in value and type. -// -// a.Exactly(int32(123), int64(123)) -func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Exactly(a.t, expected, actual, msgAndArgs...) -} - -// Exactlyf asserts that two objects are equal in value and type. -// -// a.Exactlyf(int32(123), int64(123), "error message %s", "formatted") -func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Exactlyf(a.t, expected, actual, msg, args...) -} - -// Fail reports a failure through -func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Fail(a.t, failureMessage, msgAndArgs...) -} - -// FailNow fails test -func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - FailNow(a.t, failureMessage, msgAndArgs...) -} - -// FailNowf fails test -func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - FailNowf(a.t, failureMessage, msg, args...) -} - -// Failf reports a failure through -func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Failf(a.t, failureMessage, msg, args...) -} - -// False asserts that the specified value is false. -// -// a.False(myBool) -func (a *Assertions) False(value bool, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - False(a.t, value, msgAndArgs...) -} - -// Falsef asserts that the specified value is false. -// -// a.Falsef(myBool, "error message %s", "formatted") -func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Falsef(a.t, value, msg, args...) -} - -// FileExists checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - FileExists(a.t, path, msgAndArgs...) -} - -// FileExistsf checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - FileExistsf(a.t, path, msg, args...) -} - -// Greater asserts that the first element is greater than the second -// -// a.Greater(2, 1) -// a.Greater(float64(2), float64(1)) -// a.Greater("b", "a") -func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Greater(a.t, e1, e2, msgAndArgs...) -} - -// GreaterOrEqual asserts that the first element is greater than or equal to the second -// -// a.GreaterOrEqual(2, 1) -// a.GreaterOrEqual(2, 2) -// a.GreaterOrEqual("b", "a") -// a.GreaterOrEqual("b", "b") -func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - GreaterOrEqual(a.t, e1, e2, msgAndArgs...) -} - -// GreaterOrEqualf asserts that the first element is greater than or equal to the second -// -// a.GreaterOrEqualf(2, 1, "error message %s", "formatted") -// a.GreaterOrEqualf(2, 2, "error message %s", "formatted") -// a.GreaterOrEqualf("b", "a", "error message %s", "formatted") -// a.GreaterOrEqualf("b", "b", "error message %s", "formatted") -func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - GreaterOrEqualf(a.t, e1, e2, msg, args...) -} - -// Greaterf asserts that the first element is greater than the second -// -// a.Greaterf(2, 1, "error message %s", "formatted") -// a.Greaterf(float64(2), float64(1), "error message %s", "formatted") -// a.Greaterf("b", "a", "error message %s", "formatted") -func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Greaterf(a.t, e1, e2, msg, args...) -} - -// HTTPBodyContains asserts that a specified handler returns a -// body that contains a string. -// -// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...) -} - -// HTTPBodyContainsf asserts that a specified handler returns a -// body that contains a string. -// -// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...) -} - -// HTTPBodyNotContains asserts that a specified handler returns a -// body that does not contain a string. -// -// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...) -} - -// HTTPBodyNotContainsf asserts that a specified handler returns a -// body that does not contain a string. -// -// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...) -} - -// HTTPError asserts that a specified handler returns an error status code. -// -// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPError(a.t, handler, method, url, values, msgAndArgs...) -} - -// HTTPErrorf asserts that a specified handler returns an error status code. -// -// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPErrorf(a.t, handler, method, url, values, msg, args...) -} - -// HTTPRedirect asserts that a specified handler returns a redirect status code. -// -// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...) -} - -// HTTPRedirectf asserts that a specified handler returns a redirect status code. -// -// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPRedirectf(a.t, handler, method, url, values, msg, args...) -} - -// HTTPStatusCode asserts that a specified handler returns a specified status code. -// -// a.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501) -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPStatusCode(a.t, handler, method, url, values, statuscode, msgAndArgs...) -} - -// HTTPStatusCodef asserts that a specified handler returns a specified status code. -// -// a.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPStatusCodef(a.t, handler, method, url, values, statuscode, msg, args...) -} - -// HTTPSuccess asserts that a specified handler returns a success status code. -// -// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...) -} - -// HTTPSuccessf asserts that a specified handler returns a success status code. -// -// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPSuccessf(a.t, handler, method, url, values, msg, args...) -} - -// Implements asserts that an object is implemented by the specified interface. -// -// a.Implements((*MyInterface)(nil), new(MyObject)) -func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Implements(a.t, interfaceObject, object, msgAndArgs...) -} - -// Implementsf asserts that an object is implemented by the specified interface. -// -// a.Implementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") -func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Implementsf(a.t, interfaceObject, object, msg, args...) -} - -// InDelta asserts that the two numerals are within delta of each other. -// -// a.InDelta(math.Pi, 22/7.0, 0.01) -func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InDelta(a.t, expected, actual, delta, msgAndArgs...) -} - -// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...) -} - -// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...) -} - -// InDeltaSlice is the same as InDelta, except it compares two slices. -func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) -} - -// InDeltaSlicef is the same as InDelta, except it compares two slices. -func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InDeltaSlicef(a.t, expected, actual, delta, msg, args...) -} - -// InDeltaf asserts that the two numerals are within delta of each other. -// -// a.InDeltaf(math.Pi, 22/7.0, 0.01, "error message %s", "formatted") -func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InDeltaf(a.t, expected, actual, delta, msg, args...) -} - -// InEpsilon asserts that expected and actual have a relative error less than epsilon -func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) -} - -// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. -func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...) -} - -// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. -func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...) -} - -// InEpsilonf asserts that expected and actual have a relative error less than epsilon -func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InEpsilonf(a.t, expected, actual, epsilon, msg, args...) -} - -// IsDecreasing asserts that the collection is decreasing -// -// a.IsDecreasing([]int{2, 1, 0}) -// a.IsDecreasing([]float{2, 1}) -// a.IsDecreasing([]string{"b", "a"}) -func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsDecreasing(a.t, object, msgAndArgs...) -} - -// IsDecreasingf asserts that the collection is decreasing -// -// a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted") -// a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted") -// a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted") -func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsDecreasingf(a.t, object, msg, args...) -} - -// IsIncreasing asserts that the collection is increasing -// -// a.IsIncreasing([]int{1, 2, 3}) -// a.IsIncreasing([]float{1, 2}) -// a.IsIncreasing([]string{"a", "b"}) -func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsIncreasing(a.t, object, msgAndArgs...) -} - -// IsIncreasingf asserts that the collection is increasing -// -// a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted") -// a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted") -// a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted") -func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsIncreasingf(a.t, object, msg, args...) -} - -// IsNonDecreasing asserts that the collection is not decreasing -// -// a.IsNonDecreasing([]int{1, 1, 2}) -// a.IsNonDecreasing([]float{1, 2}) -// a.IsNonDecreasing([]string{"a", "b"}) -func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsNonDecreasing(a.t, object, msgAndArgs...) -} - -// IsNonDecreasingf asserts that the collection is not decreasing -// -// a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted") -// a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted") -// a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted") -func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsNonDecreasingf(a.t, object, msg, args...) -} - -// IsNonIncreasing asserts that the collection is not increasing -// -// a.IsNonIncreasing([]int{2, 1, 1}) -// a.IsNonIncreasing([]float{2, 1}) -// a.IsNonIncreasing([]string{"b", "a"}) -func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsNonIncreasing(a.t, object, msgAndArgs...) -} - -// IsNonIncreasingf asserts that the collection is not increasing -// -// a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted") -// a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted") -// a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted") -func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsNonIncreasingf(a.t, object, msg, args...) -} - -// IsNotType asserts that the specified objects are not of the same type. -// -// a.IsNotType(&NotMyStruct{}, &MyStruct{}) -func (a *Assertions) IsNotType(theType interface{}, object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsNotType(a.t, theType, object, msgAndArgs...) -} - -// IsNotTypef asserts that the specified objects are not of the same type. -// -// a.IsNotTypef(&NotMyStruct{}, &MyStruct{}, "error message %s", "formatted") -func (a *Assertions) IsNotTypef(theType interface{}, object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsNotTypef(a.t, theType, object, msg, args...) -} - -// IsType asserts that the specified objects are of the same type. -// -// a.IsType(&MyStruct{}, &MyStruct{}) -func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsType(a.t, expectedType, object, msgAndArgs...) -} - -// IsTypef asserts that the specified objects are of the same type. -// -// a.IsTypef(&MyStruct{}, &MyStruct{}, "error message %s", "formatted") -func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsTypef(a.t, expectedType, object, msg, args...) -} - -// JSONEq asserts that two JSON strings are equivalent. -// -// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) -func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - JSONEq(a.t, expected, actual, msgAndArgs...) -} - -// JSONEqf asserts that two JSON strings are equivalent. -// -// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") -func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - JSONEqf(a.t, expected, actual, msg, args...) -} - -// Len asserts that the specified object has specific length. -// Len also fails if the object has a type that len() not accept. -// -// a.Len(mySlice, 3) -func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Len(a.t, object, length, msgAndArgs...) -} - -// Lenf asserts that the specified object has specific length. -// Lenf also fails if the object has a type that len() not accept. -// -// a.Lenf(mySlice, 3, "error message %s", "formatted") -func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Lenf(a.t, object, length, msg, args...) -} - -// Less asserts that the first element is less than the second -// -// a.Less(1, 2) -// a.Less(float64(1), float64(2)) -// a.Less("a", "b") -func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Less(a.t, e1, e2, msgAndArgs...) -} - -// LessOrEqual asserts that the first element is less than or equal to the second -// -// a.LessOrEqual(1, 2) -// a.LessOrEqual(2, 2) -// a.LessOrEqual("a", "b") -// a.LessOrEqual("b", "b") -func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - LessOrEqual(a.t, e1, e2, msgAndArgs...) -} - -// LessOrEqualf asserts that the first element is less than or equal to the second -// -// a.LessOrEqualf(1, 2, "error message %s", "formatted") -// a.LessOrEqualf(2, 2, "error message %s", "formatted") -// a.LessOrEqualf("a", "b", "error message %s", "formatted") -// a.LessOrEqualf("b", "b", "error message %s", "formatted") -func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - LessOrEqualf(a.t, e1, e2, msg, args...) -} - -// Lessf asserts that the first element is less than the second -// -// a.Lessf(1, 2, "error message %s", "formatted") -// a.Lessf(float64(1), float64(2), "error message %s", "formatted") -// a.Lessf("a", "b", "error message %s", "formatted") -func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Lessf(a.t, e1, e2, msg, args...) -} - -// Negative asserts that the specified element is negative -// -// a.Negative(-1) -// a.Negative(-1.23) -func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Negative(a.t, e, msgAndArgs...) -} - -// Negativef asserts that the specified element is negative -// -// a.Negativef(-1, "error message %s", "formatted") -// a.Negativef(-1.23, "error message %s", "formatted") -func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Negativef(a.t, e, msg, args...) -} - -// Never asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// a.Never(func() bool { return false; }, time.Second, 10*time.Millisecond) -func (a *Assertions) Never(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Never(a.t, condition, waitFor, tick, msgAndArgs...) -} - -// Neverf asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// a.Neverf(func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func (a *Assertions) Neverf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Neverf(a.t, condition, waitFor, tick, msg, args...) -} - -// Nil asserts that the specified object is nil. -// -// a.Nil(err) -func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Nil(a.t, object, msgAndArgs...) -} - -// Nilf asserts that the specified object is nil. -// -// a.Nilf(err, "error message %s", "formatted") -func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Nilf(a.t, object, msg, args...) -} - -// NoDirExists checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func (a *Assertions) NoDirExists(path string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NoDirExists(a.t, path, msgAndArgs...) -} - -// NoDirExistsf checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func (a *Assertions) NoDirExistsf(path string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NoDirExistsf(a.t, path, msg, args...) -} - -// NoError asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if a.NoError(err) { -// assert.Equal(t, expectedObj, actualObj) -// } -func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NoError(a.t, err, msgAndArgs...) -} - -// NoErrorf asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if a.NoErrorf(err, "error message %s", "formatted") { -// assert.Equal(t, expectedObj, actualObj) -// } -func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NoErrorf(a.t, err, msg, args...) -} - -// NoFileExists checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func (a *Assertions) NoFileExists(path string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NoFileExists(a.t, path, msgAndArgs...) -} - -// NoFileExistsf checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func (a *Assertions) NoFileExistsf(path string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NoFileExistsf(a.t, path, msg, args...) -} - -// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// a.NotContains("Hello World", "Earth") -// a.NotContains(["Hello", "World"], "Earth") -// a.NotContains({"Hello": "World"}, "Earth") -func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotContains(a.t, s, contains, msgAndArgs...) -} - -// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") -// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") -// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") -func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotContainsf(a.t, s, contains, msg, args...) -} - -// NotElementsMatch asserts that the specified listA(array, slice...) is NOT equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should not match. -// This is an inverse of ElementsMatch. -// -// a.NotElementsMatch([1, 1, 2, 3], [1, 1, 2, 3]) -> false -// -// a.NotElementsMatch([1, 1, 2, 3], [1, 2, 3]) -> true -// -// a.NotElementsMatch([1, 2, 3], [1, 2, 4]) -> true -func (a *Assertions) NotElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotElementsMatch(a.t, listA, listB, msgAndArgs...) -} - -// NotElementsMatchf asserts that the specified listA(array, slice...) is NOT equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should not match. -// This is an inverse of ElementsMatch. -// -// a.NotElementsMatchf([1, 1, 2, 3], [1, 1, 2, 3], "error message %s", "formatted") -> false -// -// a.NotElementsMatchf([1, 1, 2, 3], [1, 2, 3], "error message %s", "formatted") -> true -// -// a.NotElementsMatchf([1, 2, 3], [1, 2, 4], "error message %s", "formatted") -> true -func (a *Assertions) NotElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotElementsMatchf(a.t, listA, listB, msg, args...) -} - -// NotEmpty asserts that the specified object is NOT [Empty]. -// -// if a.NotEmpty(obj) { -// assert.Equal(t, "two", obj[1]) -// } -func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotEmpty(a.t, object, msgAndArgs...) -} - -// NotEmptyf asserts that the specified object is NOT [Empty]. -// -// if a.NotEmptyf(obj, "error message %s", "formatted") { -// assert.Equal(t, "two", obj[1]) -// } -func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotEmptyf(a.t, object, msg, args...) -} - -// NotEqual asserts that the specified values are NOT equal. -// -// a.NotEqual(obj1, obj2) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotEqual(a.t, expected, actual, msgAndArgs...) -} - -// NotEqualValues asserts that two objects are not equal even when converted to the same type -// -// a.NotEqualValues(obj1, obj2) -func (a *Assertions) NotEqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotEqualValues(a.t, expected, actual, msgAndArgs...) -} - -// NotEqualValuesf asserts that two objects are not equal even when converted to the same type -// -// a.NotEqualValuesf(obj1, obj2, "error message %s", "formatted") -func (a *Assertions) NotEqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotEqualValuesf(a.t, expected, actual, msg, args...) -} - -// NotEqualf asserts that the specified values are NOT equal. -// -// a.NotEqualf(obj1, obj2, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotEqualf(a.t, expected, actual, msg, args...) -} - -// NotErrorAs asserts that none of the errors in err's chain matches target, -// but if so, sets target to that error value. -func (a *Assertions) NotErrorAs(err error, target interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotErrorAs(a.t, err, target, msgAndArgs...) -} - -// NotErrorAsf asserts that none of the errors in err's chain matches target, -// but if so, sets target to that error value. -func (a *Assertions) NotErrorAsf(err error, target interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotErrorAsf(a.t, err, target, msg, args...) -} - -// NotErrorIs asserts that none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotErrorIs(a.t, err, target, msgAndArgs...) -} - -// NotErrorIsf asserts that none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotErrorIsf(a.t, err, target, msg, args...) -} - -// NotImplements asserts that an object does not implement the specified interface. -// -// a.NotImplements((*MyInterface)(nil), new(MyObject)) -func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotImplements(a.t, interfaceObject, object, msgAndArgs...) -} - -// NotImplementsf asserts that an object does not implement the specified interface. -// -// a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") -func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotImplementsf(a.t, interfaceObject, object, msg, args...) -} - -// NotNil asserts that the specified object is not nil. -// -// a.NotNil(err) -func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotNil(a.t, object, msgAndArgs...) -} - -// NotNilf asserts that the specified object is not nil. -// -// a.NotNilf(err, "error message %s", "formatted") -func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotNilf(a.t, object, msg, args...) -} - -// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// a.NotPanics(func(){ RemainCalm() }) -func (a *Assertions) NotPanics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotPanics(a.t, f, msgAndArgs...) -} - -// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") -func (a *Assertions) NotPanicsf(f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotPanicsf(a.t, f, msg, args...) -} - -// NotRegexp asserts that a specified regexp does not match a string. -// -// a.NotRegexp(regexp.MustCompile("starts"), "it's starting") -// a.NotRegexp("^start", "it's not starting") -func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotRegexp(a.t, rx, str, msgAndArgs...) -} - -// NotRegexpf asserts that a specified regexp does not match a string. -// -// a.NotRegexpf(regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") -// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") -func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotRegexpf(a.t, rx, str, msg, args...) -} - -// NotSame asserts that two pointers do not reference the same object. -// -// a.NotSame(ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) NotSame(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotSame(a.t, expected, actual, msgAndArgs...) -} - -// NotSamef asserts that two pointers do not reference the same object. -// -// a.NotSamef(ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotSamef(a.t, expected, actual, msg, args...) -} - -// NotSubset asserts that the list (array, slice, or map) does NOT contain all -// elements given in the subset (array, slice, or map). -// Map elements are key-value pairs unless compared with an array or slice where -// only the map key is evaluated. -// -// a.NotSubset([1, 3, 4], [1, 2]) -// a.NotSubset({"x": 1, "y": 2}, {"z": 3}) -// a.NotSubset([1, 3, 4], {1: "one", 2: "two"}) -// a.NotSubset({"x": 1, "y": 2}, ["z"]) -func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotSubset(a.t, list, subset, msgAndArgs...) -} - -// NotSubsetf asserts that the list (array, slice, or map) does NOT contain all -// elements given in the subset (array, slice, or map). -// Map elements are key-value pairs unless compared with an array or slice where -// only the map key is evaluated. -// -// a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted") -// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") -// a.NotSubsetf([1, 3, 4], {1: "one", 2: "two"}, "error message %s", "formatted") -// a.NotSubsetf({"x": 1, "y": 2}, ["z"], "error message %s", "formatted") -func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotSubsetf(a.t, list, subset, msg, args...) -} - -// NotZero asserts that i is not the zero value for its type. -func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotZero(a.t, i, msgAndArgs...) -} - -// NotZerof asserts that i is not the zero value for its type. -func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotZerof(a.t, i, msg, args...) -} - -// Panics asserts that the code inside the specified PanicTestFunc panics. -// -// a.Panics(func(){ GoCrazy() }) -func (a *Assertions) Panics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Panics(a.t, f, msgAndArgs...) -} - -// PanicsWithError asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// a.PanicsWithError("crazy error", func(){ GoCrazy() }) -func (a *Assertions) PanicsWithError(errString string, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - PanicsWithError(a.t, errString, f, msgAndArgs...) -} - -// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// a.PanicsWithErrorf("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func (a *Assertions) PanicsWithErrorf(errString string, f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - PanicsWithErrorf(a.t, errString, f, msg, args...) -} - -// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// a.PanicsWithValue("crazy error", func(){ GoCrazy() }) -func (a *Assertions) PanicsWithValue(expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - PanicsWithValue(a.t, expected, f, msgAndArgs...) -} - -// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func (a *Assertions) PanicsWithValuef(expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - PanicsWithValuef(a.t, expected, f, msg, args...) -} - -// Panicsf asserts that the code inside the specified PanicTestFunc panics. -// -// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") -func (a *Assertions) Panicsf(f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Panicsf(a.t, f, msg, args...) -} - -// Positive asserts that the specified element is positive -// -// a.Positive(1) -// a.Positive(1.23) -func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Positive(a.t, e, msgAndArgs...) -} - -// Positivef asserts that the specified element is positive -// -// a.Positivef(1, "error message %s", "formatted") -// a.Positivef(1.23, "error message %s", "formatted") -func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Positivef(a.t, e, msg, args...) -} - -// Regexp asserts that a specified regexp matches a string. -// -// a.Regexp(regexp.MustCompile("start"), "it's starting") -// a.Regexp("start...$", "it's not starting") -func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Regexp(a.t, rx, str, msgAndArgs...) -} - -// Regexpf asserts that a specified regexp matches a string. -// -// a.Regexpf(regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") -// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") -func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Regexpf(a.t, rx, str, msg, args...) -} - -// Same asserts that two pointers reference the same object. -// -// a.Same(ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) Same(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Same(a.t, expected, actual, msgAndArgs...) -} - -// Samef asserts that two pointers reference the same object. -// -// a.Samef(ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Samef(a.t, expected, actual, msg, args...) -} - -// Subset asserts that the list (array, slice, or map) contains all elements -// given in the subset (array, slice, or map). -// Map elements are key-value pairs unless compared with an array or slice where -// only the map key is evaluated. -// -// a.Subset([1, 2, 3], [1, 2]) -// a.Subset({"x": 1, "y": 2}, {"x": 1}) -// a.Subset([1, 2, 3], {1: "one", 2: "two"}) -// a.Subset({"x": 1, "y": 2}, ["x"]) -func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Subset(a.t, list, subset, msgAndArgs...) -} - -// Subsetf asserts that the list (array, slice, or map) contains all elements -// given in the subset (array, slice, or map). -// Map elements are key-value pairs unless compared with an array or slice where -// only the map key is evaluated. -// -// a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted") -// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") -// a.Subsetf([1, 2, 3], {1: "one", 2: "two"}, "error message %s", "formatted") -// a.Subsetf({"x": 1, "y": 2}, ["x"], "error message %s", "formatted") -func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Subsetf(a.t, list, subset, msg, args...) -} - -// True asserts that the specified value is true. -// -// a.True(myBool) -func (a *Assertions) True(value bool, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - True(a.t, value, msgAndArgs...) -} - -// Truef asserts that the specified value is true. -// -// a.Truef(myBool, "error message %s", "formatted") -func (a *Assertions) Truef(value bool, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Truef(a.t, value, msg, args...) -} - -// WithinDuration asserts that the two times are within duration delta of each other. -// -// a.WithinDuration(time.Now(), time.Now(), 10*time.Second) -func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - WithinDuration(a.t, expected, actual, delta, msgAndArgs...) -} - -// WithinDurationf asserts that the two times are within duration delta of each other. -// -// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") -func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - WithinDurationf(a.t, expected, actual, delta, msg, args...) -} - -// WithinRange asserts that a time is within a time range (inclusive). -// -// a.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) -func (a *Assertions) WithinRange(actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - WithinRange(a.t, actual, start, end, msgAndArgs...) -} - -// WithinRangef asserts that a time is within a time range (inclusive). -// -// a.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") -func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - WithinRangef(a.t, actual, start, end, msg, args...) -} - -// YAMLEq asserts that two YAML strings are equivalent. -func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - YAMLEq(a.t, expected, actual, msgAndArgs...) -} - -// YAMLEqf asserts that two YAML strings are equivalent. -func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - YAMLEqf(a.t, expected, actual, msg, args...) -} - -// Zero asserts that i is the zero value for its type. -func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Zero(a.t, i, msgAndArgs...) -} - -// Zerof asserts that i is the zero value for its type. -func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Zerof(a.t, i, msg, args...) -} diff --git a/go/sdk/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl b/go/sdk/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl deleted file mode 100644 index 54124df..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl +++ /dev/null @@ -1,5 +0,0 @@ -{{.CommentWithoutT "a"}} -func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) { - if h, ok := a.t.(tHelper); ok { h.Helper() } - {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) -} diff --git a/go/sdk/vendor/github.com/stretchr/testify/require/requirements.go b/go/sdk/vendor/github.com/stretchr/testify/require/requirements.go deleted file mode 100644 index 6b7ce92..0000000 --- a/go/sdk/vendor/github.com/stretchr/testify/require/requirements.go +++ /dev/null @@ -1,29 +0,0 @@ -package require - -// TestingT is an interface wrapper around *testing.T -type TestingT interface { - Errorf(format string, args ...interface{}) - FailNow() -} - -type tHelper = interface { - Helper() -} - -// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful -// for table driven tests. -type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) - -// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful -// for table driven tests. -type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) - -// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful -// for table driven tests. -type BoolAssertionFunc func(TestingT, bool, ...interface{}) - -// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful -// for table driven tests. -type ErrorAssertionFunc func(TestingT, error, ...interface{}) - -//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=require -template=require.go.tmpl -include-format-funcs" diff --git a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/LICENSE b/go/sdk/vendor/github.com/yosida95/uritemplate/v3/LICENSE deleted file mode 100644 index 79e8f87..0000000 --- a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (C) 2016, Kohei YOSHIDA . All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/README.rst b/go/sdk/vendor/github.com/yosida95/uritemplate/v3/README.rst deleted file mode 100644 index 6815d0a..0000000 --- a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/README.rst +++ /dev/null @@ -1,46 +0,0 @@ -uritemplate -=========== - -`uritemplate`_ is a Go implementation of `URI Template`_ [RFC6570] with -full functionality of URI Template Level 4. - -uritemplate can also generate a regexp that matches expansion of the -URI Template from a URI Template. - -Getting Started ---------------- - -Installation -~~~~~~~~~~~~ - -.. code-block:: sh - - $ go get -u github.com/yosida95/uritemplate/v3 - -Documentation -~~~~~~~~~~~~~ - -The documentation is available on GoDoc_. - -Examples --------- - -See `examples on GoDoc`_. - -License -------- - -`uritemplate`_ is distributed under the BSD 3-Clause license. -PLEASE READ ./LICENSE carefully and follow its clauses to use this software. - -Author ------- - -yosida95_ - - -.. _`URI Template`: https://tools.ietf.org/html/rfc6570 -.. _Godoc: https://godoc.org/github.com/yosida95/uritemplate -.. _`examples on GoDoc`: https://godoc.org/github.com/yosida95/uritemplate#pkg-examples -.. _yosida95: https://yosida95.com/ -.. _uritemplate: https://github.com/yosida95/uritemplate diff --git a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/compile.go b/go/sdk/vendor/github.com/yosida95/uritemplate/v3/compile.go deleted file mode 100644 index bd774d1..0000000 --- a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/compile.go +++ /dev/null @@ -1,224 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -import ( - "fmt" - "unicode/utf8" -) - -type compiler struct { - prog *prog -} - -func (c *compiler) init() { - c.prog = &prog{} -} - -func (c *compiler) op(opcode progOpcode) uint32 { - i := len(c.prog.op) - c.prog.op = append(c.prog.op, progOp{code: opcode}) - return uint32(i) -} - -func (c *compiler) opWithRune(opcode progOpcode, r rune) uint32 { - addr := c.op(opcode) - (&c.prog.op[addr]).r = r - return addr -} - -func (c *compiler) opWithRuneClass(opcode progOpcode, rc runeClass) uint32 { - addr := c.op(opcode) - (&c.prog.op[addr]).rc = rc - return addr -} - -func (c *compiler) opWithAddr(opcode progOpcode, absaddr uint32) uint32 { - addr := c.op(opcode) - (&c.prog.op[addr]).i = absaddr - return addr -} - -func (c *compiler) opWithAddrDelta(opcode progOpcode, delta uint32) uint32 { - return c.opWithAddr(opcode, uint32(len(c.prog.op))+delta) -} - -func (c *compiler) opWithName(opcode progOpcode, name string) uint32 { - addr := c.op(opcode) - (&c.prog.op[addr]).name = name - return addr -} - -func (c *compiler) compileString(str string) { - for i := 0; i < len(str); { - // NOTE(yosida95): It is confirmed at parse time that literals - // consist of only valid-UTF8 runes. - r, size := utf8.DecodeRuneInString(str[i:]) - c.opWithRune(opRune, r) - i += size - } -} - -func (c *compiler) compileRuneClass(rc runeClass, maxlen int) { - for i := 0; i < maxlen; i++ { - if i > 0 { - c.opWithAddrDelta(opSplit, 7) - } - c.opWithAddrDelta(opSplit, 3) // raw rune or pct-encoded - c.opWithRuneClass(opRuneClass, rc) // raw rune - c.opWithAddrDelta(opJmp, 4) // - c.opWithRune(opRune, '%') // pct-encoded - c.opWithRuneClass(opRuneClass, runeClassPctE) // - c.opWithRuneClass(opRuneClass, runeClassPctE) // - } -} - -func (c *compiler) compileRuneClassInfinite(rc runeClass) { - start := c.opWithAddrDelta(opSplit, 3) // raw rune or pct-encoded - c.opWithRuneClass(opRuneClass, rc) // raw rune - c.opWithAddrDelta(opJmp, 4) // - c.opWithRune(opRune, '%') // pct-encoded - c.opWithRuneClass(opRuneClass, runeClassPctE) // - c.opWithRuneClass(opRuneClass, runeClassPctE) // - c.opWithAddrDelta(opSplit, 2) // loop - c.opWithAddr(opJmp, start) // -} - -func (c *compiler) compileVarspecValue(spec varspec, expr *expression) { - var specname string - if spec.maxlen > 0 { - specname = fmt.Sprintf("%s:%d", spec.name, spec.maxlen) - } else { - specname = spec.name - } - - c.prog.numCap++ - - c.opWithName(opCapStart, specname) - - split := c.op(opSplit) - if spec.maxlen > 0 { - c.compileRuneClass(expr.allow, spec.maxlen) - } else { - c.compileRuneClassInfinite(expr.allow) - } - - capEnd := c.opWithName(opCapEnd, specname) - c.prog.op[split].i = capEnd -} - -func (c *compiler) compileVarspec(spec varspec, expr *expression) { - switch { - case expr.named && spec.explode: - split1 := c.op(opSplit) - noop := c.op(opNoop) - c.compileString(spec.name) - - split2 := c.op(opSplit) - c.opWithRune(opRune, '=') - c.compileVarspecValue(spec, expr) - - split3 := c.op(opSplit) - c.compileString(expr.sep) - c.opWithAddr(opJmp, noop) - - c.prog.op[split2].i = uint32(len(c.prog.op)) - c.compileString(expr.ifemp) - c.opWithAddr(opJmp, split3) - - c.prog.op[split1].i = uint32(len(c.prog.op)) - c.prog.op[split3].i = uint32(len(c.prog.op)) - - case expr.named && !spec.explode: - c.compileString(spec.name) - - split2 := c.op(opSplit) - c.opWithRune(opRune, '=') - - split3 := c.op(opSplit) - - split4 := c.op(opSplit) - c.compileVarspecValue(spec, expr) - - split5 := c.op(opSplit) - c.prog.op[split4].i = split5 - c.compileString(",") - c.opWithAddr(opJmp, split4) - - c.prog.op[split3].i = uint32(len(c.prog.op)) - c.compileString(",") - jmp1 := c.op(opJmp) - - c.prog.op[split2].i = uint32(len(c.prog.op)) - c.compileString(expr.ifemp) - - c.prog.op[split5].i = uint32(len(c.prog.op)) - c.prog.op[jmp1].i = uint32(len(c.prog.op)) - - case !expr.named: - start := uint32(len(c.prog.op)) - c.compileVarspecValue(spec, expr) - - split1 := c.op(opSplit) - jmp := c.op(opJmp) - - c.prog.op[split1].i = uint32(len(c.prog.op)) - if spec.explode { - c.compileString(expr.sep) - } else { - c.opWithRune(opRune, ',') - } - c.opWithAddr(opJmp, start) - - c.prog.op[jmp].i = uint32(len(c.prog.op)) - } -} - -func (c *compiler) compileExpression(expr *expression) { - if len(expr.vars) < 1 { - return - } - - split1 := c.op(opSplit) - c.compileString(expr.first) - - for i, size := 0, len(expr.vars); i < size; i++ { - spec := expr.vars[i] - - split2 := c.op(opSplit) - if i > 0 { - split3 := c.op(opSplit) - c.compileString(expr.sep) - c.prog.op[split3].i = uint32(len(c.prog.op)) - } - c.compileVarspec(spec, expr) - c.prog.op[split2].i = uint32(len(c.prog.op)) - } - - c.prog.op[split1].i = uint32(len(c.prog.op)) -} - -func (c *compiler) compileLiterals(lt literals) { - c.compileString(string(lt)) -} - -func (c *compiler) compile(tmpl *Template) { - c.op(opLineBegin) - for i := range tmpl.exprs { - expr := tmpl.exprs[i] - switch expr := expr.(type) { - default: - panic("unhandled expression") - case *expression: - c.compileExpression(expr) - case literals: - c.compileLiterals(expr) - } - } - c.op(opLineEnd) - c.op(opEnd) -} diff --git a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/equals.go b/go/sdk/vendor/github.com/yosida95/uritemplate/v3/equals.go deleted file mode 100644 index aa59a5c..0000000 --- a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/equals.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -type CompareFlags uint8 - -const ( - CompareVarname CompareFlags = 1 << iota -) - -// Equals reports whether or not two URI Templates t1 and t2 are equivalent. -func Equals(t1 *Template, t2 *Template, flags CompareFlags) bool { - if len(t1.exprs) != len(t2.exprs) { - return false - } - for i := 0; i < len(t1.exprs); i++ { - switch t1 := t1.exprs[i].(type) { - case literals: - t2, ok := t2.exprs[i].(literals) - if !ok { - return false - } - if t1 != t2 { - return false - } - case *expression: - t2, ok := t2.exprs[i].(*expression) - if !ok { - return false - } - if t1.op != t2.op || len(t1.vars) != len(t2.vars) { - return false - } - for n := 0; n < len(t1.vars); n++ { - v1 := t1.vars[n] - v2 := t2.vars[n] - if flags&CompareVarname == CompareVarname && v1.name != v2.name { - return false - } - if v1.maxlen != v2.maxlen || v1.explode != v2.explode { - return false - } - } - default: - panic("unhandled case") - } - } - return true -} diff --git a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/error.go b/go/sdk/vendor/github.com/yosida95/uritemplate/v3/error.go deleted file mode 100644 index 2fd34a8..0000000 --- a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/error.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -import ( - "fmt" -) - -func errorf(pos int, format string, a ...interface{}) error { - msg := fmt.Sprintf(format, a...) - return fmt.Errorf("uritemplate:%d:%s", pos, msg) -} diff --git a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/escape.go b/go/sdk/vendor/github.com/yosida95/uritemplate/v3/escape.go deleted file mode 100644 index 6d27e69..0000000 --- a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/escape.go +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -import ( - "strings" - "unicode" - "unicode/utf8" -) - -var ( - hex = []byte("0123456789ABCDEF") - // reserved = gen-delims / sub-delims - // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" - // sub-delims = "!" / "$" / "&" / "’" / "(" / ")" - // / "*" / "+" / "," / ";" / "=" - rangeReserved = &unicode.RangeTable{ - R16: []unicode.Range16{ - {Lo: 0x21, Hi: 0x21, Stride: 1}, // '!' - {Lo: 0x23, Hi: 0x24, Stride: 1}, // '#' - '$' - {Lo: 0x26, Hi: 0x2C, Stride: 1}, // '&' - ',' - {Lo: 0x2F, Hi: 0x2F, Stride: 1}, // '/' - {Lo: 0x3A, Hi: 0x3B, Stride: 1}, // ':' - ';' - {Lo: 0x3D, Hi: 0x3D, Stride: 1}, // '=' - {Lo: 0x3F, Hi: 0x40, Stride: 1}, // '?' - '@' - {Lo: 0x5B, Hi: 0x5B, Stride: 1}, // '[' - {Lo: 0x5D, Hi: 0x5D, Stride: 1}, // ']' - }, - LatinOffset: 9, - } - reReserved = `\x21\x23\x24\x26-\x2c\x2f\x3a\x3b\x3d\x3f\x40\x5b\x5d` - // ALPHA = %x41-5A / %x61-7A - // DIGIT = %x30-39 - // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - rangeUnreserved = &unicode.RangeTable{ - R16: []unicode.Range16{ - {Lo: 0x2D, Hi: 0x2E, Stride: 1}, // '-' - '.' - {Lo: 0x30, Hi: 0x39, Stride: 1}, // '0' - '9' - {Lo: 0x41, Hi: 0x5A, Stride: 1}, // 'A' - 'Z' - {Lo: 0x5F, Hi: 0x5F, Stride: 1}, // '_' - {Lo: 0x61, Hi: 0x7A, Stride: 1}, // 'a' - 'z' - {Lo: 0x7E, Hi: 0x7E, Stride: 1}, // '~' - }, - } - reUnreserved = `\x2d\x2e\x30-\x39\x41-\x5a\x5f\x61-\x7a\x7e` -) - -type runeClass uint8 - -const ( - runeClassU runeClass = 1 << iota - runeClassR - runeClassPctE - runeClassLast - - runeClassUR = runeClassU | runeClassR -) - -var runeClassNames = []string{ - "U", - "R", - "pct-encoded", -} - -func (rc runeClass) String() string { - ret := make([]string, 0, len(runeClassNames)) - for i, j := 0, runeClass(1); j < runeClassLast; j <<= 1 { - if rc&j == j { - ret = append(ret, runeClassNames[i]) - } - i++ - } - return strings.Join(ret, "+") -} - -func pctEncode(w *strings.Builder, r rune) { - if s := r >> 24 & 0xff; s > 0 { - w.Write([]byte{'%', hex[s/16], hex[s%16]}) - } - if s := r >> 16 & 0xff; s > 0 { - w.Write([]byte{'%', hex[s/16], hex[s%16]}) - } - if s := r >> 8 & 0xff; s > 0 { - w.Write([]byte{'%', hex[s/16], hex[s%16]}) - } - if s := r & 0xff; s > 0 { - w.Write([]byte{'%', hex[s/16], hex[s%16]}) - } -} - -func unhex(c byte) byte { - switch { - case '0' <= c && c <= '9': - return c - '0' - case 'a' <= c && c <= 'f': - return c - 'a' + 10 - case 'A' <= c && c <= 'F': - return c - 'A' + 10 - } - return 0 -} - -func ishex(c byte) bool { - switch { - case '0' <= c && c <= '9': - return true - case 'a' <= c && c <= 'f': - return true - case 'A' <= c && c <= 'F': - return true - default: - return false - } -} - -func pctDecode(s string) string { - size := len(s) - for i := 0; i < len(s); { - switch s[i] { - case '%': - size -= 2 - i += 3 - default: - i++ - } - } - if size == len(s) { - return s - } - - buf := make([]byte, size) - j := 0 - for i := 0; i < len(s); { - switch c := s[i]; c { - case '%': - buf[j] = unhex(s[i+1])<<4 | unhex(s[i+2]) - i += 3 - j++ - default: - buf[j] = c - i++ - j++ - } - } - return string(buf) -} - -type escapeFunc func(*strings.Builder, string) error - -func escapeLiteral(w *strings.Builder, v string) error { - w.WriteString(v) - return nil -} - -func escapeExceptU(w *strings.Builder, v string) error { - for i := 0; i < len(v); { - r, size := utf8.DecodeRuneInString(v[i:]) - if r == utf8.RuneError { - return errorf(i, "invalid encoding") - } - if unicode.Is(rangeUnreserved, r) { - w.WriteRune(r) - } else { - pctEncode(w, r) - } - i += size - } - return nil -} - -func escapeExceptUR(w *strings.Builder, v string) error { - for i := 0; i < len(v); { - r, size := utf8.DecodeRuneInString(v[i:]) - if r == utf8.RuneError { - return errorf(i, "invalid encoding") - } - // TODO(yosida95): is pct-encoded triplets allowed here? - if unicode.In(r, rangeUnreserved, rangeReserved) { - w.WriteRune(r) - } else { - pctEncode(w, r) - } - i += size - } - return nil -} diff --git a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/expression.go b/go/sdk/vendor/github.com/yosida95/uritemplate/v3/expression.go deleted file mode 100644 index 4858c2d..0000000 --- a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/expression.go +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -import ( - "regexp" - "strconv" - "strings" -) - -type template interface { - expand(*strings.Builder, Values) error - regexp(*strings.Builder) -} - -type literals string - -func (l literals) expand(b *strings.Builder, _ Values) error { - b.WriteString(string(l)) - return nil -} - -func (l literals) regexp(b *strings.Builder) { - b.WriteString("(?:") - b.WriteString(regexp.QuoteMeta(string(l))) - b.WriteByte(')') -} - -type varspec struct { - name string - maxlen int - explode bool -} - -type expression struct { - vars []varspec - op parseOp - first string - sep string - named bool - ifemp string - escape escapeFunc - allow runeClass -} - -func (e *expression) init() { - switch e.op { - case parseOpSimple: - e.sep = "," - e.escape = escapeExceptU - e.allow = runeClassU - case parseOpPlus: - e.sep = "," - e.escape = escapeExceptUR - e.allow = runeClassUR - case parseOpCrosshatch: - e.first = "#" - e.sep = "," - e.escape = escapeExceptUR - e.allow = runeClassUR - case parseOpDot: - e.first = "." - e.sep = "." - e.escape = escapeExceptU - e.allow = runeClassU - case parseOpSlash: - e.first = "/" - e.sep = "/" - e.escape = escapeExceptU - e.allow = runeClassU - case parseOpSemicolon: - e.first = ";" - e.sep = ";" - e.named = true - e.escape = escapeExceptU - e.allow = runeClassU - case parseOpQuestion: - e.first = "?" - e.sep = "&" - e.named = true - e.ifemp = "=" - e.escape = escapeExceptU - e.allow = runeClassU - case parseOpAmpersand: - e.first = "&" - e.sep = "&" - e.named = true - e.ifemp = "=" - e.escape = escapeExceptU - e.allow = runeClassU - } -} - -func (e *expression) expand(w *strings.Builder, values Values) error { - first := true - for _, varspec := range e.vars { - value := values.Get(varspec.name) - if !value.Valid() { - continue - } - - if first { - w.WriteString(e.first) - first = false - } else { - w.WriteString(e.sep) - } - - if err := value.expand(w, varspec, e); err != nil { - return err - } - - } - return nil -} - -func (e *expression) regexp(b *strings.Builder) { - if e.first != "" { - b.WriteString("(?:") // $1 - b.WriteString(regexp.QuoteMeta(e.first)) - } - b.WriteByte('(') // $2 - runeClassToRegexp(b, e.allow, e.named || e.vars[0].explode) - if len(e.vars) > 1 || e.vars[0].explode { - max := len(e.vars) - 1 - for i := 0; i < len(e.vars); i++ { - if e.vars[i].explode { - max = -1 - break - } - } - - b.WriteString("(?:") // $3 - b.WriteString(regexp.QuoteMeta(e.sep)) - runeClassToRegexp(b, e.allow, e.named || max < 0) - b.WriteByte(')') // $3 - if max > 0 { - b.WriteString("{0,") - b.WriteString(strconv.Itoa(max)) - b.WriteByte('}') - } else { - b.WriteByte('*') - } - } - b.WriteByte(')') // $2 - if e.first != "" { - b.WriteByte(')') // $1 - } - b.WriteByte('?') -} - -func runeClassToRegexp(b *strings.Builder, class runeClass, named bool) { - b.WriteString("(?:(?:[") - if class&runeClassR == 0 { - b.WriteString(`\x2c`) - if named { - b.WriteString(`\x3d`) - } - } - if class&runeClassU == runeClassU { - b.WriteString(reUnreserved) - } - if class&runeClassR == runeClassR { - b.WriteString(reReserved) - } - b.WriteString("]") - b.WriteString("|%[[:xdigit:]][[:xdigit:]]") - b.WriteString(")*)") -} diff --git a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/machine.go b/go/sdk/vendor/github.com/yosida95/uritemplate/v3/machine.go deleted file mode 100644 index 7b1d0b5..0000000 --- a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/machine.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -// threadList implements https://research.swtch.com/sparse. -type threadList struct { - dense []threadEntry - sparse []uint32 -} - -type threadEntry struct { - pc uint32 - t *thread -} - -type thread struct { - op *progOp - cap map[string][]int -} diff --git a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/match.go b/go/sdk/vendor/github.com/yosida95/uritemplate/v3/match.go deleted file mode 100644 index 02fe638..0000000 --- a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/match.go +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -import ( - "bytes" - "unicode" - "unicode/utf8" -) - -type matcher struct { - prog *prog - - list1 threadList - list2 threadList - matched bool - cap map[string][]int - - input string -} - -func (m *matcher) at(pos int) (rune, int, bool) { - if l := len(m.input); pos < l { - c := m.input[pos] - if c < utf8.RuneSelf { - return rune(c), 1, pos+1 < l - } - r, size := utf8.DecodeRuneInString(m.input[pos:]) - return r, size, pos+size < l - } - return -1, 0, false -} - -func (m *matcher) add(list *threadList, pc uint32, pos int, next bool, cap map[string][]int) { - if i := list.sparse[pc]; i < uint32(len(list.dense)) && list.dense[i].pc == pc { - return - } - - n := len(list.dense) - list.dense = list.dense[:n+1] - list.sparse[pc] = uint32(n) - - e := &list.dense[n] - e.pc = pc - e.t = nil - - op := &m.prog.op[pc] - switch op.code { - default: - panic("unhandled opcode") - case opRune, opRuneClass, opEnd: - e.t = &thread{ - op: &m.prog.op[pc], - cap: make(map[string][]int, len(m.cap)), - } - for k, v := range cap { - e.t.cap[k] = make([]int, len(v)) - copy(e.t.cap[k], v) - } - case opLineBegin: - if pos == 0 { - m.add(list, pc+1, pos, next, cap) - } - case opLineEnd: - if !next { - m.add(list, pc+1, pos, next, cap) - } - case opCapStart, opCapEnd: - ocap := make(map[string][]int, len(m.cap)) - for k, v := range cap { - ocap[k] = make([]int, len(v)) - copy(ocap[k], v) - } - ocap[op.name] = append(ocap[op.name], pos) - m.add(list, pc+1, pos, next, ocap) - case opSplit: - m.add(list, pc+1, pos, next, cap) - m.add(list, op.i, pos, next, cap) - case opJmp: - m.add(list, op.i, pos, next, cap) - case opJmpIfNotDefined: - m.add(list, pc+1, pos, next, cap) - m.add(list, op.i, pos, next, cap) - case opJmpIfNotFirst: - m.add(list, pc+1, pos, next, cap) - m.add(list, op.i, pos, next, cap) - case opJmpIfNotEmpty: - m.add(list, op.i, pos, next, cap) - m.add(list, pc+1, pos, next, cap) - case opNoop: - m.add(list, pc+1, pos, next, cap) - } -} - -func (m *matcher) step(clist *threadList, nlist *threadList, r rune, pos int, nextPos int, next bool) { - debug.Printf("===== %q =====", string(r)) - for i := 0; i < len(clist.dense); i++ { - e := clist.dense[i] - if debug { - var buf bytes.Buffer - dumpProg(&buf, m.prog, e.pc) - debug.Printf("\n%s", buf.String()) - } - if e.t == nil { - continue - } - - t := e.t - op := t.op - switch op.code { - default: - panic("unhandled opcode") - case opRune: - if op.r == r { - m.add(nlist, e.pc+1, nextPos, next, t.cap) - } - case opRuneClass: - ret := false - if !ret && op.rc&runeClassU == runeClassU { - ret = ret || unicode.Is(rangeUnreserved, r) - } - if !ret && op.rc&runeClassR == runeClassR { - ret = ret || unicode.Is(rangeReserved, r) - } - if !ret && op.rc&runeClassPctE == runeClassPctE { - ret = ret || unicode.Is(unicode.ASCII_Hex_Digit, r) - } - if ret { - m.add(nlist, e.pc+1, nextPos, next, t.cap) - } - case opEnd: - m.matched = true - for k, v := range t.cap { - m.cap[k] = make([]int, len(v)) - copy(m.cap[k], v) - } - clist.dense = clist.dense[:0] - } - } - clist.dense = clist.dense[:0] -} - -func (m *matcher) match() bool { - pos := 0 - clist, nlist := &m.list1, &m.list2 - for { - if len(clist.dense) == 0 && m.matched { - break - } - r, width, next := m.at(pos) - if !m.matched { - m.add(clist, 0, pos, next, m.cap) - } - m.step(clist, nlist, r, pos, pos+width, next) - - if width < 1 { - break - } - pos += width - - clist, nlist = nlist, clist - } - return m.matched -} - -func (tmpl *Template) Match(expansion string) Values { - tmpl.mu.Lock() - if tmpl.prog == nil { - c := compiler{} - c.init() - c.compile(tmpl) - tmpl.prog = c.prog - } - prog := tmpl.prog - tmpl.mu.Unlock() - - n := len(prog.op) - m := matcher{ - prog: prog, - list1: threadList{ - dense: make([]threadEntry, 0, n), - sparse: make([]uint32, n), - }, - list2: threadList{ - dense: make([]threadEntry, 0, n), - sparse: make([]uint32, n), - }, - cap: make(map[string][]int, prog.numCap), - input: expansion, - } - if !m.match() { - return nil - } - - match := make(Values, len(m.cap)) - for name, indices := range m.cap { - v := Value{V: make([]string, len(indices)/2)} - for i := range v.V { - v.V[i] = pctDecode(expansion[indices[2*i]:indices[2*i+1]]) - } - if len(v.V) == 1 { - v.T = ValueTypeString - } else { - v.T = ValueTypeList - } - match[name] = v - } - return match -} diff --git a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/parse.go b/go/sdk/vendor/github.com/yosida95/uritemplate/v3/parse.go deleted file mode 100644 index fd38a68..0000000 --- a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/parse.go +++ /dev/null @@ -1,277 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -import ( - "fmt" - "unicode" - "unicode/utf8" -) - -type parseOp int - -const ( - parseOpSimple parseOp = iota - parseOpPlus - parseOpCrosshatch - parseOpDot - parseOpSlash - parseOpSemicolon - parseOpQuestion - parseOpAmpersand -) - -var ( - rangeVarchar = &unicode.RangeTable{ - R16: []unicode.Range16{ - {Lo: 0x0030, Hi: 0x0039, Stride: 1}, // '0' - '9' - {Lo: 0x0041, Hi: 0x005A, Stride: 1}, // 'A' - 'Z' - {Lo: 0x005F, Hi: 0x005F, Stride: 1}, // '_' - {Lo: 0x0061, Hi: 0x007A, Stride: 1}, // 'a' - 'z' - }, - LatinOffset: 4, - } - rangeLiterals = &unicode.RangeTable{ - R16: []unicode.Range16{ - {Lo: 0x0021, Hi: 0x0021, Stride: 1}, // '!' - {Lo: 0x0023, Hi: 0x0024, Stride: 1}, // '#' - '$' - {Lo: 0x0026, Hi: 0x003B, Stride: 1}, // '&' ''' '(' - ';'. '''/27 used to be excluded but an errata is in the review process https://www.rfc-editor.org/errata/eid6937 - {Lo: 0x003D, Hi: 0x003D, Stride: 1}, // '=' - {Lo: 0x003F, Hi: 0x005B, Stride: 1}, // '?' - '[' - {Lo: 0x005D, Hi: 0x005D, Stride: 1}, // ']' - {Lo: 0x005F, Hi: 0x005F, Stride: 1}, // '_' - {Lo: 0x0061, Hi: 0x007A, Stride: 1}, // 'a' - 'z' - {Lo: 0x007E, Hi: 0x007E, Stride: 1}, // '~' - {Lo: 0x00A0, Hi: 0xD7FF, Stride: 1}, // ucschar - {Lo: 0xE000, Hi: 0xF8FF, Stride: 1}, // iprivate - {Lo: 0xF900, Hi: 0xFDCF, Stride: 1}, // ucschar - {Lo: 0xFDF0, Hi: 0xFFEF, Stride: 1}, // ucschar - }, - R32: []unicode.Range32{ - {Lo: 0x00010000, Hi: 0x0001FFFD, Stride: 1}, // ucschar - {Lo: 0x00020000, Hi: 0x0002FFFD, Stride: 1}, // ucschar - {Lo: 0x00030000, Hi: 0x0003FFFD, Stride: 1}, // ucschar - {Lo: 0x00040000, Hi: 0x0004FFFD, Stride: 1}, // ucschar - {Lo: 0x00050000, Hi: 0x0005FFFD, Stride: 1}, // ucschar - {Lo: 0x00060000, Hi: 0x0006FFFD, Stride: 1}, // ucschar - {Lo: 0x00070000, Hi: 0x0007FFFD, Stride: 1}, // ucschar - {Lo: 0x00080000, Hi: 0x0008FFFD, Stride: 1}, // ucschar - {Lo: 0x00090000, Hi: 0x0009FFFD, Stride: 1}, // ucschar - {Lo: 0x000A0000, Hi: 0x000AFFFD, Stride: 1}, // ucschar - {Lo: 0x000B0000, Hi: 0x000BFFFD, Stride: 1}, // ucschar - {Lo: 0x000C0000, Hi: 0x000CFFFD, Stride: 1}, // ucschar - {Lo: 0x000D0000, Hi: 0x000DFFFD, Stride: 1}, // ucschar - {Lo: 0x000E1000, Hi: 0x000EFFFD, Stride: 1}, // ucschar - {Lo: 0x000F0000, Hi: 0x000FFFFD, Stride: 1}, // iprivate - {Lo: 0x00100000, Hi: 0x0010FFFD, Stride: 1}, // iprivate - }, - LatinOffset: 10, - } -) - -type parser struct { - r string - start int - stop int - state parseState -} - -func (p *parser) errorf(i rune, format string, a ...interface{}) error { - return fmt.Errorf("%s: %s%s", fmt.Sprintf(format, a...), p.r[0:p.stop], string(i)) -} - -func (p *parser) rune() (rune, int) { - r, size := utf8.DecodeRuneInString(p.r[p.stop:]) - if r != utf8.RuneError { - p.stop += size - } - return r, size -} - -func (p *parser) unread(r rune) { - p.stop -= utf8.RuneLen(r) -} - -type parseState int - -const ( - parseStateDefault = parseState(iota) - parseStateOperator - parseStateVarList - parseStateVarName - parseStatePrefix -) - -func (p *parser) setState(state parseState) { - p.state = state - p.start = p.stop -} - -func (p *parser) parseURITemplate() (*Template, error) { - tmpl := Template{ - raw: p.r, - exprs: []template{}, - } - - var exp *expression - for { - r, size := p.rune() - if r == utf8.RuneError { - if size == 0 { - if p.state != parseStateDefault { - return nil, p.errorf('_', "incomplete expression") - } - if p.start < p.stop { - tmpl.exprs = append(tmpl.exprs, literals(p.r[p.start:p.stop])) - } - return &tmpl, nil - } - return nil, p.errorf('_', "invalid UTF-8 sequence") - } - - switch p.state { - case parseStateDefault: - switch r { - case '{': - if stop := p.stop - size; stop > p.start { - tmpl.exprs = append(tmpl.exprs, literals(p.r[p.start:stop])) - } - exp = &expression{} - tmpl.exprs = append(tmpl.exprs, exp) - p.setState(parseStateOperator) - case '%': - p.unread(r) - if err := p.consumeTriplet(); err != nil { - return nil, err - } - default: - if !unicode.Is(rangeLiterals, r) { - p.unread(r) - return nil, p.errorf('_', "unacceptable character (hint: use %%XX encoding)") - } - } - case parseStateOperator: - switch r { - default: - p.unread(r) - exp.op = parseOpSimple - case '+': - exp.op = parseOpPlus - case '#': - exp.op = parseOpCrosshatch - case '.': - exp.op = parseOpDot - case '/': - exp.op = parseOpSlash - case ';': - exp.op = parseOpSemicolon - case '?': - exp.op = parseOpQuestion - case '&': - exp.op = parseOpAmpersand - case '=', ',', '!', '@', '|': // op-reserved - return nil, p.errorf('|', "unimplemented operator (op-reserved)") - } - p.setState(parseStateVarName) - case parseStateVarList: - switch r { - case ',': - p.setState(parseStateVarName) - case '}': - exp.init() - p.setState(parseStateDefault) - default: - p.unread(r) - return nil, p.errorf('_', "unrecognized value modifier") - } - case parseStateVarName: - switch r { - case ':', '*': - name := p.r[p.start : p.stop-size] - if !isValidVarname(name) { - return nil, p.errorf('|', "unacceptable variable name") - } - explode := r == '*' - exp.vars = append(exp.vars, varspec{ - name: name, - explode: explode, - }) - if explode { - p.setState(parseStateVarList) - } else { - p.setState(parseStatePrefix) - } - case ',', '}': - p.unread(r) - name := p.r[p.start:p.stop] - if !isValidVarname(name) { - return nil, p.errorf('|', "unacceptable variable name") - } - exp.vars = append(exp.vars, varspec{ - name: name, - }) - p.setState(parseStateVarList) - case '%': - p.unread(r) - if err := p.consumeTriplet(); err != nil { - return nil, err - } - case '.': - if dot := p.stop - size; dot == p.start || p.r[dot-1] == '.' { - return nil, p.errorf('|', "unacceptable variable name") - } - default: - if !unicode.Is(rangeVarchar, r) { - p.unread(r) - return nil, p.errorf('_', "unacceptable variable name") - } - } - case parseStatePrefix: - spec := &(exp.vars[len(exp.vars)-1]) - switch { - case '0' <= r && r <= '9': - spec.maxlen *= 10 - spec.maxlen += int(r - '0') - if spec.maxlen == 0 || spec.maxlen > 9999 { - return nil, p.errorf('|', "max-length must be (0, 9999]") - } - default: - p.unread(r) - if spec.maxlen == 0 { - return nil, p.errorf('_', "max-length must be (0, 9999]") - } - p.setState(parseStateVarList) - } - default: - p.unread(r) - panic(p.errorf('_', "unhandled parseState(%d)", p.state)) - } - } -} - -func isValidVarname(name string) bool { - if l := len(name); l == 0 || name[0] == '.' || name[l-1] == '.' { - return false - } - for i := 1; i < len(name)-1; i++ { - switch c := name[i]; c { - case '.': - if name[i-1] == '.' { - return false - } - } - } - return true -} - -func (p *parser) consumeTriplet() error { - if len(p.r)-p.stop < 3 || p.r[p.stop] != '%' || !ishex(p.r[p.stop+1]) || !ishex(p.r[p.stop+2]) { - return p.errorf('_', "incomplete pct-encodeed") - } - p.stop += 3 - return nil -} diff --git a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/prog.go b/go/sdk/vendor/github.com/yosida95/uritemplate/v3/prog.go deleted file mode 100644 index 97af4f0..0000000 --- a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/prog.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -import ( - "bytes" - "strconv" -) - -type progOpcode uint16 - -const ( - // match - opRune progOpcode = iota - opRuneClass - opLineBegin - opLineEnd - // capture - opCapStart - opCapEnd - // stack - opSplit - opJmp - opJmpIfNotDefined - opJmpIfNotEmpty - opJmpIfNotFirst - // result - opEnd - // fake - opNoop - opcodeMax -) - -var opcodeNames = []string{ - // match - "opRune", - "opRuneClass", - "opLineBegin", - "opLineEnd", - // capture - "opCapStart", - "opCapEnd", - // stack - "opSplit", - "opJmp", - "opJmpIfNotDefined", - "opJmpIfNotEmpty", - "opJmpIfNotFirst", - // result - "opEnd", -} - -func (code progOpcode) String() string { - if code >= opcodeMax { - return "" - } - return opcodeNames[code] -} - -type progOp struct { - code progOpcode - r rune - rc runeClass - i uint32 - - name string -} - -func dumpProgOp(b *bytes.Buffer, op *progOp) { - b.WriteString(op.code.String()) - switch op.code { - case opRune: - b.WriteString("(") - b.WriteString(strconv.QuoteToASCII(string(op.r))) - b.WriteString(")") - case opRuneClass: - b.WriteString("(") - b.WriteString(op.rc.String()) - b.WriteString(")") - case opCapStart, opCapEnd: - b.WriteString("(") - b.WriteString(strconv.QuoteToASCII(op.name)) - b.WriteString(")") - case opSplit: - b.WriteString(" -> ") - b.WriteString(strconv.FormatInt(int64(op.i), 10)) - case opJmp, opJmpIfNotFirst: - b.WriteString(" -> ") - b.WriteString(strconv.FormatInt(int64(op.i), 10)) - case opJmpIfNotDefined, opJmpIfNotEmpty: - b.WriteString("(") - b.WriteString(strconv.QuoteToASCII(op.name)) - b.WriteString(")") - b.WriteString(" -> ") - b.WriteString(strconv.FormatInt(int64(op.i), 10)) - } -} - -type prog struct { - op []progOp - numCap int -} - -func dumpProg(b *bytes.Buffer, prog *prog, pc uint32) { - for i := range prog.op { - op := prog.op[i] - - pos := strconv.Itoa(i) - if uint32(i) == pc { - pos = "*" + pos - } - b.WriteString(" "[len(pos):]) - b.WriteString(pos) - - b.WriteByte('\t') - dumpProgOp(b, &op) - - b.WriteByte('\n') - } -} - -func (p *prog) String() string { - b := bytes.Buffer{} - dumpProg(&b, p, 0) - return b.String() -} diff --git a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/uritemplate.go b/go/sdk/vendor/github.com/yosida95/uritemplate/v3/uritemplate.go deleted file mode 100644 index dbd2673..0000000 --- a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/uritemplate.go +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -import ( - "log" - "regexp" - "strings" - "sync" -) - -var ( - debug = debugT(false) -) - -type debugT bool - -func (t debugT) Printf(format string, v ...interface{}) { - if t { - log.Printf(format, v...) - } -} - -// Template represents a URI Template. -type Template struct { - raw string - exprs []template - - // protects the rest of fields - mu sync.Mutex - varnames []string - re *regexp.Regexp - prog *prog -} - -// New parses and constructs a new Template instance based on the template. -// New returns an error if the template cannot be recognized. -func New(template string) (*Template, error) { - return (&parser{r: template}).parseURITemplate() -} - -// MustNew panics if the template cannot be recognized. -func MustNew(template string) *Template { - ret, err := New(template) - if err != nil { - panic(err) - } - return ret -} - -// Raw returns a raw URI template passed to New in string. -func (t *Template) Raw() string { - return t.raw -} - -// Varnames returns variable names used in the template. -func (t *Template) Varnames() []string { - t.mu.Lock() - defer t.mu.Unlock() - if t.varnames != nil { - return t.varnames - } - - reg := map[string]struct{}{} - t.varnames = []string{} - for i := range t.exprs { - expr, ok := t.exprs[i].(*expression) - if !ok { - continue - } - for _, spec := range expr.vars { - if _, ok := reg[spec.name]; ok { - continue - } - reg[spec.name] = struct{}{} - t.varnames = append(t.varnames, spec.name) - } - } - - return t.varnames -} - -// Expand returns a URI reference corresponding to the template expanded using the passed variables. -func (t *Template) Expand(vars Values) (string, error) { - var w strings.Builder - for i := range t.exprs { - expr := t.exprs[i] - if err := expr.expand(&w, vars); err != nil { - return w.String(), err - } - } - return w.String(), nil -} - -// Regexp converts the template to regexp and returns compiled *regexp.Regexp. -func (t *Template) Regexp() *regexp.Regexp { - t.mu.Lock() - defer t.mu.Unlock() - if t.re != nil { - return t.re - } - - var b strings.Builder - b.WriteByte('^') - for _, expr := range t.exprs { - expr.regexp(&b) - } - b.WriteByte('$') - t.re = regexp.MustCompile(b.String()) - - return t.re -} diff --git a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/value.go b/go/sdk/vendor/github.com/yosida95/uritemplate/v3/value.go deleted file mode 100644 index 0550eab..0000000 --- a/go/sdk/vendor/github.com/yosida95/uritemplate/v3/value.go +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -import "strings" - -// A varname containing pct-encoded characters is not the same variable as -// a varname with those same characters decoded. -// -// -- https://tools.ietf.org/html/rfc6570#section-2.3 -type Values map[string]Value - -func (v Values) Set(name string, value Value) { - v[name] = value -} - -func (v Values) Get(name string) Value { - if v == nil { - return Value{} - } - return v[name] -} - -type ValueType uint8 - -const ( - ValueTypeString = iota - ValueTypeList - ValueTypeKV - valueTypeLast -) - -var valueTypeNames = []string{ - "String", - "List", - "KV", -} - -func (vt ValueType) String() string { - if vt < valueTypeLast { - return valueTypeNames[vt] - } - return "" -} - -type Value struct { - T ValueType - V []string -} - -func (v Value) String() string { - if v.Valid() && v.T == ValueTypeString { - return v.V[0] - } - return "" -} - -func (v Value) List() []string { - if v.Valid() && v.T == ValueTypeList { - return v.V - } - return nil -} - -func (v Value) KV() []string { - if v.Valid() && v.T == ValueTypeKV { - return v.V - } - return nil -} - -func (v Value) Valid() bool { - switch v.T { - default: - return false - case ValueTypeString: - return len(v.V) > 0 - case ValueTypeList: - return len(v.V) > 0 - case ValueTypeKV: - return len(v.V) > 0 && len(v.V)%2 == 0 - } -} - -func (v Value) expand(w *strings.Builder, spec varspec, exp *expression) error { - switch v.T { - case ValueTypeString: - val := v.V[0] - var maxlen int - if max := len(val); spec.maxlen < 1 || spec.maxlen > max { - maxlen = max - } else { - maxlen = spec.maxlen - } - - if exp.named { - w.WriteString(spec.name) - if val == "" { - w.WriteString(exp.ifemp) - return nil - } - w.WriteByte('=') - } - return exp.escape(w, val[:maxlen]) - case ValueTypeList: - var sep string - if spec.explode { - sep = exp.sep - } else { - sep = "," - } - - var pre string - var preifemp string - if spec.explode && exp.named { - pre = spec.name + "=" - preifemp = spec.name + exp.ifemp - } - - if !spec.explode && exp.named { - w.WriteString(spec.name) - w.WriteByte('=') - } - for i := range v.V { - val := v.V[i] - if i > 0 { - w.WriteString(sep) - } - if val == "" { - w.WriteString(preifemp) - continue - } - w.WriteString(pre) - - if err := exp.escape(w, val); err != nil { - return err - } - } - case ValueTypeKV: - var sep string - var kvsep string - if spec.explode { - sep = exp.sep - kvsep = "=" - } else { - sep = "," - kvsep = "," - } - - var ifemp string - var kescape escapeFunc - if spec.explode && exp.named { - ifemp = exp.ifemp - kescape = escapeLiteral - } else { - ifemp = "," - kescape = exp.escape - } - - if !spec.explode && exp.named { - w.WriteString(spec.name) - w.WriteByte('=') - } - - for i := 0; i < len(v.V); i += 2 { - if i > 0 { - w.WriteString(sep) - } - if err := kescape(w, v.V[i]); err != nil { - return err - } - if v.V[i+1] == "" { - w.WriteString(ifemp) - continue - } - w.WriteString(kvsep) - - if err := exp.escape(w, v.V[i+1]); err != nil { - return err - } - } - } - return nil -} - -// String returns Value that represents string. -func String(v string) Value { - return Value{ - T: ValueTypeString, - V: []string{v}, - } -} - -// List returns Value that represents list. -func List(v ...string) Value { - return Value{ - T: ValueTypeList, - V: v, - } -} - -// KV returns Value that represents associative list. -// KV panics if len(kv) is not even. -func KV(kv ...string) Value { - if len(kv)%2 != 0 { - panic("uritemplate.go: count of the kv must be even number") - } - return Value{ - T: ValueTypeKV, - V: kv, - } -} diff --git a/go/sdk/vendor/golang.org/x/oauth2/.travis.yml b/go/sdk/vendor/golang.org/x/oauth2/.travis.yml deleted file mode 100644 index fa139db..0000000 --- a/go/sdk/vendor/golang.org/x/oauth2/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: go - -go: - - tip - -install: - - export GOPATH="$HOME/gopath" - - mkdir -p "$GOPATH/src/golang.org/x" - - mv "$TRAVIS_BUILD_DIR" "$GOPATH/src/golang.org/x/oauth2" - - go get -v -t -d golang.org/x/oauth2/... - -script: - - go test -v golang.org/x/oauth2/... diff --git a/go/sdk/vendor/golang.org/x/oauth2/CONTRIBUTING.md b/go/sdk/vendor/golang.org/x/oauth2/CONTRIBUTING.md deleted file mode 100644 index dfbed62..0000000 --- a/go/sdk/vendor/golang.org/x/oauth2/CONTRIBUTING.md +++ /dev/null @@ -1,26 +0,0 @@ -# Contributing to Go - -Go is an open source project. - -It is the work of hundreds of contributors. We appreciate your help! - -## Filing issues - -When [filing an issue](https://github.com/golang/oauth2/issues), make sure to answer these five questions: - -1. What version of Go are you using (`go version`)? -2. What operating system and processor architecture are you using? -3. What did you do? -4. What did you expect to see? -5. What did you see instead? - -General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. -The gophers there will answer or ask you to file an issue if you've tripped over a bug. - -## Contributing code - -Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) -before sending patches. - -Unless otherwise noted, the Go source files are distributed under -the BSD-style license found in the LICENSE file. diff --git a/go/sdk/vendor/golang.org/x/oauth2/LICENSE b/go/sdk/vendor/golang.org/x/oauth2/LICENSE deleted file mode 100644 index 2a7cf70..0000000 --- a/go/sdk/vendor/golang.org/x/oauth2/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright 2009 The Go Authors. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google LLC nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/go/sdk/vendor/golang.org/x/oauth2/README.md b/go/sdk/vendor/golang.org/x/oauth2/README.md deleted file mode 100644 index 48dbb9d..0000000 --- a/go/sdk/vendor/golang.org/x/oauth2/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# OAuth2 for Go - -[![Go Reference](https://pkg.go.dev/badge/golang.org/x/oauth2.svg)](https://pkg.go.dev/golang.org/x/oauth2) -[![Build Status](https://travis-ci.org/golang/oauth2.svg?branch=master)](https://travis-ci.org/golang/oauth2) - -oauth2 package contains a client implementation for OAuth 2.0 spec. - -See pkg.go.dev for further documentation and examples. - -* [pkg.go.dev/golang.org/x/oauth2](https://pkg.go.dev/golang.org/x/oauth2) -* [pkg.go.dev/golang.org/x/oauth2/google](https://pkg.go.dev/golang.org/x/oauth2/google) - -## Policy for new endpoints - -We no longer accept new provider-specific packages in this repo if all -they do is add a single endpoint variable. If you just want to add a -single endpoint, add it to the -[pkg.go.dev/golang.org/x/oauth2/endpoints](https://pkg.go.dev/golang.org/x/oauth2/endpoints) -package. - -## Report Issues / Send Patches - -The main issue tracker for the oauth2 repository is located at -https://github.com/golang/oauth2/issues. - -This repository uses Gerrit for code changes. To learn how to submit changes to -this repository, see https://go.dev/doc/contribute. - -The git repository is https://go.googlesource.com/oauth2. - -Note: - -* Excluding trivial changes, all contributions should be connected to an existing issue. -* API changes must go through the [change proposal process](https://go.dev/s/proposal-process) before they can be accepted. -* The code owners are listed at [dev.golang.org/owners](https://dev.golang.org/owners#:~:text=x/oauth2). diff --git a/go/sdk/vendor/golang.org/x/oauth2/deviceauth.go b/go/sdk/vendor/golang.org/x/oauth2/deviceauth.go deleted file mode 100644 index e783a94..0000000 --- a/go/sdk/vendor/golang.org/x/oauth2/deviceauth.go +++ /dev/null @@ -1,227 +0,0 @@ -package oauth2 - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io" - "mime" - "net/http" - "net/url" - "strings" - "time" - - "golang.org/x/oauth2/internal" -) - -// https://datatracker.ietf.org/doc/html/rfc8628#section-3.5 -const ( - errAuthorizationPending = "authorization_pending" - errSlowDown = "slow_down" - errAccessDenied = "access_denied" - errExpiredToken = "expired_token" -) - -// DeviceAuthResponse describes a successful RFC 8628 Device Authorization Response -// https://datatracker.ietf.org/doc/html/rfc8628#section-3.2 -type DeviceAuthResponse struct { - // DeviceCode - DeviceCode string `json:"device_code"` - // UserCode is the code the user should enter at the verification uri - UserCode string `json:"user_code"` - // VerificationURI is where user should enter the user code - VerificationURI string `json:"verification_uri"` - // VerificationURIComplete (if populated) includes the user code in the verification URI. This is typically shown to the user in non-textual form, such as a QR code. - VerificationURIComplete string `json:"verification_uri_complete,omitempty"` - // Expiry is when the device code and user code expire - Expiry time.Time `json:"expires_in,omitempty"` - // Interval is the duration in seconds that Poll should wait between requests - Interval int64 `json:"interval,omitempty"` -} - -func (d DeviceAuthResponse) MarshalJSON() ([]byte, error) { - type Alias DeviceAuthResponse - var expiresIn int64 - if !d.Expiry.IsZero() { - expiresIn = int64(time.Until(d.Expiry).Seconds()) - } - return json.Marshal(&struct { - ExpiresIn int64 `json:"expires_in,omitempty"` - *Alias - }{ - ExpiresIn: expiresIn, - Alias: (*Alias)(&d), - }) - -} - -func (c *DeviceAuthResponse) UnmarshalJSON(data []byte) error { - type Alias DeviceAuthResponse - aux := &struct { - ExpiresIn int64 `json:"expires_in"` - // workaround misspelling of verification_uri - VerificationURL string `json:"verification_url"` - *Alias - }{ - Alias: (*Alias)(c), - } - if err := json.Unmarshal(data, &aux); err != nil { - return err - } - if aux.ExpiresIn != 0 { - c.Expiry = time.Now().UTC().Add(time.Second * time.Duration(aux.ExpiresIn)) - } - if c.VerificationURI == "" { - c.VerificationURI = aux.VerificationURL - } - return nil -} - -// DeviceAuth returns a device auth struct which contains a device code -// and authorization information provided for users to enter on another device. -func (c *Config) DeviceAuth(ctx context.Context, opts ...AuthCodeOption) (*DeviceAuthResponse, error) { - // https://datatracker.ietf.org/doc/html/rfc8628#section-3.1 - v := url.Values{ - "client_id": {c.ClientID}, - } - if len(c.Scopes) > 0 { - v.Set("scope", strings.Join(c.Scopes, " ")) - } - for _, opt := range opts { - opt.setValue(v) - } - return retrieveDeviceAuth(ctx, c, v) -} - -func retrieveDeviceAuth(ctx context.Context, c *Config, v url.Values) (*DeviceAuthResponse, error) { - if c.Endpoint.DeviceAuthURL == "" { - return nil, errors.New("endpoint missing DeviceAuthURL") - } - - req, err := http.NewRequest("POST", c.Endpoint.DeviceAuthURL, strings.NewReader(v.Encode())) - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - req.Header.Set("Accept", "application/json") - - t := time.Now() - r, err := internal.ContextClient(ctx).Do(req) - if err != nil { - return nil, err - } - - body, err := io.ReadAll(io.LimitReader(r.Body, 1<<20)) - if err != nil { - return nil, fmt.Errorf("oauth2: cannot auth device: %v", err) - } - if code := r.StatusCode; code < 200 || code > 299 { - retrieveError := &RetrieveError{ - Response: r, - Body: body, - } - - content, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type")) - switch content { - case "application/x-www-form-urlencoded", "text/plain": - // some endpoints return a query string - vals, err := url.ParseQuery(string(body)) - if err != nil { - return nil, retrieveError - } - retrieveError.ErrorCode = vals.Get("error") - retrieveError.ErrorDescription = vals.Get("error_description") - retrieveError.ErrorURI = vals.Get("error_uri") - default: - var tj struct { - // https://datatracker.ietf.org/doc/html/rfc6749#section-5.2 - ErrorCode string `json:"error"` - ErrorDescription string `json:"error_description"` - ErrorURI string `json:"error_uri"` - } - if json.Unmarshal(body, &tj) != nil { - return nil, retrieveError - } - retrieveError.ErrorCode = tj.ErrorCode - retrieveError.ErrorDescription = tj.ErrorDescription - retrieveError.ErrorURI = tj.ErrorURI - } - - return nil, retrieveError - } - - da := &DeviceAuthResponse{} - err = json.Unmarshal(body, &da) - if err != nil { - return nil, fmt.Errorf("unmarshal %s", err) - } - - if !da.Expiry.IsZero() { - // Make a small adjustment to account for time taken by the request - da.Expiry = da.Expiry.Add(-time.Since(t)) - } - - return da, nil -} - -// DeviceAccessToken polls the server to exchange a device code for a token. -func (c *Config) DeviceAccessToken(ctx context.Context, da *DeviceAuthResponse, opts ...AuthCodeOption) (*Token, error) { - if !da.Expiry.IsZero() { - var cancel context.CancelFunc - ctx, cancel = context.WithDeadline(ctx, da.Expiry) - defer cancel() - } - - // https://datatracker.ietf.org/doc/html/rfc8628#section-3.4 - v := url.Values{ - "client_id": {c.ClientID}, - "grant_type": {"urn:ietf:params:oauth:grant-type:device_code"}, - "device_code": {da.DeviceCode}, - } - if len(c.Scopes) > 0 { - v.Set("scope", strings.Join(c.Scopes, " ")) - } - for _, opt := range opts { - opt.setValue(v) - } - - // "If no value is provided, clients MUST use 5 as the default." - // https://datatracker.ietf.org/doc/html/rfc8628#section-3.2 - interval := da.Interval - if interval == 0 { - interval = 5 - } - - ticker := time.NewTicker(time.Duration(interval) * time.Second) - defer ticker.Stop() - for { - select { - case <-ctx.Done(): - return nil, ctx.Err() - case <-ticker.C: - tok, err := retrieveToken(ctx, c, v) - if err == nil { - return tok, nil - } - - e, ok := err.(*RetrieveError) - if !ok { - return nil, err - } - switch e.ErrorCode { - case errSlowDown: - // https://datatracker.ietf.org/doc/html/rfc8628#section-3.5 - // "the interval MUST be increased by 5 seconds for this and all subsequent requests" - interval += 5 - ticker.Reset(time.Duration(interval) * time.Second) - case errAuthorizationPending: - // Do nothing. - case errAccessDenied, errExpiredToken: - fallthrough - default: - return tok, err - } - } - } -} diff --git a/go/sdk/vendor/golang.org/x/oauth2/internal/doc.go b/go/sdk/vendor/golang.org/x/oauth2/internal/doc.go deleted file mode 100644 index 8c7c475..0000000 --- a/go/sdk/vendor/golang.org/x/oauth2/internal/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package internal contains support packages for [golang.org/x/oauth2]. -package internal diff --git a/go/sdk/vendor/golang.org/x/oauth2/internal/oauth2.go b/go/sdk/vendor/golang.org/x/oauth2/internal/oauth2.go deleted file mode 100644 index 71ea6ad..0000000 --- a/go/sdk/vendor/golang.org/x/oauth2/internal/oauth2.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package internal - -import ( - "crypto/rsa" - "crypto/x509" - "encoding/pem" - "errors" - "fmt" -) - -// ParseKey converts the binary contents of a private key file -// to an [*rsa.PrivateKey]. It detects whether the private key is in a -// PEM container or not. If so, it extracts the private key -// from PEM container before conversion. It only supports PEM -// containers with no passphrase. -func ParseKey(key []byte) (*rsa.PrivateKey, error) { - block, _ := pem.Decode(key) - if block != nil { - key = block.Bytes - } - parsedKey, err := x509.ParsePKCS8PrivateKey(key) - if err != nil { - parsedKey, err = x509.ParsePKCS1PrivateKey(key) - if err != nil { - return nil, fmt.Errorf("private key should be a PEM or plain PKCS1 or PKCS8; parse error: %v", err) - } - } - parsed, ok := parsedKey.(*rsa.PrivateKey) - if !ok { - return nil, errors.New("private key is invalid") - } - return parsed, nil -} diff --git a/go/sdk/vendor/golang.org/x/oauth2/internal/token.go b/go/sdk/vendor/golang.org/x/oauth2/internal/token.go deleted file mode 100644 index 8389f24..0000000 --- a/go/sdk/vendor/golang.org/x/oauth2/internal/token.go +++ /dev/null @@ -1,356 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package internal - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io" - "math" - "mime" - "net/http" - "net/url" - "strconv" - "strings" - "sync" - "sync/atomic" - "time" -) - -// Token represents the credentials used to authorize -// the requests to access protected resources on the OAuth 2.0 -// provider's backend. -// -// This type is a mirror of [golang.org/x/oauth2.Token] and exists to break -// an otherwise-circular dependency. Other internal packages -// should convert this Token into an [golang.org/x/oauth2.Token] before use. -type Token struct { - // AccessToken is the token that authorizes and authenticates - // the requests. - AccessToken string - - // TokenType is the type of token. - // The Type method returns either this or "Bearer", the default. - TokenType string - - // RefreshToken is a token that's used by the application - // (as opposed to the user) to refresh the access token - // if it expires. - RefreshToken string - - // Expiry is the optional expiration time of the access token. - // - // If zero, TokenSource implementations will reuse the same - // token forever and RefreshToken or equivalent - // mechanisms for that TokenSource will not be used. - Expiry time.Time - - // ExpiresIn is the OAuth2 wire format "expires_in" field, - // which specifies how many seconds later the token expires, - // relative to an unknown time base approximately around "now". - // It is the application's responsibility to populate - // `Expiry` from `ExpiresIn` when required. - ExpiresIn int64 `json:"expires_in,omitempty"` - - // Raw optionally contains extra metadata from the server - // when updating a token. - Raw any -} - -// tokenJSON is the struct representing the HTTP response from OAuth2 -// providers returning a token or error in JSON form. -// https://datatracker.ietf.org/doc/html/rfc6749#section-5.1 -type tokenJSON struct { - AccessToken string `json:"access_token"` - TokenType string `json:"token_type"` - RefreshToken string `json:"refresh_token"` - ExpiresIn expirationTime `json:"expires_in"` // at least PayPal returns string, while most return number - // error fields - // https://datatracker.ietf.org/doc/html/rfc6749#section-5.2 - ErrorCode string `json:"error"` - ErrorDescription string `json:"error_description"` - ErrorURI string `json:"error_uri"` -} - -func (e *tokenJSON) expiry() (t time.Time) { - if v := e.ExpiresIn; v != 0 { - return time.Now().Add(time.Duration(v) * time.Second) - } - return -} - -type expirationTime int32 - -func (e *expirationTime) UnmarshalJSON(b []byte) error { - if len(b) == 0 || string(b) == "null" { - return nil - } - var n json.Number - err := json.Unmarshal(b, &n) - if err != nil { - return err - } - i, err := n.Int64() - if err != nil { - return err - } - if i > math.MaxInt32 { - i = math.MaxInt32 - } - *e = expirationTime(i) - return nil -} - -// AuthStyle is a copy of the golang.org/x/oauth2 package's AuthStyle type. -type AuthStyle int - -const ( - AuthStyleUnknown AuthStyle = 0 - AuthStyleInParams AuthStyle = 1 - AuthStyleInHeader AuthStyle = 2 -) - -// LazyAuthStyleCache is a backwards compatibility compromise to let Configs -// have a lazily-initialized AuthStyleCache. -// -// The two users of this, oauth2.Config and oauth2/clientcredentials.Config, -// both would ideally just embed an unexported AuthStyleCache but because both -// were historically allowed to be copied by value we can't retroactively add an -// uncopyable Mutex to them. -// -// We could use an atomic.Pointer, but that was added recently enough (in Go -// 1.18) that we'd break Go 1.17 users where the tests as of 2023-08-03 -// still pass. By using an atomic.Value, it supports both Go 1.17 and -// copying by value, even if that's not ideal. -type LazyAuthStyleCache struct { - v atomic.Value // of *AuthStyleCache -} - -func (lc *LazyAuthStyleCache) Get() *AuthStyleCache { - if c, ok := lc.v.Load().(*AuthStyleCache); ok { - return c - } - c := new(AuthStyleCache) - if !lc.v.CompareAndSwap(nil, c) { - c = lc.v.Load().(*AuthStyleCache) - } - return c -} - -type authStyleCacheKey struct { - url string - clientID string -} - -// AuthStyleCache is the set of tokenURLs we've successfully used via -// RetrieveToken and which style auth we ended up using. -// It's called a cache, but it doesn't (yet?) shrink. It's expected that -// the set of OAuth2 servers a program contacts over time is fixed and -// small. -type AuthStyleCache struct { - mu sync.Mutex - m map[authStyleCacheKey]AuthStyle -} - -// lookupAuthStyle reports which auth style we last used with tokenURL -// when calling RetrieveToken and whether we have ever done so. -func (c *AuthStyleCache) lookupAuthStyle(tokenURL, clientID string) (style AuthStyle, ok bool) { - c.mu.Lock() - defer c.mu.Unlock() - style, ok = c.m[authStyleCacheKey{tokenURL, clientID}] - return -} - -// setAuthStyle adds an entry to authStyleCache, documented above. -func (c *AuthStyleCache) setAuthStyle(tokenURL, clientID string, v AuthStyle) { - c.mu.Lock() - defer c.mu.Unlock() - if c.m == nil { - c.m = make(map[authStyleCacheKey]AuthStyle) - } - c.m[authStyleCacheKey{tokenURL, clientID}] = v -} - -// newTokenRequest returns a new *http.Request to retrieve a new token -// from tokenURL using the provided clientID, clientSecret, and POST -// body parameters. -// -// inParams is whether the clientID & clientSecret should be encoded -// as the POST body. An 'inParams' value of true means to send it in -// the POST body (along with any values in v); false means to send it -// in the Authorization header. -func newTokenRequest(tokenURL, clientID, clientSecret string, v url.Values, authStyle AuthStyle) (*http.Request, error) { - if authStyle == AuthStyleInParams { - v = cloneURLValues(v) - if clientID != "" { - v.Set("client_id", clientID) - } - if clientSecret != "" { - v.Set("client_secret", clientSecret) - } - } - req, err := http.NewRequest("POST", tokenURL, strings.NewReader(v.Encode())) - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - if authStyle == AuthStyleInHeader { - req.SetBasicAuth(url.QueryEscape(clientID), url.QueryEscape(clientSecret)) - } - return req, nil -} - -func cloneURLValues(v url.Values) url.Values { - v2 := make(url.Values, len(v)) - for k, vv := range v { - v2[k] = append([]string(nil), vv...) - } - return v2 -} - -func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, v url.Values, authStyle AuthStyle, styleCache *AuthStyleCache) (*Token, error) { - needsAuthStyleProbe := authStyle == AuthStyleUnknown - if needsAuthStyleProbe { - if style, ok := styleCache.lookupAuthStyle(tokenURL, clientID); ok { - authStyle = style - needsAuthStyleProbe = false - } else { - authStyle = AuthStyleInHeader // the first way we'll try - } - } - req, err := newTokenRequest(tokenURL, clientID, clientSecret, v, authStyle) - if err != nil { - return nil, err - } - token, err := doTokenRoundTrip(ctx, req) - if err != nil && needsAuthStyleProbe { - // If we get an error, assume the server wants the - // clientID & clientSecret in a different form. - // See https://code.google.com/p/goauth2/issues/detail?id=31 for background. - // In summary: - // - Reddit only accepts client secret in the Authorization header - // - Dropbox accepts either it in URL param or Auth header, but not both. - // - Google only accepts URL param (not spec compliant?), not Auth header - // - Stripe only accepts client secret in Auth header with Bearer method, not Basic - // - // We used to maintain a big table in this code of all the sites and which way - // they went, but maintaining it didn't scale & got annoying. - // So just try both ways. - authStyle = AuthStyleInParams // the second way we'll try - req, _ = newTokenRequest(tokenURL, clientID, clientSecret, v, authStyle) - token, err = doTokenRoundTrip(ctx, req) - } - if needsAuthStyleProbe && err == nil { - styleCache.setAuthStyle(tokenURL, clientID, authStyle) - } - // Don't overwrite `RefreshToken` with an empty value - // if this was a token refreshing request. - if token != nil && token.RefreshToken == "" { - token.RefreshToken = v.Get("refresh_token") - } - return token, err -} - -func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) { - r, err := ContextClient(ctx).Do(req.WithContext(ctx)) - if err != nil { - return nil, err - } - body, err := io.ReadAll(io.LimitReader(r.Body, 1<<20)) - r.Body.Close() - if err != nil { - return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err) - } - - failureStatus := r.StatusCode < 200 || r.StatusCode > 299 - retrieveError := &RetrieveError{ - Response: r, - Body: body, - // attempt to populate error detail below - } - - var token *Token - content, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type")) - switch content { - case "application/x-www-form-urlencoded", "text/plain": - // some endpoints return a query string - vals, err := url.ParseQuery(string(body)) - if err != nil { - if failureStatus { - return nil, retrieveError - } - return nil, fmt.Errorf("oauth2: cannot parse response: %v", err) - } - retrieveError.ErrorCode = vals.Get("error") - retrieveError.ErrorDescription = vals.Get("error_description") - retrieveError.ErrorURI = vals.Get("error_uri") - token = &Token{ - AccessToken: vals.Get("access_token"), - TokenType: vals.Get("token_type"), - RefreshToken: vals.Get("refresh_token"), - Raw: vals, - } - e := vals.Get("expires_in") - expires, _ := strconv.Atoi(e) - if expires != 0 { - token.Expiry = time.Now().Add(time.Duration(expires) * time.Second) - } - default: - var tj tokenJSON - if err = json.Unmarshal(body, &tj); err != nil { - if failureStatus { - return nil, retrieveError - } - return nil, fmt.Errorf("oauth2: cannot parse json: %v", err) - } - retrieveError.ErrorCode = tj.ErrorCode - retrieveError.ErrorDescription = tj.ErrorDescription - retrieveError.ErrorURI = tj.ErrorURI - token = &Token{ - AccessToken: tj.AccessToken, - TokenType: tj.TokenType, - RefreshToken: tj.RefreshToken, - Expiry: tj.expiry(), - ExpiresIn: int64(tj.ExpiresIn), - Raw: make(map[string]any), - } - json.Unmarshal(body, &token.Raw) // no error checks for optional fields - } - // according to spec, servers should respond status 400 in error case - // https://www.rfc-editor.org/rfc/rfc6749#section-5.2 - // but some unorthodox servers respond 200 in error case - if failureStatus || retrieveError.ErrorCode != "" { - return nil, retrieveError - } - if token.AccessToken == "" { - return nil, errors.New("oauth2: server response missing access_token") - } - return token, nil -} - -// mirrors oauth2.RetrieveError -type RetrieveError struct { - Response *http.Response - Body []byte - ErrorCode string - ErrorDescription string - ErrorURI string -} - -func (r *RetrieveError) Error() string { - if r.ErrorCode != "" { - s := fmt.Sprintf("oauth2: %q", r.ErrorCode) - if r.ErrorDescription != "" { - s += fmt.Sprintf(" %q", r.ErrorDescription) - } - if r.ErrorURI != "" { - s += fmt.Sprintf(" %q", r.ErrorURI) - } - return s - } - return fmt.Sprintf("oauth2: cannot fetch token: %v\nResponse: %s", r.Response.Status, r.Body) -} diff --git a/go/sdk/vendor/golang.org/x/oauth2/internal/transport.go b/go/sdk/vendor/golang.org/x/oauth2/internal/transport.go deleted file mode 100644 index afc0aeb..0000000 --- a/go/sdk/vendor/golang.org/x/oauth2/internal/transport.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package internal - -import ( - "context" - "net/http" -) - -// HTTPClient is the context key to use with [context.WithValue] -// to associate an [*http.Client] value with a context. -var HTTPClient ContextKey - -// ContextKey is just an empty struct. It exists so HTTPClient can be -// an immutable public variable with a unique type. It's immutable -// because nobody else can create a ContextKey, being unexported. -type ContextKey struct{} - -func ContextClient(ctx context.Context) *http.Client { - if ctx != nil { - if hc, ok := ctx.Value(HTTPClient).(*http.Client); ok { - return hc - } - } - return http.DefaultClient -} diff --git a/go/sdk/vendor/golang.org/x/oauth2/oauth2.go b/go/sdk/vendor/golang.org/x/oauth2/oauth2.go deleted file mode 100644 index 5c527d3..0000000 --- a/go/sdk/vendor/golang.org/x/oauth2/oauth2.go +++ /dev/null @@ -1,423 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package oauth2 provides support for making -// OAuth2 authorized and authenticated HTTP requests, -// as specified in RFC 6749. -// It can additionally grant authorization with Bearer JWT. -package oauth2 // import "golang.org/x/oauth2" - -import ( - "context" - "errors" - "net/http" - "net/url" - "strings" - "sync" - "time" - - "golang.org/x/oauth2/internal" -) - -// NoContext is the default context you should supply if not using -// your own [context.Context]. -// -// Deprecated: Use [context.Background] or [context.TODO] instead. -var NoContext = context.TODO() - -// RegisterBrokenAuthHeaderProvider previously did something. It is now a no-op. -// -// Deprecated: this function no longer does anything. Caller code that -// wants to avoid potential extra HTTP requests made during -// auto-probing of the provider's auth style should set -// Endpoint.AuthStyle. -func RegisterBrokenAuthHeaderProvider(tokenURL string) {} - -// Config describes a typical 3-legged OAuth2 flow, with both the -// client application information and the server's endpoint URLs. -// For the client credentials 2-legged OAuth2 flow, see the -// [golang.org/x/oauth2/clientcredentials] package. -type Config struct { - // ClientID is the application's ID. - ClientID string - - // ClientSecret is the application's secret. - ClientSecret string - - // Endpoint contains the authorization server's token endpoint - // URLs. These are constants specific to each server and are - // often available via site-specific packages, such as - // google.Endpoint or github.Endpoint. - Endpoint Endpoint - - // RedirectURL is the URL to redirect users going through - // the OAuth flow, after the resource owner's URLs. - RedirectURL string - - // Scopes specifies optional requested permissions. - Scopes []string - - // authStyleCache caches which auth style to use when Endpoint.AuthStyle is - // the zero value (AuthStyleAutoDetect). - authStyleCache internal.LazyAuthStyleCache -} - -// A TokenSource is anything that can return a token. -type TokenSource interface { - // Token returns a token or an error. - // Token must be safe for concurrent use by multiple goroutines. - // The returned Token must not be modified. - Token() (*Token, error) -} - -// Endpoint represents an OAuth 2.0 provider's authorization and token -// endpoint URLs. -type Endpoint struct { - AuthURL string - DeviceAuthURL string - TokenURL string - - // AuthStyle optionally specifies how the endpoint wants the - // client ID & client secret sent. The zero value means to - // auto-detect. - AuthStyle AuthStyle -} - -// AuthStyle represents how requests for tokens are authenticated -// to the server. -type AuthStyle int - -const ( - // AuthStyleAutoDetect means to auto-detect which authentication - // style the provider wants by trying both ways and caching - // the successful way for the future. - AuthStyleAutoDetect AuthStyle = 0 - - // AuthStyleInParams sends the "client_id" and "client_secret" - // in the POST body as application/x-www-form-urlencoded parameters. - AuthStyleInParams AuthStyle = 1 - - // AuthStyleInHeader sends the client_id and client_secret - // using HTTP Basic Authorization. This is an optional style - // described in the OAuth2 RFC 6749 section 2.3.1. - AuthStyleInHeader AuthStyle = 2 -) - -var ( - // AccessTypeOnline and AccessTypeOffline are options passed - // to the Options.AuthCodeURL method. They modify the - // "access_type" field that gets sent in the URL returned by - // AuthCodeURL. - // - // Online is the default if neither is specified. If your - // application needs to refresh access tokens when the user - // is not present at the browser, then use offline. This will - // result in your application obtaining a refresh token the - // first time your application exchanges an authorization - // code for a user. - AccessTypeOnline AuthCodeOption = SetAuthURLParam("access_type", "online") - AccessTypeOffline AuthCodeOption = SetAuthURLParam("access_type", "offline") - - // ApprovalForce forces the users to view the consent dialog - // and confirm the permissions request at the URL returned - // from AuthCodeURL, even if they've already done so. - ApprovalForce AuthCodeOption = SetAuthURLParam("prompt", "consent") -) - -// An AuthCodeOption is passed to Config.AuthCodeURL. -type AuthCodeOption interface { - setValue(url.Values) -} - -type setParam struct{ k, v string } - -func (p setParam) setValue(m url.Values) { m.Set(p.k, p.v) } - -// SetAuthURLParam builds an [AuthCodeOption] which passes key/value parameters -// to a provider's authorization endpoint. -func SetAuthURLParam(key, value string) AuthCodeOption { - return setParam{key, value} -} - -// AuthCodeURL returns a URL to OAuth 2.0 provider's consent page -// that asks for permissions for the required scopes explicitly. -// -// State is an opaque value used by the client to maintain state between the -// request and callback. The authorization server includes this value when -// redirecting the user agent back to the client. -// -// Opts may include [AccessTypeOnline] or [AccessTypeOffline], as well -// as [ApprovalForce]. -// -// To protect against CSRF attacks, opts should include a PKCE challenge -// (S256ChallengeOption). Not all servers support PKCE. An alternative is to -// generate a random state parameter and verify it after exchange. -// See https://datatracker.ietf.org/doc/html/rfc6749#section-10.12 (predating -// PKCE), https://www.oauth.com/oauth2-servers/pkce/ and -// https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-09.html#name-cross-site-request-forgery (describing both approaches) -func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string { - var buf strings.Builder - buf.WriteString(c.Endpoint.AuthURL) - v := url.Values{ - "response_type": {"code"}, - "client_id": {c.ClientID}, - } - if c.RedirectURL != "" { - v.Set("redirect_uri", c.RedirectURL) - } - if len(c.Scopes) > 0 { - v.Set("scope", strings.Join(c.Scopes, " ")) - } - if state != "" { - v.Set("state", state) - } - for _, opt := range opts { - opt.setValue(v) - } - if strings.Contains(c.Endpoint.AuthURL, "?") { - buf.WriteByte('&') - } else { - buf.WriteByte('?') - } - buf.WriteString(v.Encode()) - return buf.String() -} - -// PasswordCredentialsToken converts a resource owner username and password -// pair into a token. -// -// Per the RFC, this grant type should only be used "when there is a high -// degree of trust between the resource owner and the client (e.g., the client -// is part of the device operating system or a highly privileged application), -// and when other authorization grant types are not available." -// See https://tools.ietf.org/html/rfc6749#section-4.3 for more info. -// -// The provided context optionally controls which HTTP client is used. See the [HTTPClient] variable. -func (c *Config) PasswordCredentialsToken(ctx context.Context, username, password string) (*Token, error) { - v := url.Values{ - "grant_type": {"password"}, - "username": {username}, - "password": {password}, - } - if len(c.Scopes) > 0 { - v.Set("scope", strings.Join(c.Scopes, " ")) - } - return retrieveToken(ctx, c, v) -} - -// Exchange converts an authorization code into a token. -// -// It is used after a resource provider redirects the user back -// to the Redirect URI (the URL obtained from AuthCodeURL). -// -// The provided context optionally controls which HTTP client is used. See the [HTTPClient] variable. -// -// The code will be in the [http.Request.FormValue]("code"). Before -// calling Exchange, be sure to validate [http.Request.FormValue]("state") if you are -// using it to protect against CSRF attacks. -// -// If using PKCE to protect against CSRF attacks, opts should include a -// VerifierOption. -func (c *Config) Exchange(ctx context.Context, code string, opts ...AuthCodeOption) (*Token, error) { - v := url.Values{ - "grant_type": {"authorization_code"}, - "code": {code}, - } - if c.RedirectURL != "" { - v.Set("redirect_uri", c.RedirectURL) - } - for _, opt := range opts { - opt.setValue(v) - } - return retrieveToken(ctx, c, v) -} - -// Client returns an HTTP client using the provided token. -// The token will auto-refresh as necessary. The underlying -// HTTP transport will be obtained using the provided context. -// The returned client and its Transport should not be modified. -func (c *Config) Client(ctx context.Context, t *Token) *http.Client { - return NewClient(ctx, c.TokenSource(ctx, t)) -} - -// TokenSource returns a [TokenSource] that returns t until t expires, -// automatically refreshing it as necessary using the provided context. -// -// Most users will use [Config.Client] instead. -func (c *Config) TokenSource(ctx context.Context, t *Token) TokenSource { - tkr := &tokenRefresher{ - ctx: ctx, - conf: c, - } - if t != nil { - tkr.refreshToken = t.RefreshToken - } - return &reuseTokenSource{ - t: t, - new: tkr, - } -} - -// tokenRefresher is a TokenSource that makes "grant_type=refresh_token" -// HTTP requests to renew a token using a RefreshToken. -type tokenRefresher struct { - ctx context.Context // used to get HTTP requests - conf *Config - refreshToken string -} - -// WARNING: Token is not safe for concurrent access, as it -// updates the tokenRefresher's refreshToken field. -// Within this package, it is used by reuseTokenSource which -// synchronizes calls to this method with its own mutex. -func (tf *tokenRefresher) Token() (*Token, error) { - if tf.refreshToken == "" { - return nil, errors.New("oauth2: token expired and refresh token is not set") - } - - tk, err := retrieveToken(tf.ctx, tf.conf, url.Values{ - "grant_type": {"refresh_token"}, - "refresh_token": {tf.refreshToken}, - }) - - if err != nil { - return nil, err - } - if tf.refreshToken != tk.RefreshToken { - tf.refreshToken = tk.RefreshToken - } - return tk, nil -} - -// reuseTokenSource is a TokenSource that holds a single token in memory -// and validates its expiry before each call to retrieve it with -// Token. If it's expired, it will be auto-refreshed using the -// new TokenSource. -type reuseTokenSource struct { - new TokenSource // called when t is expired. - - mu sync.Mutex // guards t - t *Token - - expiryDelta time.Duration -} - -// Token returns the current token if it's still valid, else will -// refresh the current token and return the new one. -func (s *reuseTokenSource) Token() (*Token, error) { - s.mu.Lock() - defer s.mu.Unlock() - if s.t.Valid() { - return s.t, nil - } - t, err := s.new.Token() - if err != nil { - return nil, err - } - t.expiryDelta = s.expiryDelta - s.t = t - return t, nil -} - -// StaticTokenSource returns a [TokenSource] that always returns the same token. -// Because the provided token t is never refreshed, StaticTokenSource is only -// useful for tokens that never expire. -func StaticTokenSource(t *Token) TokenSource { - return staticTokenSource{t} -} - -// staticTokenSource is a TokenSource that always returns the same Token. -type staticTokenSource struct { - t *Token -} - -func (s staticTokenSource) Token() (*Token, error) { - return s.t, nil -} - -// HTTPClient is the context key to use with [context.WithValue] -// to associate a [*http.Client] value with a context. -var HTTPClient internal.ContextKey - -// NewClient creates an [*http.Client] from a [context.Context] and [TokenSource]. -// The returned client is not valid beyond the lifetime of the context. -// -// Note that if a custom [*http.Client] is provided via the [context.Context] it -// is used only for token acquisition and is not used to configure the -// [*http.Client] returned from NewClient. -// -// As a special case, if src is nil, a non-OAuth2 client is returned -// using the provided context. This exists to support related OAuth2 -// packages. -func NewClient(ctx context.Context, src TokenSource) *http.Client { - if src == nil { - return internal.ContextClient(ctx) - } - cc := internal.ContextClient(ctx) - return &http.Client{ - Transport: &Transport{ - Base: cc.Transport, - Source: ReuseTokenSource(nil, src), - }, - CheckRedirect: cc.CheckRedirect, - Jar: cc.Jar, - Timeout: cc.Timeout, - } -} - -// ReuseTokenSource returns a [TokenSource] which repeatedly returns the -// same token as long as it's valid, starting with t. -// When its cached token is invalid, a new token is obtained from src. -// -// ReuseTokenSource is typically used to reuse tokens from a cache -// (such as a file on disk) between runs of a program, rather than -// obtaining new tokens unnecessarily. -// -// The initial token t may be nil, in which case the [TokenSource] is -// wrapped in a caching version if it isn't one already. This also -// means it's always safe to wrap ReuseTokenSource around any other -// [TokenSource] without adverse effects. -func ReuseTokenSource(t *Token, src TokenSource) TokenSource { - // Don't wrap a reuseTokenSource in itself. That would work, - // but cause an unnecessary number of mutex operations. - // Just build the equivalent one. - if rt, ok := src.(*reuseTokenSource); ok { - if t == nil { - // Just use it directly. - return rt - } - src = rt.new - } - return &reuseTokenSource{ - t: t, - new: src, - } -} - -// ReuseTokenSourceWithExpiry returns a [TokenSource] that acts in the same manner as the -// [TokenSource] returned by [ReuseTokenSource], except the expiry buffer is -// configurable. The expiration time of a token is calculated as -// t.Expiry.Add(-earlyExpiry). -func ReuseTokenSourceWithExpiry(t *Token, src TokenSource, earlyExpiry time.Duration) TokenSource { - // Don't wrap a reuseTokenSource in itself. That would work, - // but cause an unnecessary number of mutex operations. - // Just build the equivalent one. - if rt, ok := src.(*reuseTokenSource); ok { - if t == nil { - // Just use it directly, but set the expiryDelta to earlyExpiry, - // so the behavior matches what the user expects. - rt.expiryDelta = earlyExpiry - return rt - } - src = rt.new - } - if t != nil { - t.expiryDelta = earlyExpiry - } - return &reuseTokenSource{ - t: t, - new: src, - expiryDelta: earlyExpiry, - } -} diff --git a/go/sdk/vendor/golang.org/x/oauth2/pkce.go b/go/sdk/vendor/golang.org/x/oauth2/pkce.go deleted file mode 100644 index f99384f..0000000 --- a/go/sdk/vendor/golang.org/x/oauth2/pkce.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package oauth2 - -import ( - "crypto/rand" - "crypto/sha256" - "encoding/base64" - "net/url" -) - -const ( - codeChallengeKey = "code_challenge" - codeChallengeMethodKey = "code_challenge_method" - codeVerifierKey = "code_verifier" -) - -// GenerateVerifier generates a PKCE code verifier with 32 octets of randomness. -// This follows recommendations in RFC 7636. -// -// A fresh verifier should be generated for each authorization. -// The resulting verifier should be passed to [Config.AuthCodeURL] or [Config.DeviceAuth] -// with [S256ChallengeOption], and to [Config.Exchange] or [Config.DeviceAccessToken] -// with [VerifierOption]. -func GenerateVerifier() string { - // "RECOMMENDED that the output of a suitable random number generator be - // used to create a 32-octet sequence. The octet sequence is then - // base64url-encoded to produce a 43-octet URL-safe string to use as the - // code verifier." - // https://datatracker.ietf.org/doc/html/rfc7636#section-4.1 - data := make([]byte, 32) - if _, err := rand.Read(data); err != nil { - panic(err) - } - return base64.RawURLEncoding.EncodeToString(data) -} - -// VerifierOption returns a PKCE code verifier [AuthCodeOption]. It should only be -// passed to [Config.Exchange] or [Config.DeviceAccessToken]. -func VerifierOption(verifier string) AuthCodeOption { - return setParam{k: codeVerifierKey, v: verifier} -} - -// S256ChallengeFromVerifier returns a PKCE code challenge derived from verifier with method S256. -// -// Prefer to use [S256ChallengeOption] where possible. -func S256ChallengeFromVerifier(verifier string) string { - sha := sha256.Sum256([]byte(verifier)) - return base64.RawURLEncoding.EncodeToString(sha[:]) -} - -// S256ChallengeOption derives a PKCE code challenge from the verifier with -// method S256. It should be passed to [Config.AuthCodeURL] or [Config.DeviceAuth] -// only. -func S256ChallengeOption(verifier string) AuthCodeOption { - return challengeOption{ - challenge_method: "S256", - challenge: S256ChallengeFromVerifier(verifier), - } -} - -type challengeOption struct{ challenge_method, challenge string } - -func (p challengeOption) setValue(m url.Values) { - m.Set(codeChallengeMethodKey, p.challenge_method) - m.Set(codeChallengeKey, p.challenge) -} diff --git a/go/sdk/vendor/golang.org/x/oauth2/token.go b/go/sdk/vendor/golang.org/x/oauth2/token.go deleted file mode 100644 index e995eeb..0000000 --- a/go/sdk/vendor/golang.org/x/oauth2/token.go +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package oauth2 - -import ( - "context" - "fmt" - "net/http" - "net/url" - "strconv" - "strings" - "time" - - "golang.org/x/oauth2/internal" -) - -// defaultExpiryDelta determines how earlier a token should be considered -// expired than its actual expiration time. It is used to avoid late -// expirations due to client-server time mismatches. -const defaultExpiryDelta = 10 * time.Second - -// Token represents the credentials used to authorize -// the requests to access protected resources on the OAuth 2.0 -// provider's backend. -// -// Most users of this package should not access fields of Token -// directly. They're exported mostly for use by related packages -// implementing derivative OAuth2 flows. -type Token struct { - // AccessToken is the token that authorizes and authenticates - // the requests. - AccessToken string `json:"access_token"` - - // TokenType is the type of token. - // The Type method returns either this or "Bearer", the default. - TokenType string `json:"token_type,omitempty"` - - // RefreshToken is a token that's used by the application - // (as opposed to the user) to refresh the access token - // if it expires. - RefreshToken string `json:"refresh_token,omitempty"` - - // Expiry is the optional expiration time of the access token. - // - // If zero, [TokenSource] implementations will reuse the same - // token forever and RefreshToken or equivalent - // mechanisms for that TokenSource will not be used. - Expiry time.Time `json:"expiry,omitempty"` - - // ExpiresIn is the OAuth2 wire format "expires_in" field, - // which specifies how many seconds later the token expires, - // relative to an unknown time base approximately around "now". - // It is the application's responsibility to populate - // `Expiry` from `ExpiresIn` when required. - ExpiresIn int64 `json:"expires_in,omitempty"` - - // raw optionally contains extra metadata from the server - // when updating a token. - raw any - - // expiryDelta is used to calculate when a token is considered - // expired, by subtracting from Expiry. If zero, defaultExpiryDelta - // is used. - expiryDelta time.Duration -} - -// Type returns t.TokenType if non-empty, else "Bearer". -func (t *Token) Type() string { - if strings.EqualFold(t.TokenType, "bearer") { - return "Bearer" - } - if strings.EqualFold(t.TokenType, "mac") { - return "MAC" - } - if strings.EqualFold(t.TokenType, "basic") { - return "Basic" - } - if t.TokenType != "" { - return t.TokenType - } - return "Bearer" -} - -// SetAuthHeader sets the Authorization header to r using the access -// token in t. -// -// This method is unnecessary when using [Transport] or an HTTP Client -// returned by this package. -func (t *Token) SetAuthHeader(r *http.Request) { - r.Header.Set("Authorization", t.Type()+" "+t.AccessToken) -} - -// WithExtra returns a new [Token] that's a clone of t, but using the -// provided raw extra map. This is only intended for use by packages -// implementing derivative OAuth2 flows. -func (t *Token) WithExtra(extra any) *Token { - t2 := new(Token) - *t2 = *t - t2.raw = extra - return t2 -} - -// Extra returns an extra field. -// Extra fields are key-value pairs returned by the server as -// part of the token retrieval response. -func (t *Token) Extra(key string) any { - if raw, ok := t.raw.(map[string]any); ok { - return raw[key] - } - - vals, ok := t.raw.(url.Values) - if !ok { - return nil - } - - v := vals.Get(key) - switch s := strings.TrimSpace(v); strings.Count(s, ".") { - case 0: // Contains no "."; try to parse as int - if i, err := strconv.ParseInt(s, 10, 64); err == nil { - return i - } - case 1: // Contains a single "."; try to parse as float - if f, err := strconv.ParseFloat(s, 64); err == nil { - return f - } - } - - return v -} - -// timeNow is time.Now but pulled out as a variable for tests. -var timeNow = time.Now - -// expired reports whether the token is expired. -// t must be non-nil. -func (t *Token) expired() bool { - if t.Expiry.IsZero() { - return false - } - - expiryDelta := defaultExpiryDelta - if t.expiryDelta != 0 { - expiryDelta = t.expiryDelta - } - return t.Expiry.Round(0).Add(-expiryDelta).Before(timeNow()) -} - -// Valid reports whether t is non-nil, has an AccessToken, and is not expired. -func (t *Token) Valid() bool { - return t != nil && t.AccessToken != "" && !t.expired() -} - -// tokenFromInternal maps an *internal.Token struct into -// a *Token struct. -func tokenFromInternal(t *internal.Token) *Token { - if t == nil { - return nil - } - return &Token{ - AccessToken: t.AccessToken, - TokenType: t.TokenType, - RefreshToken: t.RefreshToken, - Expiry: t.Expiry, - ExpiresIn: t.ExpiresIn, - raw: t.Raw, - } -} - -// retrieveToken takes a *Config and uses that to retrieve an *internal.Token. -// This token is then mapped from *internal.Token into an *oauth2.Token which is returned along -// with an error. -func retrieveToken(ctx context.Context, c *Config, v url.Values) (*Token, error) { - tk, err := internal.RetrieveToken(ctx, c.ClientID, c.ClientSecret, c.Endpoint.TokenURL, v, internal.AuthStyle(c.Endpoint.AuthStyle), c.authStyleCache.Get()) - if err != nil { - if rErr, ok := err.(*internal.RetrieveError); ok { - return nil, (*RetrieveError)(rErr) - } - return nil, err - } - return tokenFromInternal(tk), nil -} - -// RetrieveError is the error returned when the token endpoint returns a -// non-2XX HTTP status code or populates RFC 6749's 'error' parameter. -// https://datatracker.ietf.org/doc/html/rfc6749#section-5.2 -type RetrieveError struct { - Response *http.Response - // Body is the body that was consumed by reading Response.Body. - // It may be truncated. - Body []byte - // ErrorCode is RFC 6749's 'error' parameter. - ErrorCode string - // ErrorDescription is RFC 6749's 'error_description' parameter. - ErrorDescription string - // ErrorURI is RFC 6749's 'error_uri' parameter. - ErrorURI string -} - -func (r *RetrieveError) Error() string { - if r.ErrorCode != "" { - s := fmt.Sprintf("oauth2: %q", r.ErrorCode) - if r.ErrorDescription != "" { - s += fmt.Sprintf(" %q", r.ErrorDescription) - } - if r.ErrorURI != "" { - s += fmt.Sprintf(" %q", r.ErrorURI) - } - return s - } - return fmt.Sprintf("oauth2: cannot fetch token: %v\nResponse: %s", r.Response.Status, r.Body) -} diff --git a/go/sdk/vendor/golang.org/x/oauth2/transport.go b/go/sdk/vendor/golang.org/x/oauth2/transport.go deleted file mode 100644 index 9922ec3..0000000 --- a/go/sdk/vendor/golang.org/x/oauth2/transport.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package oauth2 - -import ( - "errors" - "log" - "net/http" - "sync" -) - -// Transport is an [http.RoundTripper] that makes OAuth 2.0 HTTP requests, -// wrapping a base [http.RoundTripper] and adding an Authorization header -// with a token from the supplied [TokenSource]. -// -// Transport is a low-level mechanism. Most code will use the -// higher-level [Config.Client] method instead. -type Transport struct { - // Source supplies the token to add to outgoing requests' - // Authorization headers. - Source TokenSource - - // Base is the base RoundTripper used to make HTTP requests. - // If nil, http.DefaultTransport is used. - Base http.RoundTripper -} - -// RoundTrip authorizes and authenticates the request with an -// access token from Transport's Source. -func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { - reqBodyClosed := false - if req.Body != nil { - defer func() { - if !reqBodyClosed { - req.Body.Close() - } - }() - } - - if t.Source == nil { - return nil, errors.New("oauth2: Transport's Source is nil") - } - token, err := t.Source.Token() - if err != nil { - return nil, err - } - - req2 := req.Clone(req.Context()) - token.SetAuthHeader(req2) - - // req.Body is assumed to be closed by the base RoundTripper. - reqBodyClosed = true - return t.base().RoundTrip(req2) -} - -var cancelOnce sync.Once - -// CancelRequest does nothing. It used to be a legacy cancellation mechanism -// but now only logs on first use to warn that it's deprecated. -// -// Deprecated: use contexts for cancellation instead. -func (t *Transport) CancelRequest(req *http.Request) { - cancelOnce.Do(func() { - log.Printf("deprecated: golang.org/x/oauth2: Transport.CancelRequest no longer does anything; use contexts") - }) -} - -func (t *Transport) base() http.RoundTripper { - if t.Base != nil { - return t.Base - } - return http.DefaultTransport -} diff --git a/go/sdk/vendor/golang.org/x/sys/LICENSE b/go/sdk/vendor/golang.org/x/sys/LICENSE deleted file mode 100644 index 2a7cf70..0000000 --- a/go/sdk/vendor/golang.org/x/sys/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright 2009 The Go Authors. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google LLC nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/go/sdk/vendor/golang.org/x/sys/PATENTS b/go/sdk/vendor/golang.org/x/sys/PATENTS deleted file mode 100644 index 7330990..0000000 --- a/go/sdk/vendor/golang.org/x/sys/PATENTS +++ /dev/null @@ -1,22 +0,0 @@ -Additional IP Rights Grant (Patents) - -"This implementation" means the copyrightable works distributed by -Google as part of the Go project. - -Google hereby grants to You a perpetual, worldwide, non-exclusive, -no-charge, royalty-free, irrevocable (except as stated in this section) -patent license to make, have made, use, offer to sell, sell, import, -transfer and otherwise run, modify and propagate the contents of this -implementation of Go, where such license applies only to those patent -claims, both currently owned or controlled by Google and acquired in -the future, licensable by Google that are necessarily infringed by this -implementation of Go. This grant does not include claims that would be -infringed only as a consequence of further modification of this -implementation. If you or your agent or exclusive licensee institute or -order or agree to the institution of patent litigation against any -entity (including a cross-claim or counterclaim in a lawsuit) alleging -that this implementation of Go or any code incorporated within this -implementation of Go constitutes direct or contributory patent -infringement, or inducement of patent infringement, then any patent -rights granted to you under this License for this implementation of Go -shall terminate as of the date such litigation is filed. diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s b/go/sdk/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s deleted file mode 100644 index 269e173..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build gc - -#include "textflag.h" - -// -// System calls for ppc64, AIX are implemented in runtime/syscall_aix.go -// - -TEXT ·syscall6(SB),NOSPLIT,$0-88 - JMP syscall·syscall6(SB) - -TEXT ·rawSyscall6(SB),NOSPLIT,$0-88 - JMP syscall·rawSyscall6(SB) diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/asm_darwin_x86_gc.s b/go/sdk/vendor/golang.org/x/sys/cpu/asm_darwin_x86_gc.s deleted file mode 100644 index ec2acfe..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/asm_darwin_x86_gc.s +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2024 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build darwin && amd64 && gc - -#include "textflag.h" - -TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_sysctl(SB) -GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 -DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) - -TEXT libc_sysctlbyname_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_sysctlbyname(SB) -GLOBL ·libc_sysctlbyname_trampoline_addr(SB), RODATA, $8 -DATA ·libc_sysctlbyname_trampoline_addr(SB)/8, $libc_sysctlbyname_trampoline<>(SB) diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/byteorder.go b/go/sdk/vendor/golang.org/x/sys/cpu/byteorder.go deleted file mode 100644 index 271055b..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/byteorder.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -import ( - "runtime" -) - -// byteOrder is a subset of encoding/binary.ByteOrder. -type byteOrder interface { - Uint32([]byte) uint32 - Uint64([]byte) uint64 -} - -type littleEndian struct{} -type bigEndian struct{} - -func (littleEndian) Uint32(b []byte) uint32 { - _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 - return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 -} - -func (littleEndian) Uint64(b []byte) uint64 { - _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 - return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | - uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 -} - -func (bigEndian) Uint32(b []byte) uint32 { - _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 - return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 -} - -func (bigEndian) Uint64(b []byte) uint64 { - _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 - return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | - uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 -} - -// hostByteOrder returns littleEndian on little-endian machines and -// bigEndian on big-endian machines. -func hostByteOrder() byteOrder { - switch runtime.GOARCH { - case "386", "amd64", "amd64p32", - "alpha", - "arm", "arm64", - "loong64", - "mipsle", "mips64le", "mips64p32le", - "nios2", - "ppc64le", - "riscv", "riscv64", - "sh": - return littleEndian{} - case "armbe", "arm64be", - "m68k", - "mips", "mips64", "mips64p32", - "ppc", "ppc64", - "s390", "s390x", - "shbe", - "sparc", "sparc64": - return bigEndian{} - } - panic("unknown architecture") -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu.go deleted file mode 100644 index 6354199..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu.go +++ /dev/null @@ -1,338 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package cpu implements processor feature detection for -// various CPU architectures. -package cpu - -import ( - "os" - "strings" -) - -// Initialized reports whether the CPU features were initialized. -// -// For some GOOS/GOARCH combinations initialization of the CPU features depends -// on reading an operating specific file, e.g. /proc/self/auxv on linux/arm -// Initialized will report false if reading the file fails. -var Initialized bool - -// CacheLinePad is used to pad structs to avoid false sharing. -type CacheLinePad struct{ _ [cacheLineSize]byte } - -// X86 contains the supported CPU features of the -// current X86/AMD64 platform. If the current platform -// is not X86/AMD64 then all feature flags are false. -// -// X86 is padded to avoid false sharing. Further the HasAVX -// and HasAVX2 are only set if the OS supports XMM and YMM -// registers in addition to the CPUID feature bit being set. -var X86 struct { - _ CacheLinePad - HasAES bool // AES hardware implementation (AES NI) - HasADX bool // Multi-precision add-carry instruction extensions - HasAVX bool // Advanced vector extension - HasAVX2 bool // Advanced vector extension 2 - HasAVX512 bool // Advanced vector extension 512 - HasAVX512F bool // Advanced vector extension 512 Foundation Instructions - HasAVX512CD bool // Advanced vector extension 512 Conflict Detection Instructions - HasAVX512ER bool // Advanced vector extension 512 Exponential and Reciprocal Instructions - HasAVX512PF bool // Advanced vector extension 512 Prefetch Instructions - HasAVX512VL bool // Advanced vector extension 512 Vector Length Extensions - HasAVX512BW bool // Advanced vector extension 512 Byte and Word Instructions - HasAVX512DQ bool // Advanced vector extension 512 Doubleword and Quadword Instructions - HasAVX512IFMA bool // Advanced vector extension 512 Integer Fused Multiply Add - HasAVX512VBMI bool // Advanced vector extension 512 Vector Byte Manipulation Instructions - HasAVX5124VNNIW bool // Advanced vector extension 512 Vector Neural Network Instructions Word variable precision - HasAVX5124FMAPS bool // Advanced vector extension 512 Fused Multiply Accumulation Packed Single precision - HasAVX512VPOPCNTDQ bool // Advanced vector extension 512 Double and quad word population count instructions - HasAVX512VPCLMULQDQ bool // Advanced vector extension 512 Vector carry-less multiply operations - HasAVX512VNNI bool // Advanced vector extension 512 Vector Neural Network Instructions - HasAVX512GFNI bool // Advanced vector extension 512 Galois field New Instructions - HasAVX512VAES bool // Advanced vector extension 512 Vector AES instructions - HasAVX512VBMI2 bool // Advanced vector extension 512 Vector Byte Manipulation Instructions 2 - HasAVX512BITALG bool // Advanced vector extension 512 Bit Algorithms - HasAVX512BF16 bool // Advanced vector extension 512 BFloat16 Instructions - HasAMXTile bool // Advanced Matrix Extension Tile instructions - HasAMXInt8 bool // Advanced Matrix Extension Int8 instructions - HasAMXBF16 bool // Advanced Matrix Extension BFloat16 instructions - HasBMI1 bool // Bit manipulation instruction set 1 - HasBMI2 bool // Bit manipulation instruction set 2 - HasCX16 bool // Compare and exchange 16 Bytes - HasERMS bool // Enhanced REP for MOVSB and STOSB - HasFMA bool // Fused-multiply-add instructions - HasOSXSAVE bool // OS supports XSAVE/XRESTOR for saving/restoring XMM registers. - HasPCLMULQDQ bool // PCLMULQDQ instruction - most often used for AES-GCM - HasPOPCNT bool // Hamming weight instruction POPCNT. - HasRDRAND bool // RDRAND instruction (on-chip random number generator) - HasRDSEED bool // RDSEED instruction (on-chip random number generator) - HasSSE2 bool // Streaming SIMD extension 2 (always available on amd64) - HasSSE3 bool // Streaming SIMD extension 3 - HasSSSE3 bool // Supplemental streaming SIMD extension 3 - HasSSE41 bool // Streaming SIMD extension 4 and 4.1 - HasSSE42 bool // Streaming SIMD extension 4 and 4.2 - HasAVXIFMA bool // Advanced vector extension Integer Fused Multiply Add - HasAVXVNNI bool // Advanced vector extension Vector Neural Network Instructions - HasAVXVNNIInt8 bool // Advanced vector extension Vector Neural Network Int8 instructions - _ CacheLinePad -} - -// ARM64 contains the supported CPU features of the -// current ARMv8(aarch64) platform. If the current platform -// is not arm64 then all feature flags are false. -var ARM64 struct { - _ CacheLinePad - HasFP bool // Floating-point instruction set (always available) - HasASIMD bool // Advanced SIMD (always available) - HasEVTSTRM bool // Event stream support - HasAES bool // AES hardware implementation - HasPMULL bool // Polynomial multiplication instruction set - HasSHA1 bool // SHA1 hardware implementation - HasSHA2 bool // SHA2 hardware implementation - HasCRC32 bool // CRC32 hardware implementation - HasATOMICS bool // Atomic memory operation instruction set - HasFPHP bool // Half precision floating-point instruction set - HasASIMDHP bool // Advanced SIMD half precision instruction set - HasCPUID bool // CPUID identification scheme registers - HasASIMDRDM bool // Rounding double multiply add/subtract instruction set - HasJSCVT bool // Javascript conversion from floating-point to integer - HasFCMA bool // Floating-point multiplication and addition of complex numbers - HasLRCPC bool // Release Consistent processor consistent support - HasDCPOP bool // Persistent memory support - HasSHA3 bool // SHA3 hardware implementation - HasSM3 bool // SM3 hardware implementation - HasSM4 bool // SM4 hardware implementation - HasASIMDDP bool // Advanced SIMD double precision instruction set - HasSHA512 bool // SHA512 hardware implementation - HasSVE bool // Scalable Vector Extensions - HasSVE2 bool // Scalable Vector Extensions 2 - HasASIMDFHM bool // Advanced SIMD multiplication FP16 to FP32 - HasDIT bool // Data Independent Timing support - HasI8MM bool // Advanced SIMD Int8 matrix multiplication instructions - _ CacheLinePad -} - -// ARM contains the supported CPU features of the current ARM (32-bit) platform. -// All feature flags are false if: -// 1. the current platform is not arm, or -// 2. the current operating system is not Linux. -var ARM struct { - _ CacheLinePad - HasSWP bool // SWP instruction support - HasHALF bool // Half-word load and store support - HasTHUMB bool // ARM Thumb instruction set - Has26BIT bool // Address space limited to 26-bits - HasFASTMUL bool // 32-bit operand, 64-bit result multiplication support - HasFPA bool // Floating point arithmetic support - HasVFP bool // Vector floating point support - HasEDSP bool // DSP Extensions support - HasJAVA bool // Java instruction set - HasIWMMXT bool // Intel Wireless MMX technology support - HasCRUNCH bool // MaverickCrunch context switching and handling - HasTHUMBEE bool // Thumb EE instruction set - HasNEON bool // NEON instruction set - HasVFPv3 bool // Vector floating point version 3 support - HasVFPv3D16 bool // Vector floating point version 3 D8-D15 - HasTLS bool // Thread local storage support - HasVFPv4 bool // Vector floating point version 4 support - HasIDIVA bool // Integer divide instruction support in ARM mode - HasIDIVT bool // Integer divide instruction support in Thumb mode - HasVFPD32 bool // Vector floating point version 3 D15-D31 - HasLPAE bool // Large Physical Address Extensions - HasEVTSTRM bool // Event stream support - HasAES bool // AES hardware implementation - HasPMULL bool // Polynomial multiplication instruction set - HasSHA1 bool // SHA1 hardware implementation - HasSHA2 bool // SHA2 hardware implementation - HasCRC32 bool // CRC32 hardware implementation - _ CacheLinePad -} - -// The booleans in Loong64 contain the correspondingly named cpu feature bit. -// The struct is padded to avoid false sharing. -var Loong64 struct { - _ CacheLinePad - HasLSX bool // support 128-bit vector extension - HasLASX bool // support 256-bit vector extension - HasCRC32 bool // support CRC instruction - HasLAM_BH bool // support AM{SWAP/ADD}[_DB].{B/H} instruction - HasLAMCAS bool // support AMCAS[_DB].{B/H/W/D} instruction - _ CacheLinePad -} - -// MIPS64X contains the supported CPU features of the current mips64/mips64le -// platforms. If the current platform is not mips64/mips64le or the current -// operating system is not Linux then all feature flags are false. -var MIPS64X struct { - _ CacheLinePad - HasMSA bool // MIPS SIMD architecture - _ CacheLinePad -} - -// PPC64 contains the supported CPU features of the current ppc64/ppc64le platforms. -// If the current platform is not ppc64/ppc64le then all feature flags are false. -// -// For ppc64/ppc64le, it is safe to check only for ISA level starting on ISA v3.00, -// since there are no optional categories. There are some exceptions that also -// require kernel support to work (DARN, SCV), so there are feature bits for -// those as well. The struct is padded to avoid false sharing. -var PPC64 struct { - _ CacheLinePad - HasDARN bool // Hardware random number generator (requires kernel enablement) - HasSCV bool // Syscall vectored (requires kernel enablement) - IsPOWER8 bool // ISA v2.07 (POWER8) - IsPOWER9 bool // ISA v3.00 (POWER9), implies IsPOWER8 - _ CacheLinePad -} - -// S390X contains the supported CPU features of the current IBM Z -// (s390x) platform. If the current platform is not IBM Z then all -// feature flags are false. -// -// S390X is padded to avoid false sharing. Further HasVX is only set -// if the OS supports vector registers in addition to the STFLE -// feature bit being set. -var S390X struct { - _ CacheLinePad - HasZARCH bool // z/Architecture mode is active [mandatory] - HasSTFLE bool // store facility list extended - HasLDISP bool // long (20-bit) displacements - HasEIMM bool // 32-bit immediates - HasDFP bool // decimal floating point - HasETF3EH bool // ETF-3 enhanced - HasMSA bool // message security assist (CPACF) - HasAES bool // KM-AES{128,192,256} functions - HasAESCBC bool // KMC-AES{128,192,256} functions - HasAESCTR bool // KMCTR-AES{128,192,256} functions - HasAESGCM bool // KMA-GCM-AES{128,192,256} functions - HasGHASH bool // KIMD-GHASH function - HasSHA1 bool // K{I,L}MD-SHA-1 functions - HasSHA256 bool // K{I,L}MD-SHA-256 functions - HasSHA512 bool // K{I,L}MD-SHA-512 functions - HasSHA3 bool // K{I,L}MD-SHA3-{224,256,384,512} and K{I,L}MD-SHAKE-{128,256} functions - HasVX bool // vector facility - HasVXE bool // vector-enhancements facility 1 - _ CacheLinePad -} - -// RISCV64 contains the supported CPU features and performance characteristics for riscv64 -// platforms. The booleans in RISCV64, with the exception of HasFastMisaligned, indicate -// the presence of RISC-V extensions. -// -// It is safe to assume that all the RV64G extensions are supported and so they are omitted from -// this structure. As riscv64 Go programs require at least RV64G, the code that populates -// this structure cannot run successfully if some of the RV64G extensions are missing. -// The struct is padded to avoid false sharing. -var RISCV64 struct { - _ CacheLinePad - HasFastMisaligned bool // Fast misaligned accesses - HasC bool // Compressed instruction-set extension - HasV bool // Vector extension compatible with RVV 1.0 - HasZba bool // Address generation instructions extension - HasZbb bool // Basic bit-manipulation extension - HasZbs bool // Single-bit instructions extension - HasZvbb bool // Vector Basic Bit-manipulation - HasZvbc bool // Vector Carryless Multiplication - HasZvkb bool // Vector Cryptography Bit-manipulation - HasZvkt bool // Vector Data-Independent Execution Latency - HasZvkg bool // Vector GCM/GMAC - HasZvkn bool // NIST Algorithm Suite (AES/SHA256/SHA512) - HasZvknc bool // NIST Algorithm Suite with carryless multiply - HasZvkng bool // NIST Algorithm Suite with GCM - HasZvks bool // ShangMi Algorithm Suite - HasZvksc bool // ShangMi Algorithm Suite with carryless multiplication - HasZvksg bool // ShangMi Algorithm Suite with GCM - _ CacheLinePad -} - -func init() { - archInit() - initOptions() - processOptions() -} - -// options contains the cpu debug options that can be used in GODEBUG. -// Options are arch dependent and are added by the arch specific initOptions functions. -// Features that are mandatory for the specific GOARCH should have the Required field set -// (e.g. SSE2 on amd64). -var options []option - -// Option names should be lower case. e.g. avx instead of AVX. -type option struct { - Name string - Feature *bool - Specified bool // whether feature value was specified in GODEBUG - Enable bool // whether feature should be enabled - Required bool // whether feature is mandatory and can not be disabled -} - -func processOptions() { - env := os.Getenv("GODEBUG") -field: - for env != "" { - field := "" - i := strings.IndexByte(env, ',') - if i < 0 { - field, env = env, "" - } else { - field, env = env[:i], env[i+1:] - } - if len(field) < 4 || field[:4] != "cpu." { - continue - } - i = strings.IndexByte(field, '=') - if i < 0 { - print("GODEBUG sys/cpu: no value specified for \"", field, "\"\n") - continue - } - key, value := field[4:i], field[i+1:] // e.g. "SSE2", "on" - - var enable bool - switch value { - case "on": - enable = true - case "off": - enable = false - default: - print("GODEBUG sys/cpu: value \"", value, "\" not supported for cpu option \"", key, "\"\n") - continue field - } - - if key == "all" { - for i := range options { - options[i].Specified = true - options[i].Enable = enable || options[i].Required - } - continue field - } - - for i := range options { - if options[i].Name == key { - options[i].Specified = true - options[i].Enable = enable - continue field - } - } - - print("GODEBUG sys/cpu: unknown cpu feature \"", key, "\"\n") - } - - for _, o := range options { - if !o.Specified { - continue - } - - if o.Enable && !*o.Feature { - print("GODEBUG sys/cpu: can not enable \"", o.Name, "\", missing CPU support\n") - continue - } - - if !o.Enable && o.Required { - print("GODEBUG sys/cpu: can not disable \"", o.Name, "\", required CPU feature\n") - continue - } - - *o.Feature = o.Enable - } -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_aix.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_aix.go deleted file mode 100644 index 9bf0c32..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_aix.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build aix - -package cpu - -const ( - // getsystemcfg constants - _SC_IMPL = 2 - _IMPL_POWER8 = 0x10000 - _IMPL_POWER9 = 0x20000 -) - -func archInit() { - impl := getsystemcfg(_SC_IMPL) - if impl&_IMPL_POWER8 != 0 { - PPC64.IsPOWER8 = true - } - if impl&_IMPL_POWER9 != 0 { - PPC64.IsPOWER8 = true - PPC64.IsPOWER9 = true - } - - Initialized = true -} - -func getsystemcfg(label int) (n uint64) { - r0, _ := callgetsystemcfg(label) - n = uint64(r0) - return -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_arm.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_arm.go deleted file mode 100644 index 301b752..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_arm.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -const cacheLineSize = 32 - -// HWCAP/HWCAP2 bits. -// These are specific to Linux. -const ( - hwcap_SWP = 1 << 0 - hwcap_HALF = 1 << 1 - hwcap_THUMB = 1 << 2 - hwcap_26BIT = 1 << 3 - hwcap_FAST_MULT = 1 << 4 - hwcap_FPA = 1 << 5 - hwcap_VFP = 1 << 6 - hwcap_EDSP = 1 << 7 - hwcap_JAVA = 1 << 8 - hwcap_IWMMXT = 1 << 9 - hwcap_CRUNCH = 1 << 10 - hwcap_THUMBEE = 1 << 11 - hwcap_NEON = 1 << 12 - hwcap_VFPv3 = 1 << 13 - hwcap_VFPv3D16 = 1 << 14 - hwcap_TLS = 1 << 15 - hwcap_VFPv4 = 1 << 16 - hwcap_IDIVA = 1 << 17 - hwcap_IDIVT = 1 << 18 - hwcap_VFPD32 = 1 << 19 - hwcap_LPAE = 1 << 20 - hwcap_EVTSTRM = 1 << 21 - - hwcap2_AES = 1 << 0 - hwcap2_PMULL = 1 << 1 - hwcap2_SHA1 = 1 << 2 - hwcap2_SHA2 = 1 << 3 - hwcap2_CRC32 = 1 << 4 -) - -func initOptions() { - options = []option{ - {Name: "pmull", Feature: &ARM.HasPMULL}, - {Name: "sha1", Feature: &ARM.HasSHA1}, - {Name: "sha2", Feature: &ARM.HasSHA2}, - {Name: "swp", Feature: &ARM.HasSWP}, - {Name: "thumb", Feature: &ARM.HasTHUMB}, - {Name: "thumbee", Feature: &ARM.HasTHUMBEE}, - {Name: "tls", Feature: &ARM.HasTLS}, - {Name: "vfp", Feature: &ARM.HasVFP}, - {Name: "vfpd32", Feature: &ARM.HasVFPD32}, - {Name: "vfpv3", Feature: &ARM.HasVFPv3}, - {Name: "vfpv3d16", Feature: &ARM.HasVFPv3D16}, - {Name: "vfpv4", Feature: &ARM.HasVFPv4}, - {Name: "half", Feature: &ARM.HasHALF}, - {Name: "26bit", Feature: &ARM.Has26BIT}, - {Name: "fastmul", Feature: &ARM.HasFASTMUL}, - {Name: "fpa", Feature: &ARM.HasFPA}, - {Name: "edsp", Feature: &ARM.HasEDSP}, - {Name: "java", Feature: &ARM.HasJAVA}, - {Name: "iwmmxt", Feature: &ARM.HasIWMMXT}, - {Name: "crunch", Feature: &ARM.HasCRUNCH}, - {Name: "neon", Feature: &ARM.HasNEON}, - {Name: "idivt", Feature: &ARM.HasIDIVT}, - {Name: "idiva", Feature: &ARM.HasIDIVA}, - {Name: "lpae", Feature: &ARM.HasLPAE}, - {Name: "evtstrm", Feature: &ARM.HasEVTSTRM}, - {Name: "aes", Feature: &ARM.HasAES}, - {Name: "crc32", Feature: &ARM.HasCRC32}, - } - -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_arm64.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_arm64.go deleted file mode 100644 index af2aa99..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_arm64.go +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -import "runtime" - -// cacheLineSize is used to prevent false sharing of cache lines. -// We choose 128 because Apple Silicon, a.k.a. M1, has 128-byte cache line size. -// It doesn't cost much and is much more future-proof. -const cacheLineSize = 128 - -func initOptions() { - options = []option{ - {Name: "fp", Feature: &ARM64.HasFP}, - {Name: "asimd", Feature: &ARM64.HasASIMD}, - {Name: "evstrm", Feature: &ARM64.HasEVTSTRM}, - {Name: "aes", Feature: &ARM64.HasAES}, - {Name: "fphp", Feature: &ARM64.HasFPHP}, - {Name: "jscvt", Feature: &ARM64.HasJSCVT}, - {Name: "lrcpc", Feature: &ARM64.HasLRCPC}, - {Name: "pmull", Feature: &ARM64.HasPMULL}, - {Name: "sha1", Feature: &ARM64.HasSHA1}, - {Name: "sha2", Feature: &ARM64.HasSHA2}, - {Name: "sha3", Feature: &ARM64.HasSHA3}, - {Name: "sha512", Feature: &ARM64.HasSHA512}, - {Name: "sm3", Feature: &ARM64.HasSM3}, - {Name: "sm4", Feature: &ARM64.HasSM4}, - {Name: "sve", Feature: &ARM64.HasSVE}, - {Name: "sve2", Feature: &ARM64.HasSVE2}, - {Name: "crc32", Feature: &ARM64.HasCRC32}, - {Name: "atomics", Feature: &ARM64.HasATOMICS}, - {Name: "asimdhp", Feature: &ARM64.HasASIMDHP}, - {Name: "cpuid", Feature: &ARM64.HasCPUID}, - {Name: "asimrdm", Feature: &ARM64.HasASIMDRDM}, - {Name: "fcma", Feature: &ARM64.HasFCMA}, - {Name: "dcpop", Feature: &ARM64.HasDCPOP}, - {Name: "asimddp", Feature: &ARM64.HasASIMDDP}, - {Name: "asimdfhm", Feature: &ARM64.HasASIMDFHM}, - {Name: "dit", Feature: &ARM64.HasDIT}, - {Name: "i8mm", Feature: &ARM64.HasI8MM}, - } -} - -func archInit() { - switch runtime.GOOS { - case "freebsd": - readARM64Registers() - case "linux", "netbsd", "openbsd": - doinit() - default: - // Many platforms don't seem to allow reading these registers. - setMinimalFeatures() - } -} - -// setMinimalFeatures fakes the minimal ARM64 features expected by -// TestARM64minimalFeatures. -func setMinimalFeatures() { - ARM64.HasASIMD = true - ARM64.HasFP = true -} - -func readARM64Registers() { - Initialized = true - - parseARM64SystemRegisters(getisar0(), getisar1(), getpfr0()) -} - -func parseARM64SystemRegisters(isar0, isar1, pfr0 uint64) { - // ID_AA64ISAR0_EL1 - switch extractBits(isar0, 4, 7) { - case 1: - ARM64.HasAES = true - case 2: - ARM64.HasAES = true - ARM64.HasPMULL = true - } - - switch extractBits(isar0, 8, 11) { - case 1: - ARM64.HasSHA1 = true - } - - switch extractBits(isar0, 12, 15) { - case 1: - ARM64.HasSHA2 = true - case 2: - ARM64.HasSHA2 = true - ARM64.HasSHA512 = true - } - - switch extractBits(isar0, 16, 19) { - case 1: - ARM64.HasCRC32 = true - } - - switch extractBits(isar0, 20, 23) { - case 2: - ARM64.HasATOMICS = true - } - - switch extractBits(isar0, 28, 31) { - case 1: - ARM64.HasASIMDRDM = true - } - - switch extractBits(isar0, 32, 35) { - case 1: - ARM64.HasSHA3 = true - } - - switch extractBits(isar0, 36, 39) { - case 1: - ARM64.HasSM3 = true - } - - switch extractBits(isar0, 40, 43) { - case 1: - ARM64.HasSM4 = true - } - - switch extractBits(isar0, 44, 47) { - case 1: - ARM64.HasASIMDDP = true - } - - // ID_AA64ISAR1_EL1 - switch extractBits(isar1, 0, 3) { - case 1: - ARM64.HasDCPOP = true - } - - switch extractBits(isar1, 12, 15) { - case 1: - ARM64.HasJSCVT = true - } - - switch extractBits(isar1, 16, 19) { - case 1: - ARM64.HasFCMA = true - } - - switch extractBits(isar1, 20, 23) { - case 1: - ARM64.HasLRCPC = true - } - - switch extractBits(isar1, 52, 55) { - case 1: - ARM64.HasI8MM = true - } - - // ID_AA64PFR0_EL1 - switch extractBits(pfr0, 16, 19) { - case 0: - ARM64.HasFP = true - case 1: - ARM64.HasFP = true - ARM64.HasFPHP = true - } - - switch extractBits(pfr0, 20, 23) { - case 0: - ARM64.HasASIMD = true - case 1: - ARM64.HasASIMD = true - ARM64.HasASIMDHP = true - } - - switch extractBits(pfr0, 32, 35) { - case 1: - ARM64.HasSVE = true - - parseARM64SVERegister(getzfr0()) - } - - switch extractBits(pfr0, 48, 51) { - case 1: - ARM64.HasDIT = true - } -} - -func parseARM64SVERegister(zfr0 uint64) { - switch extractBits(zfr0, 0, 3) { - case 1: - ARM64.HasSVE2 = true - } -} - -func extractBits(data uint64, start, end uint) uint { - return (uint)(data>>start) & ((1 << (end - start + 1)) - 1) -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_arm64.s b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_arm64.s deleted file mode 100644 index 3b0450a..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_arm64.s +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build gc - -#include "textflag.h" - -// func getisar0() uint64 -TEXT ·getisar0(SB),NOSPLIT,$0-8 - // get Instruction Set Attributes 0 into x0 - MRS ID_AA64ISAR0_EL1, R0 - MOVD R0, ret+0(FP) - RET - -// func getisar1() uint64 -TEXT ·getisar1(SB),NOSPLIT,$0-8 - // get Instruction Set Attributes 1 into x0 - MRS ID_AA64ISAR1_EL1, R0 - MOVD R0, ret+0(FP) - RET - -// func getpfr0() uint64 -TEXT ·getpfr0(SB),NOSPLIT,$0-8 - // get Processor Feature Register 0 into x0 - MRS ID_AA64PFR0_EL1, R0 - MOVD R0, ret+0(FP) - RET - -// func getzfr0() uint64 -TEXT ·getzfr0(SB),NOSPLIT,$0-8 - // get SVE Feature Register 0 into x0 - MRS ID_AA64ZFR0_EL1, R0 - MOVD R0, ret+0(FP) - RET diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go deleted file mode 100644 index b838cb9..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2024 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build darwin && amd64 && gc - -package cpu - -// darwinSupportsAVX512 checks Darwin kernel for AVX512 support via sysctl -// call (see issue 43089). It also restricts AVX512 support for Darwin to -// kernel version 21.3.0 (MacOS 12.2.0) or later (see issue 49233). -// -// Background: -// Darwin implements a special mechanism to economize on thread state when -// AVX512 specific registers are not in use. This scheme minimizes state when -// preempting threads that haven't yet used any AVX512 instructions, but adds -// special requirements to check for AVX512 hardware support at runtime (e.g. -// via sysctl call or commpage inspection). See issue 43089 and link below for -// full background: -// https://github.com/apple-oss-distributions/xnu/blob/xnu-11215.1.10/osfmk/i386/fpu.c#L214-L240 -// -// Additionally, all versions of the Darwin kernel from 19.6.0 through 21.2.0 -// (corresponding to MacOS 10.15.6 - 12.1) have a bug that can cause corruption -// of the AVX512 mask registers (K0-K7) upon signal return. For this reason -// AVX512 is considered unsafe to use on Darwin for kernel versions prior to -// 21.3.0, where a fix has been confirmed. See issue 49233 for full background. -func darwinSupportsAVX512() bool { - return darwinSysctlEnabled([]byte("hw.optional.avx512f\x00")) && darwinKernelVersionCheck(21, 3, 0) -} - -// Ensure Darwin kernel version is at least major.minor.patch, avoiding dependencies -func darwinKernelVersionCheck(major, minor, patch int) bool { - var release [256]byte - err := darwinOSRelease(&release) - if err != nil { - return false - } - - var mmp [3]int - c := 0 -Loop: - for _, b := range release[:] { - switch { - case b >= '0' && b <= '9': - mmp[c] = 10*mmp[c] + int(b-'0') - case b == '.': - c++ - if c > 2 { - return false - } - case b == 0: - break Loop - default: - return false - } - } - if c != 2 { - return false - } - return mmp[0] > major || mmp[0] == major && (mmp[1] > minor || mmp[1] == minor && mmp[2] >= patch) -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go deleted file mode 100644 index 6ac6e1e..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build gc - -package cpu - -func getisar0() uint64 -func getisar1() uint64 -func getpfr0() uint64 -func getzfr0() uint64 diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go deleted file mode 100644 index c8ae6dd..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build gc - -package cpu - -// haveAsmFunctions reports whether the other functions in this file can -// be safely called. -func haveAsmFunctions() bool { return true } - -// The following feature detection functions are defined in cpu_s390x.s. -// They are likely to be expensive to call so the results should be cached. -func stfle() facilityList -func kmQuery() queryResult -func kmcQuery() queryResult -func kmctrQuery() queryResult -func kmaQuery() queryResult -func kimdQuery() queryResult -func klmdQuery() queryResult diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go deleted file mode 100644 index 32a4451..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build (386 || amd64 || amd64p32) && gc - -package cpu - -// cpuid is implemented in cpu_gc_x86.s for gc compiler -// and in cpu_gccgo.c for gccgo. -func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) - -// xgetbv with ecx = 0 is implemented in cpu_gc_x86.s for gc compiler -// and in cpu_gccgo.c for gccgo. -func xgetbv() (eax, edx uint32) diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gc_x86.s b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gc_x86.s deleted file mode 100644 index ce208ce..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gc_x86.s +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build (386 || amd64 || amd64p32) && gc - -#include "textflag.h" - -// func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) -TEXT ·cpuid(SB), NOSPLIT, $0-24 - MOVL eaxArg+0(FP), AX - MOVL ecxArg+4(FP), CX - CPUID - MOVL AX, eax+8(FP) - MOVL BX, ebx+12(FP) - MOVL CX, ecx+16(FP) - MOVL DX, edx+20(FP) - RET - -// func xgetbv() (eax, edx uint32) -TEXT ·xgetbv(SB), NOSPLIT, $0-8 - MOVL $0, CX - XGETBV - MOVL AX, eax+0(FP) - MOVL DX, edx+4(FP) - RET diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go deleted file mode 100644 index 7f19467..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build gccgo - -package cpu - -func getisar0() uint64 { return 0 } -func getisar1() uint64 { return 0 } -func getpfr0() uint64 { return 0 } diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go deleted file mode 100644 index 9526d2c..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build gccgo - -package cpu - -// haveAsmFunctions reports whether the other functions in this file can -// be safely called. -func haveAsmFunctions() bool { return false } - -// TODO(mundaym): the following feature detection functions are currently -// stubs. See https://golang.org/cl/162887 for how to fix this. -// They are likely to be expensive to call so the results should be cached. -func stfle() facilityList { panic("not implemented for gccgo") } -func kmQuery() queryResult { panic("not implemented for gccgo") } -func kmcQuery() queryResult { panic("not implemented for gccgo") } -func kmctrQuery() queryResult { panic("not implemented for gccgo") } -func kmaQuery() queryResult { panic("not implemented for gccgo") } -func kimdQuery() queryResult { panic("not implemented for gccgo") } -func klmdQuery() queryResult { panic("not implemented for gccgo") } diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c deleted file mode 100644 index 3f73a05..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build (386 || amd64 || amd64p32) && gccgo - -#include -#include -#include - -// Need to wrap __get_cpuid_count because it's declared as static. -int -gccgoGetCpuidCount(uint32_t leaf, uint32_t subleaf, - uint32_t *eax, uint32_t *ebx, - uint32_t *ecx, uint32_t *edx) -{ - return __get_cpuid_count(leaf, subleaf, eax, ebx, ecx, edx); -} - -#pragma GCC diagnostic ignored "-Wunknown-pragmas" -#pragma GCC push_options -#pragma GCC target("xsave") -#pragma clang attribute push (__attribute__((target("xsave"))), apply_to=function) - -// xgetbv reads the contents of an XCR (Extended Control Register) -// specified in the ECX register into registers EDX:EAX. -// Currently, the only supported value for XCR is 0. -void -gccgoXgetbv(uint32_t *eax, uint32_t *edx) -{ - uint64_t v = _xgetbv(0); - *eax = v & 0xffffffff; - *edx = v >> 32; -} - -#pragma clang attribute pop -#pragma GCC pop_options diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go deleted file mode 100644 index 170d21d..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build (386 || amd64 || amd64p32) && gccgo - -package cpu - -//extern gccgoGetCpuidCount -func gccgoGetCpuidCount(eaxArg, ecxArg uint32, eax, ebx, ecx, edx *uint32) - -func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) { - var a, b, c, d uint32 - gccgoGetCpuidCount(eaxArg, ecxArg, &a, &b, &c, &d) - return a, b, c, d -} - -//extern gccgoXgetbv -func gccgoXgetbv(eax, edx *uint32) - -func xgetbv() (eax, edx uint32) { - var a, d uint32 - gccgoXgetbv(&a, &d) - return a, d -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux.go deleted file mode 100644 index 743eb54..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !386 && !amd64 && !amd64p32 && !arm64 - -package cpu - -func archInit() { - if err := readHWCAP(); err != nil { - return - } - doinit() - Initialized = true -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_arm.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_arm.go deleted file mode 100644 index 2057006..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_arm.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -func doinit() { - ARM.HasSWP = isSet(hwCap, hwcap_SWP) - ARM.HasHALF = isSet(hwCap, hwcap_HALF) - ARM.HasTHUMB = isSet(hwCap, hwcap_THUMB) - ARM.Has26BIT = isSet(hwCap, hwcap_26BIT) - ARM.HasFASTMUL = isSet(hwCap, hwcap_FAST_MULT) - ARM.HasFPA = isSet(hwCap, hwcap_FPA) - ARM.HasVFP = isSet(hwCap, hwcap_VFP) - ARM.HasEDSP = isSet(hwCap, hwcap_EDSP) - ARM.HasJAVA = isSet(hwCap, hwcap_JAVA) - ARM.HasIWMMXT = isSet(hwCap, hwcap_IWMMXT) - ARM.HasCRUNCH = isSet(hwCap, hwcap_CRUNCH) - ARM.HasTHUMBEE = isSet(hwCap, hwcap_THUMBEE) - ARM.HasNEON = isSet(hwCap, hwcap_NEON) - ARM.HasVFPv3 = isSet(hwCap, hwcap_VFPv3) - ARM.HasVFPv3D16 = isSet(hwCap, hwcap_VFPv3D16) - ARM.HasTLS = isSet(hwCap, hwcap_TLS) - ARM.HasVFPv4 = isSet(hwCap, hwcap_VFPv4) - ARM.HasIDIVA = isSet(hwCap, hwcap_IDIVA) - ARM.HasIDIVT = isSet(hwCap, hwcap_IDIVT) - ARM.HasVFPD32 = isSet(hwCap, hwcap_VFPD32) - ARM.HasLPAE = isSet(hwCap, hwcap_LPAE) - ARM.HasEVTSTRM = isSet(hwCap, hwcap_EVTSTRM) - ARM.HasAES = isSet(hwCap2, hwcap2_AES) - ARM.HasPMULL = isSet(hwCap2, hwcap2_PMULL) - ARM.HasSHA1 = isSet(hwCap2, hwcap2_SHA1) - ARM.HasSHA2 = isSet(hwCap2, hwcap2_SHA2) - ARM.HasCRC32 = isSet(hwCap2, hwcap2_CRC32) -} - -func isSet(hwc uint, value uint) bool { - return hwc&value != 0 -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go deleted file mode 100644 index f1caf0f..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -import ( - "strings" - "syscall" -) - -// HWCAP/HWCAP2 bits. These are exposed by Linux. -const ( - hwcap_FP = 1 << 0 - hwcap_ASIMD = 1 << 1 - hwcap_EVTSTRM = 1 << 2 - hwcap_AES = 1 << 3 - hwcap_PMULL = 1 << 4 - hwcap_SHA1 = 1 << 5 - hwcap_SHA2 = 1 << 6 - hwcap_CRC32 = 1 << 7 - hwcap_ATOMICS = 1 << 8 - hwcap_FPHP = 1 << 9 - hwcap_ASIMDHP = 1 << 10 - hwcap_CPUID = 1 << 11 - hwcap_ASIMDRDM = 1 << 12 - hwcap_JSCVT = 1 << 13 - hwcap_FCMA = 1 << 14 - hwcap_LRCPC = 1 << 15 - hwcap_DCPOP = 1 << 16 - hwcap_SHA3 = 1 << 17 - hwcap_SM3 = 1 << 18 - hwcap_SM4 = 1 << 19 - hwcap_ASIMDDP = 1 << 20 - hwcap_SHA512 = 1 << 21 - hwcap_SVE = 1 << 22 - hwcap_ASIMDFHM = 1 << 23 - hwcap_DIT = 1 << 24 - - hwcap2_SVE2 = 1 << 1 - hwcap2_I8MM = 1 << 13 -) - -// linuxKernelCanEmulateCPUID reports whether we're running -// on Linux 4.11+. Ideally we'd like to ask the question about -// whether the current kernel contains -// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=77c97b4ee21290f5f083173d957843b615abbff2 -// but the version number will have to do. -func linuxKernelCanEmulateCPUID() bool { - var un syscall.Utsname - syscall.Uname(&un) - var sb strings.Builder - for _, b := range un.Release[:] { - if b == 0 { - break - } - sb.WriteByte(byte(b)) - } - major, minor, _, ok := parseRelease(sb.String()) - return ok && (major > 4 || major == 4 && minor >= 11) -} - -func doinit() { - if err := readHWCAP(); err != nil { - // We failed to read /proc/self/auxv. This can happen if the binary has - // been given extra capabilities(7) with /bin/setcap. - // - // When this happens, we have two options. If the Linux kernel is new - // enough (4.11+), we can read the arm64 registers directly which'll - // trap into the kernel and then return back to userspace. - // - // But on older kernels, such as Linux 4.4.180 as used on many Synology - // devices, calling readARM64Registers (specifically getisar0) will - // cause a SIGILL and we'll die. So for older kernels, parse /proc/cpuinfo - // instead. - // - // See golang/go#57336. - if linuxKernelCanEmulateCPUID() { - readARM64Registers() - } else { - readLinuxProcCPUInfo() - } - return - } - - // HWCAP feature bits - ARM64.HasFP = isSet(hwCap, hwcap_FP) - ARM64.HasASIMD = isSet(hwCap, hwcap_ASIMD) - ARM64.HasEVTSTRM = isSet(hwCap, hwcap_EVTSTRM) - ARM64.HasAES = isSet(hwCap, hwcap_AES) - ARM64.HasPMULL = isSet(hwCap, hwcap_PMULL) - ARM64.HasSHA1 = isSet(hwCap, hwcap_SHA1) - ARM64.HasSHA2 = isSet(hwCap, hwcap_SHA2) - ARM64.HasCRC32 = isSet(hwCap, hwcap_CRC32) - ARM64.HasATOMICS = isSet(hwCap, hwcap_ATOMICS) - ARM64.HasFPHP = isSet(hwCap, hwcap_FPHP) - ARM64.HasASIMDHP = isSet(hwCap, hwcap_ASIMDHP) - ARM64.HasCPUID = isSet(hwCap, hwcap_CPUID) - ARM64.HasASIMDRDM = isSet(hwCap, hwcap_ASIMDRDM) - ARM64.HasJSCVT = isSet(hwCap, hwcap_JSCVT) - ARM64.HasFCMA = isSet(hwCap, hwcap_FCMA) - ARM64.HasLRCPC = isSet(hwCap, hwcap_LRCPC) - ARM64.HasDCPOP = isSet(hwCap, hwcap_DCPOP) - ARM64.HasSHA3 = isSet(hwCap, hwcap_SHA3) - ARM64.HasSM3 = isSet(hwCap, hwcap_SM3) - ARM64.HasSM4 = isSet(hwCap, hwcap_SM4) - ARM64.HasASIMDDP = isSet(hwCap, hwcap_ASIMDDP) - ARM64.HasSHA512 = isSet(hwCap, hwcap_SHA512) - ARM64.HasSVE = isSet(hwCap, hwcap_SVE) - ARM64.HasASIMDFHM = isSet(hwCap, hwcap_ASIMDFHM) - ARM64.HasDIT = isSet(hwCap, hwcap_DIT) - - // HWCAP2 feature bits - ARM64.HasSVE2 = isSet(hwCap2, hwcap2_SVE2) - ARM64.HasI8MM = isSet(hwCap2, hwcap2_I8MM) -} - -func isSet(hwc uint, value uint) bool { - return hwc&value != 0 -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_loong64.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_loong64.go deleted file mode 100644 index 4f34114..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_loong64.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2025 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -// HWCAP bits. These are exposed by the Linux kernel. -const ( - hwcap_LOONGARCH_LSX = 1 << 4 - hwcap_LOONGARCH_LASX = 1 << 5 -) - -func doinit() { - // TODO: Features that require kernel support like LSX and LASX can - // be detected here once needed in std library or by the compiler. - Loong64.HasLSX = hwcIsSet(hwCap, hwcap_LOONGARCH_LSX) - Loong64.HasLASX = hwcIsSet(hwCap, hwcap_LOONGARCH_LASX) -} - -func hwcIsSet(hwc uint, val uint) bool { - return hwc&val != 0 -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_mips64x.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_mips64x.go deleted file mode 100644 index 4686c1d..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_mips64x.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build linux && (mips64 || mips64le) - -package cpu - -// HWCAP bits. These are exposed by the Linux kernel 5.4. -const ( - // CPU features - hwcap_MIPS_MSA = 1 << 1 -) - -func doinit() { - // HWCAP feature bits - MIPS64X.HasMSA = isSet(hwCap, hwcap_MIPS_MSA) -} - -func isSet(hwc uint, value uint) bool { - return hwc&value != 0 -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go deleted file mode 100644 index a428dec..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build linux && !arm && !arm64 && !loong64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !s390x && !riscv64 - -package cpu - -func doinit() {} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go deleted file mode 100644 index 197188e..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build linux && (ppc64 || ppc64le) - -package cpu - -// HWCAP/HWCAP2 bits. These are exposed by the kernel. -const ( - // ISA Level - _PPC_FEATURE2_ARCH_2_07 = 0x80000000 - _PPC_FEATURE2_ARCH_3_00 = 0x00800000 - - // CPU features - _PPC_FEATURE2_DARN = 0x00200000 - _PPC_FEATURE2_SCV = 0x00100000 -) - -func doinit() { - // HWCAP2 feature bits - PPC64.IsPOWER8 = isSet(hwCap2, _PPC_FEATURE2_ARCH_2_07) - PPC64.IsPOWER9 = isSet(hwCap2, _PPC_FEATURE2_ARCH_3_00) - PPC64.HasDARN = isSet(hwCap2, _PPC_FEATURE2_DARN) - PPC64.HasSCV = isSet(hwCap2, _PPC_FEATURE2_SCV) -} - -func isSet(hwc uint, value uint) bool { - return hwc&value != 0 -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go deleted file mode 100644 index ad74153..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2024 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -import ( - "syscall" - "unsafe" -) - -// RISC-V extension discovery code for Linux. The approach here is to first try the riscv_hwprobe -// syscall falling back to HWCAP to check for the C extension if riscv_hwprobe is not available. -// -// A note on detection of the Vector extension using HWCAP. -// -// Support for the Vector extension version 1.0 was added to the Linux kernel in release 6.5. -// Support for the riscv_hwprobe syscall was added in 6.4. It follows that if the riscv_hwprobe -// syscall is not available then neither is the Vector extension (which needs kernel support). -// The riscv_hwprobe syscall should then be all we need to detect the Vector extension. -// However, some RISC-V board manufacturers ship boards with an older kernel on top of which -// they have back-ported various versions of the Vector extension patches but not the riscv_hwprobe -// patches. These kernels advertise support for the Vector extension using HWCAP. Falling -// back to HWCAP to detect the Vector extension, if riscv_hwprobe is not available, or simply not -// bothering with riscv_hwprobe at all and just using HWCAP may then seem like an attractive option. -// -// Unfortunately, simply checking the 'V' bit in AT_HWCAP will not work as this bit is used by -// RISC-V board and cloud instance providers to mean different things. The Lichee Pi 4A board -// and the Scaleway RV1 cloud instances use the 'V' bit to advertise their support for the unratified -// 0.7.1 version of the Vector Specification. The Banana Pi BPI-F3 and the CanMV-K230 board use -// it to advertise support for 1.0 of the Vector extension. Versions 0.7.1 and 1.0 of the Vector -// extension are binary incompatible. HWCAP can then not be used in isolation to populate the -// HasV field as this field indicates that the underlying CPU is compatible with RVV 1.0. -// -// There is a way at runtime to distinguish between versions 0.7.1 and 1.0 of the Vector -// specification by issuing a RVV 1.0 vsetvli instruction and checking the vill bit of the vtype -// register. This check would allow us to safely detect version 1.0 of the Vector extension -// with HWCAP, if riscv_hwprobe were not available. However, the check cannot -// be added until the assembler supports the Vector instructions. -// -// Note the riscv_hwprobe syscall does not suffer from these ambiguities by design as all of the -// extensions it advertises support for are explicitly versioned. It's also worth noting that -// the riscv_hwprobe syscall is the only way to detect multi-letter RISC-V extensions, e.g., Zba. -// These cannot be detected using HWCAP and so riscv_hwprobe must be used to detect the majority -// of RISC-V extensions. -// -// Please see https://docs.kernel.org/arch/riscv/hwprobe.html for more information. - -// golang.org/x/sys/cpu is not allowed to depend on golang.org/x/sys/unix so we must -// reproduce the constants, types and functions needed to make the riscv_hwprobe syscall -// here. - -const ( - // Copied from golang.org/x/sys/unix/ztypes_linux_riscv64.go. - riscv_HWPROBE_KEY_IMA_EXT_0 = 0x4 - riscv_HWPROBE_IMA_C = 0x2 - riscv_HWPROBE_IMA_V = 0x4 - riscv_HWPROBE_EXT_ZBA = 0x8 - riscv_HWPROBE_EXT_ZBB = 0x10 - riscv_HWPROBE_EXT_ZBS = 0x20 - riscv_HWPROBE_EXT_ZVBB = 0x20000 - riscv_HWPROBE_EXT_ZVBC = 0x40000 - riscv_HWPROBE_EXT_ZVKB = 0x80000 - riscv_HWPROBE_EXT_ZVKG = 0x100000 - riscv_HWPROBE_EXT_ZVKNED = 0x200000 - riscv_HWPROBE_EXT_ZVKNHB = 0x800000 - riscv_HWPROBE_EXT_ZVKSED = 0x1000000 - riscv_HWPROBE_EXT_ZVKSH = 0x2000000 - riscv_HWPROBE_EXT_ZVKT = 0x4000000 - riscv_HWPROBE_KEY_CPUPERF_0 = 0x5 - riscv_HWPROBE_MISALIGNED_FAST = 0x3 - riscv_HWPROBE_MISALIGNED_MASK = 0x7 -) - -const ( - // sys_RISCV_HWPROBE is copied from golang.org/x/sys/unix/zsysnum_linux_riscv64.go. - sys_RISCV_HWPROBE = 258 -) - -// riscvHWProbePairs is copied from golang.org/x/sys/unix/ztypes_linux_riscv64.go. -type riscvHWProbePairs struct { - key int64 - value uint64 -} - -const ( - // CPU features - hwcap_RISCV_ISA_C = 1 << ('C' - 'A') -) - -func doinit() { - // A slice of key/value pair structures is passed to the RISCVHWProbe syscall. The key - // field should be initialised with one of the key constants defined above, e.g., - // RISCV_HWPROBE_KEY_IMA_EXT_0. The syscall will set the value field to the appropriate value. - // If the kernel does not recognise a key it will set the key field to -1 and the value field to 0. - - pairs := []riscvHWProbePairs{ - {riscv_HWPROBE_KEY_IMA_EXT_0, 0}, - {riscv_HWPROBE_KEY_CPUPERF_0, 0}, - } - - // This call only indicates that extensions are supported if they are implemented on all cores. - if riscvHWProbe(pairs, 0) { - if pairs[0].key != -1 { - v := uint(pairs[0].value) - RISCV64.HasC = isSet(v, riscv_HWPROBE_IMA_C) - RISCV64.HasV = isSet(v, riscv_HWPROBE_IMA_V) - RISCV64.HasZba = isSet(v, riscv_HWPROBE_EXT_ZBA) - RISCV64.HasZbb = isSet(v, riscv_HWPROBE_EXT_ZBB) - RISCV64.HasZbs = isSet(v, riscv_HWPROBE_EXT_ZBS) - RISCV64.HasZvbb = isSet(v, riscv_HWPROBE_EXT_ZVBB) - RISCV64.HasZvbc = isSet(v, riscv_HWPROBE_EXT_ZVBC) - RISCV64.HasZvkb = isSet(v, riscv_HWPROBE_EXT_ZVKB) - RISCV64.HasZvkg = isSet(v, riscv_HWPROBE_EXT_ZVKG) - RISCV64.HasZvkt = isSet(v, riscv_HWPROBE_EXT_ZVKT) - // Cryptography shorthand extensions - RISCV64.HasZvkn = isSet(v, riscv_HWPROBE_EXT_ZVKNED) && - isSet(v, riscv_HWPROBE_EXT_ZVKNHB) && RISCV64.HasZvkb && RISCV64.HasZvkt - RISCV64.HasZvknc = RISCV64.HasZvkn && RISCV64.HasZvbc - RISCV64.HasZvkng = RISCV64.HasZvkn && RISCV64.HasZvkg - RISCV64.HasZvks = isSet(v, riscv_HWPROBE_EXT_ZVKSED) && - isSet(v, riscv_HWPROBE_EXT_ZVKSH) && RISCV64.HasZvkb && RISCV64.HasZvkt - RISCV64.HasZvksc = RISCV64.HasZvks && RISCV64.HasZvbc - RISCV64.HasZvksg = RISCV64.HasZvks && RISCV64.HasZvkg - } - if pairs[1].key != -1 { - v := pairs[1].value & riscv_HWPROBE_MISALIGNED_MASK - RISCV64.HasFastMisaligned = v == riscv_HWPROBE_MISALIGNED_FAST - } - } - - // Let's double check with HWCAP if the C extension does not appear to be supported. - // This may happen if we're running on a kernel older than 6.4. - - if !RISCV64.HasC { - RISCV64.HasC = isSet(hwCap, hwcap_RISCV_ISA_C) - } -} - -func isSet(hwc uint, value uint) bool { - return hwc&value != 0 -} - -// riscvHWProbe is a simplified version of the generated wrapper function found in -// golang.org/x/sys/unix/zsyscall_linux_riscv64.go. We simplify it by removing the -// cpuCount and cpus parameters which we do not need. We always want to pass 0 for -// these parameters here so the kernel only reports the extensions that are present -// on all cores. -func riscvHWProbe(pairs []riscvHWProbePairs, flags uint) bool { - var _zero uintptr - var p0 unsafe.Pointer - if len(pairs) > 0 { - p0 = unsafe.Pointer(&pairs[0]) - } else { - p0 = unsafe.Pointer(&_zero) - } - - _, _, e1 := syscall.Syscall6(sys_RISCV_HWPROBE, uintptr(p0), uintptr(len(pairs)), uintptr(0), uintptr(0), uintptr(flags), 0) - return e1 == 0 -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go deleted file mode 100644 index 1517ac6..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -const ( - // bit mask values from /usr/include/bits/hwcap.h - hwcap_ZARCH = 2 - hwcap_STFLE = 4 - hwcap_MSA = 8 - hwcap_LDISP = 16 - hwcap_EIMM = 32 - hwcap_DFP = 64 - hwcap_ETF3EH = 256 - hwcap_VX = 2048 - hwcap_VXE = 8192 -) - -func initS390Xbase() { - // test HWCAP bit vector - has := func(featureMask uint) bool { - return hwCap&featureMask == featureMask - } - - // mandatory - S390X.HasZARCH = has(hwcap_ZARCH) - - // optional - S390X.HasSTFLE = has(hwcap_STFLE) - S390X.HasLDISP = has(hwcap_LDISP) - S390X.HasEIMM = has(hwcap_EIMM) - S390X.HasETF3EH = has(hwcap_ETF3EH) - S390X.HasDFP = has(hwcap_DFP) - S390X.HasMSA = has(hwcap_MSA) - S390X.HasVX = has(hwcap_VX) - if S390X.HasVX { - S390X.HasVXE = has(hwcap_VXE) - } -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_loong64.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_loong64.go deleted file mode 100644 index 45ecb29..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_loong64.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build loong64 - -package cpu - -const cacheLineSize = 64 - -// Bit fields for CPUCFG registers, Related reference documents: -// https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_cpucfg -const ( - // CPUCFG1 bits - cpucfg1_CRC32 = 1 << 25 - - // CPUCFG2 bits - cpucfg2_LAM_BH = 1 << 27 - cpucfg2_LAMCAS = 1 << 28 -) - -func initOptions() { - options = []option{ - {Name: "lsx", Feature: &Loong64.HasLSX}, - {Name: "lasx", Feature: &Loong64.HasLASX}, - {Name: "crc32", Feature: &Loong64.HasCRC32}, - {Name: "lam_bh", Feature: &Loong64.HasLAM_BH}, - {Name: "lamcas", Feature: &Loong64.HasLAMCAS}, - } - - // The CPUCFG data on Loong64 only reflects the hardware capabilities, - // not the kernel support status, so features such as LSX and LASX that - // require kernel support cannot be obtained from the CPUCFG data. - // - // These features only require hardware capability support and do not - // require kernel specific support, so they can be obtained directly - // through CPUCFG - cfg1 := get_cpucfg(1) - cfg2 := get_cpucfg(2) - - Loong64.HasCRC32 = cfgIsSet(cfg1, cpucfg1_CRC32) - Loong64.HasLAMCAS = cfgIsSet(cfg2, cpucfg2_LAMCAS) - Loong64.HasLAM_BH = cfgIsSet(cfg2, cpucfg2_LAM_BH) -} - -func get_cpucfg(reg uint32) uint32 - -func cfgIsSet(cfg uint32, val uint32) bool { - return cfg&val != 0 -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_loong64.s b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_loong64.s deleted file mode 100644 index 71cbaf1..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_loong64.s +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2025 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "textflag.h" - -// func get_cpucfg(reg uint32) uint32 -TEXT ·get_cpucfg(SB), NOSPLIT|NOFRAME, $0 - MOVW reg+0(FP), R5 - // CPUCFG R5, R4 = 0x00006ca4 - WORD $0x00006ca4 - MOVW R4, ret+8(FP) - RET diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_mips64x.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_mips64x.go deleted file mode 100644 index fedb00c..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_mips64x.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build mips64 || mips64le - -package cpu - -const cacheLineSize = 32 - -func initOptions() { - options = []option{ - {Name: "msa", Feature: &MIPS64X.HasMSA}, - } -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_mipsx.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_mipsx.go deleted file mode 100644 index ffb4ec7..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_mipsx.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build mips || mipsle - -package cpu - -const cacheLineSize = 32 - -func initOptions() {} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go deleted file mode 100644 index ebfb3fc..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -import ( - "syscall" - "unsafe" -) - -// Minimal copy of functionality from x/sys/unix so the cpu package can call -// sysctl without depending on x/sys/unix. - -const ( - _CTL_QUERY = -2 - - _SYSCTL_VERS_1 = 0x1000000 -) - -var _zero uintptr - -func sysctl(mib []int32, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, errno := syscall.Syscall6( - syscall.SYS___SYSCTL, - uintptr(_p0), - uintptr(len(mib)), - uintptr(unsafe.Pointer(old)), - uintptr(unsafe.Pointer(oldlen)), - uintptr(unsafe.Pointer(new)), - uintptr(newlen)) - if errno != 0 { - return errno - } - return nil -} - -type sysctlNode struct { - Flags uint32 - Num int32 - Name [32]int8 - Ver uint32 - __rsvd uint32 - Un [16]byte - _sysctl_size [8]byte - _sysctl_func [8]byte - _sysctl_parent [8]byte - _sysctl_desc [8]byte -} - -func sysctlNodes(mib []int32) ([]sysctlNode, error) { - var olen uintptr - - // Get a list of all sysctl nodes below the given MIB by performing - // a sysctl for the given MIB with CTL_QUERY appended. - mib = append(mib, _CTL_QUERY) - qnode := sysctlNode{Flags: _SYSCTL_VERS_1} - qp := (*byte)(unsafe.Pointer(&qnode)) - sz := unsafe.Sizeof(qnode) - if err := sysctl(mib, nil, &olen, qp, sz); err != nil { - return nil, err - } - - // Now that we know the size, get the actual nodes. - nodes := make([]sysctlNode, olen/sz) - np := (*byte)(unsafe.Pointer(&nodes[0])) - if err := sysctl(mib, np, &olen, qp, sz); err != nil { - return nil, err - } - - return nodes, nil -} - -func nametomib(name string) ([]int32, error) { - // Split name into components. - var parts []string - last := 0 - for i := 0; i < len(name); i++ { - if name[i] == '.' { - parts = append(parts, name[last:i]) - last = i + 1 - } - } - parts = append(parts, name[last:]) - - mib := []int32{} - // Discover the nodes and construct the MIB OID. - for partno, part := range parts { - nodes, err := sysctlNodes(mib) - if err != nil { - return nil, err - } - for _, node := range nodes { - n := make([]byte, 0) - for i := range node.Name { - if node.Name[i] != 0 { - n = append(n, byte(node.Name[i])) - } - } - if string(n) == part { - mib = append(mib, int32(node.Num)) - break - } - } - if len(mib) != partno+1 { - return nil, err - } - } - - return mib, nil -} - -// aarch64SysctlCPUID is struct aarch64_sysctl_cpu_id from NetBSD's -type aarch64SysctlCPUID struct { - midr uint64 /* Main ID Register */ - revidr uint64 /* Revision ID Register */ - mpidr uint64 /* Multiprocessor Affinity Register */ - aa64dfr0 uint64 /* A64 Debug Feature Register 0 */ - aa64dfr1 uint64 /* A64 Debug Feature Register 1 */ - aa64isar0 uint64 /* A64 Instruction Set Attribute Register 0 */ - aa64isar1 uint64 /* A64 Instruction Set Attribute Register 1 */ - aa64mmfr0 uint64 /* A64 Memory Model Feature Register 0 */ - aa64mmfr1 uint64 /* A64 Memory Model Feature Register 1 */ - aa64mmfr2 uint64 /* A64 Memory Model Feature Register 2 */ - aa64pfr0 uint64 /* A64 Processor Feature Register 0 */ - aa64pfr1 uint64 /* A64 Processor Feature Register 1 */ - aa64zfr0 uint64 /* A64 SVE Feature ID Register 0 */ - mvfr0 uint32 /* Media and VFP Feature Register 0 */ - mvfr1 uint32 /* Media and VFP Feature Register 1 */ - mvfr2 uint32 /* Media and VFP Feature Register 2 */ - pad uint32 - clidr uint64 /* Cache Level ID Register */ - ctr uint64 /* Cache Type Register */ -} - -func sysctlCPUID(name string) (*aarch64SysctlCPUID, error) { - mib, err := nametomib(name) - if err != nil { - return nil, err - } - - out := aarch64SysctlCPUID{} - n := unsafe.Sizeof(out) - _, _, errno := syscall.Syscall6( - syscall.SYS___SYSCTL, - uintptr(unsafe.Pointer(&mib[0])), - uintptr(len(mib)), - uintptr(unsafe.Pointer(&out)), - uintptr(unsafe.Pointer(&n)), - uintptr(0), - uintptr(0)) - if errno != 0 { - return nil, errno - } - return &out, nil -} - -func doinit() { - cpuid, err := sysctlCPUID("machdep.cpu0.cpu_id") - if err != nil { - setMinimalFeatures() - return - } - parseARM64SystemRegisters(cpuid.aa64isar0, cpuid.aa64isar1, cpuid.aa64pfr0) - - Initialized = true -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.go deleted file mode 100644 index 85b64d5..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -import ( - "syscall" - "unsafe" -) - -// Minimal copy of functionality from x/sys/unix so the cpu package can call -// sysctl without depending on x/sys/unix. - -const ( - // From OpenBSD's sys/sysctl.h. - _CTL_MACHDEP = 7 - - // From OpenBSD's machine/cpu.h. - _CPU_ID_AA64ISAR0 = 2 - _CPU_ID_AA64ISAR1 = 3 -) - -// Implemented in the runtime package (runtime/sys_openbsd3.go) -func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) - -//go:linkname syscall_syscall6 syscall.syscall6 - -func sysctl(mib []uint32, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - _, _, errno := syscall_syscall6(libc_sysctl_trampoline_addr, uintptr(unsafe.Pointer(&mib[0])), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if errno != 0 { - return errno - } - return nil -} - -var libc_sysctl_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_sysctl sysctl "libc.so" - -func sysctlUint64(mib []uint32) (uint64, bool) { - var out uint64 - nout := unsafe.Sizeof(out) - if err := sysctl(mib, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0); err != nil { - return 0, false - } - return out, true -} - -func doinit() { - setMinimalFeatures() - - // Get ID_AA64ISAR0 and ID_AA64ISAR1 from sysctl. - isar0, ok := sysctlUint64([]uint32{_CTL_MACHDEP, _CPU_ID_AA64ISAR0}) - if !ok { - return - } - isar1, ok := sysctlUint64([]uint32{_CTL_MACHDEP, _CPU_ID_AA64ISAR1}) - if !ok { - return - } - parseARM64SystemRegisters(isar0, isar1, 0) - - Initialized = true -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.s b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.s deleted file mode 100644 index 054ba05..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.s +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "textflag.h" - -TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_sysctl(SB) - -GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 -DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_other_arm.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_other_arm.go deleted file mode 100644 index e9ecf2a..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_other_arm.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !linux && arm - -package cpu - -func archInit() {} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go deleted file mode 100644 index 5341e7f..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !linux && !netbsd && !openbsd && arm64 - -package cpu - -func doinit() {} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_other_mips64x.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_other_mips64x.go deleted file mode 100644 index 5f8f241..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_other_mips64x.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !linux && (mips64 || mips64le) - -package cpu - -func archInit() { - Initialized = true -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_other_ppc64x.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_other_ppc64x.go deleted file mode 100644 index 89608fb..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_other_ppc64x.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !aix && !linux && (ppc64 || ppc64le) - -package cpu - -func archInit() { - PPC64.IsPOWER8 = true - Initialized = true -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_other_riscv64.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_other_riscv64.go deleted file mode 100644 index 5ab8780..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_other_riscv64.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !linux && riscv64 - -package cpu - -func archInit() { - Initialized = true -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_other_x86.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_other_x86.go deleted file mode 100644 index a0fd7e2..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_other_x86.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2024 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build 386 || amd64p32 || (amd64 && (!darwin || !gc)) - -package cpu - -func darwinSupportsAVX512() bool { - panic("only implemented for gc && amd64 && darwin") -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_ppc64x.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_ppc64x.go deleted file mode 100644 index c14f12b..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_ppc64x.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build ppc64 || ppc64le - -package cpu - -const cacheLineSize = 128 - -func initOptions() { - options = []option{ - {Name: "darn", Feature: &PPC64.HasDARN}, - {Name: "scv", Feature: &PPC64.HasSCV}, - } -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_riscv64.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_riscv64.go deleted file mode 100644 index 0f617ae..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_riscv64.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build riscv64 - -package cpu - -const cacheLineSize = 64 - -func initOptions() { - options = []option{ - {Name: "fastmisaligned", Feature: &RISCV64.HasFastMisaligned}, - {Name: "c", Feature: &RISCV64.HasC}, - {Name: "v", Feature: &RISCV64.HasV}, - {Name: "zba", Feature: &RISCV64.HasZba}, - {Name: "zbb", Feature: &RISCV64.HasZbb}, - {Name: "zbs", Feature: &RISCV64.HasZbs}, - // RISC-V Cryptography Extensions - {Name: "zvbb", Feature: &RISCV64.HasZvbb}, - {Name: "zvbc", Feature: &RISCV64.HasZvbc}, - {Name: "zvkb", Feature: &RISCV64.HasZvkb}, - {Name: "zvkg", Feature: &RISCV64.HasZvkg}, - {Name: "zvkt", Feature: &RISCV64.HasZvkt}, - {Name: "zvkn", Feature: &RISCV64.HasZvkn}, - {Name: "zvknc", Feature: &RISCV64.HasZvknc}, - {Name: "zvkng", Feature: &RISCV64.HasZvkng}, - {Name: "zvks", Feature: &RISCV64.HasZvks}, - {Name: "zvksc", Feature: &RISCV64.HasZvksc}, - {Name: "zvksg", Feature: &RISCV64.HasZvksg}, - } -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_s390x.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_s390x.go deleted file mode 100644 index 5881b88..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_s390x.go +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -const cacheLineSize = 256 - -func initOptions() { - options = []option{ - {Name: "zarch", Feature: &S390X.HasZARCH, Required: true}, - {Name: "stfle", Feature: &S390X.HasSTFLE, Required: true}, - {Name: "ldisp", Feature: &S390X.HasLDISP, Required: true}, - {Name: "eimm", Feature: &S390X.HasEIMM, Required: true}, - {Name: "dfp", Feature: &S390X.HasDFP}, - {Name: "etf3eh", Feature: &S390X.HasETF3EH}, - {Name: "msa", Feature: &S390X.HasMSA}, - {Name: "aes", Feature: &S390X.HasAES}, - {Name: "aescbc", Feature: &S390X.HasAESCBC}, - {Name: "aesctr", Feature: &S390X.HasAESCTR}, - {Name: "aesgcm", Feature: &S390X.HasAESGCM}, - {Name: "ghash", Feature: &S390X.HasGHASH}, - {Name: "sha1", Feature: &S390X.HasSHA1}, - {Name: "sha256", Feature: &S390X.HasSHA256}, - {Name: "sha3", Feature: &S390X.HasSHA3}, - {Name: "sha512", Feature: &S390X.HasSHA512}, - {Name: "vx", Feature: &S390X.HasVX}, - {Name: "vxe", Feature: &S390X.HasVXE}, - } -} - -// bitIsSet reports whether the bit at index is set. The bit index -// is in big endian order, so bit index 0 is the leftmost bit. -func bitIsSet(bits []uint64, index uint) bool { - return bits[index/64]&((1<<63)>>(index%64)) != 0 -} - -// facility is a bit index for the named facility. -type facility uint8 - -const ( - // mandatory facilities - zarch facility = 1 // z architecture mode is active - stflef facility = 7 // store-facility-list-extended - ldisp facility = 18 // long-displacement - eimm facility = 21 // extended-immediate - - // miscellaneous facilities - dfp facility = 42 // decimal-floating-point - etf3eh facility = 30 // extended-translation 3 enhancement - - // cryptography facilities - msa facility = 17 // message-security-assist - msa3 facility = 76 // message-security-assist extension 3 - msa4 facility = 77 // message-security-assist extension 4 - msa5 facility = 57 // message-security-assist extension 5 - msa8 facility = 146 // message-security-assist extension 8 - msa9 facility = 155 // message-security-assist extension 9 - - // vector facilities - vx facility = 129 // vector facility - vxe facility = 135 // vector-enhancements 1 - vxe2 facility = 148 // vector-enhancements 2 -) - -// facilityList contains the result of an STFLE call. -// Bits are numbered in big endian order so the -// leftmost bit (the MSB) is at index 0. -type facilityList struct { - bits [4]uint64 -} - -// Has reports whether the given facilities are present. -func (s *facilityList) Has(fs ...facility) bool { - if len(fs) == 0 { - panic("no facility bits provided") - } - for _, f := range fs { - if !bitIsSet(s.bits[:], uint(f)) { - return false - } - } - return true -} - -// function is the code for the named cryptographic function. -type function uint8 - -const ( - // KM{,A,C,CTR} function codes - aes128 function = 18 // AES-128 - aes192 function = 19 // AES-192 - aes256 function = 20 // AES-256 - - // K{I,L}MD function codes - sha1 function = 1 // SHA-1 - sha256 function = 2 // SHA-256 - sha512 function = 3 // SHA-512 - sha3_224 function = 32 // SHA3-224 - sha3_256 function = 33 // SHA3-256 - sha3_384 function = 34 // SHA3-384 - sha3_512 function = 35 // SHA3-512 - shake128 function = 36 // SHAKE-128 - shake256 function = 37 // SHAKE-256 - - // KLMD function codes - ghash function = 65 // GHASH -) - -// queryResult contains the result of a Query function -// call. Bits are numbered in big endian order so the -// leftmost bit (the MSB) is at index 0. -type queryResult struct { - bits [2]uint64 -} - -// Has reports whether the given functions are present. -func (q *queryResult) Has(fns ...function) bool { - if len(fns) == 0 { - panic("no function codes provided") - } - for _, f := range fns { - if !bitIsSet(q.bits[:], uint(f)) { - return false - } - } - return true -} - -func doinit() { - initS390Xbase() - - // We need implementations of stfle, km and so on - // to detect cryptographic features. - if !haveAsmFunctions() { - return - } - - // optional cryptographic functions - if S390X.HasMSA { - aes := []function{aes128, aes192, aes256} - - // cipher message - km, kmc := kmQuery(), kmcQuery() - S390X.HasAES = km.Has(aes...) - S390X.HasAESCBC = kmc.Has(aes...) - if S390X.HasSTFLE { - facilities := stfle() - if facilities.Has(msa4) { - kmctr := kmctrQuery() - S390X.HasAESCTR = kmctr.Has(aes...) - } - if facilities.Has(msa8) { - kma := kmaQuery() - S390X.HasAESGCM = kma.Has(aes...) - } - } - - // compute message digest - kimd := kimdQuery() // intermediate (no padding) - klmd := klmdQuery() // last (padding) - S390X.HasSHA1 = kimd.Has(sha1) && klmd.Has(sha1) - S390X.HasSHA256 = kimd.Has(sha256) && klmd.Has(sha256) - S390X.HasSHA512 = kimd.Has(sha512) && klmd.Has(sha512) - S390X.HasGHASH = kimd.Has(ghash) // KLMD-GHASH does not exist - sha3 := []function{ - sha3_224, sha3_256, sha3_384, sha3_512, - shake128, shake256, - } - S390X.HasSHA3 = kimd.Has(sha3...) && klmd.Has(sha3...) - } -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_s390x.s b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_s390x.s deleted file mode 100644 index 1fb4b70..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_s390x.s +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build gc - -#include "textflag.h" - -// func stfle() facilityList -TEXT ·stfle(SB), NOSPLIT|NOFRAME, $0-32 - MOVD $ret+0(FP), R1 - MOVD $3, R0 // last doubleword index to store - XC $32, (R1), (R1) // clear 4 doublewords (32 bytes) - WORD $0xb2b01000 // store facility list extended (STFLE) - RET - -// func kmQuery() queryResult -TEXT ·kmQuery(SB), NOSPLIT|NOFRAME, $0-16 - MOVD $0, R0 // set function code to 0 (KM-Query) - MOVD $ret+0(FP), R1 // address of 16-byte return value - WORD $0xB92E0024 // cipher message (KM) - RET - -// func kmcQuery() queryResult -TEXT ·kmcQuery(SB), NOSPLIT|NOFRAME, $0-16 - MOVD $0, R0 // set function code to 0 (KMC-Query) - MOVD $ret+0(FP), R1 // address of 16-byte return value - WORD $0xB92F0024 // cipher message with chaining (KMC) - RET - -// func kmctrQuery() queryResult -TEXT ·kmctrQuery(SB), NOSPLIT|NOFRAME, $0-16 - MOVD $0, R0 // set function code to 0 (KMCTR-Query) - MOVD $ret+0(FP), R1 // address of 16-byte return value - WORD $0xB92D4024 // cipher message with counter (KMCTR) - RET - -// func kmaQuery() queryResult -TEXT ·kmaQuery(SB), NOSPLIT|NOFRAME, $0-16 - MOVD $0, R0 // set function code to 0 (KMA-Query) - MOVD $ret+0(FP), R1 // address of 16-byte return value - WORD $0xb9296024 // cipher message with authentication (KMA) - RET - -// func kimdQuery() queryResult -TEXT ·kimdQuery(SB), NOSPLIT|NOFRAME, $0-16 - MOVD $0, R0 // set function code to 0 (KIMD-Query) - MOVD $ret+0(FP), R1 // address of 16-byte return value - WORD $0xB93E0024 // compute intermediate message digest (KIMD) - RET - -// func klmdQuery() queryResult -TEXT ·klmdQuery(SB), NOSPLIT|NOFRAME, $0-16 - MOVD $0, R0 // set function code to 0 (KLMD-Query) - MOVD $ret+0(FP), R1 // address of 16-byte return value - WORD $0xB93F0024 // compute last message digest (KLMD) - RET diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_wasm.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_wasm.go deleted file mode 100644 index 384787e..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_wasm.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build wasm - -package cpu - -// We're compiling the cpu package for an unknown (software-abstracted) CPU. -// Make CacheLinePad an empty struct and hope that the usual struct alignment -// rules are good enough. - -const cacheLineSize = 0 - -func initOptions() {} - -func archInit() {} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_x86.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_x86.go deleted file mode 100644 index f5723d4..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_x86.go +++ /dev/null @@ -1,236 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build 386 || amd64 || amd64p32 - -package cpu - -import "runtime" - -const cacheLineSize = 64 - -func initOptions() { - options = []option{ - {Name: "adx", Feature: &X86.HasADX}, - {Name: "aes", Feature: &X86.HasAES}, - {Name: "avx", Feature: &X86.HasAVX}, - {Name: "avx2", Feature: &X86.HasAVX2}, - {Name: "avx512", Feature: &X86.HasAVX512}, - {Name: "avx512f", Feature: &X86.HasAVX512F}, - {Name: "avx512cd", Feature: &X86.HasAVX512CD}, - {Name: "avx512er", Feature: &X86.HasAVX512ER}, - {Name: "avx512pf", Feature: &X86.HasAVX512PF}, - {Name: "avx512vl", Feature: &X86.HasAVX512VL}, - {Name: "avx512bw", Feature: &X86.HasAVX512BW}, - {Name: "avx512dq", Feature: &X86.HasAVX512DQ}, - {Name: "avx512ifma", Feature: &X86.HasAVX512IFMA}, - {Name: "avx512vbmi", Feature: &X86.HasAVX512VBMI}, - {Name: "avx512vnniw", Feature: &X86.HasAVX5124VNNIW}, - {Name: "avx5124fmaps", Feature: &X86.HasAVX5124FMAPS}, - {Name: "avx512vpopcntdq", Feature: &X86.HasAVX512VPOPCNTDQ}, - {Name: "avx512vpclmulqdq", Feature: &X86.HasAVX512VPCLMULQDQ}, - {Name: "avx512vnni", Feature: &X86.HasAVX512VNNI}, - {Name: "avx512gfni", Feature: &X86.HasAVX512GFNI}, - {Name: "avx512vaes", Feature: &X86.HasAVX512VAES}, - {Name: "avx512vbmi2", Feature: &X86.HasAVX512VBMI2}, - {Name: "avx512bitalg", Feature: &X86.HasAVX512BITALG}, - {Name: "avx512bf16", Feature: &X86.HasAVX512BF16}, - {Name: "amxtile", Feature: &X86.HasAMXTile}, - {Name: "amxint8", Feature: &X86.HasAMXInt8}, - {Name: "amxbf16", Feature: &X86.HasAMXBF16}, - {Name: "bmi1", Feature: &X86.HasBMI1}, - {Name: "bmi2", Feature: &X86.HasBMI2}, - {Name: "cx16", Feature: &X86.HasCX16}, - {Name: "erms", Feature: &X86.HasERMS}, - {Name: "fma", Feature: &X86.HasFMA}, - {Name: "osxsave", Feature: &X86.HasOSXSAVE}, - {Name: "pclmulqdq", Feature: &X86.HasPCLMULQDQ}, - {Name: "popcnt", Feature: &X86.HasPOPCNT}, - {Name: "rdrand", Feature: &X86.HasRDRAND}, - {Name: "rdseed", Feature: &X86.HasRDSEED}, - {Name: "sse3", Feature: &X86.HasSSE3}, - {Name: "sse41", Feature: &X86.HasSSE41}, - {Name: "sse42", Feature: &X86.HasSSE42}, - {Name: "ssse3", Feature: &X86.HasSSSE3}, - {Name: "avxifma", Feature: &X86.HasAVXIFMA}, - {Name: "avxvnni", Feature: &X86.HasAVXVNNI}, - {Name: "avxvnniint8", Feature: &X86.HasAVXVNNIInt8}, - - // These capabilities should always be enabled on amd64: - {Name: "sse2", Feature: &X86.HasSSE2, Required: runtime.GOARCH == "amd64"}, - } -} - -func archInit() { - - // From internal/cpu - const ( - // eax bits - cpuid_AVXVNNI = 1 << 4 - - // ecx bits - cpuid_SSE3 = 1 << 0 - cpuid_PCLMULQDQ = 1 << 1 - cpuid_AVX512VBMI = 1 << 1 - cpuid_AVX512VBMI2 = 1 << 6 - cpuid_SSSE3 = 1 << 9 - cpuid_AVX512GFNI = 1 << 8 - cpuid_AVX512VAES = 1 << 9 - cpuid_AVX512VNNI = 1 << 11 - cpuid_AVX512BITALG = 1 << 12 - cpuid_FMA = 1 << 12 - cpuid_AVX512VPOPCNTDQ = 1 << 14 - cpuid_SSE41 = 1 << 19 - cpuid_SSE42 = 1 << 20 - cpuid_POPCNT = 1 << 23 - cpuid_AES = 1 << 25 - cpuid_OSXSAVE = 1 << 27 - cpuid_AVX = 1 << 28 - - // "Extended Feature Flag" bits returned in EBX for CPUID EAX=0x7 ECX=0x0 - cpuid_BMI1 = 1 << 3 - cpuid_AVX2 = 1 << 5 - cpuid_BMI2 = 1 << 8 - cpuid_ERMS = 1 << 9 - cpuid_AVX512F = 1 << 16 - cpuid_AVX512DQ = 1 << 17 - cpuid_ADX = 1 << 19 - cpuid_AVX512CD = 1 << 28 - cpuid_SHA = 1 << 29 - cpuid_AVX512BW = 1 << 30 - cpuid_AVX512VL = 1 << 31 - - // "Extended Feature Flag" bits returned in ECX for CPUID EAX=0x7 ECX=0x0 - cpuid_AVX512_VBMI = 1 << 1 - cpuid_AVX512_VBMI2 = 1 << 6 - cpuid_GFNI = 1 << 8 - cpuid_AVX512VPCLMULQDQ = 1 << 10 - cpuid_AVX512_BITALG = 1 << 12 - - // edx bits - cpuid_FSRM = 1 << 4 - // edx bits for CPUID 0x80000001 - cpuid_RDTSCP = 1 << 27 - ) - // Additional constants not in internal/cpu - const ( - // eax=1: edx - cpuid_SSE2 = 1 << 26 - // eax=1: ecx - cpuid_CX16 = 1 << 13 - cpuid_RDRAND = 1 << 30 - // eax=7,ecx=0: ebx - cpuid_RDSEED = 1 << 18 - cpuid_AVX512IFMA = 1 << 21 - cpuid_AVX512PF = 1 << 26 - cpuid_AVX512ER = 1 << 27 - // eax=7,ecx=0: edx - cpuid_AVX5124VNNIW = 1 << 2 - cpuid_AVX5124FMAPS = 1 << 3 - cpuid_AMXBF16 = 1 << 22 - cpuid_AMXTile = 1 << 24 - cpuid_AMXInt8 = 1 << 25 - // eax=7,ecx=1: eax - cpuid_AVX512BF16 = 1 << 5 - cpuid_AVXIFMA = 1 << 23 - // eax=7,ecx=1: edx - cpuid_AVXVNNIInt8 = 1 << 4 - ) - - Initialized = true - - maxID, _, _, _ := cpuid(0, 0) - - if maxID < 1 { - return - } - - _, _, ecx1, edx1 := cpuid(1, 0) - X86.HasSSE2 = isSet(edx1, cpuid_SSE2) - - X86.HasSSE3 = isSet(ecx1, cpuid_SSE3) - X86.HasPCLMULQDQ = isSet(ecx1, cpuid_PCLMULQDQ) - X86.HasSSSE3 = isSet(ecx1, cpuid_SSSE3) - X86.HasFMA = isSet(ecx1, cpuid_FMA) - X86.HasCX16 = isSet(ecx1, cpuid_CX16) - X86.HasSSE41 = isSet(ecx1, cpuid_SSE41) - X86.HasSSE42 = isSet(ecx1, cpuid_SSE42) - X86.HasPOPCNT = isSet(ecx1, cpuid_POPCNT) - X86.HasAES = isSet(ecx1, cpuid_AES) - X86.HasOSXSAVE = isSet(ecx1, cpuid_OSXSAVE) - X86.HasRDRAND = isSet(ecx1, cpuid_RDRAND) - - var osSupportsAVX, osSupportsAVX512 bool - // For XGETBV, OSXSAVE bit is required and sufficient. - if X86.HasOSXSAVE { - eax, _ := xgetbv() - // Check if XMM and YMM registers have OS support. - osSupportsAVX = isSet(eax, 1<<1) && isSet(eax, 1<<2) - - if runtime.GOOS == "darwin" { - // Darwin requires special AVX512 checks, see cpu_darwin_x86.go - osSupportsAVX512 = osSupportsAVX && darwinSupportsAVX512() - } else { - // Check if OPMASK and ZMM registers have OS support. - osSupportsAVX512 = osSupportsAVX && isSet(eax, 1<<5) && isSet(eax, 1<<6) && isSet(eax, 1<<7) - } - } - - X86.HasAVX = isSet(ecx1, cpuid_AVX) && osSupportsAVX - - if maxID < 7 { - return - } - - eax7, ebx7, ecx7, edx7 := cpuid(7, 0) - X86.HasBMI1 = isSet(ebx7, cpuid_BMI1) - X86.HasAVX2 = isSet(ebx7, cpuid_AVX2) && osSupportsAVX - X86.HasBMI2 = isSet(ebx7, cpuid_BMI2) - X86.HasERMS = isSet(ebx7, cpuid_ERMS) - X86.HasRDSEED = isSet(ebx7, cpuid_RDSEED) - X86.HasADX = isSet(ebx7, cpuid_ADX) - - X86.HasAVX512 = isSet(ebx7, cpuid_AVX512F) && osSupportsAVX512 // Because avx-512 foundation is the core required extension - if X86.HasAVX512 { - X86.HasAVX512F = true - X86.HasAVX512CD = isSet(ebx7, cpuid_AVX512CD) - X86.HasAVX512ER = isSet(ebx7, cpuid_AVX512ER) - X86.HasAVX512PF = isSet(ebx7, cpuid_AVX512PF) - X86.HasAVX512VL = isSet(ebx7, cpuid_AVX512VL) - X86.HasAVX512BW = isSet(ebx7, cpuid_AVX512BW) - X86.HasAVX512DQ = isSet(ebx7, cpuid_AVX512DQ) - X86.HasAVX512IFMA = isSet(ebx7, cpuid_AVX512IFMA) - X86.HasAVX512VBMI = isSet(ecx7, cpuid_AVX512_VBMI) - X86.HasAVX5124VNNIW = isSet(edx7, cpuid_AVX5124VNNIW) - X86.HasAVX5124FMAPS = isSet(edx7, cpuid_AVX5124FMAPS) - X86.HasAVX512VPOPCNTDQ = isSet(ecx7, cpuid_AVX512VPOPCNTDQ) - X86.HasAVX512VPCLMULQDQ = isSet(ecx7, cpuid_AVX512VPCLMULQDQ) - X86.HasAVX512VNNI = isSet(ecx7, cpuid_AVX512VNNI) - X86.HasAVX512GFNI = isSet(ecx7, cpuid_AVX512GFNI) - X86.HasAVX512VAES = isSet(ecx7, cpuid_AVX512VAES) - X86.HasAVX512VBMI2 = isSet(ecx7, cpuid_AVX512VBMI2) - X86.HasAVX512BITALG = isSet(ecx7, cpuid_AVX512BITALG) - } - - X86.HasAMXTile = isSet(edx7, cpuid_AMXTile) - X86.HasAMXInt8 = isSet(edx7, cpuid_AMXInt8) - X86.HasAMXBF16 = isSet(edx7, cpuid_AMXBF16) - - // These features depend on the second level of extended features. - if eax7 >= 1 { - eax71, _, _, edx71 := cpuid(7, 1) - if X86.HasAVX512 { - X86.HasAVX512BF16 = isSet(eax71, cpuid_AVX512BF16) - } - if X86.HasAVX { - X86.HasAVXIFMA = isSet(eax71, cpuid_AVXIFMA) - X86.HasAVXVNNI = isSet(eax71, cpuid_AVXVNNI) - X86.HasAVXVNNIInt8 = isSet(edx71, cpuid_AVXVNNIInt8) - } - } -} - -func isSet(hwc uint32, value uint32) bool { - return hwc&value != 0 -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_zos.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_zos.go deleted file mode 100644 index 5f54683..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_zos.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -func archInit() { - doinit() - Initialized = true -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_zos_s390x.go b/go/sdk/vendor/golang.org/x/sys/cpu/cpu_zos_s390x.go deleted file mode 100644 index ccb1b70..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/cpu_zos_s390x.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -func initS390Xbase() { - // get the facilities list - facilities := stfle() - - // mandatory - S390X.HasZARCH = facilities.Has(zarch) - S390X.HasSTFLE = facilities.Has(stflef) - S390X.HasLDISP = facilities.Has(ldisp) - S390X.HasEIMM = facilities.Has(eimm) - - // optional - S390X.HasETF3EH = facilities.Has(etf3eh) - S390X.HasDFP = facilities.Has(dfp) - S390X.HasMSA = facilities.Has(msa) - S390X.HasVX = facilities.Has(vx) - if S390X.HasVX { - S390X.HasVXE = facilities.Has(vxe) - } -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/endian_big.go b/go/sdk/vendor/golang.org/x/sys/cpu/endian_big.go deleted file mode 100644 index 7fe04b0..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/endian_big.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build armbe || arm64be || m68k || mips || mips64 || mips64p32 || ppc || ppc64 || s390 || s390x || shbe || sparc || sparc64 - -package cpu - -// IsBigEndian records whether the GOARCH's byte order is big endian. -const IsBigEndian = true diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/endian_little.go b/go/sdk/vendor/golang.org/x/sys/cpu/endian_little.go deleted file mode 100644 index 48eccc4..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/endian_little.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build 386 || amd64 || amd64p32 || alpha || arm || arm64 || loong64 || mipsle || mips64le || mips64p32le || nios2 || ppc64le || riscv || riscv64 || sh || wasm - -package cpu - -// IsBigEndian records whether the GOARCH's byte order is big endian. -const IsBigEndian = false diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/hwcap_linux.go b/go/sdk/vendor/golang.org/x/sys/cpu/hwcap_linux.go deleted file mode 100644 index 34e49f9..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/hwcap_linux.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -import ( - "os" -) - -const ( - _AT_HWCAP = 16 - _AT_HWCAP2 = 26 - - procAuxv = "/proc/self/auxv" - - uintSize = int(32 << (^uint(0) >> 63)) -) - -// For those platforms don't have a 'cpuid' equivalent we use HWCAP/HWCAP2 -// These are initialized in cpu_$GOARCH.go -// and should not be changed after they are initialized. -var hwCap uint -var hwCap2 uint - -func readHWCAP() error { - // For Go 1.21+, get auxv from the Go runtime. - if a := getAuxv(); len(a) > 0 { - for len(a) >= 2 { - tag, val := a[0], uint(a[1]) - a = a[2:] - switch tag { - case _AT_HWCAP: - hwCap = val - case _AT_HWCAP2: - hwCap2 = val - } - } - return nil - } - - buf, err := os.ReadFile(procAuxv) - if err != nil { - // e.g. on android /proc/self/auxv is not accessible, so silently - // ignore the error and leave Initialized = false. On some - // architectures (e.g. arm64) doinit() implements a fallback - // readout and will set Initialized = true again. - return err - } - bo := hostByteOrder() - for len(buf) >= 2*(uintSize/8) { - var tag, val uint - switch uintSize { - case 32: - tag = uint(bo.Uint32(buf[0:])) - val = uint(bo.Uint32(buf[4:])) - buf = buf[8:] - case 64: - tag = uint(bo.Uint64(buf[0:])) - val = uint(bo.Uint64(buf[8:])) - buf = buf[16:] - } - switch tag { - case _AT_HWCAP: - hwCap = val - case _AT_HWCAP2: - hwCap2 = val - } - } - return nil -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/parse.go b/go/sdk/vendor/golang.org/x/sys/cpu/parse.go deleted file mode 100644 index 56a7e1a..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/parse.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -import "strconv" - -// parseRelease parses a dot-separated version number. It follows the semver -// syntax, but allows the minor and patch versions to be elided. -// -// This is a copy of the Go runtime's parseRelease from -// https://golang.org/cl/209597. -func parseRelease(rel string) (major, minor, patch int, ok bool) { - // Strip anything after a dash or plus. - for i := range len(rel) { - if rel[i] == '-' || rel[i] == '+' { - rel = rel[:i] - break - } - } - - next := func() (int, bool) { - for i := range len(rel) { - if rel[i] == '.' { - ver, err := strconv.Atoi(rel[:i]) - rel = rel[i+1:] - return ver, err == nil - } - } - ver, err := strconv.Atoi(rel) - rel = "" - return ver, err == nil - } - if major, ok = next(); !ok || rel == "" { - return - } - if minor, ok = next(); !ok || rel == "" { - return - } - patch, ok = next() - return -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/proc_cpuinfo_linux.go b/go/sdk/vendor/golang.org/x/sys/cpu/proc_cpuinfo_linux.go deleted file mode 100644 index 4cd64c7..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/proc_cpuinfo_linux.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build linux && arm64 - -package cpu - -import ( - "errors" - "io" - "os" - "strings" -) - -func readLinuxProcCPUInfo() error { - f, err := os.Open("/proc/cpuinfo") - if err != nil { - return err - } - defer f.Close() - - var buf [1 << 10]byte // enough for first CPU - n, err := io.ReadFull(f, buf[:]) - if err != nil && err != io.ErrUnexpectedEOF { - return err - } - in := string(buf[:n]) - const features = "\nFeatures : " - i := strings.Index(in, features) - if i == -1 { - return errors.New("no CPU features found") - } - in = in[i+len(features):] - if i := strings.Index(in, "\n"); i != -1 { - in = in[:i] - } - m := map[string]*bool{} - - initOptions() // need it early here; it's harmless to call twice - for _, o := range options { - m[o.Name] = o.Feature - } - // The EVTSTRM field has alias "evstrm" in Go, but Linux calls it "evtstrm". - m["evtstrm"] = &ARM64.HasEVTSTRM - - for _, f := range strings.Fields(in) { - if p, ok := m[f]; ok { - *p = true - } - } - return nil -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/runtime_auxv.go b/go/sdk/vendor/golang.org/x/sys/cpu/runtime_auxv.go deleted file mode 100644 index 5f92ac9..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/runtime_auxv.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -// getAuxvFn is non-nil on Go 1.21+ (via runtime_auxv_go121.go init) -// on platforms that use auxv. -var getAuxvFn func() []uintptr - -func getAuxv() []uintptr { - if getAuxvFn == nil { - return nil - } - return getAuxvFn() -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/runtime_auxv_go121.go b/go/sdk/vendor/golang.org/x/sys/cpu/runtime_auxv_go121.go deleted file mode 100644 index 4c9788e..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/runtime_auxv_go121.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package cpu - -import ( - _ "unsafe" // for linkname -) - -//go:linkname runtime_getAuxv runtime.getAuxv -func runtime_getAuxv() []uintptr - -func init() { - getAuxvFn = runtime_getAuxv -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/syscall_aix_gccgo.go b/go/sdk/vendor/golang.org/x/sys/cpu/syscall_aix_gccgo.go deleted file mode 100644 index 1b9ccb0..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/syscall_aix_gccgo.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Recreate a getsystemcfg syscall handler instead of -// using the one provided by x/sys/unix to avoid having -// the dependency between them. (See golang.org/issue/32102) -// Moreover, this file will be used during the building of -// gccgo's libgo and thus must not used a CGo method. - -//go:build aix && gccgo - -package cpu - -import ( - "syscall" -) - -//extern getsystemcfg -func gccgoGetsystemcfg(label uint32) (r uint64) - -func callgetsystemcfg(label int) (r1 uintptr, e1 syscall.Errno) { - r1 = uintptr(gccgoGetsystemcfg(uint32(label))) - e1 = syscall.GetErrno() - return -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go b/go/sdk/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go deleted file mode 100644 index e8b6cdb..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Minimal copy of x/sys/unix so the cpu package can make a -// system call on AIX without depending on x/sys/unix. -// (See golang.org/issue/32102) - -//go:build aix && ppc64 && gc - -package cpu - -import ( - "syscall" - "unsafe" -) - -//go:cgo_import_dynamic libc_getsystemcfg getsystemcfg "libc.a/shr_64.o" - -//go:linkname libc_getsystemcfg libc_getsystemcfg - -type syscallFunc uintptr - -var libc_getsystemcfg syscallFunc - -type errno = syscall.Errno - -// Implemented in runtime/syscall_aix.go. -func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err errno) -func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err errno) - -func callgetsystemcfg(label int) (r1 uintptr, e1 errno) { - r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_getsystemcfg)), 1, uintptr(label), 0, 0, 0, 0, 0) - return -} diff --git a/go/sdk/vendor/golang.org/x/sys/cpu/syscall_darwin_x86_gc.go b/go/sdk/vendor/golang.org/x/sys/cpu/syscall_darwin_x86_gc.go deleted file mode 100644 index 4d0888b..0000000 --- a/go/sdk/vendor/golang.org/x/sys/cpu/syscall_darwin_x86_gc.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2024 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Minimal copy of x/sys/unix so the cpu package can make a -// system call on Darwin without depending on x/sys/unix. - -//go:build darwin && amd64 && gc - -package cpu - -import ( - "syscall" - "unsafe" -) - -type _C_int int32 - -// adapted from unix.Uname() at x/sys/unix/syscall_darwin.go L419 -func darwinOSRelease(release *[256]byte) error { - // from x/sys/unix/zerrors_openbsd_amd64.go - const ( - CTL_KERN = 0x1 - KERN_OSRELEASE = 0x2 - ) - - mib := []_C_int{CTL_KERN, KERN_OSRELEASE} - n := unsafe.Sizeof(*release) - - return sysctl(mib, &release[0], &n, nil, 0) -} - -type Errno = syscall.Errno - -var _zero uintptr // Single-word zero for use when we need a valid pointer to 0 bytes. - -// from x/sys/unix/zsyscall_darwin_amd64.go L791-807 -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - if _, _, err := syscall_syscall6( - libc_sysctl_trampoline_addr, - uintptr(_p0), - uintptr(len(mib)), - uintptr(unsafe.Pointer(old)), - uintptr(unsafe.Pointer(oldlen)), - uintptr(unsafe.Pointer(new)), - uintptr(newlen), - ); err != 0 { - return err - } - - return nil -} - -var libc_sysctl_trampoline_addr uintptr - -// adapted from internal/cpu/cpu_arm64_darwin.go -func darwinSysctlEnabled(name []byte) bool { - out := int32(0) - nout := unsafe.Sizeof(out) - if ret := sysctlbyname(&name[0], (*byte)(unsafe.Pointer(&out)), &nout, nil, 0); ret != nil { - return false - } - return out > 0 -} - -//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib" - -var libc_sysctlbyname_trampoline_addr uintptr - -// adapted from runtime/sys_darwin.go in the pattern of sysctl() above, as defined in x/sys/unix -func sysctlbyname(name *byte, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error { - if _, _, err := syscall_syscall6( - libc_sysctlbyname_trampoline_addr, - uintptr(unsafe.Pointer(name)), - uintptr(unsafe.Pointer(old)), - uintptr(unsafe.Pointer(oldlen)), - uintptr(unsafe.Pointer(new)), - uintptr(newlen), - 0, - ); err != 0 { - return err - } - - return nil -} - -//go:cgo_import_dynamic libc_sysctlbyname sysctlbyname "/usr/lib/libSystem.B.dylib" - -// Implemented in the runtime package (runtime/sys_darwin.go) -func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) - -//go:linkname syscall_syscall6 syscall.syscall6 diff --git a/go/sdk/vendor/gopkg.in/yaml.v3/LICENSE b/go/sdk/vendor/gopkg.in/yaml.v3/LICENSE deleted file mode 100644 index 2683e4b..0000000 --- a/go/sdk/vendor/gopkg.in/yaml.v3/LICENSE +++ /dev/null @@ -1,50 +0,0 @@ - -This project is covered by two different licenses: MIT and Apache. - -#### MIT License #### - -The following files were ported to Go from C files of libyaml, and thus -are still covered by their original MIT license, with the additional -copyright staring in 2011 when the project was ported over: - - apic.go emitterc.go parserc.go readerc.go scannerc.go - writerc.go yamlh.go yamlprivateh.go - -Copyright (c) 2006-2010 Kirill Simonov -Copyright (c) 2006-2011 Kirill Simonov - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -### Apache License ### - -All the remaining project files are covered by the Apache license: - -Copyright (c) 2011-2019 Canonical Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/go/sdk/vendor/gopkg.in/yaml.v3/NOTICE b/go/sdk/vendor/gopkg.in/yaml.v3/NOTICE deleted file mode 100644 index 866d74a..0000000 --- a/go/sdk/vendor/gopkg.in/yaml.v3/NOTICE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2011-2016 Canonical Ltd. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/go/sdk/vendor/gopkg.in/yaml.v3/README.md b/go/sdk/vendor/gopkg.in/yaml.v3/README.md deleted file mode 100644 index 08eb1ba..0000000 --- a/go/sdk/vendor/gopkg.in/yaml.v3/README.md +++ /dev/null @@ -1,150 +0,0 @@ -# YAML support for the Go language - -Introduction ------------- - -The yaml package enables Go programs to comfortably encode and decode YAML -values. It was developed within [Canonical](https://www.canonical.com) as -part of the [juju](https://juju.ubuntu.com) project, and is based on a -pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) -C library to parse and generate YAML data quickly and reliably. - -Compatibility -------------- - -The yaml package supports most of YAML 1.2, but preserves some behavior -from 1.1 for backwards compatibility. - -Specifically, as of v3 of the yaml package: - - - YAML 1.1 bools (_yes/no, on/off_) are supported as long as they are being - decoded into a typed bool value. Otherwise they behave as a string. Booleans - in YAML 1.2 are _true/false_ only. - - Octals encode and decode as _0777_ per YAML 1.1, rather than _0o777_ - as specified in YAML 1.2, because most parsers still use the old format. - Octals in the _0o777_ format are supported though, so new files work. - - Does not support base-60 floats. These are gone from YAML 1.2, and were - actually never supported by this package as it's clearly a poor choice. - -and offers backwards -compatibility with YAML 1.1 in some cases. -1.2, including support for -anchors, tags, map merging, etc. Multi-document unmarshalling is not yet -implemented, and base-60 floats from YAML 1.1 are purposefully not -supported since they're a poor design and are gone in YAML 1.2. - -Installation and usage ----------------------- - -The import path for the package is *gopkg.in/yaml.v3*. - -To install it, run: - - go get gopkg.in/yaml.v3 - -API documentation ------------------ - -If opened in a browser, the import path itself leads to the API documentation: - - - [https://gopkg.in/yaml.v3](https://gopkg.in/yaml.v3) - -API stability -------------- - -The package API for yaml v3 will remain stable as described in [gopkg.in](https://gopkg.in). - - -License -------- - -The yaml package is licensed under the MIT and Apache License 2.0 licenses. -Please see the LICENSE file for details. - - -Example -------- - -```Go -package main - -import ( - "fmt" - "log" - - "gopkg.in/yaml.v3" -) - -var data = ` -a: Easy! -b: - c: 2 - d: [3, 4] -` - -// Note: struct fields must be public in order for unmarshal to -// correctly populate the data. -type T struct { - A string - B struct { - RenamedC int `yaml:"c"` - D []int `yaml:",flow"` - } -} - -func main() { - t := T{} - - err := yaml.Unmarshal([]byte(data), &t) - if err != nil { - log.Fatalf("error: %v", err) - } - fmt.Printf("--- t:\n%v\n\n", t) - - d, err := yaml.Marshal(&t) - if err != nil { - log.Fatalf("error: %v", err) - } - fmt.Printf("--- t dump:\n%s\n\n", string(d)) - - m := make(map[interface{}]interface{}) - - err = yaml.Unmarshal([]byte(data), &m) - if err != nil { - log.Fatalf("error: %v", err) - } - fmt.Printf("--- m:\n%v\n\n", m) - - d, err = yaml.Marshal(&m) - if err != nil { - log.Fatalf("error: %v", err) - } - fmt.Printf("--- m dump:\n%s\n\n", string(d)) -} -``` - -This example will generate the following output: - -``` ---- t: -{Easy! {2 [3 4]}} - ---- t dump: -a: Easy! -b: - c: 2 - d: [3, 4] - - ---- m: -map[a:Easy! b:map[c:2 d:[3 4]]] - ---- m dump: -a: Easy! -b: - c: 2 - d: - - 3 - - 4 -``` - diff --git a/go/sdk/vendor/gopkg.in/yaml.v3/apic.go b/go/sdk/vendor/gopkg.in/yaml.v3/apic.go deleted file mode 100644 index 05fd305..0000000 --- a/go/sdk/vendor/gopkg.in/yaml.v3/apic.go +++ /dev/null @@ -1,747 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -// of the Software, and to permit persons to whom the Software is furnished to do -// so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -package yaml - -import ( - "io" -) - -func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) { - //fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens)) - - // Check if we can move the queue at the beginning of the buffer. - if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) { - if parser.tokens_head != len(parser.tokens) { - copy(parser.tokens, parser.tokens[parser.tokens_head:]) - } - parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head] - parser.tokens_head = 0 - } - parser.tokens = append(parser.tokens, *token) - if pos < 0 { - return - } - copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:]) - parser.tokens[parser.tokens_head+pos] = *token -} - -// Create a new parser object. -func yaml_parser_initialize(parser *yaml_parser_t) bool { - *parser = yaml_parser_t{ - raw_buffer: make([]byte, 0, input_raw_buffer_size), - buffer: make([]byte, 0, input_buffer_size), - } - return true -} - -// Destroy a parser object. -func yaml_parser_delete(parser *yaml_parser_t) { - *parser = yaml_parser_t{} -} - -// String read handler. -func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { - if parser.input_pos == len(parser.input) { - return 0, io.EOF - } - n = copy(buffer, parser.input[parser.input_pos:]) - parser.input_pos += n - return n, nil -} - -// Reader read handler. -func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { - return parser.input_reader.Read(buffer) -} - -// Set a string input. -func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) { - if parser.read_handler != nil { - panic("must set the input source only once") - } - parser.read_handler = yaml_string_read_handler - parser.input = input - parser.input_pos = 0 -} - -// Set a file input. -func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) { - if parser.read_handler != nil { - panic("must set the input source only once") - } - parser.read_handler = yaml_reader_read_handler - parser.input_reader = r -} - -// Set the source encoding. -func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) { - if parser.encoding != yaml_ANY_ENCODING { - panic("must set the encoding only once") - } - parser.encoding = encoding -} - -// Create a new emitter object. -func yaml_emitter_initialize(emitter *yaml_emitter_t) { - *emitter = yaml_emitter_t{ - buffer: make([]byte, output_buffer_size), - raw_buffer: make([]byte, 0, output_raw_buffer_size), - states: make([]yaml_emitter_state_t, 0, initial_stack_size), - events: make([]yaml_event_t, 0, initial_queue_size), - best_width: -1, - } -} - -// Destroy an emitter object. -func yaml_emitter_delete(emitter *yaml_emitter_t) { - *emitter = yaml_emitter_t{} -} - -// String write handler. -func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error { - *emitter.output_buffer = append(*emitter.output_buffer, buffer...) - return nil -} - -// yaml_writer_write_handler uses emitter.output_writer to write the -// emitted text. -func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error { - _, err := emitter.output_writer.Write(buffer) - return err -} - -// Set a string output. -func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) { - if emitter.write_handler != nil { - panic("must set the output target only once") - } - emitter.write_handler = yaml_string_write_handler - emitter.output_buffer = output_buffer -} - -// Set a file output. -func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) { - if emitter.write_handler != nil { - panic("must set the output target only once") - } - emitter.write_handler = yaml_writer_write_handler - emitter.output_writer = w -} - -// Set the output encoding. -func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) { - if emitter.encoding != yaml_ANY_ENCODING { - panic("must set the output encoding only once") - } - emitter.encoding = encoding -} - -// Set the canonical output style. -func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) { - emitter.canonical = canonical -} - -// Set the indentation increment. -func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) { - if indent < 2 || indent > 9 { - indent = 2 - } - emitter.best_indent = indent -} - -// Set the preferred line width. -func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) { - if width < 0 { - width = -1 - } - emitter.best_width = width -} - -// Set if unescaped non-ASCII characters are allowed. -func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) { - emitter.unicode = unicode -} - -// Set the preferred line break character. -func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) { - emitter.line_break = line_break -} - -///* -// * Destroy a token object. -// */ -// -//YAML_DECLARE(void) -//yaml_token_delete(yaml_token_t *token) -//{ -// assert(token); // Non-NULL token object expected. -// -// switch (token.type) -// { -// case YAML_TAG_DIRECTIVE_TOKEN: -// yaml_free(token.data.tag_directive.handle); -// yaml_free(token.data.tag_directive.prefix); -// break; -// -// case YAML_ALIAS_TOKEN: -// yaml_free(token.data.alias.value); -// break; -// -// case YAML_ANCHOR_TOKEN: -// yaml_free(token.data.anchor.value); -// break; -// -// case YAML_TAG_TOKEN: -// yaml_free(token.data.tag.handle); -// yaml_free(token.data.tag.suffix); -// break; -// -// case YAML_SCALAR_TOKEN: -// yaml_free(token.data.scalar.value); -// break; -// -// default: -// break; -// } -// -// memset(token, 0, sizeof(yaml_token_t)); -//} -// -///* -// * Check if a string is a valid UTF-8 sequence. -// * -// * Check 'reader.c' for more details on UTF-8 encoding. -// */ -// -//static int -//yaml_check_utf8(yaml_char_t *start, size_t length) -//{ -// yaml_char_t *end = start+length; -// yaml_char_t *pointer = start; -// -// while (pointer < end) { -// unsigned char octet; -// unsigned int width; -// unsigned int value; -// size_t k; -// -// octet = pointer[0]; -// width = (octet & 0x80) == 0x00 ? 1 : -// (octet & 0xE0) == 0xC0 ? 2 : -// (octet & 0xF0) == 0xE0 ? 3 : -// (octet & 0xF8) == 0xF0 ? 4 : 0; -// value = (octet & 0x80) == 0x00 ? octet & 0x7F : -// (octet & 0xE0) == 0xC0 ? octet & 0x1F : -// (octet & 0xF0) == 0xE0 ? octet & 0x0F : -// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; -// if (!width) return 0; -// if (pointer+width > end) return 0; -// for (k = 1; k < width; k ++) { -// octet = pointer[k]; -// if ((octet & 0xC0) != 0x80) return 0; -// value = (value << 6) + (octet & 0x3F); -// } -// if (!((width == 1) || -// (width == 2 && value >= 0x80) || -// (width == 3 && value >= 0x800) || -// (width == 4 && value >= 0x10000))) return 0; -// -// pointer += width; -// } -// -// return 1; -//} -// - -// Create STREAM-START. -func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) { - *event = yaml_event_t{ - typ: yaml_STREAM_START_EVENT, - encoding: encoding, - } -} - -// Create STREAM-END. -func yaml_stream_end_event_initialize(event *yaml_event_t) { - *event = yaml_event_t{ - typ: yaml_STREAM_END_EVENT, - } -} - -// Create DOCUMENT-START. -func yaml_document_start_event_initialize( - event *yaml_event_t, - version_directive *yaml_version_directive_t, - tag_directives []yaml_tag_directive_t, - implicit bool, -) { - *event = yaml_event_t{ - typ: yaml_DOCUMENT_START_EVENT, - version_directive: version_directive, - tag_directives: tag_directives, - implicit: implicit, - } -} - -// Create DOCUMENT-END. -func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) { - *event = yaml_event_t{ - typ: yaml_DOCUMENT_END_EVENT, - implicit: implicit, - } -} - -// Create ALIAS. -func yaml_alias_event_initialize(event *yaml_event_t, anchor []byte) bool { - *event = yaml_event_t{ - typ: yaml_ALIAS_EVENT, - anchor: anchor, - } - return true -} - -// Create SCALAR. -func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool { - *event = yaml_event_t{ - typ: yaml_SCALAR_EVENT, - anchor: anchor, - tag: tag, - value: value, - implicit: plain_implicit, - quoted_implicit: quoted_implicit, - style: yaml_style_t(style), - } - return true -} - -// Create SEQUENCE-START. -func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool { - *event = yaml_event_t{ - typ: yaml_SEQUENCE_START_EVENT, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(style), - } - return true -} - -// Create SEQUENCE-END. -func yaml_sequence_end_event_initialize(event *yaml_event_t) bool { - *event = yaml_event_t{ - typ: yaml_SEQUENCE_END_EVENT, - } - return true -} - -// Create MAPPING-START. -func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) { - *event = yaml_event_t{ - typ: yaml_MAPPING_START_EVENT, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(style), - } -} - -// Create MAPPING-END. -func yaml_mapping_end_event_initialize(event *yaml_event_t) { - *event = yaml_event_t{ - typ: yaml_MAPPING_END_EVENT, - } -} - -// Destroy an event object. -func yaml_event_delete(event *yaml_event_t) { - *event = yaml_event_t{} -} - -///* -// * Create a document object. -// */ -// -//YAML_DECLARE(int) -//yaml_document_initialize(document *yaml_document_t, -// version_directive *yaml_version_directive_t, -// tag_directives_start *yaml_tag_directive_t, -// tag_directives_end *yaml_tag_directive_t, -// start_implicit int, end_implicit int) -//{ -// struct { -// error yaml_error_type_t -// } context -// struct { -// start *yaml_node_t -// end *yaml_node_t -// top *yaml_node_t -// } nodes = { NULL, NULL, NULL } -// version_directive_copy *yaml_version_directive_t = NULL -// struct { -// start *yaml_tag_directive_t -// end *yaml_tag_directive_t -// top *yaml_tag_directive_t -// } tag_directives_copy = { NULL, NULL, NULL } -// value yaml_tag_directive_t = { NULL, NULL } -// mark yaml_mark_t = { 0, 0, 0 } -// -// assert(document) // Non-NULL document object is expected. -// assert((tag_directives_start && tag_directives_end) || -// (tag_directives_start == tag_directives_end)) -// // Valid tag directives are expected. -// -// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error -// -// if (version_directive) { -// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t)) -// if (!version_directive_copy) goto error -// version_directive_copy.major = version_directive.major -// version_directive_copy.minor = version_directive.minor -// } -// -// if (tag_directives_start != tag_directives_end) { -// tag_directive *yaml_tag_directive_t -// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE)) -// goto error -// for (tag_directive = tag_directives_start -// tag_directive != tag_directives_end; tag_directive ++) { -// assert(tag_directive.handle) -// assert(tag_directive.prefix) -// if (!yaml_check_utf8(tag_directive.handle, -// strlen((char *)tag_directive.handle))) -// goto error -// if (!yaml_check_utf8(tag_directive.prefix, -// strlen((char *)tag_directive.prefix))) -// goto error -// value.handle = yaml_strdup(tag_directive.handle) -// value.prefix = yaml_strdup(tag_directive.prefix) -// if (!value.handle || !value.prefix) goto error -// if (!PUSH(&context, tag_directives_copy, value)) -// goto error -// value.handle = NULL -// value.prefix = NULL -// } -// } -// -// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy, -// tag_directives_copy.start, tag_directives_copy.top, -// start_implicit, end_implicit, mark, mark) -// -// return 1 -// -//error: -// STACK_DEL(&context, nodes) -// yaml_free(version_directive_copy) -// while (!STACK_EMPTY(&context, tag_directives_copy)) { -// value yaml_tag_directive_t = POP(&context, tag_directives_copy) -// yaml_free(value.handle) -// yaml_free(value.prefix) -// } -// STACK_DEL(&context, tag_directives_copy) -// yaml_free(value.handle) -// yaml_free(value.prefix) -// -// return 0 -//} -// -///* -// * Destroy a document object. -// */ -// -//YAML_DECLARE(void) -//yaml_document_delete(document *yaml_document_t) -//{ -// struct { -// error yaml_error_type_t -// } context -// tag_directive *yaml_tag_directive_t -// -// context.error = YAML_NO_ERROR // Eliminate a compiler warning. -// -// assert(document) // Non-NULL document object is expected. -// -// while (!STACK_EMPTY(&context, document.nodes)) { -// node yaml_node_t = POP(&context, document.nodes) -// yaml_free(node.tag) -// switch (node.type) { -// case YAML_SCALAR_NODE: -// yaml_free(node.data.scalar.value) -// break -// case YAML_SEQUENCE_NODE: -// STACK_DEL(&context, node.data.sequence.items) -// break -// case YAML_MAPPING_NODE: -// STACK_DEL(&context, node.data.mapping.pairs) -// break -// default: -// assert(0) // Should not happen. -// } -// } -// STACK_DEL(&context, document.nodes) -// -// yaml_free(document.version_directive) -// for (tag_directive = document.tag_directives.start -// tag_directive != document.tag_directives.end -// tag_directive++) { -// yaml_free(tag_directive.handle) -// yaml_free(tag_directive.prefix) -// } -// yaml_free(document.tag_directives.start) -// -// memset(document, 0, sizeof(yaml_document_t)) -//} -// -///** -// * Get a document node. -// */ -// -//YAML_DECLARE(yaml_node_t *) -//yaml_document_get_node(document *yaml_document_t, index int) -//{ -// assert(document) // Non-NULL document object is expected. -// -// if (index > 0 && document.nodes.start + index <= document.nodes.top) { -// return document.nodes.start + index - 1 -// } -// return NULL -//} -// -///** -// * Get the root object. -// */ -// -//YAML_DECLARE(yaml_node_t *) -//yaml_document_get_root_node(document *yaml_document_t) -//{ -// assert(document) // Non-NULL document object is expected. -// -// if (document.nodes.top != document.nodes.start) { -// return document.nodes.start -// } -// return NULL -//} -// -///* -// * Add a scalar node to a document. -// */ -// -//YAML_DECLARE(int) -//yaml_document_add_scalar(document *yaml_document_t, -// tag *yaml_char_t, value *yaml_char_t, length int, -// style yaml_scalar_style_t) -//{ -// struct { -// error yaml_error_type_t -// } context -// mark yaml_mark_t = { 0, 0, 0 } -// tag_copy *yaml_char_t = NULL -// value_copy *yaml_char_t = NULL -// node yaml_node_t -// -// assert(document) // Non-NULL document object is expected. -// assert(value) // Non-NULL value is expected. -// -// if (!tag) { -// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG -// } -// -// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error -// tag_copy = yaml_strdup(tag) -// if (!tag_copy) goto error -// -// if (length < 0) { -// length = strlen((char *)value) -// } -// -// if (!yaml_check_utf8(value, length)) goto error -// value_copy = yaml_malloc(length+1) -// if (!value_copy) goto error -// memcpy(value_copy, value, length) -// value_copy[length] = '\0' -// -// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark) -// if (!PUSH(&context, document.nodes, node)) goto error -// -// return document.nodes.top - document.nodes.start -// -//error: -// yaml_free(tag_copy) -// yaml_free(value_copy) -// -// return 0 -//} -// -///* -// * Add a sequence node to a document. -// */ -// -//YAML_DECLARE(int) -//yaml_document_add_sequence(document *yaml_document_t, -// tag *yaml_char_t, style yaml_sequence_style_t) -//{ -// struct { -// error yaml_error_type_t -// } context -// mark yaml_mark_t = { 0, 0, 0 } -// tag_copy *yaml_char_t = NULL -// struct { -// start *yaml_node_item_t -// end *yaml_node_item_t -// top *yaml_node_item_t -// } items = { NULL, NULL, NULL } -// node yaml_node_t -// -// assert(document) // Non-NULL document object is expected. -// -// if (!tag) { -// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG -// } -// -// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error -// tag_copy = yaml_strdup(tag) -// if (!tag_copy) goto error -// -// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error -// -// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end, -// style, mark, mark) -// if (!PUSH(&context, document.nodes, node)) goto error -// -// return document.nodes.top - document.nodes.start -// -//error: -// STACK_DEL(&context, items) -// yaml_free(tag_copy) -// -// return 0 -//} -// -///* -// * Add a mapping node to a document. -// */ -// -//YAML_DECLARE(int) -//yaml_document_add_mapping(document *yaml_document_t, -// tag *yaml_char_t, style yaml_mapping_style_t) -//{ -// struct { -// error yaml_error_type_t -// } context -// mark yaml_mark_t = { 0, 0, 0 } -// tag_copy *yaml_char_t = NULL -// struct { -// start *yaml_node_pair_t -// end *yaml_node_pair_t -// top *yaml_node_pair_t -// } pairs = { NULL, NULL, NULL } -// node yaml_node_t -// -// assert(document) // Non-NULL document object is expected. -// -// if (!tag) { -// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG -// } -// -// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error -// tag_copy = yaml_strdup(tag) -// if (!tag_copy) goto error -// -// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error -// -// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end, -// style, mark, mark) -// if (!PUSH(&context, document.nodes, node)) goto error -// -// return document.nodes.top - document.nodes.start -// -//error: -// STACK_DEL(&context, pairs) -// yaml_free(tag_copy) -// -// return 0 -//} -// -///* -// * Append an item to a sequence node. -// */ -// -//YAML_DECLARE(int) -//yaml_document_append_sequence_item(document *yaml_document_t, -// sequence int, item int) -//{ -// struct { -// error yaml_error_type_t -// } context -// -// assert(document) // Non-NULL document is required. -// assert(sequence > 0 -// && document.nodes.start + sequence <= document.nodes.top) -// // Valid sequence id is required. -// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE) -// // A sequence node is required. -// assert(item > 0 && document.nodes.start + item <= document.nodes.top) -// // Valid item id is required. -// -// if (!PUSH(&context, -// document.nodes.start[sequence-1].data.sequence.items, item)) -// return 0 -// -// return 1 -//} -// -///* -// * Append a pair of a key and a value to a mapping node. -// */ -// -//YAML_DECLARE(int) -//yaml_document_append_mapping_pair(document *yaml_document_t, -// mapping int, key int, value int) -//{ -// struct { -// error yaml_error_type_t -// } context -// -// pair yaml_node_pair_t -// -// assert(document) // Non-NULL document is required. -// assert(mapping > 0 -// && document.nodes.start + mapping <= document.nodes.top) -// // Valid mapping id is required. -// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE) -// // A mapping node is required. -// assert(key > 0 && document.nodes.start + key <= document.nodes.top) -// // Valid key id is required. -// assert(value > 0 && document.nodes.start + value <= document.nodes.top) -// // Valid value id is required. -// -// pair.key = key -// pair.value = value -// -// if (!PUSH(&context, -// document.nodes.start[mapping-1].data.mapping.pairs, pair)) -// return 0 -// -// return 1 -//} -// -// diff --git a/go/sdk/vendor/gopkg.in/yaml.v3/decode.go b/go/sdk/vendor/gopkg.in/yaml.v3/decode.go deleted file mode 100644 index 0173b69..0000000 --- a/go/sdk/vendor/gopkg.in/yaml.v3/decode.go +++ /dev/null @@ -1,1000 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package yaml - -import ( - "encoding" - "encoding/base64" - "fmt" - "io" - "math" - "reflect" - "strconv" - "time" -) - -// ---------------------------------------------------------------------------- -// Parser, produces a node tree out of a libyaml event stream. - -type parser struct { - parser yaml_parser_t - event yaml_event_t - doc *Node - anchors map[string]*Node - doneInit bool - textless bool -} - -func newParser(b []byte) *parser { - p := parser{} - if !yaml_parser_initialize(&p.parser) { - panic("failed to initialize YAML emitter") - } - if len(b) == 0 { - b = []byte{'\n'} - } - yaml_parser_set_input_string(&p.parser, b) - return &p -} - -func newParserFromReader(r io.Reader) *parser { - p := parser{} - if !yaml_parser_initialize(&p.parser) { - panic("failed to initialize YAML emitter") - } - yaml_parser_set_input_reader(&p.parser, r) - return &p -} - -func (p *parser) init() { - if p.doneInit { - return - } - p.anchors = make(map[string]*Node) - p.expect(yaml_STREAM_START_EVENT) - p.doneInit = true -} - -func (p *parser) destroy() { - if p.event.typ != yaml_NO_EVENT { - yaml_event_delete(&p.event) - } - yaml_parser_delete(&p.parser) -} - -// expect consumes an event from the event stream and -// checks that it's of the expected type. -func (p *parser) expect(e yaml_event_type_t) { - if p.event.typ == yaml_NO_EVENT { - if !yaml_parser_parse(&p.parser, &p.event) { - p.fail() - } - } - if p.event.typ == yaml_STREAM_END_EVENT { - failf("attempted to go past the end of stream; corrupted value?") - } - if p.event.typ != e { - p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ) - p.fail() - } - yaml_event_delete(&p.event) - p.event.typ = yaml_NO_EVENT -} - -// peek peeks at the next event in the event stream, -// puts the results into p.event and returns the event type. -func (p *parser) peek() yaml_event_type_t { - if p.event.typ != yaml_NO_EVENT { - return p.event.typ - } - // It's curious choice from the underlying API to generally return a - // positive result on success, but on this case return true in an error - // scenario. This was the source of bugs in the past (issue #666). - if !yaml_parser_parse(&p.parser, &p.event) || p.parser.error != yaml_NO_ERROR { - p.fail() - } - return p.event.typ -} - -func (p *parser) fail() { - var where string - var line int - if p.parser.context_mark.line != 0 { - line = p.parser.context_mark.line - // Scanner errors don't iterate line before returning error - if p.parser.error == yaml_SCANNER_ERROR { - line++ - } - } else if p.parser.problem_mark.line != 0 { - line = p.parser.problem_mark.line - // Scanner errors don't iterate line before returning error - if p.parser.error == yaml_SCANNER_ERROR { - line++ - } - } - if line != 0 { - where = "line " + strconv.Itoa(line) + ": " - } - var msg string - if len(p.parser.problem) > 0 { - msg = p.parser.problem - } else { - msg = "unknown problem parsing YAML content" - } - failf("%s%s", where, msg) -} - -func (p *parser) anchor(n *Node, anchor []byte) { - if anchor != nil { - n.Anchor = string(anchor) - p.anchors[n.Anchor] = n - } -} - -func (p *parser) parse() *Node { - p.init() - switch p.peek() { - case yaml_SCALAR_EVENT: - return p.scalar() - case yaml_ALIAS_EVENT: - return p.alias() - case yaml_MAPPING_START_EVENT: - return p.mapping() - case yaml_SEQUENCE_START_EVENT: - return p.sequence() - case yaml_DOCUMENT_START_EVENT: - return p.document() - case yaml_STREAM_END_EVENT: - // Happens when attempting to decode an empty buffer. - return nil - case yaml_TAIL_COMMENT_EVENT: - panic("internal error: unexpected tail comment event (please report)") - default: - panic("internal error: attempted to parse unknown event (please report): " + p.event.typ.String()) - } -} - -func (p *parser) node(kind Kind, defaultTag, tag, value string) *Node { - var style Style - if tag != "" && tag != "!" { - tag = shortTag(tag) - style = TaggedStyle - } else if defaultTag != "" { - tag = defaultTag - } else if kind == ScalarNode { - tag, _ = resolve("", value) - } - n := &Node{ - Kind: kind, - Tag: tag, - Value: value, - Style: style, - } - if !p.textless { - n.Line = p.event.start_mark.line + 1 - n.Column = p.event.start_mark.column + 1 - n.HeadComment = string(p.event.head_comment) - n.LineComment = string(p.event.line_comment) - n.FootComment = string(p.event.foot_comment) - } - return n -} - -func (p *parser) parseChild(parent *Node) *Node { - child := p.parse() - parent.Content = append(parent.Content, child) - return child -} - -func (p *parser) document() *Node { - n := p.node(DocumentNode, "", "", "") - p.doc = n - p.expect(yaml_DOCUMENT_START_EVENT) - p.parseChild(n) - if p.peek() == yaml_DOCUMENT_END_EVENT { - n.FootComment = string(p.event.foot_comment) - } - p.expect(yaml_DOCUMENT_END_EVENT) - return n -} - -func (p *parser) alias() *Node { - n := p.node(AliasNode, "", "", string(p.event.anchor)) - n.Alias = p.anchors[n.Value] - if n.Alias == nil { - failf("unknown anchor '%s' referenced", n.Value) - } - p.expect(yaml_ALIAS_EVENT) - return n -} - -func (p *parser) scalar() *Node { - var parsedStyle = p.event.scalar_style() - var nodeStyle Style - switch { - case parsedStyle&yaml_DOUBLE_QUOTED_SCALAR_STYLE != 0: - nodeStyle = DoubleQuotedStyle - case parsedStyle&yaml_SINGLE_QUOTED_SCALAR_STYLE != 0: - nodeStyle = SingleQuotedStyle - case parsedStyle&yaml_LITERAL_SCALAR_STYLE != 0: - nodeStyle = LiteralStyle - case parsedStyle&yaml_FOLDED_SCALAR_STYLE != 0: - nodeStyle = FoldedStyle - } - var nodeValue = string(p.event.value) - var nodeTag = string(p.event.tag) - var defaultTag string - if nodeStyle == 0 { - if nodeValue == "<<" { - defaultTag = mergeTag - } - } else { - defaultTag = strTag - } - n := p.node(ScalarNode, defaultTag, nodeTag, nodeValue) - n.Style |= nodeStyle - p.anchor(n, p.event.anchor) - p.expect(yaml_SCALAR_EVENT) - return n -} - -func (p *parser) sequence() *Node { - n := p.node(SequenceNode, seqTag, string(p.event.tag), "") - if p.event.sequence_style()&yaml_FLOW_SEQUENCE_STYLE != 0 { - n.Style |= FlowStyle - } - p.anchor(n, p.event.anchor) - p.expect(yaml_SEQUENCE_START_EVENT) - for p.peek() != yaml_SEQUENCE_END_EVENT { - p.parseChild(n) - } - n.LineComment = string(p.event.line_comment) - n.FootComment = string(p.event.foot_comment) - p.expect(yaml_SEQUENCE_END_EVENT) - return n -} - -func (p *parser) mapping() *Node { - n := p.node(MappingNode, mapTag, string(p.event.tag), "") - block := true - if p.event.mapping_style()&yaml_FLOW_MAPPING_STYLE != 0 { - block = false - n.Style |= FlowStyle - } - p.anchor(n, p.event.anchor) - p.expect(yaml_MAPPING_START_EVENT) - for p.peek() != yaml_MAPPING_END_EVENT { - k := p.parseChild(n) - if block && k.FootComment != "" { - // Must be a foot comment for the prior value when being dedented. - if len(n.Content) > 2 { - n.Content[len(n.Content)-3].FootComment = k.FootComment - k.FootComment = "" - } - } - v := p.parseChild(n) - if k.FootComment == "" && v.FootComment != "" { - k.FootComment = v.FootComment - v.FootComment = "" - } - if p.peek() == yaml_TAIL_COMMENT_EVENT { - if k.FootComment == "" { - k.FootComment = string(p.event.foot_comment) - } - p.expect(yaml_TAIL_COMMENT_EVENT) - } - } - n.LineComment = string(p.event.line_comment) - n.FootComment = string(p.event.foot_comment) - if n.Style&FlowStyle == 0 && n.FootComment != "" && len(n.Content) > 1 { - n.Content[len(n.Content)-2].FootComment = n.FootComment - n.FootComment = "" - } - p.expect(yaml_MAPPING_END_EVENT) - return n -} - -// ---------------------------------------------------------------------------- -// Decoder, unmarshals a node into a provided value. - -type decoder struct { - doc *Node - aliases map[*Node]bool - terrors []string - - stringMapType reflect.Type - generalMapType reflect.Type - - knownFields bool - uniqueKeys bool - decodeCount int - aliasCount int - aliasDepth int - - mergedFields map[interface{}]bool -} - -var ( - nodeType = reflect.TypeOf(Node{}) - durationType = reflect.TypeOf(time.Duration(0)) - stringMapType = reflect.TypeOf(map[string]interface{}{}) - generalMapType = reflect.TypeOf(map[interface{}]interface{}{}) - ifaceType = generalMapType.Elem() - timeType = reflect.TypeOf(time.Time{}) - ptrTimeType = reflect.TypeOf(&time.Time{}) -) - -func newDecoder() *decoder { - d := &decoder{ - stringMapType: stringMapType, - generalMapType: generalMapType, - uniqueKeys: true, - } - d.aliases = make(map[*Node]bool) - return d -} - -func (d *decoder) terror(n *Node, tag string, out reflect.Value) { - if n.Tag != "" { - tag = n.Tag - } - value := n.Value - if tag != seqTag && tag != mapTag { - if len(value) > 10 { - value = " `" + value[:7] + "...`" - } else { - value = " `" + value + "`" - } - } - d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.Line, shortTag(tag), value, out.Type())) -} - -func (d *decoder) callUnmarshaler(n *Node, u Unmarshaler) (good bool) { - err := u.UnmarshalYAML(n) - if e, ok := err.(*TypeError); ok { - d.terrors = append(d.terrors, e.Errors...) - return false - } - if err != nil { - fail(err) - } - return true -} - -func (d *decoder) callObsoleteUnmarshaler(n *Node, u obsoleteUnmarshaler) (good bool) { - terrlen := len(d.terrors) - err := u.UnmarshalYAML(func(v interface{}) (err error) { - defer handleErr(&err) - d.unmarshal(n, reflect.ValueOf(v)) - if len(d.terrors) > terrlen { - issues := d.terrors[terrlen:] - d.terrors = d.terrors[:terrlen] - return &TypeError{issues} - } - return nil - }) - if e, ok := err.(*TypeError); ok { - d.terrors = append(d.terrors, e.Errors...) - return false - } - if err != nil { - fail(err) - } - return true -} - -// d.prepare initializes and dereferences pointers and calls UnmarshalYAML -// if a value is found to implement it. -// It returns the initialized and dereferenced out value, whether -// unmarshalling was already done by UnmarshalYAML, and if so whether -// its types unmarshalled appropriately. -// -// If n holds a null value, prepare returns before doing anything. -func (d *decoder) prepare(n *Node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) { - if n.ShortTag() == nullTag { - return out, false, false - } - again := true - for again { - again = false - if out.Kind() == reflect.Ptr { - if out.IsNil() { - out.Set(reflect.New(out.Type().Elem())) - } - out = out.Elem() - again = true - } - if out.CanAddr() { - outi := out.Addr().Interface() - if u, ok := outi.(Unmarshaler); ok { - good = d.callUnmarshaler(n, u) - return out, true, good - } - if u, ok := outi.(obsoleteUnmarshaler); ok { - good = d.callObsoleteUnmarshaler(n, u) - return out, true, good - } - } - } - return out, false, false -} - -func (d *decoder) fieldByIndex(n *Node, v reflect.Value, index []int) (field reflect.Value) { - if n.ShortTag() == nullTag { - return reflect.Value{} - } - for _, num := range index { - for { - if v.Kind() == reflect.Ptr { - if v.IsNil() { - v.Set(reflect.New(v.Type().Elem())) - } - v = v.Elem() - continue - } - break - } - v = v.Field(num) - } - return v -} - -const ( - // 400,000 decode operations is ~500kb of dense object declarations, or - // ~5kb of dense object declarations with 10000% alias expansion - alias_ratio_range_low = 400000 - - // 4,000,000 decode operations is ~5MB of dense object declarations, or - // ~4.5MB of dense object declarations with 10% alias expansion - alias_ratio_range_high = 4000000 - - // alias_ratio_range is the range over which we scale allowed alias ratios - alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low) -) - -func allowedAliasRatio(decodeCount int) float64 { - switch { - case decodeCount <= alias_ratio_range_low: - // allow 99% to come from alias expansion for small-to-medium documents - return 0.99 - case decodeCount >= alias_ratio_range_high: - // allow 10% to come from alias expansion for very large documents - return 0.10 - default: - // scale smoothly from 99% down to 10% over the range. - // this maps to 396,000 - 400,000 allowed alias-driven decodes over the range. - // 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps). - return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range) - } -} - -func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) { - d.decodeCount++ - if d.aliasDepth > 0 { - d.aliasCount++ - } - if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) { - failf("document contains excessive aliasing") - } - if out.Type() == nodeType { - out.Set(reflect.ValueOf(n).Elem()) - return true - } - switch n.Kind { - case DocumentNode: - return d.document(n, out) - case AliasNode: - return d.alias(n, out) - } - out, unmarshaled, good := d.prepare(n, out) - if unmarshaled { - return good - } - switch n.Kind { - case ScalarNode: - good = d.scalar(n, out) - case MappingNode: - good = d.mapping(n, out) - case SequenceNode: - good = d.sequence(n, out) - case 0: - if n.IsZero() { - return d.null(out) - } - fallthrough - default: - failf("cannot decode node with unknown kind %d", n.Kind) - } - return good -} - -func (d *decoder) document(n *Node, out reflect.Value) (good bool) { - if len(n.Content) == 1 { - d.doc = n - d.unmarshal(n.Content[0], out) - return true - } - return false -} - -func (d *decoder) alias(n *Node, out reflect.Value) (good bool) { - if d.aliases[n] { - // TODO this could actually be allowed in some circumstances. - failf("anchor '%s' value contains itself", n.Value) - } - d.aliases[n] = true - d.aliasDepth++ - good = d.unmarshal(n.Alias, out) - d.aliasDepth-- - delete(d.aliases, n) - return good -} - -var zeroValue reflect.Value - -func resetMap(out reflect.Value) { - for _, k := range out.MapKeys() { - out.SetMapIndex(k, zeroValue) - } -} - -func (d *decoder) null(out reflect.Value) bool { - if out.CanAddr() { - switch out.Kind() { - case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: - out.Set(reflect.Zero(out.Type())) - return true - } - } - return false -} - -func (d *decoder) scalar(n *Node, out reflect.Value) bool { - var tag string - var resolved interface{} - if n.indicatedString() { - tag = strTag - resolved = n.Value - } else { - tag, resolved = resolve(n.Tag, n.Value) - if tag == binaryTag { - data, err := base64.StdEncoding.DecodeString(resolved.(string)) - if err != nil { - failf("!!binary value contains invalid base64 data") - } - resolved = string(data) - } - } - if resolved == nil { - return d.null(out) - } - if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { - // We've resolved to exactly the type we want, so use that. - out.Set(resolvedv) - return true - } - // Perhaps we can use the value as a TextUnmarshaler to - // set its value. - if out.CanAddr() { - u, ok := out.Addr().Interface().(encoding.TextUnmarshaler) - if ok { - var text []byte - if tag == binaryTag { - text = []byte(resolved.(string)) - } else { - // We let any value be unmarshaled into TextUnmarshaler. - // That might be more lax than we'd like, but the - // TextUnmarshaler itself should bowl out any dubious values. - text = []byte(n.Value) - } - err := u.UnmarshalText(text) - if err != nil { - fail(err) - } - return true - } - } - switch out.Kind() { - case reflect.String: - if tag == binaryTag { - out.SetString(resolved.(string)) - return true - } - out.SetString(n.Value) - return true - case reflect.Interface: - out.Set(reflect.ValueOf(resolved)) - return true - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - // This used to work in v2, but it's very unfriendly. - isDuration := out.Type() == durationType - - switch resolved := resolved.(type) { - case int: - if !isDuration && !out.OverflowInt(int64(resolved)) { - out.SetInt(int64(resolved)) - return true - } - case int64: - if !isDuration && !out.OverflowInt(resolved) { - out.SetInt(resolved) - return true - } - case uint64: - if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { - out.SetInt(int64(resolved)) - return true - } - case float64: - if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { - out.SetInt(int64(resolved)) - return true - } - case string: - if out.Type() == durationType { - d, err := time.ParseDuration(resolved) - if err == nil { - out.SetInt(int64(d)) - return true - } - } - } - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - switch resolved := resolved.(type) { - case int: - if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { - out.SetUint(uint64(resolved)) - return true - } - case int64: - if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { - out.SetUint(uint64(resolved)) - return true - } - case uint64: - if !out.OverflowUint(uint64(resolved)) { - out.SetUint(uint64(resolved)) - return true - } - case float64: - if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) { - out.SetUint(uint64(resolved)) - return true - } - } - case reflect.Bool: - switch resolved := resolved.(type) { - case bool: - out.SetBool(resolved) - return true - case string: - // This offers some compatibility with the 1.1 spec (https://yaml.org/type/bool.html). - // It only works if explicitly attempting to unmarshal into a typed bool value. - switch resolved { - case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON": - out.SetBool(true) - return true - case "n", "N", "no", "No", "NO", "off", "Off", "OFF": - out.SetBool(false) - return true - } - } - case reflect.Float32, reflect.Float64: - switch resolved := resolved.(type) { - case int: - out.SetFloat(float64(resolved)) - return true - case int64: - out.SetFloat(float64(resolved)) - return true - case uint64: - out.SetFloat(float64(resolved)) - return true - case float64: - out.SetFloat(resolved) - return true - } - case reflect.Struct: - if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { - out.Set(resolvedv) - return true - } - case reflect.Ptr: - panic("yaml internal error: please report the issue") - } - d.terror(n, tag, out) - return false -} - -func settableValueOf(i interface{}) reflect.Value { - v := reflect.ValueOf(i) - sv := reflect.New(v.Type()).Elem() - sv.Set(v) - return sv -} - -func (d *decoder) sequence(n *Node, out reflect.Value) (good bool) { - l := len(n.Content) - - var iface reflect.Value - switch out.Kind() { - case reflect.Slice: - out.Set(reflect.MakeSlice(out.Type(), l, l)) - case reflect.Array: - if l != out.Len() { - failf("invalid array: want %d elements but got %d", out.Len(), l) - } - case reflect.Interface: - // No type hints. Will have to use a generic sequence. - iface = out - out = settableValueOf(make([]interface{}, l)) - default: - d.terror(n, seqTag, out) - return false - } - et := out.Type().Elem() - - j := 0 - for i := 0; i < l; i++ { - e := reflect.New(et).Elem() - if ok := d.unmarshal(n.Content[i], e); ok { - out.Index(j).Set(e) - j++ - } - } - if out.Kind() != reflect.Array { - out.Set(out.Slice(0, j)) - } - if iface.IsValid() { - iface.Set(out) - } - return true -} - -func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) { - l := len(n.Content) - if d.uniqueKeys { - nerrs := len(d.terrors) - for i := 0; i < l; i += 2 { - ni := n.Content[i] - for j := i + 2; j < l; j += 2 { - nj := n.Content[j] - if ni.Kind == nj.Kind && ni.Value == nj.Value { - d.terrors = append(d.terrors, fmt.Sprintf("line %d: mapping key %#v already defined at line %d", nj.Line, nj.Value, ni.Line)) - } - } - } - if len(d.terrors) > nerrs { - return false - } - } - switch out.Kind() { - case reflect.Struct: - return d.mappingStruct(n, out) - case reflect.Map: - // okay - case reflect.Interface: - iface := out - if isStringMap(n) { - out = reflect.MakeMap(d.stringMapType) - } else { - out = reflect.MakeMap(d.generalMapType) - } - iface.Set(out) - default: - d.terror(n, mapTag, out) - return false - } - - outt := out.Type() - kt := outt.Key() - et := outt.Elem() - - stringMapType := d.stringMapType - generalMapType := d.generalMapType - if outt.Elem() == ifaceType { - if outt.Key().Kind() == reflect.String { - d.stringMapType = outt - } else if outt.Key() == ifaceType { - d.generalMapType = outt - } - } - - mergedFields := d.mergedFields - d.mergedFields = nil - - var mergeNode *Node - - mapIsNew := false - if out.IsNil() { - out.Set(reflect.MakeMap(outt)) - mapIsNew = true - } - for i := 0; i < l; i += 2 { - if isMerge(n.Content[i]) { - mergeNode = n.Content[i+1] - continue - } - k := reflect.New(kt).Elem() - if d.unmarshal(n.Content[i], k) { - if mergedFields != nil { - ki := k.Interface() - if mergedFields[ki] { - continue - } - mergedFields[ki] = true - } - kkind := k.Kind() - if kkind == reflect.Interface { - kkind = k.Elem().Kind() - } - if kkind == reflect.Map || kkind == reflect.Slice { - failf("invalid map key: %#v", k.Interface()) - } - e := reflect.New(et).Elem() - if d.unmarshal(n.Content[i+1], e) || n.Content[i+1].ShortTag() == nullTag && (mapIsNew || !out.MapIndex(k).IsValid()) { - out.SetMapIndex(k, e) - } - } - } - - d.mergedFields = mergedFields - if mergeNode != nil { - d.merge(n, mergeNode, out) - } - - d.stringMapType = stringMapType - d.generalMapType = generalMapType - return true -} - -func isStringMap(n *Node) bool { - if n.Kind != MappingNode { - return false - } - l := len(n.Content) - for i := 0; i < l; i += 2 { - shortTag := n.Content[i].ShortTag() - if shortTag != strTag && shortTag != mergeTag { - return false - } - } - return true -} - -func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) { - sinfo, err := getStructInfo(out.Type()) - if err != nil { - panic(err) - } - - var inlineMap reflect.Value - var elemType reflect.Type - if sinfo.InlineMap != -1 { - inlineMap = out.Field(sinfo.InlineMap) - elemType = inlineMap.Type().Elem() - } - - for _, index := range sinfo.InlineUnmarshalers { - field := d.fieldByIndex(n, out, index) - d.prepare(n, field) - } - - mergedFields := d.mergedFields - d.mergedFields = nil - var mergeNode *Node - var doneFields []bool - if d.uniqueKeys { - doneFields = make([]bool, len(sinfo.FieldsList)) - } - name := settableValueOf("") - l := len(n.Content) - for i := 0; i < l; i += 2 { - ni := n.Content[i] - if isMerge(ni) { - mergeNode = n.Content[i+1] - continue - } - if !d.unmarshal(ni, name) { - continue - } - sname := name.String() - if mergedFields != nil { - if mergedFields[sname] { - continue - } - mergedFields[sname] = true - } - if info, ok := sinfo.FieldsMap[sname]; ok { - if d.uniqueKeys { - if doneFields[info.Id] { - d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type())) - continue - } - doneFields[info.Id] = true - } - var field reflect.Value - if info.Inline == nil { - field = out.Field(info.Num) - } else { - field = d.fieldByIndex(n, out, info.Inline) - } - d.unmarshal(n.Content[i+1], field) - } else if sinfo.InlineMap != -1 { - if inlineMap.IsNil() { - inlineMap.Set(reflect.MakeMap(inlineMap.Type())) - } - value := reflect.New(elemType).Elem() - d.unmarshal(n.Content[i+1], value) - inlineMap.SetMapIndex(name, value) - } else if d.knownFields { - d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type())) - } - } - - d.mergedFields = mergedFields - if mergeNode != nil { - d.merge(n, mergeNode, out) - } - return true -} - -func failWantMap() { - failf("map merge requires map or sequence of maps as the value") -} - -func (d *decoder) merge(parent *Node, merge *Node, out reflect.Value) { - mergedFields := d.mergedFields - if mergedFields == nil { - d.mergedFields = make(map[interface{}]bool) - for i := 0; i < len(parent.Content); i += 2 { - k := reflect.New(ifaceType).Elem() - if d.unmarshal(parent.Content[i], k) { - d.mergedFields[k.Interface()] = true - } - } - } - - switch merge.Kind { - case MappingNode: - d.unmarshal(merge, out) - case AliasNode: - if merge.Alias != nil && merge.Alias.Kind != MappingNode { - failWantMap() - } - d.unmarshal(merge, out) - case SequenceNode: - for i := 0; i < len(merge.Content); i++ { - ni := merge.Content[i] - if ni.Kind == AliasNode { - if ni.Alias != nil && ni.Alias.Kind != MappingNode { - failWantMap() - } - } else if ni.Kind != MappingNode { - failWantMap() - } - d.unmarshal(ni, out) - } - default: - failWantMap() - } - - d.mergedFields = mergedFields -} - -func isMerge(n *Node) bool { - return n.Kind == ScalarNode && n.Value == "<<" && (n.Tag == "" || n.Tag == "!" || shortTag(n.Tag) == mergeTag) -} diff --git a/go/sdk/vendor/gopkg.in/yaml.v3/emitterc.go b/go/sdk/vendor/gopkg.in/yaml.v3/emitterc.go deleted file mode 100644 index dde20e5..0000000 --- a/go/sdk/vendor/gopkg.in/yaml.v3/emitterc.go +++ /dev/null @@ -1,2019 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -// of the Software, and to permit persons to whom the Software is furnished to do -// so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -package yaml - -import ( - "bytes" - "fmt" -) - -// Flush the buffer if needed. -func flush(emitter *yaml_emitter_t) bool { - if emitter.buffer_pos+5 >= len(emitter.buffer) { - return yaml_emitter_flush(emitter) - } - return true -} - -// Put a character to the output buffer. -func put(emitter *yaml_emitter_t, value byte) bool { - if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { - return false - } - emitter.buffer[emitter.buffer_pos] = value - emitter.buffer_pos++ - emitter.column++ - return true -} - -// Put a line break to the output buffer. -func put_break(emitter *yaml_emitter_t) bool { - if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { - return false - } - switch emitter.line_break { - case yaml_CR_BREAK: - emitter.buffer[emitter.buffer_pos] = '\r' - emitter.buffer_pos += 1 - case yaml_LN_BREAK: - emitter.buffer[emitter.buffer_pos] = '\n' - emitter.buffer_pos += 1 - case yaml_CRLN_BREAK: - emitter.buffer[emitter.buffer_pos+0] = '\r' - emitter.buffer[emitter.buffer_pos+1] = '\n' - emitter.buffer_pos += 2 - default: - panic("unknown line break setting") - } - if emitter.column == 0 { - emitter.space_above = true - } - emitter.column = 0 - emitter.line++ - // [Go] Do this here and below and drop from everywhere else (see commented lines). - emitter.indention = true - return true -} - -// Copy a character from a string into buffer. -func write(emitter *yaml_emitter_t, s []byte, i *int) bool { - if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { - return false - } - p := emitter.buffer_pos - w := width(s[*i]) - switch w { - case 4: - emitter.buffer[p+3] = s[*i+3] - fallthrough - case 3: - emitter.buffer[p+2] = s[*i+2] - fallthrough - case 2: - emitter.buffer[p+1] = s[*i+1] - fallthrough - case 1: - emitter.buffer[p+0] = s[*i+0] - default: - panic("unknown character width") - } - emitter.column++ - emitter.buffer_pos += w - *i += w - return true -} - -// Write a whole string into buffer. -func write_all(emitter *yaml_emitter_t, s []byte) bool { - for i := 0; i < len(s); { - if !write(emitter, s, &i) { - return false - } - } - return true -} - -// Copy a line break character from a string into buffer. -func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool { - if s[*i] == '\n' { - if !put_break(emitter) { - return false - } - *i++ - } else { - if !write(emitter, s, i) { - return false - } - if emitter.column == 0 { - emitter.space_above = true - } - emitter.column = 0 - emitter.line++ - // [Go] Do this here and above and drop from everywhere else (see commented lines). - emitter.indention = true - } - return true -} - -// Set an emitter error and return false. -func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool { - emitter.error = yaml_EMITTER_ERROR - emitter.problem = problem - return false -} - -// Emit an event. -func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool { - emitter.events = append(emitter.events, *event) - for !yaml_emitter_need_more_events(emitter) { - event := &emitter.events[emitter.events_head] - if !yaml_emitter_analyze_event(emitter, event) { - return false - } - if !yaml_emitter_state_machine(emitter, event) { - return false - } - yaml_event_delete(event) - emitter.events_head++ - } - return true -} - -// Check if we need to accumulate more events before emitting. -// -// We accumulate extra -// - 1 event for DOCUMENT-START -// - 2 events for SEQUENCE-START -// - 3 events for MAPPING-START -func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool { - if emitter.events_head == len(emitter.events) { - return true - } - var accumulate int - switch emitter.events[emitter.events_head].typ { - case yaml_DOCUMENT_START_EVENT: - accumulate = 1 - break - case yaml_SEQUENCE_START_EVENT: - accumulate = 2 - break - case yaml_MAPPING_START_EVENT: - accumulate = 3 - break - default: - return false - } - if len(emitter.events)-emitter.events_head > accumulate { - return false - } - var level int - for i := emitter.events_head; i < len(emitter.events); i++ { - switch emitter.events[i].typ { - case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT: - level++ - case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT: - level-- - } - if level == 0 { - return false - } - } - return true -} - -// Append a directive to the directives stack. -func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool { - for i := 0; i < len(emitter.tag_directives); i++ { - if bytes.Equal(value.handle, emitter.tag_directives[i].handle) { - if allow_duplicates { - return true - } - return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive") - } - } - - // [Go] Do we actually need to copy this given garbage collection - // and the lack of deallocating destructors? - tag_copy := yaml_tag_directive_t{ - handle: make([]byte, len(value.handle)), - prefix: make([]byte, len(value.prefix)), - } - copy(tag_copy.handle, value.handle) - copy(tag_copy.prefix, value.prefix) - emitter.tag_directives = append(emitter.tag_directives, tag_copy) - return true -} - -// Increase the indentation level. -func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool { - emitter.indents = append(emitter.indents, emitter.indent) - if emitter.indent < 0 { - if flow { - emitter.indent = emitter.best_indent - } else { - emitter.indent = 0 - } - } else if !indentless { - // [Go] This was changed so that indentations are more regular. - if emitter.states[len(emitter.states)-1] == yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE { - // The first indent inside a sequence will just skip the "- " indicator. - emitter.indent += 2 - } else { - // Everything else aligns to the chosen indentation. - emitter.indent = emitter.best_indent * ((emitter.indent + emitter.best_indent) / emitter.best_indent) - } - } - return true -} - -// State dispatcher. -func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool { - switch emitter.state { - default: - case yaml_EMIT_STREAM_START_STATE: - return yaml_emitter_emit_stream_start(emitter, event) - - case yaml_EMIT_FIRST_DOCUMENT_START_STATE: - return yaml_emitter_emit_document_start(emitter, event, true) - - case yaml_EMIT_DOCUMENT_START_STATE: - return yaml_emitter_emit_document_start(emitter, event, false) - - case yaml_EMIT_DOCUMENT_CONTENT_STATE: - return yaml_emitter_emit_document_content(emitter, event) - - case yaml_EMIT_DOCUMENT_END_STATE: - return yaml_emitter_emit_document_end(emitter, event) - - case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE: - return yaml_emitter_emit_flow_sequence_item(emitter, event, true, false) - - case yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE: - return yaml_emitter_emit_flow_sequence_item(emitter, event, false, true) - - case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE: - return yaml_emitter_emit_flow_sequence_item(emitter, event, false, false) - - case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE: - return yaml_emitter_emit_flow_mapping_key(emitter, event, true, false) - - case yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE: - return yaml_emitter_emit_flow_mapping_key(emitter, event, false, true) - - case yaml_EMIT_FLOW_MAPPING_KEY_STATE: - return yaml_emitter_emit_flow_mapping_key(emitter, event, false, false) - - case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE: - return yaml_emitter_emit_flow_mapping_value(emitter, event, true) - - case yaml_EMIT_FLOW_MAPPING_VALUE_STATE: - return yaml_emitter_emit_flow_mapping_value(emitter, event, false) - - case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE: - return yaml_emitter_emit_block_sequence_item(emitter, event, true) - - case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE: - return yaml_emitter_emit_block_sequence_item(emitter, event, false) - - case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE: - return yaml_emitter_emit_block_mapping_key(emitter, event, true) - - case yaml_EMIT_BLOCK_MAPPING_KEY_STATE: - return yaml_emitter_emit_block_mapping_key(emitter, event, false) - - case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE: - return yaml_emitter_emit_block_mapping_value(emitter, event, true) - - case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE: - return yaml_emitter_emit_block_mapping_value(emitter, event, false) - - case yaml_EMIT_END_STATE: - return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END") - } - panic("invalid emitter state") -} - -// Expect STREAM-START. -func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if event.typ != yaml_STREAM_START_EVENT { - return yaml_emitter_set_emitter_error(emitter, "expected STREAM-START") - } - if emitter.encoding == yaml_ANY_ENCODING { - emitter.encoding = event.encoding - if emitter.encoding == yaml_ANY_ENCODING { - emitter.encoding = yaml_UTF8_ENCODING - } - } - if emitter.best_indent < 2 || emitter.best_indent > 9 { - emitter.best_indent = 2 - } - if emitter.best_width >= 0 && emitter.best_width <= emitter.best_indent*2 { - emitter.best_width = 80 - } - if emitter.best_width < 0 { - emitter.best_width = 1<<31 - 1 - } - if emitter.line_break == yaml_ANY_BREAK { - emitter.line_break = yaml_LN_BREAK - } - - emitter.indent = -1 - emitter.line = 0 - emitter.column = 0 - emitter.whitespace = true - emitter.indention = true - emitter.space_above = true - emitter.foot_indent = -1 - - if emitter.encoding != yaml_UTF8_ENCODING { - if !yaml_emitter_write_bom(emitter) { - return false - } - } - emitter.state = yaml_EMIT_FIRST_DOCUMENT_START_STATE - return true -} - -// Expect DOCUMENT-START or STREAM-END. -func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { - - if event.typ == yaml_DOCUMENT_START_EVENT { - - if event.version_directive != nil { - if !yaml_emitter_analyze_version_directive(emitter, event.version_directive) { - return false - } - } - - for i := 0; i < len(event.tag_directives); i++ { - tag_directive := &event.tag_directives[i] - if !yaml_emitter_analyze_tag_directive(emitter, tag_directive) { - return false - } - if !yaml_emitter_append_tag_directive(emitter, tag_directive, false) { - return false - } - } - - for i := 0; i < len(default_tag_directives); i++ { - tag_directive := &default_tag_directives[i] - if !yaml_emitter_append_tag_directive(emitter, tag_directive, true) { - return false - } - } - - implicit := event.implicit - if !first || emitter.canonical { - implicit = false - } - - if emitter.open_ended && (event.version_directive != nil || len(event.tag_directives) > 0) { - if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - - if event.version_directive != nil { - implicit = false - if !yaml_emitter_write_indicator(emitter, []byte("%YAML"), true, false, false) { - return false - } - if !yaml_emitter_write_indicator(emitter, []byte("1.1"), true, false, false) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - - if len(event.tag_directives) > 0 { - implicit = false - for i := 0; i < len(event.tag_directives); i++ { - tag_directive := &event.tag_directives[i] - if !yaml_emitter_write_indicator(emitter, []byte("%TAG"), true, false, false) { - return false - } - if !yaml_emitter_write_tag_handle(emitter, tag_directive.handle) { - return false - } - if !yaml_emitter_write_tag_content(emitter, tag_directive.prefix, true) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - } - - if yaml_emitter_check_empty_document(emitter) { - implicit = false - } - if !implicit { - if !yaml_emitter_write_indent(emitter) { - return false - } - if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) { - return false - } - if emitter.canonical || true { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - } - - if len(emitter.head_comment) > 0 { - if !yaml_emitter_process_head_comment(emitter) { - return false - } - if !put_break(emitter) { - return false - } - } - - emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE - return true - } - - if event.typ == yaml_STREAM_END_EVENT { - if emitter.open_ended { - if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !yaml_emitter_flush(emitter) { - return false - } - emitter.state = yaml_EMIT_END_STATE - return true - } - - return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END") -} - -// Expect the root node. -func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool { - emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE) - - if !yaml_emitter_process_head_comment(emitter) { - return false - } - if !yaml_emitter_emit_node(emitter, event, true, false, false, false) { - return false - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - return true -} - -// Expect DOCUMENT-END. -func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if event.typ != yaml_DOCUMENT_END_EVENT { - return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END") - } - // [Go] Force document foot separation. - emitter.foot_indent = 0 - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - emitter.foot_indent = -1 - if !yaml_emitter_write_indent(emitter) { - return false - } - if !event.implicit { - // [Go] Allocate the slice elsewhere. - if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !yaml_emitter_flush(emitter) { - return false - } - emitter.state = yaml_EMIT_DOCUMENT_START_STATE - emitter.tag_directives = emitter.tag_directives[:0] - return true -} - -// Expect a flow item node. -func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool { - if first { - if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) { - return false - } - if !yaml_emitter_increase_indent(emitter, true, false) { - return false - } - emitter.flow_level++ - } - - if event.typ == yaml_SEQUENCE_END_EVENT { - if emitter.canonical && !first && !trail { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - } - emitter.flow_level-- - emitter.indent = emitter.indents[len(emitter.indents)-1] - emitter.indents = emitter.indents[:len(emitter.indents)-1] - if emitter.column == 0 || emitter.canonical && !first { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) { - return false - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - - return true - } - - if !first && !trail { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - } - - if !yaml_emitter_process_head_comment(emitter) { - return false - } - if emitter.column == 0 { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - - if emitter.canonical || emitter.column > emitter.best_width { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { - emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE) - } else { - emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE) - } - if !yaml_emitter_emit_node(emitter, event, false, true, false, false) { - return false - } - if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - return true -} - -// Expect a flow key node. -func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool { - if first { - if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) { - return false - } - if !yaml_emitter_increase_indent(emitter, true, false) { - return false - } - emitter.flow_level++ - } - - if event.typ == yaml_MAPPING_END_EVENT { - if (emitter.canonical || len(emitter.head_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0) && !first && !trail { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - } - if !yaml_emitter_process_head_comment(emitter) { - return false - } - emitter.flow_level-- - emitter.indent = emitter.indents[len(emitter.indents)-1] - emitter.indents = emitter.indents[:len(emitter.indents)-1] - if emitter.canonical && !first { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) { - return false - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - return true - } - - if !first && !trail { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - } - - if !yaml_emitter_process_head_comment(emitter) { - return false - } - - if emitter.column == 0 { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - - if emitter.canonical || emitter.column > emitter.best_width { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - - if !emitter.canonical && yaml_emitter_check_simple_key(emitter) { - emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE) - return yaml_emitter_emit_node(emitter, event, false, false, true, true) - } - if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, false) { - return false - } - emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_VALUE_STATE) - return yaml_emitter_emit_node(emitter, event, false, false, true, false) -} - -// Expect a flow value node. -func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { - if simple { - if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { - return false - } - } else { - if emitter.canonical || emitter.column > emitter.best_width { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, false) { - return false - } - } - if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { - emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE) - } else { - emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE) - } - if !yaml_emitter_emit_node(emitter, event, false, false, true, false) { - return false - } - if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - return true -} - -// Expect a block item node. -func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { - if first { - if !yaml_emitter_increase_indent(emitter, false, false) { - return false - } - } - if event.typ == yaml_SEQUENCE_END_EVENT { - emitter.indent = emitter.indents[len(emitter.indents)-1] - emitter.indents = emitter.indents[:len(emitter.indents)-1] - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - return true - } - if !yaml_emitter_process_head_comment(emitter) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - if !yaml_emitter_write_indicator(emitter, []byte{'-'}, true, false, true) { - return false - } - emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE) - if !yaml_emitter_emit_node(emitter, event, false, true, false, false) { - return false - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - return true -} - -// Expect a block key node. -func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { - if first { - if !yaml_emitter_increase_indent(emitter, false, false) { - return false - } - } - if !yaml_emitter_process_head_comment(emitter) { - return false - } - if event.typ == yaml_MAPPING_END_EVENT { - emitter.indent = emitter.indents[len(emitter.indents)-1] - emitter.indents = emitter.indents[:len(emitter.indents)-1] - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - return true - } - if !yaml_emitter_write_indent(emitter) { - return false - } - if len(emitter.line_comment) > 0 { - // [Go] A line comment was provided for the key. That's unusual as the - // scanner associates line comments with the value. Either way, - // save the line comment and render it appropriately later. - emitter.key_line_comment = emitter.line_comment - emitter.line_comment = nil - } - if yaml_emitter_check_simple_key(emitter) { - emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE) - return yaml_emitter_emit_node(emitter, event, false, false, true, true) - } - if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, true) { - return false - } - emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_VALUE_STATE) - return yaml_emitter_emit_node(emitter, event, false, false, true, false) -} - -// Expect a block value node. -func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { - if simple { - if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { - return false - } - } else { - if !yaml_emitter_write_indent(emitter) { - return false - } - if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, true) { - return false - } - } - if len(emitter.key_line_comment) > 0 { - // [Go] Line comments are generally associated with the value, but when there's - // no value on the same line as a mapping key they end up attached to the - // key itself. - if event.typ == yaml_SCALAR_EVENT { - if len(emitter.line_comment) == 0 { - // A scalar is coming and it has no line comments by itself yet, - // so just let it handle the line comment as usual. If it has a - // line comment, we can't have both so the one from the key is lost. - emitter.line_comment = emitter.key_line_comment - emitter.key_line_comment = nil - } - } else if event.sequence_style() != yaml_FLOW_SEQUENCE_STYLE && (event.typ == yaml_MAPPING_START_EVENT || event.typ == yaml_SEQUENCE_START_EVENT) { - // An indented block follows, so write the comment right now. - emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment - if !yaml_emitter_process_line_comment(emitter) { - return false - } - emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment - } - } - emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE) - if !yaml_emitter_emit_node(emitter, event, false, false, true, false) { - return false - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - return true -} - -func yaml_emitter_silent_nil_event(emitter *yaml_emitter_t, event *yaml_event_t) bool { - return event.typ == yaml_SCALAR_EVENT && event.implicit && !emitter.canonical && len(emitter.scalar_data.value) == 0 -} - -// Expect a node. -func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t, - root bool, sequence bool, mapping bool, simple_key bool) bool { - - emitter.root_context = root - emitter.sequence_context = sequence - emitter.mapping_context = mapping - emitter.simple_key_context = simple_key - - switch event.typ { - case yaml_ALIAS_EVENT: - return yaml_emitter_emit_alias(emitter, event) - case yaml_SCALAR_EVENT: - return yaml_emitter_emit_scalar(emitter, event) - case yaml_SEQUENCE_START_EVENT: - return yaml_emitter_emit_sequence_start(emitter, event) - case yaml_MAPPING_START_EVENT: - return yaml_emitter_emit_mapping_start(emitter, event) - default: - return yaml_emitter_set_emitter_error(emitter, - fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.typ)) - } -} - -// Expect ALIAS. -func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if !yaml_emitter_process_anchor(emitter) { - return false - } - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - return true -} - -// Expect SCALAR. -func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if !yaml_emitter_select_scalar_style(emitter, event) { - return false - } - if !yaml_emitter_process_anchor(emitter) { - return false - } - if !yaml_emitter_process_tag(emitter) { - return false - } - if !yaml_emitter_increase_indent(emitter, true, false) { - return false - } - if !yaml_emitter_process_scalar(emitter) { - return false - } - emitter.indent = emitter.indents[len(emitter.indents)-1] - emitter.indents = emitter.indents[:len(emitter.indents)-1] - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - return true -} - -// Expect SEQUENCE-START. -func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if !yaml_emitter_process_anchor(emitter) { - return false - } - if !yaml_emitter_process_tag(emitter) { - return false - } - if emitter.flow_level > 0 || emitter.canonical || event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE || - yaml_emitter_check_empty_sequence(emitter) { - emitter.state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE - } else { - emitter.state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE - } - return true -} - -// Expect MAPPING-START. -func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if !yaml_emitter_process_anchor(emitter) { - return false - } - if !yaml_emitter_process_tag(emitter) { - return false - } - if emitter.flow_level > 0 || emitter.canonical || event.mapping_style() == yaml_FLOW_MAPPING_STYLE || - yaml_emitter_check_empty_mapping(emitter) { - emitter.state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE - } else { - emitter.state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE - } - return true -} - -// Check if the document content is an empty scalar. -func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool { - return false // [Go] Huh? -} - -// Check if the next events represent an empty sequence. -func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool { - if len(emitter.events)-emitter.events_head < 2 { - return false - } - return emitter.events[emitter.events_head].typ == yaml_SEQUENCE_START_EVENT && - emitter.events[emitter.events_head+1].typ == yaml_SEQUENCE_END_EVENT -} - -// Check if the next events represent an empty mapping. -func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool { - if len(emitter.events)-emitter.events_head < 2 { - return false - } - return emitter.events[emitter.events_head].typ == yaml_MAPPING_START_EVENT && - emitter.events[emitter.events_head+1].typ == yaml_MAPPING_END_EVENT -} - -// Check if the next node can be expressed as a simple key. -func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool { - length := 0 - switch emitter.events[emitter.events_head].typ { - case yaml_ALIAS_EVENT: - length += len(emitter.anchor_data.anchor) - case yaml_SCALAR_EVENT: - if emitter.scalar_data.multiline { - return false - } - length += len(emitter.anchor_data.anchor) + - len(emitter.tag_data.handle) + - len(emitter.tag_data.suffix) + - len(emitter.scalar_data.value) - case yaml_SEQUENCE_START_EVENT: - if !yaml_emitter_check_empty_sequence(emitter) { - return false - } - length += len(emitter.anchor_data.anchor) + - len(emitter.tag_data.handle) + - len(emitter.tag_data.suffix) - case yaml_MAPPING_START_EVENT: - if !yaml_emitter_check_empty_mapping(emitter) { - return false - } - length += len(emitter.anchor_data.anchor) + - len(emitter.tag_data.handle) + - len(emitter.tag_data.suffix) - default: - return false - } - return length <= 128 -} - -// Determine an acceptable scalar style. -func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool { - - no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 - if no_tag && !event.implicit && !event.quoted_implicit { - return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified") - } - - style := event.scalar_style() - if style == yaml_ANY_SCALAR_STYLE { - style = yaml_PLAIN_SCALAR_STYLE - } - if emitter.canonical { - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - if emitter.simple_key_context && emitter.scalar_data.multiline { - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - - if style == yaml_PLAIN_SCALAR_STYLE { - if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed || - emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed { - style = yaml_SINGLE_QUOTED_SCALAR_STYLE - } - if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) { - style = yaml_SINGLE_QUOTED_SCALAR_STYLE - } - if no_tag && !event.implicit { - style = yaml_SINGLE_QUOTED_SCALAR_STYLE - } - } - if style == yaml_SINGLE_QUOTED_SCALAR_STYLE { - if !emitter.scalar_data.single_quoted_allowed { - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - } - if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE { - if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context { - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - } - - if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE { - emitter.tag_data.handle = []byte{'!'} - } - emitter.scalar_data.style = style - return true -} - -// Write an anchor. -func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool { - if emitter.anchor_data.anchor == nil { - return true - } - c := []byte{'&'} - if emitter.anchor_data.alias { - c[0] = '*' - } - if !yaml_emitter_write_indicator(emitter, c, true, false, false) { - return false - } - return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor) -} - -// Write a tag. -func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool { - if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 { - return true - } - if len(emitter.tag_data.handle) > 0 { - if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) { - return false - } - if len(emitter.tag_data.suffix) > 0 { - if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { - return false - } - } - } else { - // [Go] Allocate these slices elsewhere. - if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) { - return false - } - if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { - return false - } - if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) { - return false - } - } - return true -} - -// Write a scalar. -func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool { - switch emitter.scalar_data.style { - case yaml_PLAIN_SCALAR_STYLE: - return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) - - case yaml_SINGLE_QUOTED_SCALAR_STYLE: - return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) - - case yaml_DOUBLE_QUOTED_SCALAR_STYLE: - return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) - - case yaml_LITERAL_SCALAR_STYLE: - return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value) - - case yaml_FOLDED_SCALAR_STYLE: - return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value) - } - panic("unknown scalar style") -} - -// Write a head comment. -func yaml_emitter_process_head_comment(emitter *yaml_emitter_t) bool { - if len(emitter.tail_comment) > 0 { - if !yaml_emitter_write_indent(emitter) { - return false - } - if !yaml_emitter_write_comment(emitter, emitter.tail_comment) { - return false - } - emitter.tail_comment = emitter.tail_comment[:0] - emitter.foot_indent = emitter.indent - if emitter.foot_indent < 0 { - emitter.foot_indent = 0 - } - } - - if len(emitter.head_comment) == 0 { - return true - } - if !yaml_emitter_write_indent(emitter) { - return false - } - if !yaml_emitter_write_comment(emitter, emitter.head_comment) { - return false - } - emitter.head_comment = emitter.head_comment[:0] - return true -} - -// Write an line comment. -func yaml_emitter_process_line_comment(emitter *yaml_emitter_t) bool { - if len(emitter.line_comment) == 0 { - return true - } - if !emitter.whitespace { - if !put(emitter, ' ') { - return false - } - } - if !yaml_emitter_write_comment(emitter, emitter.line_comment) { - return false - } - emitter.line_comment = emitter.line_comment[:0] - return true -} - -// Write a foot comment. -func yaml_emitter_process_foot_comment(emitter *yaml_emitter_t) bool { - if len(emitter.foot_comment) == 0 { - return true - } - if !yaml_emitter_write_indent(emitter) { - return false - } - if !yaml_emitter_write_comment(emitter, emitter.foot_comment) { - return false - } - emitter.foot_comment = emitter.foot_comment[:0] - emitter.foot_indent = emitter.indent - if emitter.foot_indent < 0 { - emitter.foot_indent = 0 - } - return true -} - -// Check if a %YAML directive is valid. -func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool { - if version_directive.major != 1 || version_directive.minor != 1 { - return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive") - } - return true -} - -// Check if a %TAG directive is valid. -func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool { - handle := tag_directive.handle - prefix := tag_directive.prefix - if len(handle) == 0 { - return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty") - } - if handle[0] != '!' { - return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'") - } - if handle[len(handle)-1] != '!' { - return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'") - } - for i := 1; i < len(handle)-1; i += width(handle[i]) { - if !is_alpha(handle, i) { - return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only") - } - } - if len(prefix) == 0 { - return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty") - } - return true -} - -// Check if an anchor is valid. -func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool { - if len(anchor) == 0 { - problem := "anchor value must not be empty" - if alias { - problem = "alias value must not be empty" - } - return yaml_emitter_set_emitter_error(emitter, problem) - } - for i := 0; i < len(anchor); i += width(anchor[i]) { - if !is_alpha(anchor, i) { - problem := "anchor value must contain alphanumerical characters only" - if alias { - problem = "alias value must contain alphanumerical characters only" - } - return yaml_emitter_set_emitter_error(emitter, problem) - } - } - emitter.anchor_data.anchor = anchor - emitter.anchor_data.alias = alias - return true -} - -// Check if a tag is valid. -func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool { - if len(tag) == 0 { - return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty") - } - for i := 0; i < len(emitter.tag_directives); i++ { - tag_directive := &emitter.tag_directives[i] - if bytes.HasPrefix(tag, tag_directive.prefix) { - emitter.tag_data.handle = tag_directive.handle - emitter.tag_data.suffix = tag[len(tag_directive.prefix):] - return true - } - } - emitter.tag_data.suffix = tag - return true -} - -// Check if a scalar is valid. -func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool { - var ( - block_indicators = false - flow_indicators = false - line_breaks = false - special_characters = false - tab_characters = false - - leading_space = false - leading_break = false - trailing_space = false - trailing_break = false - break_space = false - space_break = false - - preceded_by_whitespace = false - followed_by_whitespace = false - previous_space = false - previous_break = false - ) - - emitter.scalar_data.value = value - - if len(value) == 0 { - emitter.scalar_data.multiline = false - emitter.scalar_data.flow_plain_allowed = false - emitter.scalar_data.block_plain_allowed = true - emitter.scalar_data.single_quoted_allowed = true - emitter.scalar_data.block_allowed = false - return true - } - - if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) { - block_indicators = true - flow_indicators = true - } - - preceded_by_whitespace = true - for i, w := 0, 0; i < len(value); i += w { - w = width(value[i]) - followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w) - - if i == 0 { - switch value[i] { - case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`': - flow_indicators = true - block_indicators = true - case '?', ':': - flow_indicators = true - if followed_by_whitespace { - block_indicators = true - } - case '-': - if followed_by_whitespace { - flow_indicators = true - block_indicators = true - } - } - } else { - switch value[i] { - case ',', '?', '[', ']', '{', '}': - flow_indicators = true - case ':': - flow_indicators = true - if followed_by_whitespace { - block_indicators = true - } - case '#': - if preceded_by_whitespace { - flow_indicators = true - block_indicators = true - } - } - } - - if value[i] == '\t' { - tab_characters = true - } else if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode { - special_characters = true - } - if is_space(value, i) { - if i == 0 { - leading_space = true - } - if i+width(value[i]) == len(value) { - trailing_space = true - } - if previous_break { - break_space = true - } - previous_space = true - previous_break = false - } else if is_break(value, i) { - line_breaks = true - if i == 0 { - leading_break = true - } - if i+width(value[i]) == len(value) { - trailing_break = true - } - if previous_space { - space_break = true - } - previous_space = false - previous_break = true - } else { - previous_space = false - previous_break = false - } - - // [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition. - preceded_by_whitespace = is_blankz(value, i) - } - - emitter.scalar_data.multiline = line_breaks - emitter.scalar_data.flow_plain_allowed = true - emitter.scalar_data.block_plain_allowed = true - emitter.scalar_data.single_quoted_allowed = true - emitter.scalar_data.block_allowed = true - - if leading_space || leading_break || trailing_space || trailing_break { - emitter.scalar_data.flow_plain_allowed = false - emitter.scalar_data.block_plain_allowed = false - } - if trailing_space { - emitter.scalar_data.block_allowed = false - } - if break_space { - emitter.scalar_data.flow_plain_allowed = false - emitter.scalar_data.block_plain_allowed = false - emitter.scalar_data.single_quoted_allowed = false - } - if space_break || tab_characters || special_characters { - emitter.scalar_data.flow_plain_allowed = false - emitter.scalar_data.block_plain_allowed = false - emitter.scalar_data.single_quoted_allowed = false - } - if space_break || special_characters { - emitter.scalar_data.block_allowed = false - } - if line_breaks { - emitter.scalar_data.flow_plain_allowed = false - emitter.scalar_data.block_plain_allowed = false - } - if flow_indicators { - emitter.scalar_data.flow_plain_allowed = false - } - if block_indicators { - emitter.scalar_data.block_plain_allowed = false - } - return true -} - -// Check if the event data is valid. -func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool { - - emitter.anchor_data.anchor = nil - emitter.tag_data.handle = nil - emitter.tag_data.suffix = nil - emitter.scalar_data.value = nil - - if len(event.head_comment) > 0 { - emitter.head_comment = event.head_comment - } - if len(event.line_comment) > 0 { - emitter.line_comment = event.line_comment - } - if len(event.foot_comment) > 0 { - emitter.foot_comment = event.foot_comment - } - if len(event.tail_comment) > 0 { - emitter.tail_comment = event.tail_comment - } - - switch event.typ { - case yaml_ALIAS_EVENT: - if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) { - return false - } - - case yaml_SCALAR_EVENT: - if len(event.anchor) > 0 { - if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { - return false - } - } - if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) { - if !yaml_emitter_analyze_tag(emitter, event.tag) { - return false - } - } - if !yaml_emitter_analyze_scalar(emitter, event.value) { - return false - } - - case yaml_SEQUENCE_START_EVENT: - if len(event.anchor) > 0 { - if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { - return false - } - } - if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { - if !yaml_emitter_analyze_tag(emitter, event.tag) { - return false - } - } - - case yaml_MAPPING_START_EVENT: - if len(event.anchor) > 0 { - if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { - return false - } - } - if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { - if !yaml_emitter_analyze_tag(emitter, event.tag) { - return false - } - } - } - return true -} - -// Write the BOM character. -func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool { - if !flush(emitter) { - return false - } - pos := emitter.buffer_pos - emitter.buffer[pos+0] = '\xEF' - emitter.buffer[pos+1] = '\xBB' - emitter.buffer[pos+2] = '\xBF' - emitter.buffer_pos += 3 - return true -} - -func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool { - indent := emitter.indent - if indent < 0 { - indent = 0 - } - if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) { - if !put_break(emitter) { - return false - } - } - if emitter.foot_indent == indent { - if !put_break(emitter) { - return false - } - } - for emitter.column < indent { - if !put(emitter, ' ') { - return false - } - } - emitter.whitespace = true - //emitter.indention = true - emitter.space_above = false - emitter.foot_indent = -1 - return true -} - -func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []byte, need_whitespace, is_whitespace, is_indention bool) bool { - if need_whitespace && !emitter.whitespace { - if !put(emitter, ' ') { - return false - } - } - if !write_all(emitter, indicator) { - return false - } - emitter.whitespace = is_whitespace - emitter.indention = (emitter.indention && is_indention) - emitter.open_ended = false - return true -} - -func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bool { - if !write_all(emitter, value) { - return false - } - emitter.whitespace = false - emitter.indention = false - return true -} - -func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte) bool { - if !emitter.whitespace { - if !put(emitter, ' ') { - return false - } - } - if !write_all(emitter, value) { - return false - } - emitter.whitespace = false - emitter.indention = false - return true -} - -func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_whitespace bool) bool { - if need_whitespace && !emitter.whitespace { - if !put(emitter, ' ') { - return false - } - } - for i := 0; i < len(value); { - var must_write bool - switch value[i] { - case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']': - must_write = true - default: - must_write = is_alpha(value, i) - } - if must_write { - if !write(emitter, value, &i) { - return false - } - } else { - w := width(value[i]) - for k := 0; k < w; k++ { - octet := value[i] - i++ - if !put(emitter, '%') { - return false - } - - c := octet >> 4 - if c < 10 { - c += '0' - } else { - c += 'A' - 10 - } - if !put(emitter, c) { - return false - } - - c = octet & 0x0f - if c < 10 { - c += '0' - } else { - c += 'A' - 10 - } - if !put(emitter, c) { - return false - } - } - } - } - emitter.whitespace = false - emitter.indention = false - return true -} - -func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { - if len(value) > 0 && !emitter.whitespace { - if !put(emitter, ' ') { - return false - } - } - - spaces := false - breaks := false - for i := 0; i < len(value); { - if is_space(value, i) { - if allow_breaks && !spaces && emitter.column > emitter.best_width && !is_space(value, i+1) { - if !yaml_emitter_write_indent(emitter) { - return false - } - i += width(value[i]) - } else { - if !write(emitter, value, &i) { - return false - } - } - spaces = true - } else if is_break(value, i) { - if !breaks && value[i] == '\n' { - if !put_break(emitter) { - return false - } - } - if !write_break(emitter, value, &i) { - return false - } - //emitter.indention = true - breaks = true - } else { - if breaks { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !write(emitter, value, &i) { - return false - } - emitter.indention = false - spaces = false - breaks = false - } - } - - if len(value) > 0 { - emitter.whitespace = false - } - emitter.indention = false - if emitter.root_context { - emitter.open_ended = true - } - - return true -} - -func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { - - if !yaml_emitter_write_indicator(emitter, []byte{'\''}, true, false, false) { - return false - } - - spaces := false - breaks := false - for i := 0; i < len(value); { - if is_space(value, i) { - if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !is_space(value, i+1) { - if !yaml_emitter_write_indent(emitter) { - return false - } - i += width(value[i]) - } else { - if !write(emitter, value, &i) { - return false - } - } - spaces = true - } else if is_break(value, i) { - if !breaks && value[i] == '\n' { - if !put_break(emitter) { - return false - } - } - if !write_break(emitter, value, &i) { - return false - } - //emitter.indention = true - breaks = true - } else { - if breaks { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if value[i] == '\'' { - if !put(emitter, '\'') { - return false - } - } - if !write(emitter, value, &i) { - return false - } - emitter.indention = false - spaces = false - breaks = false - } - } - if !yaml_emitter_write_indicator(emitter, []byte{'\''}, false, false, false) { - return false - } - emitter.whitespace = false - emitter.indention = false - return true -} - -func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { - spaces := false - if !yaml_emitter_write_indicator(emitter, []byte{'"'}, true, false, false) { - return false - } - - for i := 0; i < len(value); { - if !is_printable(value, i) || (!emitter.unicode && !is_ascii(value, i)) || - is_bom(value, i) || is_break(value, i) || - value[i] == '"' || value[i] == '\\' { - - octet := value[i] - - var w int - var v rune - switch { - case octet&0x80 == 0x00: - w, v = 1, rune(octet&0x7F) - case octet&0xE0 == 0xC0: - w, v = 2, rune(octet&0x1F) - case octet&0xF0 == 0xE0: - w, v = 3, rune(octet&0x0F) - case octet&0xF8 == 0xF0: - w, v = 4, rune(octet&0x07) - } - for k := 1; k < w; k++ { - octet = value[i+k] - v = (v << 6) + (rune(octet) & 0x3F) - } - i += w - - if !put(emitter, '\\') { - return false - } - - var ok bool - switch v { - case 0x00: - ok = put(emitter, '0') - case 0x07: - ok = put(emitter, 'a') - case 0x08: - ok = put(emitter, 'b') - case 0x09: - ok = put(emitter, 't') - case 0x0A: - ok = put(emitter, 'n') - case 0x0b: - ok = put(emitter, 'v') - case 0x0c: - ok = put(emitter, 'f') - case 0x0d: - ok = put(emitter, 'r') - case 0x1b: - ok = put(emitter, 'e') - case 0x22: - ok = put(emitter, '"') - case 0x5c: - ok = put(emitter, '\\') - case 0x85: - ok = put(emitter, 'N') - case 0xA0: - ok = put(emitter, '_') - case 0x2028: - ok = put(emitter, 'L') - case 0x2029: - ok = put(emitter, 'P') - default: - if v <= 0xFF { - ok = put(emitter, 'x') - w = 2 - } else if v <= 0xFFFF { - ok = put(emitter, 'u') - w = 4 - } else { - ok = put(emitter, 'U') - w = 8 - } - for k := (w - 1) * 4; ok && k >= 0; k -= 4 { - digit := byte((v >> uint(k)) & 0x0F) - if digit < 10 { - ok = put(emitter, digit+'0') - } else { - ok = put(emitter, digit+'A'-10) - } - } - } - if !ok { - return false - } - spaces = false - } else if is_space(value, i) { - if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 { - if !yaml_emitter_write_indent(emitter) { - return false - } - if is_space(value, i+1) { - if !put(emitter, '\\') { - return false - } - } - i += width(value[i]) - } else if !write(emitter, value, &i) { - return false - } - spaces = true - } else { - if !write(emitter, value, &i) { - return false - } - spaces = false - } - } - if !yaml_emitter_write_indicator(emitter, []byte{'"'}, false, false, false) { - return false - } - emitter.whitespace = false - emitter.indention = false - return true -} - -func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool { - if is_space(value, 0) || is_break(value, 0) { - indent_hint := []byte{'0' + byte(emitter.best_indent)} - if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) { - return false - } - } - - emitter.open_ended = false - - var chomp_hint [1]byte - if len(value) == 0 { - chomp_hint[0] = '-' - } else { - i := len(value) - 1 - for value[i]&0xC0 == 0x80 { - i-- - } - if !is_break(value, i) { - chomp_hint[0] = '-' - } else if i == 0 { - chomp_hint[0] = '+' - emitter.open_ended = true - } else { - i-- - for value[i]&0xC0 == 0x80 { - i-- - } - if is_break(value, i) { - chomp_hint[0] = '+' - emitter.open_ended = true - } - } - } - if chomp_hint[0] != 0 { - if !yaml_emitter_write_indicator(emitter, chomp_hint[:], false, false, false) { - return false - } - } - return true -} - -func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bool { - if !yaml_emitter_write_indicator(emitter, []byte{'|'}, true, false, false) { - return false - } - if !yaml_emitter_write_block_scalar_hints(emitter, value) { - return false - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - //emitter.indention = true - emitter.whitespace = true - breaks := true - for i := 0; i < len(value); { - if is_break(value, i) { - if !write_break(emitter, value, &i) { - return false - } - //emitter.indention = true - breaks = true - } else { - if breaks { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !write(emitter, value, &i) { - return false - } - emitter.indention = false - breaks = false - } - } - - return true -} - -func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) bool { - if !yaml_emitter_write_indicator(emitter, []byte{'>'}, true, false, false) { - return false - } - if !yaml_emitter_write_block_scalar_hints(emitter, value) { - return false - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - - //emitter.indention = true - emitter.whitespace = true - - breaks := true - leading_spaces := true - for i := 0; i < len(value); { - if is_break(value, i) { - if !breaks && !leading_spaces && value[i] == '\n' { - k := 0 - for is_break(value, k) { - k += width(value[k]) - } - if !is_blankz(value, k) { - if !put_break(emitter) { - return false - } - } - } - if !write_break(emitter, value, &i) { - return false - } - //emitter.indention = true - breaks = true - } else { - if breaks { - if !yaml_emitter_write_indent(emitter) { - return false - } - leading_spaces = is_blank(value, i) - } - if !breaks && is_space(value, i) && !is_space(value, i+1) && emitter.column > emitter.best_width { - if !yaml_emitter_write_indent(emitter) { - return false - } - i += width(value[i]) - } else { - if !write(emitter, value, &i) { - return false - } - } - emitter.indention = false - breaks = false - } - } - return true -} - -func yaml_emitter_write_comment(emitter *yaml_emitter_t, comment []byte) bool { - breaks := false - pound := false - for i := 0; i < len(comment); { - if is_break(comment, i) { - if !write_break(emitter, comment, &i) { - return false - } - //emitter.indention = true - breaks = true - pound = false - } else { - if breaks && !yaml_emitter_write_indent(emitter) { - return false - } - if !pound { - if comment[i] != '#' && (!put(emitter, '#') || !put(emitter, ' ')) { - return false - } - pound = true - } - if !write(emitter, comment, &i) { - return false - } - emitter.indention = false - breaks = false - } - } - if !breaks && !put_break(emitter) { - return false - } - - emitter.whitespace = true - //emitter.indention = true - return true -} diff --git a/go/sdk/vendor/gopkg.in/yaml.v3/encode.go b/go/sdk/vendor/gopkg.in/yaml.v3/encode.go deleted file mode 100644 index de9e72a..0000000 --- a/go/sdk/vendor/gopkg.in/yaml.v3/encode.go +++ /dev/null @@ -1,577 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package yaml - -import ( - "encoding" - "fmt" - "io" - "reflect" - "regexp" - "sort" - "strconv" - "strings" - "time" - "unicode/utf8" -) - -type encoder struct { - emitter yaml_emitter_t - event yaml_event_t - out []byte - flow bool - indent int - doneInit bool -} - -func newEncoder() *encoder { - e := &encoder{} - yaml_emitter_initialize(&e.emitter) - yaml_emitter_set_output_string(&e.emitter, &e.out) - yaml_emitter_set_unicode(&e.emitter, true) - return e -} - -func newEncoderWithWriter(w io.Writer) *encoder { - e := &encoder{} - yaml_emitter_initialize(&e.emitter) - yaml_emitter_set_output_writer(&e.emitter, w) - yaml_emitter_set_unicode(&e.emitter, true) - return e -} - -func (e *encoder) init() { - if e.doneInit { - return - } - if e.indent == 0 { - e.indent = 4 - } - e.emitter.best_indent = e.indent - yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING) - e.emit() - e.doneInit = true -} - -func (e *encoder) finish() { - e.emitter.open_ended = false - yaml_stream_end_event_initialize(&e.event) - e.emit() -} - -func (e *encoder) destroy() { - yaml_emitter_delete(&e.emitter) -} - -func (e *encoder) emit() { - // This will internally delete the e.event value. - e.must(yaml_emitter_emit(&e.emitter, &e.event)) -} - -func (e *encoder) must(ok bool) { - if !ok { - msg := e.emitter.problem - if msg == "" { - msg = "unknown problem generating YAML content" - } - failf("%s", msg) - } -} - -func (e *encoder) marshalDoc(tag string, in reflect.Value) { - e.init() - var node *Node - if in.IsValid() { - node, _ = in.Interface().(*Node) - } - if node != nil && node.Kind == DocumentNode { - e.nodev(in) - } else { - yaml_document_start_event_initialize(&e.event, nil, nil, true) - e.emit() - e.marshal(tag, in) - yaml_document_end_event_initialize(&e.event, true) - e.emit() - } -} - -func (e *encoder) marshal(tag string, in reflect.Value) { - tag = shortTag(tag) - if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() { - e.nilv() - return - } - iface := in.Interface() - switch value := iface.(type) { - case *Node: - e.nodev(in) - return - case Node: - if !in.CanAddr() { - var n = reflect.New(in.Type()).Elem() - n.Set(in) - in = n - } - e.nodev(in.Addr()) - return - case time.Time: - e.timev(tag, in) - return - case *time.Time: - e.timev(tag, in.Elem()) - return - case time.Duration: - e.stringv(tag, reflect.ValueOf(value.String())) - return - case Marshaler: - v, err := value.MarshalYAML() - if err != nil { - fail(err) - } - if v == nil { - e.nilv() - return - } - e.marshal(tag, reflect.ValueOf(v)) - return - case encoding.TextMarshaler: - text, err := value.MarshalText() - if err != nil { - fail(err) - } - in = reflect.ValueOf(string(text)) - case nil: - e.nilv() - return - } - switch in.Kind() { - case reflect.Interface: - e.marshal(tag, in.Elem()) - case reflect.Map: - e.mapv(tag, in) - case reflect.Ptr: - e.marshal(tag, in.Elem()) - case reflect.Struct: - e.structv(tag, in) - case reflect.Slice, reflect.Array: - e.slicev(tag, in) - case reflect.String: - e.stringv(tag, in) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - e.intv(tag, in) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - e.uintv(tag, in) - case reflect.Float32, reflect.Float64: - e.floatv(tag, in) - case reflect.Bool: - e.boolv(tag, in) - default: - panic("cannot marshal type: " + in.Type().String()) - } -} - -func (e *encoder) mapv(tag string, in reflect.Value) { - e.mappingv(tag, func() { - keys := keyList(in.MapKeys()) - sort.Sort(keys) - for _, k := range keys { - e.marshal("", k) - e.marshal("", in.MapIndex(k)) - } - }) -} - -func (e *encoder) fieldByIndex(v reflect.Value, index []int) (field reflect.Value) { - for _, num := range index { - for { - if v.Kind() == reflect.Ptr { - if v.IsNil() { - return reflect.Value{} - } - v = v.Elem() - continue - } - break - } - v = v.Field(num) - } - return v -} - -func (e *encoder) structv(tag string, in reflect.Value) { - sinfo, err := getStructInfo(in.Type()) - if err != nil { - panic(err) - } - e.mappingv(tag, func() { - for _, info := range sinfo.FieldsList { - var value reflect.Value - if info.Inline == nil { - value = in.Field(info.Num) - } else { - value = e.fieldByIndex(in, info.Inline) - if !value.IsValid() { - continue - } - } - if info.OmitEmpty && isZero(value) { - continue - } - e.marshal("", reflect.ValueOf(info.Key)) - e.flow = info.Flow - e.marshal("", value) - } - if sinfo.InlineMap >= 0 { - m := in.Field(sinfo.InlineMap) - if m.Len() > 0 { - e.flow = false - keys := keyList(m.MapKeys()) - sort.Sort(keys) - for _, k := range keys { - if _, found := sinfo.FieldsMap[k.String()]; found { - panic(fmt.Sprintf("cannot have key %q in inlined map: conflicts with struct field", k.String())) - } - e.marshal("", k) - e.flow = false - e.marshal("", m.MapIndex(k)) - } - } - } - }) -} - -func (e *encoder) mappingv(tag string, f func()) { - implicit := tag == "" - style := yaml_BLOCK_MAPPING_STYLE - if e.flow { - e.flow = false - style = yaml_FLOW_MAPPING_STYLE - } - yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style) - e.emit() - f() - yaml_mapping_end_event_initialize(&e.event) - e.emit() -} - -func (e *encoder) slicev(tag string, in reflect.Value) { - implicit := tag == "" - style := yaml_BLOCK_SEQUENCE_STYLE - if e.flow { - e.flow = false - style = yaml_FLOW_SEQUENCE_STYLE - } - e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) - e.emit() - n := in.Len() - for i := 0; i < n; i++ { - e.marshal("", in.Index(i)) - } - e.must(yaml_sequence_end_event_initialize(&e.event)) - e.emit() -} - -// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1. -// -// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported -// in YAML 1.2 and by this package, but these should be marshalled quoted for -// the time being for compatibility with other parsers. -func isBase60Float(s string) (result bool) { - // Fast path. - if s == "" { - return false - } - c := s[0] - if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 { - return false - } - // Do the full match. - return base60float.MatchString(s) -} - -// From http://yaml.org/type/float.html, except the regular expression there -// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix. -var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`) - -// isOldBool returns whether s is bool notation as defined in YAML 1.1. -// -// We continue to force strings that YAML 1.1 would interpret as booleans to be -// rendered as quotes strings so that the marshalled output valid for YAML 1.1 -// parsing. -func isOldBool(s string) (result bool) { - switch s { - case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON", - "n", "N", "no", "No", "NO", "off", "Off", "OFF": - return true - default: - return false - } -} - -func (e *encoder) stringv(tag string, in reflect.Value) { - var style yaml_scalar_style_t - s := in.String() - canUsePlain := true - switch { - case !utf8.ValidString(s): - if tag == binaryTag { - failf("explicitly tagged !!binary data must be base64-encoded") - } - if tag != "" { - failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag)) - } - // It can't be encoded directly as YAML so use a binary tag - // and encode it as base64. - tag = binaryTag - s = encodeBase64(s) - case tag == "": - // Check to see if it would resolve to a specific - // tag when encoded unquoted. If it doesn't, - // there's no need to quote it. - rtag, _ := resolve("", s) - canUsePlain = rtag == strTag && !(isBase60Float(s) || isOldBool(s)) - } - // Note: it's possible for user code to emit invalid YAML - // if they explicitly specify a tag and a string containing - // text that's incompatible with that tag. - switch { - case strings.Contains(s, "\n"): - if e.flow { - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } else { - style = yaml_LITERAL_SCALAR_STYLE - } - case canUsePlain: - style = yaml_PLAIN_SCALAR_STYLE - default: - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - e.emitScalar(s, "", tag, style, nil, nil, nil, nil) -} - -func (e *encoder) boolv(tag string, in reflect.Value) { - var s string - if in.Bool() { - s = "true" - } else { - s = "false" - } - e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) -} - -func (e *encoder) intv(tag string, in reflect.Value) { - s := strconv.FormatInt(in.Int(), 10) - e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) -} - -func (e *encoder) uintv(tag string, in reflect.Value) { - s := strconv.FormatUint(in.Uint(), 10) - e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) -} - -func (e *encoder) timev(tag string, in reflect.Value) { - t := in.Interface().(time.Time) - s := t.Format(time.RFC3339Nano) - e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) -} - -func (e *encoder) floatv(tag string, in reflect.Value) { - // Issue #352: When formatting, use the precision of the underlying value - precision := 64 - if in.Kind() == reflect.Float32 { - precision = 32 - } - - s := strconv.FormatFloat(in.Float(), 'g', -1, precision) - switch s { - case "+Inf": - s = ".inf" - case "-Inf": - s = "-.inf" - case "NaN": - s = ".nan" - } - e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) -} - -func (e *encoder) nilv() { - e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) -} - -func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t, head, line, foot, tail []byte) { - // TODO Kill this function. Replace all initialize calls by their underlining Go literals. - implicit := tag == "" - if !implicit { - tag = longTag(tag) - } - e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style)) - e.event.head_comment = head - e.event.line_comment = line - e.event.foot_comment = foot - e.event.tail_comment = tail - e.emit() -} - -func (e *encoder) nodev(in reflect.Value) { - e.node(in.Interface().(*Node), "") -} - -func (e *encoder) node(node *Node, tail string) { - // Zero nodes behave as nil. - if node.Kind == 0 && node.IsZero() { - e.nilv() - return - } - - // If the tag was not explicitly requested, and dropping it won't change the - // implicit tag of the value, don't include it in the presentation. - var tag = node.Tag - var stag = shortTag(tag) - var forceQuoting bool - if tag != "" && node.Style&TaggedStyle == 0 { - if node.Kind == ScalarNode { - if stag == strTag && node.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0 { - tag = "" - } else { - rtag, _ := resolve("", node.Value) - if rtag == stag { - tag = "" - } else if stag == strTag { - tag = "" - forceQuoting = true - } - } - } else { - var rtag string - switch node.Kind { - case MappingNode: - rtag = mapTag - case SequenceNode: - rtag = seqTag - } - if rtag == stag { - tag = "" - } - } - } - - switch node.Kind { - case DocumentNode: - yaml_document_start_event_initialize(&e.event, nil, nil, true) - e.event.head_comment = []byte(node.HeadComment) - e.emit() - for _, node := range node.Content { - e.node(node, "") - } - yaml_document_end_event_initialize(&e.event, true) - e.event.foot_comment = []byte(node.FootComment) - e.emit() - - case SequenceNode: - style := yaml_BLOCK_SEQUENCE_STYLE - if node.Style&FlowStyle != 0 { - style = yaml_FLOW_SEQUENCE_STYLE - } - e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style)) - e.event.head_comment = []byte(node.HeadComment) - e.emit() - for _, node := range node.Content { - e.node(node, "") - } - e.must(yaml_sequence_end_event_initialize(&e.event)) - e.event.line_comment = []byte(node.LineComment) - e.event.foot_comment = []byte(node.FootComment) - e.emit() - - case MappingNode: - style := yaml_BLOCK_MAPPING_STYLE - if node.Style&FlowStyle != 0 { - style = yaml_FLOW_MAPPING_STYLE - } - yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style) - e.event.tail_comment = []byte(tail) - e.event.head_comment = []byte(node.HeadComment) - e.emit() - - // The tail logic below moves the foot comment of prior keys to the following key, - // since the value for each key may be a nested structure and the foot needs to be - // processed only the entirety of the value is streamed. The last tail is processed - // with the mapping end event. - var tail string - for i := 0; i+1 < len(node.Content); i += 2 { - k := node.Content[i] - foot := k.FootComment - if foot != "" { - kopy := *k - kopy.FootComment = "" - k = &kopy - } - e.node(k, tail) - tail = foot - - v := node.Content[i+1] - e.node(v, "") - } - - yaml_mapping_end_event_initialize(&e.event) - e.event.tail_comment = []byte(tail) - e.event.line_comment = []byte(node.LineComment) - e.event.foot_comment = []byte(node.FootComment) - e.emit() - - case AliasNode: - yaml_alias_event_initialize(&e.event, []byte(node.Value)) - e.event.head_comment = []byte(node.HeadComment) - e.event.line_comment = []byte(node.LineComment) - e.event.foot_comment = []byte(node.FootComment) - e.emit() - - case ScalarNode: - value := node.Value - if !utf8.ValidString(value) { - if stag == binaryTag { - failf("explicitly tagged !!binary data must be base64-encoded") - } - if stag != "" { - failf("cannot marshal invalid UTF-8 data as %s", stag) - } - // It can't be encoded directly as YAML so use a binary tag - // and encode it as base64. - tag = binaryTag - value = encodeBase64(value) - } - - style := yaml_PLAIN_SCALAR_STYLE - switch { - case node.Style&DoubleQuotedStyle != 0: - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - case node.Style&SingleQuotedStyle != 0: - style = yaml_SINGLE_QUOTED_SCALAR_STYLE - case node.Style&LiteralStyle != 0: - style = yaml_LITERAL_SCALAR_STYLE - case node.Style&FoldedStyle != 0: - style = yaml_FOLDED_SCALAR_STYLE - case strings.Contains(value, "\n"): - style = yaml_LITERAL_SCALAR_STYLE - case forceQuoting: - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - - e.emitScalar(value, node.Anchor, tag, style, []byte(node.HeadComment), []byte(node.LineComment), []byte(node.FootComment), []byte(tail)) - default: - failf("cannot encode node with unknown kind %d", node.Kind) - } -} diff --git a/go/sdk/vendor/gopkg.in/yaml.v3/parserc.go b/go/sdk/vendor/gopkg.in/yaml.v3/parserc.go deleted file mode 100644 index 25fe823..0000000 --- a/go/sdk/vendor/gopkg.in/yaml.v3/parserc.go +++ /dev/null @@ -1,1274 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -// of the Software, and to permit persons to whom the Software is furnished to do -// so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -package yaml - -import ( - "bytes" -) - -// The parser implements the following grammar: -// -// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END -// implicit_document ::= block_node DOCUMENT-END* -// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* -// block_node_or_indentless_sequence ::= -// ALIAS -// | properties (block_content | indentless_block_sequence)? -// | block_content -// | indentless_block_sequence -// block_node ::= ALIAS -// | properties block_content? -// | block_content -// flow_node ::= ALIAS -// | properties flow_content? -// | flow_content -// properties ::= TAG ANCHOR? | ANCHOR TAG? -// block_content ::= block_collection | flow_collection | SCALAR -// flow_content ::= flow_collection | SCALAR -// block_collection ::= block_sequence | block_mapping -// flow_collection ::= flow_sequence | flow_mapping -// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END -// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ -// block_mapping ::= BLOCK-MAPPING_START -// ((KEY block_node_or_indentless_sequence?)? -// (VALUE block_node_or_indentless_sequence?)?)* -// BLOCK-END -// flow_sequence ::= FLOW-SEQUENCE-START -// (flow_sequence_entry FLOW-ENTRY)* -// flow_sequence_entry? -// FLOW-SEQUENCE-END -// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// flow_mapping ::= FLOW-MAPPING-START -// (flow_mapping_entry FLOW-ENTRY)* -// flow_mapping_entry? -// FLOW-MAPPING-END -// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? - -// Peek the next token in the token queue. -func peek_token(parser *yaml_parser_t) *yaml_token_t { - if parser.token_available || yaml_parser_fetch_more_tokens(parser) { - token := &parser.tokens[parser.tokens_head] - yaml_parser_unfold_comments(parser, token) - return token - } - return nil -} - -// yaml_parser_unfold_comments walks through the comments queue and joins all -// comments behind the position of the provided token into the respective -// top-level comment slices in the parser. -func yaml_parser_unfold_comments(parser *yaml_parser_t, token *yaml_token_t) { - for parser.comments_head < len(parser.comments) && token.start_mark.index >= parser.comments[parser.comments_head].token_mark.index { - comment := &parser.comments[parser.comments_head] - if len(comment.head) > 0 { - if token.typ == yaml_BLOCK_END_TOKEN { - // No heads on ends, so keep comment.head for a follow up token. - break - } - if len(parser.head_comment) > 0 { - parser.head_comment = append(parser.head_comment, '\n') - } - parser.head_comment = append(parser.head_comment, comment.head...) - } - if len(comment.foot) > 0 { - if len(parser.foot_comment) > 0 { - parser.foot_comment = append(parser.foot_comment, '\n') - } - parser.foot_comment = append(parser.foot_comment, comment.foot...) - } - if len(comment.line) > 0 { - if len(parser.line_comment) > 0 { - parser.line_comment = append(parser.line_comment, '\n') - } - parser.line_comment = append(parser.line_comment, comment.line...) - } - *comment = yaml_comment_t{} - parser.comments_head++ - } -} - -// Remove the next token from the queue (must be called after peek_token). -func skip_token(parser *yaml_parser_t) { - parser.token_available = false - parser.tokens_parsed++ - parser.stream_end_produced = parser.tokens[parser.tokens_head].typ == yaml_STREAM_END_TOKEN - parser.tokens_head++ -} - -// Get the next event. -func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool { - // Erase the event object. - *event = yaml_event_t{} - - // No events after the end of the stream or error. - if parser.stream_end_produced || parser.error != yaml_NO_ERROR || parser.state == yaml_PARSE_END_STATE { - return true - } - - // Generate the next event. - return yaml_parser_state_machine(parser, event) -} - -// Set parser error. -func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string, problem_mark yaml_mark_t) bool { - parser.error = yaml_PARSER_ERROR - parser.problem = problem - parser.problem_mark = problem_mark - return false -} - -func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string, problem_mark yaml_mark_t) bool { - parser.error = yaml_PARSER_ERROR - parser.context = context - parser.context_mark = context_mark - parser.problem = problem - parser.problem_mark = problem_mark - return false -} - -// State dispatcher. -func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool { - //trace("yaml_parser_state_machine", "state:", parser.state.String()) - - switch parser.state { - case yaml_PARSE_STREAM_START_STATE: - return yaml_parser_parse_stream_start(parser, event) - - case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: - return yaml_parser_parse_document_start(parser, event, true) - - case yaml_PARSE_DOCUMENT_START_STATE: - return yaml_parser_parse_document_start(parser, event, false) - - case yaml_PARSE_DOCUMENT_CONTENT_STATE: - return yaml_parser_parse_document_content(parser, event) - - case yaml_PARSE_DOCUMENT_END_STATE: - return yaml_parser_parse_document_end(parser, event) - - case yaml_PARSE_BLOCK_NODE_STATE: - return yaml_parser_parse_node(parser, event, true, false) - - case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: - return yaml_parser_parse_node(parser, event, true, true) - - case yaml_PARSE_FLOW_NODE_STATE: - return yaml_parser_parse_node(parser, event, false, false) - - case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: - return yaml_parser_parse_block_sequence_entry(parser, event, true) - - case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: - return yaml_parser_parse_block_sequence_entry(parser, event, false) - - case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: - return yaml_parser_parse_indentless_sequence_entry(parser, event) - - case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: - return yaml_parser_parse_block_mapping_key(parser, event, true) - - case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: - return yaml_parser_parse_block_mapping_key(parser, event, false) - - case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: - return yaml_parser_parse_block_mapping_value(parser, event) - - case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: - return yaml_parser_parse_flow_sequence_entry(parser, event, true) - - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: - return yaml_parser_parse_flow_sequence_entry(parser, event, false) - - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: - return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event) - - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: - return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event) - - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: - return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event) - - case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: - return yaml_parser_parse_flow_mapping_key(parser, event, true) - - case yaml_PARSE_FLOW_MAPPING_KEY_STATE: - return yaml_parser_parse_flow_mapping_key(parser, event, false) - - case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: - return yaml_parser_parse_flow_mapping_value(parser, event, false) - - case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: - return yaml_parser_parse_flow_mapping_value(parser, event, true) - - default: - panic("invalid parser state") - } -} - -// Parse the production: -// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END -// -// ************ -func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_STREAM_START_TOKEN { - return yaml_parser_set_parser_error(parser, "did not find expected ", token.start_mark) - } - parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE - *event = yaml_event_t{ - typ: yaml_STREAM_START_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - encoding: token.encoding, - } - skip_token(parser) - return true -} - -// Parse the productions: -// implicit_document ::= block_node DOCUMENT-END* -// -// * -// -// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* -// -// ************************* -func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool { - - token := peek_token(parser) - if token == nil { - return false - } - - // Parse extra document end indicators. - if !implicit { - for token.typ == yaml_DOCUMENT_END_TOKEN { - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } - } - - if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN && - token.typ != yaml_TAG_DIRECTIVE_TOKEN && - token.typ != yaml_DOCUMENT_START_TOKEN && - token.typ != yaml_STREAM_END_TOKEN { - // Parse an implicit document. - if !yaml_parser_process_directives(parser, nil, nil) { - return false - } - parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) - parser.state = yaml_PARSE_BLOCK_NODE_STATE - - var head_comment []byte - if len(parser.head_comment) > 0 { - // [Go] Scan the header comment backwards, and if an empty line is found, break - // the header so the part before the last empty line goes into the - // document header, while the bottom of it goes into a follow up event. - for i := len(parser.head_comment) - 1; i > 0; i-- { - if parser.head_comment[i] == '\n' { - if i == len(parser.head_comment)-1 { - head_comment = parser.head_comment[:i] - parser.head_comment = parser.head_comment[i+1:] - break - } else if parser.head_comment[i-1] == '\n' { - head_comment = parser.head_comment[:i-1] - parser.head_comment = parser.head_comment[i+1:] - break - } - } - } - } - - *event = yaml_event_t{ - typ: yaml_DOCUMENT_START_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - - head_comment: head_comment, - } - - } else if token.typ != yaml_STREAM_END_TOKEN { - // Parse an explicit document. - var version_directive *yaml_version_directive_t - var tag_directives []yaml_tag_directive_t - start_mark := token.start_mark - if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) { - return false - } - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_DOCUMENT_START_TOKEN { - yaml_parser_set_parser_error(parser, - "did not find expected ", token.start_mark) - return false - } - parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) - parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE - end_mark := token.end_mark - - *event = yaml_event_t{ - typ: yaml_DOCUMENT_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - version_directive: version_directive, - tag_directives: tag_directives, - implicit: false, - } - skip_token(parser) - - } else { - // Parse the stream end. - parser.state = yaml_PARSE_END_STATE - *event = yaml_event_t{ - typ: yaml_STREAM_END_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - } - skip_token(parser) - } - - return true -} - -// Parse the productions: -// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* -// -// *********** -func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - - if token.typ == yaml_VERSION_DIRECTIVE_TOKEN || - token.typ == yaml_TAG_DIRECTIVE_TOKEN || - token.typ == yaml_DOCUMENT_START_TOKEN || - token.typ == yaml_DOCUMENT_END_TOKEN || - token.typ == yaml_STREAM_END_TOKEN { - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - return yaml_parser_process_empty_scalar(parser, event, - token.start_mark) - } - return yaml_parser_parse_node(parser, event, true, false) -} - -// Parse the productions: -// implicit_document ::= block_node DOCUMENT-END* -// -// ************* -// -// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* -func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - - start_mark := token.start_mark - end_mark := token.start_mark - - implicit := true - if token.typ == yaml_DOCUMENT_END_TOKEN { - end_mark = token.end_mark - skip_token(parser) - implicit = false - } - - parser.tag_directives = parser.tag_directives[:0] - - parser.state = yaml_PARSE_DOCUMENT_START_STATE - *event = yaml_event_t{ - typ: yaml_DOCUMENT_END_EVENT, - start_mark: start_mark, - end_mark: end_mark, - implicit: implicit, - } - yaml_parser_set_event_comments(parser, event) - if len(event.head_comment) > 0 && len(event.foot_comment) == 0 { - event.foot_comment = event.head_comment - event.head_comment = nil - } - return true -} - -func yaml_parser_set_event_comments(parser *yaml_parser_t, event *yaml_event_t) { - event.head_comment = parser.head_comment - event.line_comment = parser.line_comment - event.foot_comment = parser.foot_comment - parser.head_comment = nil - parser.line_comment = nil - parser.foot_comment = nil - parser.tail_comment = nil - parser.stem_comment = nil -} - -// Parse the productions: -// block_node_or_indentless_sequence ::= -// -// ALIAS -// ***** -// | properties (block_content | indentless_block_sequence)? -// ********** * -// | block_content | indentless_block_sequence -// * -// -// block_node ::= ALIAS -// -// ***** -// | properties block_content? -// ********** * -// | block_content -// * -// -// flow_node ::= ALIAS -// -// ***** -// | properties flow_content? -// ********** * -// | flow_content -// * -// -// properties ::= TAG ANCHOR? | ANCHOR TAG? -// -// ************************* -// -// block_content ::= block_collection | flow_collection | SCALAR -// -// ****** -// -// flow_content ::= flow_collection | SCALAR -// -// ****** -func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool { - //defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)() - - token := peek_token(parser) - if token == nil { - return false - } - - if token.typ == yaml_ALIAS_TOKEN { - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - *event = yaml_event_t{ - typ: yaml_ALIAS_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - anchor: token.value, - } - yaml_parser_set_event_comments(parser, event) - skip_token(parser) - return true - } - - start_mark := token.start_mark - end_mark := token.start_mark - - var tag_token bool - var tag_handle, tag_suffix, anchor []byte - var tag_mark yaml_mark_t - if token.typ == yaml_ANCHOR_TOKEN { - anchor = token.value - start_mark = token.start_mark - end_mark = token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ == yaml_TAG_TOKEN { - tag_token = true - tag_handle = token.value - tag_suffix = token.suffix - tag_mark = token.start_mark - end_mark = token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } - } else if token.typ == yaml_TAG_TOKEN { - tag_token = true - tag_handle = token.value - tag_suffix = token.suffix - start_mark = token.start_mark - tag_mark = token.start_mark - end_mark = token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ == yaml_ANCHOR_TOKEN { - anchor = token.value - end_mark = token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } - } - - var tag []byte - if tag_token { - if len(tag_handle) == 0 { - tag = tag_suffix - tag_suffix = nil - } else { - for i := range parser.tag_directives { - if bytes.Equal(parser.tag_directives[i].handle, tag_handle) { - tag = append([]byte(nil), parser.tag_directives[i].prefix...) - tag = append(tag, tag_suffix...) - break - } - } - if len(tag) == 0 { - yaml_parser_set_parser_error_context(parser, - "while parsing a node", start_mark, - "found undefined tag handle", tag_mark) - return false - } - } - } - - implicit := len(tag) == 0 - if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN { - end_mark = token.end_mark - parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE - *event = yaml_event_t{ - typ: yaml_SEQUENCE_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), - } - return true - } - if token.typ == yaml_SCALAR_TOKEN { - var plain_implicit, quoted_implicit bool - end_mark = token.end_mark - if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') { - plain_implicit = true - } else if len(tag) == 0 { - quoted_implicit = true - } - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - - *event = yaml_event_t{ - typ: yaml_SCALAR_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - value: token.value, - implicit: plain_implicit, - quoted_implicit: quoted_implicit, - style: yaml_style_t(token.style), - } - yaml_parser_set_event_comments(parser, event) - skip_token(parser) - return true - } - if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN { - // [Go] Some of the events below can be merged as they differ only on style. - end_mark = token.end_mark - parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE - *event = yaml_event_t{ - typ: yaml_SEQUENCE_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(yaml_FLOW_SEQUENCE_STYLE), - } - yaml_parser_set_event_comments(parser, event) - return true - } - if token.typ == yaml_FLOW_MAPPING_START_TOKEN { - end_mark = token.end_mark - parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE - *event = yaml_event_t{ - typ: yaml_MAPPING_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), - } - yaml_parser_set_event_comments(parser, event) - return true - } - if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN { - end_mark = token.end_mark - parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE - *event = yaml_event_t{ - typ: yaml_SEQUENCE_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), - } - if parser.stem_comment != nil { - event.head_comment = parser.stem_comment - parser.stem_comment = nil - } - return true - } - if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN { - end_mark = token.end_mark - parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE - *event = yaml_event_t{ - typ: yaml_MAPPING_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(yaml_BLOCK_MAPPING_STYLE), - } - if parser.stem_comment != nil { - event.head_comment = parser.stem_comment - parser.stem_comment = nil - } - return true - } - if len(anchor) > 0 || len(tag) > 0 { - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - - *event = yaml_event_t{ - typ: yaml_SCALAR_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - quoted_implicit: false, - style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), - } - return true - } - - context := "while parsing a flow node" - if block { - context = "while parsing a block node" - } - yaml_parser_set_parser_error_context(parser, context, start_mark, - "did not find expected node content", token.start_mark) - return false -} - -// Parse the productions: -// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END -// -// ******************** *********** * ********* -func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { - if first { - token := peek_token(parser) - if token == nil { - return false - } - parser.marks = append(parser.marks, token.start_mark) - skip_token(parser) - } - - token := peek_token(parser) - if token == nil { - return false - } - - if token.typ == yaml_BLOCK_ENTRY_TOKEN { - mark := token.end_mark - prior_head_len := len(parser.head_comment) - skip_token(parser) - yaml_parser_split_stem_comment(parser, prior_head_len) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE) - return yaml_parser_parse_node(parser, event, true, false) - } else { - parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE - return yaml_parser_process_empty_scalar(parser, event, mark) - } - } - if token.typ == yaml_BLOCK_END_TOKEN { - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - - *event = yaml_event_t{ - typ: yaml_SEQUENCE_END_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - } - - skip_token(parser) - return true - } - - context_mark := parser.marks[len(parser.marks)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - return yaml_parser_set_parser_error_context(parser, - "while parsing a block collection", context_mark, - "did not find expected '-' indicator", token.start_mark) -} - -// Parse the productions: -// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ -// -// *********** * -func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - - if token.typ == yaml_BLOCK_ENTRY_TOKEN { - mark := token.end_mark - prior_head_len := len(parser.head_comment) - skip_token(parser) - yaml_parser_split_stem_comment(parser, prior_head_len) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_BLOCK_ENTRY_TOKEN && - token.typ != yaml_KEY_TOKEN && - token.typ != yaml_VALUE_TOKEN && - token.typ != yaml_BLOCK_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE) - return yaml_parser_parse_node(parser, event, true, false) - } - parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE - return yaml_parser_process_empty_scalar(parser, event, mark) - } - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - - *event = yaml_event_t{ - typ: yaml_SEQUENCE_END_EVENT, - start_mark: token.start_mark, - end_mark: token.start_mark, // [Go] Shouldn't this be token.end_mark? - } - return true -} - -// Split stem comment from head comment. -// -// When a sequence or map is found under a sequence entry, the former head comment -// is assigned to the underlying sequence or map as a whole, not the individual -// sequence or map entry as would be expected otherwise. To handle this case the -// previous head comment is moved aside as the stem comment. -func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) { - if stem_len == 0 { - return - } - - token := peek_token(parser) - if token == nil || token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN { - return - } - - parser.stem_comment = parser.head_comment[:stem_len] - if len(parser.head_comment) == stem_len { - parser.head_comment = nil - } else { - // Copy suffix to prevent very strange bugs if someone ever appends - // further bytes to the prefix in the stem_comment slice above. - parser.head_comment = append([]byte(nil), parser.head_comment[stem_len+1:]...) - } -} - -// Parse the productions: -// block_mapping ::= BLOCK-MAPPING_START -// -// ******************* -// ((KEY block_node_or_indentless_sequence?)? -// *** * -// (VALUE block_node_or_indentless_sequence?)?)* -// -// BLOCK-END -// ********* -func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { - if first { - token := peek_token(parser) - if token == nil { - return false - } - parser.marks = append(parser.marks, token.start_mark) - skip_token(parser) - } - - token := peek_token(parser) - if token == nil { - return false - } - - // [Go] A tail comment was left from the prior mapping value processed. Emit an event - // as it needs to be processed with that value and not the following key. - if len(parser.tail_comment) > 0 { - *event = yaml_event_t{ - typ: yaml_TAIL_COMMENT_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - foot_comment: parser.tail_comment, - } - parser.tail_comment = nil - return true - } - - if token.typ == yaml_KEY_TOKEN { - mark := token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_KEY_TOKEN && - token.typ != yaml_VALUE_TOKEN && - token.typ != yaml_BLOCK_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE) - return yaml_parser_parse_node(parser, event, true, true) - } else { - parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE - return yaml_parser_process_empty_scalar(parser, event, mark) - } - } else if token.typ == yaml_BLOCK_END_TOKEN { - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - *event = yaml_event_t{ - typ: yaml_MAPPING_END_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - } - yaml_parser_set_event_comments(parser, event) - skip_token(parser) - return true - } - - context_mark := parser.marks[len(parser.marks)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - return yaml_parser_set_parser_error_context(parser, - "while parsing a block mapping", context_mark, - "did not find expected key", token.start_mark) -} - -// Parse the productions: -// block_mapping ::= BLOCK-MAPPING_START -// -// ((KEY block_node_or_indentless_sequence?)? -// -// (VALUE block_node_or_indentless_sequence?)?)* -// ***** * -// BLOCK-END -func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - if token.typ == yaml_VALUE_TOKEN { - mark := token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_KEY_TOKEN && - token.typ != yaml_VALUE_TOKEN && - token.typ != yaml_BLOCK_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE) - return yaml_parser_parse_node(parser, event, true, true) - } - parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE - return yaml_parser_process_empty_scalar(parser, event, mark) - } - parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE - return yaml_parser_process_empty_scalar(parser, event, token.start_mark) -} - -// Parse the productions: -// flow_sequence ::= FLOW-SEQUENCE-START -// -// ******************* -// (flow_sequence_entry FLOW-ENTRY)* -// * ********** -// flow_sequence_entry? -// * -// FLOW-SEQUENCE-END -// ***************** -// -// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// -// * -func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { - if first { - token := peek_token(parser) - if token == nil { - return false - } - parser.marks = append(parser.marks, token.start_mark) - skip_token(parser) - } - token := peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { - if !first { - if token.typ == yaml_FLOW_ENTRY_TOKEN { - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } else { - context_mark := parser.marks[len(parser.marks)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - return yaml_parser_set_parser_error_context(parser, - "while parsing a flow sequence", context_mark, - "did not find expected ',' or ']'", token.start_mark) - } - } - - if token.typ == yaml_KEY_TOKEN { - parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE - *event = yaml_event_t{ - typ: yaml_MAPPING_START_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - implicit: true, - style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), - } - skip_token(parser) - return true - } else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } - } - - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - - *event = yaml_event_t{ - typ: yaml_SEQUENCE_END_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - } - yaml_parser_set_event_comments(parser, event) - - skip_token(parser) - return true -} - -// Parse the productions: -// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// -// *** * -func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_VALUE_TOKEN && - token.typ != yaml_FLOW_ENTRY_TOKEN && - token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } - mark := token.end_mark - skip_token(parser) - parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE - return yaml_parser_process_empty_scalar(parser, event, mark) -} - -// Parse the productions: -// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// -// ***** * -func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - if token.typ == yaml_VALUE_TOKEN { - skip_token(parser) - token := peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } - } - parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE - return yaml_parser_process_empty_scalar(parser, event, token.start_mark) -} - -// Parse the productions: -// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// -// * -func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE - *event = yaml_event_t{ - typ: yaml_MAPPING_END_EVENT, - start_mark: token.start_mark, - end_mark: token.start_mark, // [Go] Shouldn't this be end_mark? - } - return true -} - -// Parse the productions: -// flow_mapping ::= FLOW-MAPPING-START -// -// ****************** -// (flow_mapping_entry FLOW-ENTRY)* -// * ********** -// flow_mapping_entry? -// ****************** -// FLOW-MAPPING-END -// **************** -// -// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// - *** * -func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { - if first { - token := peek_token(parser) - parser.marks = append(parser.marks, token.start_mark) - skip_token(parser) - } - - token := peek_token(parser) - if token == nil { - return false - } - - if token.typ != yaml_FLOW_MAPPING_END_TOKEN { - if !first { - if token.typ == yaml_FLOW_ENTRY_TOKEN { - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } else { - context_mark := parser.marks[len(parser.marks)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - return yaml_parser_set_parser_error_context(parser, - "while parsing a flow mapping", context_mark, - "did not find expected ',' or '}'", token.start_mark) - } - } - - if token.typ == yaml_KEY_TOKEN { - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_VALUE_TOKEN && - token.typ != yaml_FLOW_ENTRY_TOKEN && - token.typ != yaml_FLOW_MAPPING_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } else { - parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE - return yaml_parser_process_empty_scalar(parser, event, token.start_mark) - } - } else if token.typ != yaml_FLOW_MAPPING_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } - } - - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - *event = yaml_event_t{ - typ: yaml_MAPPING_END_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - } - yaml_parser_set_event_comments(parser, event) - skip_token(parser) - return true -} - -// Parse the productions: -// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// - ***** * -func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool { - token := peek_token(parser) - if token == nil { - return false - } - if empty { - parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE - return yaml_parser_process_empty_scalar(parser, event, token.start_mark) - } - if token.typ == yaml_VALUE_TOKEN { - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } - } - parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE - return yaml_parser_process_empty_scalar(parser, event, token.start_mark) -} - -// Generate an empty scalar event. -func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool { - *event = yaml_event_t{ - typ: yaml_SCALAR_EVENT, - start_mark: mark, - end_mark: mark, - value: nil, // Empty - implicit: true, - style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), - } - return true -} - -var default_tag_directives = []yaml_tag_directive_t{ - {[]byte("!"), []byte("!")}, - {[]byte("!!"), []byte("tag:yaml.org,2002:")}, -} - -// Parse directives. -func yaml_parser_process_directives(parser *yaml_parser_t, - version_directive_ref **yaml_version_directive_t, - tag_directives_ref *[]yaml_tag_directive_t) bool { - - var version_directive *yaml_version_directive_t - var tag_directives []yaml_tag_directive_t - - token := peek_token(parser) - if token == nil { - return false - } - - for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN { - if token.typ == yaml_VERSION_DIRECTIVE_TOKEN { - if version_directive != nil { - yaml_parser_set_parser_error(parser, - "found duplicate %YAML directive", token.start_mark) - return false - } - if token.major != 1 || token.minor != 1 { - yaml_parser_set_parser_error(parser, - "found incompatible YAML document", token.start_mark) - return false - } - version_directive = &yaml_version_directive_t{ - major: token.major, - minor: token.minor, - } - } else if token.typ == yaml_TAG_DIRECTIVE_TOKEN { - value := yaml_tag_directive_t{ - handle: token.value, - prefix: token.prefix, - } - if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) { - return false - } - tag_directives = append(tag_directives, value) - } - - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } - - for i := range default_tag_directives { - if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) { - return false - } - } - - if version_directive_ref != nil { - *version_directive_ref = version_directive - } - if tag_directives_ref != nil { - *tag_directives_ref = tag_directives - } - return true -} - -// Append a tag directive to the directives stack. -func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool { - for i := range parser.tag_directives { - if bytes.Equal(value.handle, parser.tag_directives[i].handle) { - if allow_duplicates { - return true - } - return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark) - } - } - - // [Go] I suspect the copy is unnecessary. This was likely done - // because there was no way to track ownership of the data. - value_copy := yaml_tag_directive_t{ - handle: make([]byte, len(value.handle)), - prefix: make([]byte, len(value.prefix)), - } - copy(value_copy.handle, value.handle) - copy(value_copy.prefix, value.prefix) - parser.tag_directives = append(parser.tag_directives, value_copy) - return true -} diff --git a/go/sdk/vendor/gopkg.in/yaml.v3/readerc.go b/go/sdk/vendor/gopkg.in/yaml.v3/readerc.go deleted file mode 100644 index 56af245..0000000 --- a/go/sdk/vendor/gopkg.in/yaml.v3/readerc.go +++ /dev/null @@ -1,434 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -// of the Software, and to permit persons to whom the Software is furnished to do -// so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -package yaml - -import ( - "io" -) - -// Set the reader error and return 0. -func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool { - parser.error = yaml_READER_ERROR - parser.problem = problem - parser.problem_offset = offset - parser.problem_value = value - return false -} - -// Byte order marks. -const ( - bom_UTF8 = "\xef\xbb\xbf" - bom_UTF16LE = "\xff\xfe" - bom_UTF16BE = "\xfe\xff" -) - -// Determine the input stream encoding by checking the BOM symbol. If no BOM is -// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure. -func yaml_parser_determine_encoding(parser *yaml_parser_t) bool { - // Ensure that we had enough bytes in the raw buffer. - for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 { - if !yaml_parser_update_raw_buffer(parser) { - return false - } - } - - // Determine the encoding. - buf := parser.raw_buffer - pos := parser.raw_buffer_pos - avail := len(buf) - pos - if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] { - parser.encoding = yaml_UTF16LE_ENCODING - parser.raw_buffer_pos += 2 - parser.offset += 2 - } else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] { - parser.encoding = yaml_UTF16BE_ENCODING - parser.raw_buffer_pos += 2 - parser.offset += 2 - } else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] { - parser.encoding = yaml_UTF8_ENCODING - parser.raw_buffer_pos += 3 - parser.offset += 3 - } else { - parser.encoding = yaml_UTF8_ENCODING - } - return true -} - -// Update the raw buffer. -func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool { - size_read := 0 - - // Return if the raw buffer is full. - if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) { - return true - } - - // Return on EOF. - if parser.eof { - return true - } - - // Move the remaining bytes in the raw buffer to the beginning. - if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) { - copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:]) - } - parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos] - parser.raw_buffer_pos = 0 - - // Call the read handler to fill the buffer. - size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)]) - parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read] - if err == io.EOF { - parser.eof = true - } else if err != nil { - return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1) - } - return true -} - -// Ensure that the buffer contains at least `length` characters. -// Return true on success, false on failure. -// -// The length is supposed to be significantly less that the buffer size. -func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool { - if parser.read_handler == nil { - panic("read handler must be set") - } - - // [Go] This function was changed to guarantee the requested length size at EOF. - // The fact we need to do this is pretty awful, but the description above implies - // for that to be the case, and there are tests - - // If the EOF flag is set and the raw buffer is empty, do nothing. - if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) { - // [Go] ACTUALLY! Read the documentation of this function above. - // This is just broken. To return true, we need to have the - // given length in the buffer. Not doing that means every single - // check that calls this function to make sure the buffer has a - // given length is Go) panicking; or C) accessing invalid memory. - //return true - } - - // Return if the buffer contains enough characters. - if parser.unread >= length { - return true - } - - // Determine the input encoding if it is not known yet. - if parser.encoding == yaml_ANY_ENCODING { - if !yaml_parser_determine_encoding(parser) { - return false - } - } - - // Move the unread characters to the beginning of the buffer. - buffer_len := len(parser.buffer) - if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len { - copy(parser.buffer, parser.buffer[parser.buffer_pos:]) - buffer_len -= parser.buffer_pos - parser.buffer_pos = 0 - } else if parser.buffer_pos == buffer_len { - buffer_len = 0 - parser.buffer_pos = 0 - } - - // Open the whole buffer for writing, and cut it before returning. - parser.buffer = parser.buffer[:cap(parser.buffer)] - - // Fill the buffer until it has enough characters. - first := true - for parser.unread < length { - - // Fill the raw buffer if necessary. - if !first || parser.raw_buffer_pos == len(parser.raw_buffer) { - if !yaml_parser_update_raw_buffer(parser) { - parser.buffer = parser.buffer[:buffer_len] - return false - } - } - first = false - - // Decode the raw buffer. - inner: - for parser.raw_buffer_pos != len(parser.raw_buffer) { - var value rune - var width int - - raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos - - // Decode the next character. - switch parser.encoding { - case yaml_UTF8_ENCODING: - // Decode a UTF-8 character. Check RFC 3629 - // (http://www.ietf.org/rfc/rfc3629.txt) for more details. - // - // The following table (taken from the RFC) is used for - // decoding. - // - // Char. number range | UTF-8 octet sequence - // (hexadecimal) | (binary) - // --------------------+------------------------------------ - // 0000 0000-0000 007F | 0xxxxxxx - // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx - // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx - // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - // - // Additionally, the characters in the range 0xD800-0xDFFF - // are prohibited as they are reserved for use with UTF-16 - // surrogate pairs. - - // Determine the length of the UTF-8 sequence. - octet := parser.raw_buffer[parser.raw_buffer_pos] - switch { - case octet&0x80 == 0x00: - width = 1 - case octet&0xE0 == 0xC0: - width = 2 - case octet&0xF0 == 0xE0: - width = 3 - case octet&0xF8 == 0xF0: - width = 4 - default: - // The leading octet is invalid. - return yaml_parser_set_reader_error(parser, - "invalid leading UTF-8 octet", - parser.offset, int(octet)) - } - - // Check if the raw buffer contains an incomplete character. - if width > raw_unread { - if parser.eof { - return yaml_parser_set_reader_error(parser, - "incomplete UTF-8 octet sequence", - parser.offset, -1) - } - break inner - } - - // Decode the leading octet. - switch { - case octet&0x80 == 0x00: - value = rune(octet & 0x7F) - case octet&0xE0 == 0xC0: - value = rune(octet & 0x1F) - case octet&0xF0 == 0xE0: - value = rune(octet & 0x0F) - case octet&0xF8 == 0xF0: - value = rune(octet & 0x07) - default: - value = 0 - } - - // Check and decode the trailing octets. - for k := 1; k < width; k++ { - octet = parser.raw_buffer[parser.raw_buffer_pos+k] - - // Check if the octet is valid. - if (octet & 0xC0) != 0x80 { - return yaml_parser_set_reader_error(parser, - "invalid trailing UTF-8 octet", - parser.offset+k, int(octet)) - } - - // Decode the octet. - value = (value << 6) + rune(octet&0x3F) - } - - // Check the length of the sequence against the value. - switch { - case width == 1: - case width == 2 && value >= 0x80: - case width == 3 && value >= 0x800: - case width == 4 && value >= 0x10000: - default: - return yaml_parser_set_reader_error(parser, - "invalid length of a UTF-8 sequence", - parser.offset, -1) - } - - // Check the range of the value. - if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF { - return yaml_parser_set_reader_error(parser, - "invalid Unicode character", - parser.offset, int(value)) - } - - case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING: - var low, high int - if parser.encoding == yaml_UTF16LE_ENCODING { - low, high = 0, 1 - } else { - low, high = 1, 0 - } - - // The UTF-16 encoding is not as simple as one might - // naively think. Check RFC 2781 - // (http://www.ietf.org/rfc/rfc2781.txt). - // - // Normally, two subsequent bytes describe a Unicode - // character. However a special technique (called a - // surrogate pair) is used for specifying character - // values larger than 0xFFFF. - // - // A surrogate pair consists of two pseudo-characters: - // high surrogate area (0xD800-0xDBFF) - // low surrogate area (0xDC00-0xDFFF) - // - // The following formulas are used for decoding - // and encoding characters using surrogate pairs: - // - // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF) - // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF) - // W1 = 110110yyyyyyyyyy - // W2 = 110111xxxxxxxxxx - // - // where U is the character value, W1 is the high surrogate - // area, W2 is the low surrogate area. - - // Check for incomplete UTF-16 character. - if raw_unread < 2 { - if parser.eof { - return yaml_parser_set_reader_error(parser, - "incomplete UTF-16 character", - parser.offset, -1) - } - break inner - } - - // Get the character. - value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) + - (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8) - - // Check for unexpected low surrogate area. - if value&0xFC00 == 0xDC00 { - return yaml_parser_set_reader_error(parser, - "unexpected low surrogate area", - parser.offset, int(value)) - } - - // Check for a high surrogate area. - if value&0xFC00 == 0xD800 { - width = 4 - - // Check for incomplete surrogate pair. - if raw_unread < 4 { - if parser.eof { - return yaml_parser_set_reader_error(parser, - "incomplete UTF-16 surrogate pair", - parser.offset, -1) - } - break inner - } - - // Get the next character. - value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) + - (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8) - - // Check for a low surrogate area. - if value2&0xFC00 != 0xDC00 { - return yaml_parser_set_reader_error(parser, - "expected low surrogate area", - parser.offset+2, int(value2)) - } - - // Generate the value of the surrogate pair. - value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF) - } else { - width = 2 - } - - default: - panic("impossible") - } - - // Check if the character is in the allowed range: - // #x9 | #xA | #xD | [#x20-#x7E] (8 bit) - // | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit) - // | [#x10000-#x10FFFF] (32 bit) - switch { - case value == 0x09: - case value == 0x0A: - case value == 0x0D: - case value >= 0x20 && value <= 0x7E: - case value == 0x85: - case value >= 0xA0 && value <= 0xD7FF: - case value >= 0xE000 && value <= 0xFFFD: - case value >= 0x10000 && value <= 0x10FFFF: - default: - return yaml_parser_set_reader_error(parser, - "control characters are not allowed", - parser.offset, int(value)) - } - - // Move the raw pointers. - parser.raw_buffer_pos += width - parser.offset += width - - // Finally put the character into the buffer. - if value <= 0x7F { - // 0000 0000-0000 007F . 0xxxxxxx - parser.buffer[buffer_len+0] = byte(value) - buffer_len += 1 - } else if value <= 0x7FF { - // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx - parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6)) - parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F)) - buffer_len += 2 - } else if value <= 0xFFFF { - // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx - parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12)) - parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F)) - parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F)) - buffer_len += 3 - } else { - // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18)) - parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F)) - parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F)) - parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F)) - buffer_len += 4 - } - - parser.unread++ - } - - // On EOF, put NUL into the buffer and return. - if parser.eof { - parser.buffer[buffer_len] = 0 - buffer_len++ - parser.unread++ - break - } - } - // [Go] Read the documentation of this function above. To return true, - // we need to have the given length in the buffer. Not doing that means - // every single check that calls this function to make sure the buffer - // has a given length is Go) panicking; or C) accessing invalid memory. - // This happens here due to the EOF above breaking early. - for buffer_len < length { - parser.buffer[buffer_len] = 0 - buffer_len++ - } - parser.buffer = parser.buffer[:buffer_len] - return true -} diff --git a/go/sdk/vendor/gopkg.in/yaml.v3/resolve.go b/go/sdk/vendor/gopkg.in/yaml.v3/resolve.go deleted file mode 100644 index 64ae888..0000000 --- a/go/sdk/vendor/gopkg.in/yaml.v3/resolve.go +++ /dev/null @@ -1,326 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package yaml - -import ( - "encoding/base64" - "math" - "regexp" - "strconv" - "strings" - "time" -) - -type resolveMapItem struct { - value interface{} - tag string -} - -var resolveTable = make([]byte, 256) -var resolveMap = make(map[string]resolveMapItem) - -func init() { - t := resolveTable - t[int('+')] = 'S' // Sign - t[int('-')] = 'S' - for _, c := range "0123456789" { - t[int(c)] = 'D' // Digit - } - for _, c := range "yYnNtTfFoO~" { - t[int(c)] = 'M' // In map - } - t[int('.')] = '.' // Float (potentially in map) - - var resolveMapList = []struct { - v interface{} - tag string - l []string - }{ - {true, boolTag, []string{"true", "True", "TRUE"}}, - {false, boolTag, []string{"false", "False", "FALSE"}}, - {nil, nullTag, []string{"", "~", "null", "Null", "NULL"}}, - {math.NaN(), floatTag, []string{".nan", ".NaN", ".NAN"}}, - {math.Inf(+1), floatTag, []string{".inf", ".Inf", ".INF"}}, - {math.Inf(+1), floatTag, []string{"+.inf", "+.Inf", "+.INF"}}, - {math.Inf(-1), floatTag, []string{"-.inf", "-.Inf", "-.INF"}}, - {"<<", mergeTag, []string{"<<"}}, - } - - m := resolveMap - for _, item := range resolveMapList { - for _, s := range item.l { - m[s] = resolveMapItem{item.v, item.tag} - } - } -} - -const ( - nullTag = "!!null" - boolTag = "!!bool" - strTag = "!!str" - intTag = "!!int" - floatTag = "!!float" - timestampTag = "!!timestamp" - seqTag = "!!seq" - mapTag = "!!map" - binaryTag = "!!binary" - mergeTag = "!!merge" -) - -var longTags = make(map[string]string) -var shortTags = make(map[string]string) - -func init() { - for _, stag := range []string{nullTag, boolTag, strTag, intTag, floatTag, timestampTag, seqTag, mapTag, binaryTag, mergeTag} { - ltag := longTag(stag) - longTags[stag] = ltag - shortTags[ltag] = stag - } -} - -const longTagPrefix = "tag:yaml.org,2002:" - -func shortTag(tag string) string { - if strings.HasPrefix(tag, longTagPrefix) { - if stag, ok := shortTags[tag]; ok { - return stag - } - return "!!" + tag[len(longTagPrefix):] - } - return tag -} - -func longTag(tag string) string { - if strings.HasPrefix(tag, "!!") { - if ltag, ok := longTags[tag]; ok { - return ltag - } - return longTagPrefix + tag[2:] - } - return tag -} - -func resolvableTag(tag string) bool { - switch tag { - case "", strTag, boolTag, intTag, floatTag, nullTag, timestampTag: - return true - } - return false -} - -var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`) - -func resolve(tag string, in string) (rtag string, out interface{}) { - tag = shortTag(tag) - if !resolvableTag(tag) { - return tag, in - } - - defer func() { - switch tag { - case "", rtag, strTag, binaryTag: - return - case floatTag: - if rtag == intTag { - switch v := out.(type) { - case int64: - rtag = floatTag - out = float64(v) - return - case int: - rtag = floatTag - out = float64(v) - return - } - } - } - failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag)) - }() - - // Any data is accepted as a !!str or !!binary. - // Otherwise, the prefix is enough of a hint about what it might be. - hint := byte('N') - if in != "" { - hint = resolveTable[in[0]] - } - if hint != 0 && tag != strTag && tag != binaryTag { - // Handle things we can lookup in a map. - if item, ok := resolveMap[in]; ok { - return item.tag, item.value - } - - // Base 60 floats are a bad idea, were dropped in YAML 1.2, and - // are purposefully unsupported here. They're still quoted on - // the way out for compatibility with other parser, though. - - switch hint { - case 'M': - // We've already checked the map above. - - case '.': - // Not in the map, so maybe a normal float. - floatv, err := strconv.ParseFloat(in, 64) - if err == nil { - return floatTag, floatv - } - - case 'D', 'S': - // Int, float, or timestamp. - // Only try values as a timestamp if the value is unquoted or there's an explicit - // !!timestamp tag. - if tag == "" || tag == timestampTag { - t, ok := parseTimestamp(in) - if ok { - return timestampTag, t - } - } - - plain := strings.Replace(in, "_", "", -1) - intv, err := strconv.ParseInt(plain, 0, 64) - if err == nil { - if intv == int64(int(intv)) { - return intTag, int(intv) - } else { - return intTag, intv - } - } - uintv, err := strconv.ParseUint(plain, 0, 64) - if err == nil { - return intTag, uintv - } - if yamlStyleFloat.MatchString(plain) { - floatv, err := strconv.ParseFloat(plain, 64) - if err == nil { - return floatTag, floatv - } - } - if strings.HasPrefix(plain, "0b") { - intv, err := strconv.ParseInt(plain[2:], 2, 64) - if err == nil { - if intv == int64(int(intv)) { - return intTag, int(intv) - } else { - return intTag, intv - } - } - uintv, err := strconv.ParseUint(plain[2:], 2, 64) - if err == nil { - return intTag, uintv - } - } else if strings.HasPrefix(plain, "-0b") { - intv, err := strconv.ParseInt("-"+plain[3:], 2, 64) - if err == nil { - if true || intv == int64(int(intv)) { - return intTag, int(intv) - } else { - return intTag, intv - } - } - } - // Octals as introduced in version 1.2 of the spec. - // Octals from the 1.1 spec, spelled as 0777, are still - // decoded by default in v3 as well for compatibility. - // May be dropped in v4 depending on how usage evolves. - if strings.HasPrefix(plain, "0o") { - intv, err := strconv.ParseInt(plain[2:], 8, 64) - if err == nil { - if intv == int64(int(intv)) { - return intTag, int(intv) - } else { - return intTag, intv - } - } - uintv, err := strconv.ParseUint(plain[2:], 8, 64) - if err == nil { - return intTag, uintv - } - } else if strings.HasPrefix(plain, "-0o") { - intv, err := strconv.ParseInt("-"+plain[3:], 8, 64) - if err == nil { - if true || intv == int64(int(intv)) { - return intTag, int(intv) - } else { - return intTag, intv - } - } - } - default: - panic("internal error: missing handler for resolver table: " + string(rune(hint)) + " (with " + in + ")") - } - } - return strTag, in -} - -// encodeBase64 encodes s as base64 that is broken up into multiple lines -// as appropriate for the resulting length. -func encodeBase64(s string) string { - const lineLen = 70 - encLen := base64.StdEncoding.EncodedLen(len(s)) - lines := encLen/lineLen + 1 - buf := make([]byte, encLen*2+lines) - in := buf[0:encLen] - out := buf[encLen:] - base64.StdEncoding.Encode(in, []byte(s)) - k := 0 - for i := 0; i < len(in); i += lineLen { - j := i + lineLen - if j > len(in) { - j = len(in) - } - k += copy(out[k:], in[i:j]) - if lines > 1 { - out[k] = '\n' - k++ - } - } - return string(out[:k]) -} - -// This is a subset of the formats allowed by the regular expression -// defined at http://yaml.org/type/timestamp.html. -var allowedTimestampFormats = []string{ - "2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields. - "2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t". - "2006-1-2 15:4:5.999999999", // space separated with no time zone - "2006-1-2", // date only - // Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5" - // from the set of examples. -} - -// parseTimestamp parses s as a timestamp string and -// returns the timestamp and reports whether it succeeded. -// Timestamp formats are defined at http://yaml.org/type/timestamp.html -func parseTimestamp(s string) (time.Time, bool) { - // TODO write code to check all the formats supported by - // http://yaml.org/type/timestamp.html instead of using time.Parse. - - // Quick check: all date formats start with YYYY-. - i := 0 - for ; i < len(s); i++ { - if c := s[i]; c < '0' || c > '9' { - break - } - } - if i != 4 || i == len(s) || s[i] != '-' { - return time.Time{}, false - } - for _, format := range allowedTimestampFormats { - if t, err := time.Parse(format, s); err == nil { - return t, true - } - } - return time.Time{}, false -} diff --git a/go/sdk/vendor/gopkg.in/yaml.v3/scannerc.go b/go/sdk/vendor/gopkg.in/yaml.v3/scannerc.go deleted file mode 100644 index 30b1f08..0000000 --- a/go/sdk/vendor/gopkg.in/yaml.v3/scannerc.go +++ /dev/null @@ -1,3040 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -// of the Software, and to permit persons to whom the Software is furnished to do -// so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -package yaml - -import ( - "bytes" - "fmt" -) - -// Introduction -// ************ -// -// The following notes assume that you are familiar with the YAML specification -// (http://yaml.org/spec/1.2/spec.html). We mostly follow it, although in -// some cases we are less restrictive that it requires. -// -// The process of transforming a YAML stream into a sequence of events is -// divided on two steps: Scanning and Parsing. -// -// The Scanner transforms the input stream into a sequence of tokens, while the -// parser transform the sequence of tokens produced by the Scanner into a -// sequence of parsing events. -// -// The Scanner is rather clever and complicated. The Parser, on the contrary, -// is a straightforward implementation of a recursive-descendant parser (or, -// LL(1) parser, as it is usually called). -// -// Actually there are two issues of Scanning that might be called "clever", the -// rest is quite straightforward. The issues are "block collection start" and -// "simple keys". Both issues are explained below in details. -// -// Here the Scanning step is explained and implemented. We start with the list -// of all the tokens produced by the Scanner together with short descriptions. -// -// Now, tokens: -// -// STREAM-START(encoding) # The stream start. -// STREAM-END # The stream end. -// VERSION-DIRECTIVE(major,minor) # The '%YAML' directive. -// TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive. -// DOCUMENT-START # '---' -// DOCUMENT-END # '...' -// BLOCK-SEQUENCE-START # Indentation increase denoting a block -// BLOCK-MAPPING-START # sequence or a block mapping. -// BLOCK-END # Indentation decrease. -// FLOW-SEQUENCE-START # '[' -// FLOW-SEQUENCE-END # ']' -// BLOCK-SEQUENCE-START # '{' -// BLOCK-SEQUENCE-END # '}' -// BLOCK-ENTRY # '-' -// FLOW-ENTRY # ',' -// KEY # '?' or nothing (simple keys). -// VALUE # ':' -// ALIAS(anchor) # '*anchor' -// ANCHOR(anchor) # '&anchor' -// TAG(handle,suffix) # '!handle!suffix' -// SCALAR(value,style) # A scalar. -// -// The following two tokens are "virtual" tokens denoting the beginning and the -// end of the stream: -// -// STREAM-START(encoding) -// STREAM-END -// -// We pass the information about the input stream encoding with the -// STREAM-START token. -// -// The next two tokens are responsible for tags: -// -// VERSION-DIRECTIVE(major,minor) -// TAG-DIRECTIVE(handle,prefix) -// -// Example: -// -// %YAML 1.1 -// %TAG ! !foo -// %TAG !yaml! tag:yaml.org,2002: -// --- -// -// The correspoding sequence of tokens: -// -// STREAM-START(utf-8) -// VERSION-DIRECTIVE(1,1) -// TAG-DIRECTIVE("!","!foo") -// TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:") -// DOCUMENT-START -// STREAM-END -// -// Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole -// line. -// -// The document start and end indicators are represented by: -// -// DOCUMENT-START -// DOCUMENT-END -// -// Note that if a YAML stream contains an implicit document (without '---' -// and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be -// produced. -// -// In the following examples, we present whole documents together with the -// produced tokens. -// -// 1. An implicit document: -// -// 'a scalar' -// -// Tokens: -// -// STREAM-START(utf-8) -// SCALAR("a scalar",single-quoted) -// STREAM-END -// -// 2. An explicit document: -// -// --- -// 'a scalar' -// ... -// -// Tokens: -// -// STREAM-START(utf-8) -// DOCUMENT-START -// SCALAR("a scalar",single-quoted) -// DOCUMENT-END -// STREAM-END -// -// 3. Several documents in a stream: -// -// 'a scalar' -// --- -// 'another scalar' -// --- -// 'yet another scalar' -// -// Tokens: -// -// STREAM-START(utf-8) -// SCALAR("a scalar",single-quoted) -// DOCUMENT-START -// SCALAR("another scalar",single-quoted) -// DOCUMENT-START -// SCALAR("yet another scalar",single-quoted) -// STREAM-END -// -// We have already introduced the SCALAR token above. The following tokens are -// used to describe aliases, anchors, tag, and scalars: -// -// ALIAS(anchor) -// ANCHOR(anchor) -// TAG(handle,suffix) -// SCALAR(value,style) -// -// The following series of examples illustrate the usage of these tokens: -// -// 1. A recursive sequence: -// -// &A [ *A ] -// -// Tokens: -// -// STREAM-START(utf-8) -// ANCHOR("A") -// FLOW-SEQUENCE-START -// ALIAS("A") -// FLOW-SEQUENCE-END -// STREAM-END -// -// 2. A tagged scalar: -// -// !!float "3.14" # A good approximation. -// -// Tokens: -// -// STREAM-START(utf-8) -// TAG("!!","float") -// SCALAR("3.14",double-quoted) -// STREAM-END -// -// 3. Various scalar styles: -// -// --- # Implicit empty plain scalars do not produce tokens. -// --- a plain scalar -// --- 'a single-quoted scalar' -// --- "a double-quoted scalar" -// --- |- -// a literal scalar -// --- >- -// a folded -// scalar -// -// Tokens: -// -// STREAM-START(utf-8) -// DOCUMENT-START -// DOCUMENT-START -// SCALAR("a plain scalar",plain) -// DOCUMENT-START -// SCALAR("a single-quoted scalar",single-quoted) -// DOCUMENT-START -// SCALAR("a double-quoted scalar",double-quoted) -// DOCUMENT-START -// SCALAR("a literal scalar",literal) -// DOCUMENT-START -// SCALAR("a folded scalar",folded) -// STREAM-END -// -// Now it's time to review collection-related tokens. We will start with -// flow collections: -// -// FLOW-SEQUENCE-START -// FLOW-SEQUENCE-END -// FLOW-MAPPING-START -// FLOW-MAPPING-END -// FLOW-ENTRY -// KEY -// VALUE -// -// The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and -// FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}' -// correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the -// indicators '?' and ':', which are used for denoting mapping keys and values, -// are represented by the KEY and VALUE tokens. -// -// The following examples show flow collections: -// -// 1. A flow sequence: -// -// [item 1, item 2, item 3] -// -// Tokens: -// -// STREAM-START(utf-8) -// FLOW-SEQUENCE-START -// SCALAR("item 1",plain) -// FLOW-ENTRY -// SCALAR("item 2",plain) -// FLOW-ENTRY -// SCALAR("item 3",plain) -// FLOW-SEQUENCE-END -// STREAM-END -// -// 2. A flow mapping: -// -// { -// a simple key: a value, # Note that the KEY token is produced. -// ? a complex key: another value, -// } -// -// Tokens: -// -// STREAM-START(utf-8) -// FLOW-MAPPING-START -// KEY -// SCALAR("a simple key",plain) -// VALUE -// SCALAR("a value",plain) -// FLOW-ENTRY -// KEY -// SCALAR("a complex key",plain) -// VALUE -// SCALAR("another value",plain) -// FLOW-ENTRY -// FLOW-MAPPING-END -// STREAM-END -// -// A simple key is a key which is not denoted by the '?' indicator. Note that -// the Scanner still produce the KEY token whenever it encounters a simple key. -// -// For scanning block collections, the following tokens are used (note that we -// repeat KEY and VALUE here): -// -// BLOCK-SEQUENCE-START -// BLOCK-MAPPING-START -// BLOCK-END -// BLOCK-ENTRY -// KEY -// VALUE -// -// The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation -// increase that precedes a block collection (cf. the INDENT token in Python). -// The token BLOCK-END denote indentation decrease that ends a block collection -// (cf. the DEDENT token in Python). However YAML has some syntax pecularities -// that makes detections of these tokens more complex. -// -// The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators -// '-', '?', and ':' correspondingly. -// -// The following examples show how the tokens BLOCK-SEQUENCE-START, -// BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner: -// -// 1. Block sequences: -// -// - item 1 -// - item 2 -// - -// - item 3.1 -// - item 3.2 -// - -// key 1: value 1 -// key 2: value 2 -// -// Tokens: -// -// STREAM-START(utf-8) -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// SCALAR("item 1",plain) -// BLOCK-ENTRY -// SCALAR("item 2",plain) -// BLOCK-ENTRY -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// SCALAR("item 3.1",plain) -// BLOCK-ENTRY -// SCALAR("item 3.2",plain) -// BLOCK-END -// BLOCK-ENTRY -// BLOCK-MAPPING-START -// KEY -// SCALAR("key 1",plain) -// VALUE -// SCALAR("value 1",plain) -// KEY -// SCALAR("key 2",plain) -// VALUE -// SCALAR("value 2",plain) -// BLOCK-END -// BLOCK-END -// STREAM-END -// -// 2. Block mappings: -// -// a simple key: a value # The KEY token is produced here. -// ? a complex key -// : another value -// a mapping: -// key 1: value 1 -// key 2: value 2 -// a sequence: -// - item 1 -// - item 2 -// -// Tokens: -// -// STREAM-START(utf-8) -// BLOCK-MAPPING-START -// KEY -// SCALAR("a simple key",plain) -// VALUE -// SCALAR("a value",plain) -// KEY -// SCALAR("a complex key",plain) -// VALUE -// SCALAR("another value",plain) -// KEY -// SCALAR("a mapping",plain) -// BLOCK-MAPPING-START -// KEY -// SCALAR("key 1",plain) -// VALUE -// SCALAR("value 1",plain) -// KEY -// SCALAR("key 2",plain) -// VALUE -// SCALAR("value 2",plain) -// BLOCK-END -// KEY -// SCALAR("a sequence",plain) -// VALUE -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// SCALAR("item 1",plain) -// BLOCK-ENTRY -// SCALAR("item 2",plain) -// BLOCK-END -// BLOCK-END -// STREAM-END -// -// YAML does not always require to start a new block collection from a new -// line. If the current line contains only '-', '?', and ':' indicators, a new -// block collection may start at the current line. The following examples -// illustrate this case: -// -// 1. Collections in a sequence: -// -// - - item 1 -// - item 2 -// - key 1: value 1 -// key 2: value 2 -// - ? complex key -// : complex value -// -// Tokens: -// -// STREAM-START(utf-8) -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// SCALAR("item 1",plain) -// BLOCK-ENTRY -// SCALAR("item 2",plain) -// BLOCK-END -// BLOCK-ENTRY -// BLOCK-MAPPING-START -// KEY -// SCALAR("key 1",plain) -// VALUE -// SCALAR("value 1",plain) -// KEY -// SCALAR("key 2",plain) -// VALUE -// SCALAR("value 2",plain) -// BLOCK-END -// BLOCK-ENTRY -// BLOCK-MAPPING-START -// KEY -// SCALAR("complex key") -// VALUE -// SCALAR("complex value") -// BLOCK-END -// BLOCK-END -// STREAM-END -// -// 2. Collections in a mapping: -// -// ? a sequence -// : - item 1 -// - item 2 -// ? a mapping -// : key 1: value 1 -// key 2: value 2 -// -// Tokens: -// -// STREAM-START(utf-8) -// BLOCK-MAPPING-START -// KEY -// SCALAR("a sequence",plain) -// VALUE -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// SCALAR("item 1",plain) -// BLOCK-ENTRY -// SCALAR("item 2",plain) -// BLOCK-END -// KEY -// SCALAR("a mapping",plain) -// VALUE -// BLOCK-MAPPING-START -// KEY -// SCALAR("key 1",plain) -// VALUE -// SCALAR("value 1",plain) -// KEY -// SCALAR("key 2",plain) -// VALUE -// SCALAR("value 2",plain) -// BLOCK-END -// BLOCK-END -// STREAM-END -// -// YAML also permits non-indented sequences if they are included into a block -// mapping. In this case, the token BLOCK-SEQUENCE-START is not produced: -// -// key: -// - item 1 # BLOCK-SEQUENCE-START is NOT produced here. -// - item 2 -// -// Tokens: -// -// STREAM-START(utf-8) -// BLOCK-MAPPING-START -// KEY -// SCALAR("key",plain) -// VALUE -// BLOCK-ENTRY -// SCALAR("item 1",plain) -// BLOCK-ENTRY -// SCALAR("item 2",plain) -// BLOCK-END -// - -// Ensure that the buffer contains the required number of characters. -// Return true on success, false on failure (reader error or memory error). -func cache(parser *yaml_parser_t, length int) bool { - // [Go] This was inlined: !cache(A, B) -> unread < B && !update(A, B) - return parser.unread >= length || yaml_parser_update_buffer(parser, length) -} - -// Advance the buffer pointer. -func skip(parser *yaml_parser_t) { - if !is_blank(parser.buffer, parser.buffer_pos) { - parser.newlines = 0 - } - parser.mark.index++ - parser.mark.column++ - parser.unread-- - parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) -} - -func skip_line(parser *yaml_parser_t) { - if is_crlf(parser.buffer, parser.buffer_pos) { - parser.mark.index += 2 - parser.mark.column = 0 - parser.mark.line++ - parser.unread -= 2 - parser.buffer_pos += 2 - parser.newlines++ - } else if is_break(parser.buffer, parser.buffer_pos) { - parser.mark.index++ - parser.mark.column = 0 - parser.mark.line++ - parser.unread-- - parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) - parser.newlines++ - } -} - -// Copy a character to a string buffer and advance pointers. -func read(parser *yaml_parser_t, s []byte) []byte { - if !is_blank(parser.buffer, parser.buffer_pos) { - parser.newlines = 0 - } - w := width(parser.buffer[parser.buffer_pos]) - if w == 0 { - panic("invalid character sequence") - } - if len(s) == 0 { - s = make([]byte, 0, 32) - } - if w == 1 && len(s)+w <= cap(s) { - s = s[:len(s)+1] - s[len(s)-1] = parser.buffer[parser.buffer_pos] - parser.buffer_pos++ - } else { - s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...) - parser.buffer_pos += w - } - parser.mark.index++ - parser.mark.column++ - parser.unread-- - return s -} - -// Copy a line break character to a string buffer and advance pointers. -func read_line(parser *yaml_parser_t, s []byte) []byte { - buf := parser.buffer - pos := parser.buffer_pos - switch { - case buf[pos] == '\r' && buf[pos+1] == '\n': - // CR LF . LF - s = append(s, '\n') - parser.buffer_pos += 2 - parser.mark.index++ - parser.unread-- - case buf[pos] == '\r' || buf[pos] == '\n': - // CR|LF . LF - s = append(s, '\n') - parser.buffer_pos += 1 - case buf[pos] == '\xC2' && buf[pos+1] == '\x85': - // NEL . LF - s = append(s, '\n') - parser.buffer_pos += 2 - case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'): - // LS|PS . LS|PS - s = append(s, buf[parser.buffer_pos:pos+3]...) - parser.buffer_pos += 3 - default: - return s - } - parser.mark.index++ - parser.mark.column = 0 - parser.mark.line++ - parser.unread-- - parser.newlines++ - return s -} - -// Get the next token. -func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool { - // Erase the token object. - *token = yaml_token_t{} // [Go] Is this necessary? - - // No tokens after STREAM-END or error. - if parser.stream_end_produced || parser.error != yaml_NO_ERROR { - return true - } - - // Ensure that the tokens queue contains enough tokens. - if !parser.token_available { - if !yaml_parser_fetch_more_tokens(parser) { - return false - } - } - - // Fetch the next token from the queue. - *token = parser.tokens[parser.tokens_head] - parser.tokens_head++ - parser.tokens_parsed++ - parser.token_available = false - - if token.typ == yaml_STREAM_END_TOKEN { - parser.stream_end_produced = true - } - return true -} - -// Set the scanner error and return false. -func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string) bool { - parser.error = yaml_SCANNER_ERROR - parser.context = context - parser.context_mark = context_mark - parser.problem = problem - parser.problem_mark = parser.mark - return false -} - -func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, context_mark yaml_mark_t, problem string) bool { - context := "while parsing a tag" - if directive { - context = "while parsing a %TAG directive" - } - return yaml_parser_set_scanner_error(parser, context, context_mark, problem) -} - -func trace(args ...interface{}) func() { - pargs := append([]interface{}{"+++"}, args...) - fmt.Println(pargs...) - pargs = append([]interface{}{"---"}, args...) - return func() { fmt.Println(pargs...) } -} - -// Ensure that the tokens queue contains at least one token which can be -// returned to the Parser. -func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool { - // While we need more tokens to fetch, do it. - for { - // [Go] The comment parsing logic requires a lookahead of two tokens - // so that foot comments may be parsed in time of associating them - // with the tokens that are parsed before them, and also for line - // comments to be transformed into head comments in some edge cases. - if parser.tokens_head < len(parser.tokens)-2 { - // If a potential simple key is at the head position, we need to fetch - // the next token to disambiguate it. - head_tok_idx, ok := parser.simple_keys_by_tok[parser.tokens_parsed] - if !ok { - break - } else if valid, ok := yaml_simple_key_is_valid(parser, &parser.simple_keys[head_tok_idx]); !ok { - return false - } else if !valid { - break - } - } - // Fetch the next token. - if !yaml_parser_fetch_next_token(parser) { - return false - } - } - - parser.token_available = true - return true -} - -// The dispatcher for token fetchers. -func yaml_parser_fetch_next_token(parser *yaml_parser_t) (ok bool) { - // Ensure that the buffer is initialized. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - // Check if we just started scanning. Fetch STREAM-START then. - if !parser.stream_start_produced { - return yaml_parser_fetch_stream_start(parser) - } - - scan_mark := parser.mark - - // Eat whitespaces and comments until we reach the next token. - if !yaml_parser_scan_to_next_token(parser) { - return false - } - - // [Go] While unrolling indents, transform the head comments of prior - // indentation levels observed after scan_start into foot comments at - // the respective indexes. - - // Check the indentation level against the current column. - if !yaml_parser_unroll_indent(parser, parser.mark.column, scan_mark) { - return false - } - - // Ensure that the buffer contains at least 4 characters. 4 is the length - // of the longest indicators ('--- ' and '... '). - if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { - return false - } - - // Is it the end of the stream? - if is_z(parser.buffer, parser.buffer_pos) { - return yaml_parser_fetch_stream_end(parser) - } - - // Is it a directive? - if parser.mark.column == 0 && parser.buffer[parser.buffer_pos] == '%' { - return yaml_parser_fetch_directive(parser) - } - - buf := parser.buffer - pos := parser.buffer_pos - - // Is it the document start indicator? - if parser.mark.column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && is_blankz(buf, pos+3) { - return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_START_TOKEN) - } - - // Is it the document end indicator? - if parser.mark.column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && is_blankz(buf, pos+3) { - return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN) - } - - comment_mark := parser.mark - if len(parser.tokens) > 0 && (parser.flow_level == 0 && buf[pos] == ':' || parser.flow_level > 0 && buf[pos] == ',') { - // Associate any following comments with the prior token. - comment_mark = parser.tokens[len(parser.tokens)-1].start_mark - } - defer func() { - if !ok { - return - } - if len(parser.tokens) > 0 && parser.tokens[len(parser.tokens)-1].typ == yaml_BLOCK_ENTRY_TOKEN { - // Sequence indicators alone have no line comments. It becomes - // a head comment for whatever follows. - return - } - if !yaml_parser_scan_line_comment(parser, comment_mark) { - ok = false - return - } - }() - - // Is it the flow sequence start indicator? - if buf[pos] == '[' { - return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN) - } - - // Is it the flow mapping start indicator? - if parser.buffer[parser.buffer_pos] == '{' { - return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_MAPPING_START_TOKEN) - } - - // Is it the flow sequence end indicator? - if parser.buffer[parser.buffer_pos] == ']' { - return yaml_parser_fetch_flow_collection_end(parser, - yaml_FLOW_SEQUENCE_END_TOKEN) - } - - // Is it the flow mapping end indicator? - if parser.buffer[parser.buffer_pos] == '}' { - return yaml_parser_fetch_flow_collection_end(parser, - yaml_FLOW_MAPPING_END_TOKEN) - } - - // Is it the flow entry indicator? - if parser.buffer[parser.buffer_pos] == ',' { - return yaml_parser_fetch_flow_entry(parser) - } - - // Is it the block entry indicator? - if parser.buffer[parser.buffer_pos] == '-' && is_blankz(parser.buffer, parser.buffer_pos+1) { - return yaml_parser_fetch_block_entry(parser) - } - - // Is it the key indicator? - if parser.buffer[parser.buffer_pos] == '?' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { - return yaml_parser_fetch_key(parser) - } - - // Is it the value indicator? - if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { - return yaml_parser_fetch_value(parser) - } - - // Is it an alias? - if parser.buffer[parser.buffer_pos] == '*' { - return yaml_parser_fetch_anchor(parser, yaml_ALIAS_TOKEN) - } - - // Is it an anchor? - if parser.buffer[parser.buffer_pos] == '&' { - return yaml_parser_fetch_anchor(parser, yaml_ANCHOR_TOKEN) - } - - // Is it a tag? - if parser.buffer[parser.buffer_pos] == '!' { - return yaml_parser_fetch_tag(parser) - } - - // Is it a literal scalar? - if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 { - return yaml_parser_fetch_block_scalar(parser, true) - } - - // Is it a folded scalar? - if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 { - return yaml_parser_fetch_block_scalar(parser, false) - } - - // Is it a single-quoted scalar? - if parser.buffer[parser.buffer_pos] == '\'' { - return yaml_parser_fetch_flow_scalar(parser, true) - } - - // Is it a double-quoted scalar? - if parser.buffer[parser.buffer_pos] == '"' { - return yaml_parser_fetch_flow_scalar(parser, false) - } - - // Is it a plain scalar? - // - // A plain scalar may start with any non-blank characters except - // - // '-', '?', ':', ',', '[', ']', '{', '}', - // '#', '&', '*', '!', '|', '>', '\'', '\"', - // '%', '@', '`'. - // - // In the block context (and, for the '-' indicator, in the flow context - // too), it may also start with the characters - // - // '-', '?', ':' - // - // if it is followed by a non-space character. - // - // The last rule is more restrictive than the specification requires. - // [Go] TODO Make this logic more reasonable. - //switch parser.buffer[parser.buffer_pos] { - //case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`': - //} - if !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' || - parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' || - parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' || - parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || - parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' || - parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' || - parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' || - parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' || - parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' || - parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') || - (parser.buffer[parser.buffer_pos] == '-' && !is_blank(parser.buffer, parser.buffer_pos+1)) || - (parser.flow_level == 0 && - (parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') && - !is_blankz(parser.buffer, parser.buffer_pos+1)) { - return yaml_parser_fetch_plain_scalar(parser) - } - - // If we don't determine the token type so far, it is an error. - return yaml_parser_set_scanner_error(parser, - "while scanning for the next token", parser.mark, - "found character that cannot start any token") -} - -func yaml_simple_key_is_valid(parser *yaml_parser_t, simple_key *yaml_simple_key_t) (valid, ok bool) { - if !simple_key.possible { - return false, true - } - - // The 1.2 specification says: - // - // "If the ? indicator is omitted, parsing needs to see past the - // implicit key to recognize it as such. To limit the amount of - // lookahead required, the “:” indicator must appear at most 1024 - // Unicode characters beyond the start of the key. In addition, the key - // is restricted to a single line." - // - if simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index { - // Check if the potential simple key to be removed is required. - if simple_key.required { - return false, yaml_parser_set_scanner_error(parser, - "while scanning a simple key", simple_key.mark, - "could not find expected ':'") - } - simple_key.possible = false - return false, true - } - return true, true -} - -// Check if a simple key may start at the current position and add it if -// needed. -func yaml_parser_save_simple_key(parser *yaml_parser_t) bool { - // A simple key is required at the current position if the scanner is in - // the block context and the current column coincides with the indentation - // level. - - required := parser.flow_level == 0 && parser.indent == parser.mark.column - - // - // If the current position may start a simple key, save it. - // - if parser.simple_key_allowed { - simple_key := yaml_simple_key_t{ - possible: true, - required: required, - token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), - mark: parser.mark, - } - - if !yaml_parser_remove_simple_key(parser) { - return false - } - parser.simple_keys[len(parser.simple_keys)-1] = simple_key - parser.simple_keys_by_tok[simple_key.token_number] = len(parser.simple_keys) - 1 - } - return true -} - -// Remove a potential simple key at the current flow level. -func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool { - i := len(parser.simple_keys) - 1 - if parser.simple_keys[i].possible { - // If the key is required, it is an error. - if parser.simple_keys[i].required { - return yaml_parser_set_scanner_error(parser, - "while scanning a simple key", parser.simple_keys[i].mark, - "could not find expected ':'") - } - // Remove the key from the stack. - parser.simple_keys[i].possible = false - delete(parser.simple_keys_by_tok, parser.simple_keys[i].token_number) - } - return true -} - -// max_flow_level limits the flow_level -const max_flow_level = 10000 - -// Increase the flow level and resize the simple key list if needed. -func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool { - // Reset the simple key on the next level. - parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{ - possible: false, - required: false, - token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), - mark: parser.mark, - }) - - // Increase the flow level. - parser.flow_level++ - if parser.flow_level > max_flow_level { - return yaml_parser_set_scanner_error(parser, - "while increasing flow level", parser.simple_keys[len(parser.simple_keys)-1].mark, - fmt.Sprintf("exceeded max depth of %d", max_flow_level)) - } - return true -} - -// Decrease the flow level. -func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool { - if parser.flow_level > 0 { - parser.flow_level-- - last := len(parser.simple_keys) - 1 - delete(parser.simple_keys_by_tok, parser.simple_keys[last].token_number) - parser.simple_keys = parser.simple_keys[:last] - } - return true -} - -// max_indents limits the indents stack size -const max_indents = 10000 - -// Push the current indentation level to the stack and set the new level -// the current column is greater than the indentation level. In this case, -// append or insert the specified token into the token queue. -func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml_token_type_t, mark yaml_mark_t) bool { - // In the flow context, do nothing. - if parser.flow_level > 0 { - return true - } - - if parser.indent < column { - // Push the current indentation level to the stack and set the new - // indentation level. - parser.indents = append(parser.indents, parser.indent) - parser.indent = column - if len(parser.indents) > max_indents { - return yaml_parser_set_scanner_error(parser, - "while increasing indent level", parser.simple_keys[len(parser.simple_keys)-1].mark, - fmt.Sprintf("exceeded max depth of %d", max_indents)) - } - - // Create a token and insert it into the queue. - token := yaml_token_t{ - typ: typ, - start_mark: mark, - end_mark: mark, - } - if number > -1 { - number -= parser.tokens_parsed - } - yaml_insert_token(parser, number, &token) - } - return true -} - -// Pop indentation levels from the indents stack until the current level -// becomes less or equal to the column. For each indentation level, append -// the BLOCK-END token. -func yaml_parser_unroll_indent(parser *yaml_parser_t, column int, scan_mark yaml_mark_t) bool { - // In the flow context, do nothing. - if parser.flow_level > 0 { - return true - } - - block_mark := scan_mark - block_mark.index-- - - // Loop through the indentation levels in the stack. - for parser.indent > column { - - // [Go] Reposition the end token before potential following - // foot comments of parent blocks. For that, search - // backwards for recent comments that were at the same - // indent as the block that is ending now. - stop_index := block_mark.index - for i := len(parser.comments) - 1; i >= 0; i-- { - comment := &parser.comments[i] - - if comment.end_mark.index < stop_index { - // Don't go back beyond the start of the comment/whitespace scan, unless column < 0. - // If requested indent column is < 0, then the document is over and everything else - // is a foot anyway. - break - } - if comment.start_mark.column == parser.indent+1 { - // This is a good match. But maybe there's a former comment - // at that same indent level, so keep searching. - block_mark = comment.start_mark - } - - // While the end of the former comment matches with - // the start of the following one, we know there's - // nothing in between and scanning is still safe. - stop_index = comment.scan_mark.index - } - - // Create a token and append it to the queue. - token := yaml_token_t{ - typ: yaml_BLOCK_END_TOKEN, - start_mark: block_mark, - end_mark: block_mark, - } - yaml_insert_token(parser, -1, &token) - - // Pop the indentation level. - parser.indent = parser.indents[len(parser.indents)-1] - parser.indents = parser.indents[:len(parser.indents)-1] - } - return true -} - -// Initialize the scanner and produce the STREAM-START token. -func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool { - - // Set the initial indentation. - parser.indent = -1 - - // Initialize the simple key stack. - parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) - - parser.simple_keys_by_tok = make(map[int]int) - - // A simple key is allowed at the beginning of the stream. - parser.simple_key_allowed = true - - // We have started. - parser.stream_start_produced = true - - // Create the STREAM-START token and append it to the queue. - token := yaml_token_t{ - typ: yaml_STREAM_START_TOKEN, - start_mark: parser.mark, - end_mark: parser.mark, - encoding: parser.encoding, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the STREAM-END token and shut down the scanner. -func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool { - - // Force new line. - if parser.mark.column != 0 { - parser.mark.column = 0 - parser.mark.line++ - } - - // Reset the indentation level. - if !yaml_parser_unroll_indent(parser, -1, parser.mark) { - return false - } - - // Reset simple keys. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - parser.simple_key_allowed = false - - // Create the STREAM-END token and append it to the queue. - token := yaml_token_t{ - typ: yaml_STREAM_END_TOKEN, - start_mark: parser.mark, - end_mark: parser.mark, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token. -func yaml_parser_fetch_directive(parser *yaml_parser_t) bool { - // Reset the indentation level. - if !yaml_parser_unroll_indent(parser, -1, parser.mark) { - return false - } - - // Reset simple keys. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - parser.simple_key_allowed = false - - // Create the YAML-DIRECTIVE or TAG-DIRECTIVE token. - token := yaml_token_t{} - if !yaml_parser_scan_directive(parser, &token) { - return false - } - // Append the token to the queue. - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the DOCUMENT-START or DOCUMENT-END token. -func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool { - // Reset the indentation level. - if !yaml_parser_unroll_indent(parser, -1, parser.mark) { - return false - } - - // Reset simple keys. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - parser.simple_key_allowed = false - - // Consume the token. - start_mark := parser.mark - - skip(parser) - skip(parser) - skip(parser) - - end_mark := parser.mark - - // Create the DOCUMENT-START or DOCUMENT-END token. - token := yaml_token_t{ - typ: typ, - start_mark: start_mark, - end_mark: end_mark, - } - // Append the token to the queue. - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token. -func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool { - - // The indicators '[' and '{' may start a simple key. - if !yaml_parser_save_simple_key(parser) { - return false - } - - // Increase the flow level. - if !yaml_parser_increase_flow_level(parser) { - return false - } - - // A simple key may follow the indicators '[' and '{'. - parser.simple_key_allowed = true - - // Consume the token. - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token. - token := yaml_token_t{ - typ: typ, - start_mark: start_mark, - end_mark: end_mark, - } - // Append the token to the queue. - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token. -func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ yaml_token_type_t) bool { - // Reset any potential simple key on the current flow level. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - // Decrease the flow level. - if !yaml_parser_decrease_flow_level(parser) { - return false - } - - // No simple keys after the indicators ']' and '}'. - parser.simple_key_allowed = false - - // Consume the token. - - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token. - token := yaml_token_t{ - typ: typ, - start_mark: start_mark, - end_mark: end_mark, - } - // Append the token to the queue. - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the FLOW-ENTRY token. -func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool { - // Reset any potential simple keys on the current flow level. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - // Simple keys are allowed after ','. - parser.simple_key_allowed = true - - // Consume the token. - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the FLOW-ENTRY token and append it to the queue. - token := yaml_token_t{ - typ: yaml_FLOW_ENTRY_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the BLOCK-ENTRY token. -func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool { - // Check if the scanner is in the block context. - if parser.flow_level == 0 { - // Check if we are allowed to start a new entry. - if !parser.simple_key_allowed { - return yaml_parser_set_scanner_error(parser, "", parser.mark, - "block sequence entries are not allowed in this context") - } - // Add the BLOCK-SEQUENCE-START token if needed. - if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_SEQUENCE_START_TOKEN, parser.mark) { - return false - } - } else { - // It is an error for the '-' indicator to occur in the flow context, - // but we let the Parser detect and report about it because the Parser - // is able to point to the context. - } - - // Reset any potential simple keys on the current flow level. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - // Simple keys are allowed after '-'. - parser.simple_key_allowed = true - - // Consume the token. - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the BLOCK-ENTRY token and append it to the queue. - token := yaml_token_t{ - typ: yaml_BLOCK_ENTRY_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the KEY token. -func yaml_parser_fetch_key(parser *yaml_parser_t) bool { - - // In the block context, additional checks are required. - if parser.flow_level == 0 { - // Check if we are allowed to start a new key (not nessesary simple). - if !parser.simple_key_allowed { - return yaml_parser_set_scanner_error(parser, "", parser.mark, - "mapping keys are not allowed in this context") - } - // Add the BLOCK-MAPPING-START token if needed. - if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { - return false - } - } - - // Reset any potential simple keys on the current flow level. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - // Simple keys are allowed after '?' in the block context. - parser.simple_key_allowed = parser.flow_level == 0 - - // Consume the token. - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the KEY token and append it to the queue. - token := yaml_token_t{ - typ: yaml_KEY_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the VALUE token. -func yaml_parser_fetch_value(parser *yaml_parser_t) bool { - - simple_key := &parser.simple_keys[len(parser.simple_keys)-1] - - // Have we found a simple key? - if valid, ok := yaml_simple_key_is_valid(parser, simple_key); !ok { - return false - - } else if valid { - - // Create the KEY token and insert it into the queue. - token := yaml_token_t{ - typ: yaml_KEY_TOKEN, - start_mark: simple_key.mark, - end_mark: simple_key.mark, - } - yaml_insert_token(parser, simple_key.token_number-parser.tokens_parsed, &token) - - // In the block context, we may need to add the BLOCK-MAPPING-START token. - if !yaml_parser_roll_indent(parser, simple_key.mark.column, - simple_key.token_number, - yaml_BLOCK_MAPPING_START_TOKEN, simple_key.mark) { - return false - } - - // Remove the simple key. - simple_key.possible = false - delete(parser.simple_keys_by_tok, simple_key.token_number) - - // A simple key cannot follow another simple key. - parser.simple_key_allowed = false - - } else { - // The ':' indicator follows a complex key. - - // In the block context, extra checks are required. - if parser.flow_level == 0 { - - // Check if we are allowed to start a complex value. - if !parser.simple_key_allowed { - return yaml_parser_set_scanner_error(parser, "", parser.mark, - "mapping values are not allowed in this context") - } - - // Add the BLOCK-MAPPING-START token if needed. - if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { - return false - } - } - - // Simple keys after ':' are allowed in the block context. - parser.simple_key_allowed = parser.flow_level == 0 - } - - // Consume the token. - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the VALUE token and append it to the queue. - token := yaml_token_t{ - typ: yaml_VALUE_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the ALIAS or ANCHOR token. -func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type_t) bool { - // An anchor or an alias could be a simple key. - if !yaml_parser_save_simple_key(parser) { - return false - } - - // A simple key cannot follow an anchor or an alias. - parser.simple_key_allowed = false - - // Create the ALIAS or ANCHOR token and append it to the queue. - var token yaml_token_t - if !yaml_parser_scan_anchor(parser, &token, typ) { - return false - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the TAG token. -func yaml_parser_fetch_tag(parser *yaml_parser_t) bool { - // A tag could be a simple key. - if !yaml_parser_save_simple_key(parser) { - return false - } - - // A simple key cannot follow a tag. - parser.simple_key_allowed = false - - // Create the TAG token and append it to the queue. - var token yaml_token_t - if !yaml_parser_scan_tag(parser, &token) { - return false - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens. -func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool) bool { - // Remove any potential simple keys. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - // A simple key may follow a block scalar. - parser.simple_key_allowed = true - - // Create the SCALAR token and append it to the queue. - var token yaml_token_t - if !yaml_parser_scan_block_scalar(parser, &token, literal) { - return false - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens. -func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) bool { - // A plain scalar could be a simple key. - if !yaml_parser_save_simple_key(parser) { - return false - } - - // A simple key cannot follow a flow scalar. - parser.simple_key_allowed = false - - // Create the SCALAR token and append it to the queue. - var token yaml_token_t - if !yaml_parser_scan_flow_scalar(parser, &token, single) { - return false - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the SCALAR(...,plain) token. -func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool { - // A plain scalar could be a simple key. - if !yaml_parser_save_simple_key(parser) { - return false - } - - // A simple key cannot follow a flow scalar. - parser.simple_key_allowed = false - - // Create the SCALAR token and append it to the queue. - var token yaml_token_t - if !yaml_parser_scan_plain_scalar(parser, &token) { - return false - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Eat whitespaces and comments until the next token is found. -func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool { - - scan_mark := parser.mark - - // Until the next token is not found. - for { - // Allow the BOM mark to start a line. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if parser.mark.column == 0 && is_bom(parser.buffer, parser.buffer_pos) { - skip(parser) - } - - // Eat whitespaces. - // Tabs are allowed: - // - in the flow context - // - in the block context, but not at the beginning of the line or - // after '-', '?', or ':' (complex value). - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Check if we just had a line comment under a sequence entry that - // looks more like a header to the following content. Similar to this: - // - // - # The comment - // - Some data - // - // If so, transform the line comment to a head comment and reposition. - if len(parser.comments) > 0 && len(parser.tokens) > 1 { - tokenA := parser.tokens[len(parser.tokens)-2] - tokenB := parser.tokens[len(parser.tokens)-1] - comment := &parser.comments[len(parser.comments)-1] - if tokenA.typ == yaml_BLOCK_SEQUENCE_START_TOKEN && tokenB.typ == yaml_BLOCK_ENTRY_TOKEN && len(comment.line) > 0 && !is_break(parser.buffer, parser.buffer_pos) { - // If it was in the prior line, reposition so it becomes a - // header of the follow up token. Otherwise, keep it in place - // so it becomes a header of the former. - comment.head = comment.line - comment.line = nil - if comment.start_mark.line == parser.mark.line-1 { - comment.token_mark = parser.mark - } - } - } - - // Eat a comment until a line break. - if parser.buffer[parser.buffer_pos] == '#' { - if !yaml_parser_scan_comments(parser, scan_mark) { - return false - } - } - - // If it is a line break, eat it. - if is_break(parser.buffer, parser.buffer_pos) { - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - skip_line(parser) - - // In the block context, a new line may start a simple key. - if parser.flow_level == 0 { - parser.simple_key_allowed = true - } - } else { - break // We have found a token. - } - } - - return true -} - -// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token. -// -// Scope: -// -// %YAML 1.1 # a comment \n -// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -// %TAG !yaml! tag:yaml.org,2002: \n -// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool { - // Eat '%'. - start_mark := parser.mark - skip(parser) - - // Scan the directive name. - var name []byte - if !yaml_parser_scan_directive_name(parser, start_mark, &name) { - return false - } - - // Is it a YAML directive? - if bytes.Equal(name, []byte("YAML")) { - // Scan the VERSION directive value. - var major, minor int8 - if !yaml_parser_scan_version_directive_value(parser, start_mark, &major, &minor) { - return false - } - end_mark := parser.mark - - // Create a VERSION-DIRECTIVE token. - *token = yaml_token_t{ - typ: yaml_VERSION_DIRECTIVE_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - major: major, - minor: minor, - } - - // Is it a TAG directive? - } else if bytes.Equal(name, []byte("TAG")) { - // Scan the TAG directive value. - var handle, prefix []byte - if !yaml_parser_scan_tag_directive_value(parser, start_mark, &handle, &prefix) { - return false - } - end_mark := parser.mark - - // Create a TAG-DIRECTIVE token. - *token = yaml_token_t{ - typ: yaml_TAG_DIRECTIVE_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - value: handle, - prefix: prefix, - } - - // Unknown directive. - } else { - yaml_parser_set_scanner_error(parser, "while scanning a directive", - start_mark, "found unknown directive name") - return false - } - - // Eat the rest of the line including any comments. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - for is_blank(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - if parser.buffer[parser.buffer_pos] == '#' { - // [Go] Discard this inline comment for the time being. - //if !yaml_parser_scan_line_comment(parser, start_mark) { - // return false - //} - for !is_breakz(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - } - - // Check if we are at the end of the line. - if !is_breakz(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a directive", - start_mark, "did not find expected comment or line break") - return false - } - - // Eat a line break. - if is_break(parser.buffer, parser.buffer_pos) { - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - skip_line(parser) - } - - return true -} - -// Scan the directive name. -// -// Scope: -// -// %YAML 1.1 # a comment \n -// ^^^^ -// %TAG !yaml! tag:yaml.org,2002: \n -// ^^^ -func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool { - // Consume the directive name. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - var s []byte - for is_alpha(parser.buffer, parser.buffer_pos) { - s = read(parser, s) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Check if the name is empty. - if len(s) == 0 { - yaml_parser_set_scanner_error(parser, "while scanning a directive", - start_mark, "could not find expected directive name") - return false - } - - // Check for an blank character after the name. - if !is_blankz(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a directive", - start_mark, "found unexpected non-alphabetical character") - return false - } - *name = s - return true -} - -// Scan the value of VERSION-DIRECTIVE. -// -// Scope: -// -// %YAML 1.1 # a comment \n -// ^^^^^^ -func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool { - // Eat whitespaces. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - for is_blank(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Consume the major version number. - if !yaml_parser_scan_version_directive_number(parser, start_mark, major) { - return false - } - - // Eat '.'. - if parser.buffer[parser.buffer_pos] != '.' { - return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", - start_mark, "did not find expected digit or '.' character") - } - - skip(parser) - - // Consume the minor version number. - if !yaml_parser_scan_version_directive_number(parser, start_mark, minor) { - return false - } - return true -} - -const max_number_length = 2 - -// Scan the version number of VERSION-DIRECTIVE. -// -// Scope: -// -// %YAML 1.1 # a comment \n -// ^ -// %YAML 1.1 # a comment \n -// ^ -func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool { - - // Repeat while the next character is digit. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - var value, length int8 - for is_digit(parser.buffer, parser.buffer_pos) { - // Check if the number is too long. - length++ - if length > max_number_length { - return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", - start_mark, "found extremely long version number") - } - value = value*10 + int8(as_digit(parser.buffer, parser.buffer_pos)) - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Check if the number was present. - if length == 0 { - return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", - start_mark, "did not find expected version number") - } - *number = value - return true -} - -// Scan the value of a TAG-DIRECTIVE token. -// -// Scope: -// -// %TAG !yaml! tag:yaml.org,2002: \n -// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool { - var handle_value, prefix_value []byte - - // Eat whitespaces. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - for is_blank(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Scan a handle. - if !yaml_parser_scan_tag_handle(parser, true, start_mark, &handle_value) { - return false - } - - // Expect a whitespace. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if !is_blank(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", - start_mark, "did not find expected whitespace") - return false - } - - // Eat whitespaces. - for is_blank(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Scan a prefix. - if !yaml_parser_scan_tag_uri(parser, true, nil, start_mark, &prefix_value) { - return false - } - - // Expect a whitespace or line break. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if !is_blankz(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", - start_mark, "did not find expected whitespace or line break") - return false - } - - *handle = handle_value - *prefix = prefix_value - return true -} - -func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t, typ yaml_token_type_t) bool { - var s []byte - - // Eat the indicator character. - start_mark := parser.mark - skip(parser) - - // Consume the value. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - for is_alpha(parser.buffer, parser.buffer_pos) { - s = read(parser, s) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - end_mark := parser.mark - - /* - * Check if length of the anchor is greater than 0 and it is followed by - * a whitespace character or one of the indicators: - * - * '?', ':', ',', ']', '}', '%', '@', '`'. - */ - - if len(s) == 0 || - !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' || - parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' || - parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' || - parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' || - parser.buffer[parser.buffer_pos] == '`') { - context := "while scanning an alias" - if typ == yaml_ANCHOR_TOKEN { - context = "while scanning an anchor" - } - yaml_parser_set_scanner_error(parser, context, start_mark, - "did not find expected alphabetic or numeric character") - return false - } - - // Create a token. - *token = yaml_token_t{ - typ: typ, - start_mark: start_mark, - end_mark: end_mark, - value: s, - } - - return true -} - -/* - * Scan a TAG token. - */ - -func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bool { - var handle, suffix []byte - - start_mark := parser.mark - - // Check if the tag is in the canonical form. - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - - if parser.buffer[parser.buffer_pos+1] == '<' { - // Keep the handle as '' - - // Eat '!<' - skip(parser) - skip(parser) - - // Consume the tag value. - if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { - return false - } - - // Check for '>' and eat it. - if parser.buffer[parser.buffer_pos] != '>' { - yaml_parser_set_scanner_error(parser, "while scanning a tag", - start_mark, "did not find the expected '>'") - return false - } - - skip(parser) - } else { - // The tag has either the '!suffix' or the '!handle!suffix' form. - - // First, try to scan a handle. - if !yaml_parser_scan_tag_handle(parser, false, start_mark, &handle) { - return false - } - - // Check if it is, indeed, handle. - if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' { - // Scan the suffix now. - if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { - return false - } - } else { - // It wasn't a handle after all. Scan the rest of the tag. - if !yaml_parser_scan_tag_uri(parser, false, handle, start_mark, &suffix) { - return false - } - - // Set the handle to '!'. - handle = []byte{'!'} - - // A special case: the '!' tag. Set the handle to '' and the - // suffix to '!'. - if len(suffix) == 0 { - handle, suffix = suffix, handle - } - } - } - - // Check the character which ends the tag. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if !is_blankz(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a tag", - start_mark, "did not find expected whitespace or line break") - return false - } - - end_mark := parser.mark - - // Create a token. - *token = yaml_token_t{ - typ: yaml_TAG_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - value: handle, - suffix: suffix, - } - return true -} - -// Scan a tag handle. -func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, handle *[]byte) bool { - // Check the initial '!' character. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if parser.buffer[parser.buffer_pos] != '!' { - yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "did not find expected '!'") - return false - } - - var s []byte - - // Copy the '!' character. - s = read(parser, s) - - // Copy all subsequent alphabetical and numerical characters. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - for is_alpha(parser.buffer, parser.buffer_pos) { - s = read(parser, s) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Check if the trailing character is '!' and copy it. - if parser.buffer[parser.buffer_pos] == '!' { - s = read(parser, s) - } else { - // It's either the '!' tag or not really a tag handle. If it's a %TAG - // directive, it's an error. If it's a tag token, it must be a part of URI. - if directive && string(s) != "!" { - yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "did not find expected '!'") - return false - } - } - - *handle = s - return true -} - -// Scan a tag. -func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool { - //size_t length = head ? strlen((char *)head) : 0 - var s []byte - hasTag := len(head) > 0 - - // Copy the head if needed. - // - // Note that we don't copy the leading '!' character. - if len(head) > 1 { - s = append(s, head[1:]...) - } - - // Scan the tag. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - // The set of characters that may appear in URI is as follows: - // - // '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&', - // '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']', - // '%'. - // [Go] TODO Convert this into more reasonable logic. - for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' || - parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' || - parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' || - parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '=' || - parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '$' || - parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '.' || - parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '~' || - parser.buffer[parser.buffer_pos] == '*' || parser.buffer[parser.buffer_pos] == '\'' || - parser.buffer[parser.buffer_pos] == '(' || parser.buffer[parser.buffer_pos] == ')' || - parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == ']' || - parser.buffer[parser.buffer_pos] == '%' { - // Check if it is a URI-escape sequence. - if parser.buffer[parser.buffer_pos] == '%' { - if !yaml_parser_scan_uri_escapes(parser, directive, start_mark, &s) { - return false - } - } else { - s = read(parser, s) - } - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - hasTag = true - } - - if !hasTag { - yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "did not find expected tag URI") - return false - } - *uri = s - return true -} - -// Decode an URI-escape sequence corresponding to a single UTF-8 character. -func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, s *[]byte) bool { - - // Decode the required number of characters. - w := 1024 - for w > 0 { - // Check for a URI-escaped octet. - if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { - return false - } - - if !(parser.buffer[parser.buffer_pos] == '%' && - is_hex(parser.buffer, parser.buffer_pos+1) && - is_hex(parser.buffer, parser.buffer_pos+2)) { - return yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "did not find URI escaped octet") - } - - // Get the octet. - octet := byte((as_hex(parser.buffer, parser.buffer_pos+1) << 4) + as_hex(parser.buffer, parser.buffer_pos+2)) - - // If it is the leading octet, determine the length of the UTF-8 sequence. - if w == 1024 { - w = width(octet) - if w == 0 { - return yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "found an incorrect leading UTF-8 octet") - } - } else { - // Check if the trailing octet is correct. - if octet&0xC0 != 0x80 { - return yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "found an incorrect trailing UTF-8 octet") - } - } - - // Copy the octet and move the pointers. - *s = append(*s, octet) - skip(parser) - skip(parser) - skip(parser) - w-- - } - return true -} - -// Scan a block scalar. -func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, literal bool) bool { - // Eat the indicator '|' or '>'. - start_mark := parser.mark - skip(parser) - - // Scan the additional block scalar indicators. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - // Check for a chomping indicator. - var chomping, increment int - if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { - // Set the chomping method and eat the indicator. - if parser.buffer[parser.buffer_pos] == '+' { - chomping = +1 - } else { - chomping = -1 - } - skip(parser) - - // Check for an indentation indicator. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if is_digit(parser.buffer, parser.buffer_pos) { - // Check that the indentation is greater than 0. - if parser.buffer[parser.buffer_pos] == '0' { - yaml_parser_set_scanner_error(parser, "while scanning a block scalar", - start_mark, "found an indentation indicator equal to 0") - return false - } - - // Get the indentation level and eat the indicator. - increment = as_digit(parser.buffer, parser.buffer_pos) - skip(parser) - } - - } else if is_digit(parser.buffer, parser.buffer_pos) { - // Do the same as above, but in the opposite order. - - if parser.buffer[parser.buffer_pos] == '0' { - yaml_parser_set_scanner_error(parser, "while scanning a block scalar", - start_mark, "found an indentation indicator equal to 0") - return false - } - increment = as_digit(parser.buffer, parser.buffer_pos) - skip(parser) - - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { - if parser.buffer[parser.buffer_pos] == '+' { - chomping = +1 - } else { - chomping = -1 - } - skip(parser) - } - } - - // Eat whitespaces and comments to the end of the line. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - for is_blank(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - if parser.buffer[parser.buffer_pos] == '#' { - if !yaml_parser_scan_line_comment(parser, start_mark) { - return false - } - for !is_breakz(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - } - - // Check if we are at the end of the line. - if !is_breakz(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a block scalar", - start_mark, "did not find expected comment or line break") - return false - } - - // Eat a line break. - if is_break(parser.buffer, parser.buffer_pos) { - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - skip_line(parser) - } - - end_mark := parser.mark - - // Set the indentation level if it was specified. - var indent int - if increment > 0 { - if parser.indent >= 0 { - indent = parser.indent + increment - } else { - indent = increment - } - } - - // Scan the leading line breaks and determine the indentation level if needed. - var s, leading_break, trailing_breaks []byte - if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { - return false - } - - // Scan the block scalar content. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - var leading_blank, trailing_blank bool - for parser.mark.column == indent && !is_z(parser.buffer, parser.buffer_pos) { - // We are at the beginning of a non-empty line. - - // Is it a trailing whitespace? - trailing_blank = is_blank(parser.buffer, parser.buffer_pos) - - // Check if we need to fold the leading line break. - if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' { - // Do we need to join the lines by space? - if len(trailing_breaks) == 0 { - s = append(s, ' ') - } - } else { - s = append(s, leading_break...) - } - leading_break = leading_break[:0] - - // Append the remaining line breaks. - s = append(s, trailing_breaks...) - trailing_breaks = trailing_breaks[:0] - - // Is it a leading whitespace? - leading_blank = is_blank(parser.buffer, parser.buffer_pos) - - // Consume the current line. - for !is_breakz(parser.buffer, parser.buffer_pos) { - s = read(parser, s) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Consume the line break. - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - - leading_break = read_line(parser, leading_break) - - // Eat the following indentation spaces and line breaks. - if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { - return false - } - } - - // Chomp the tail. - if chomping != -1 { - s = append(s, leading_break...) - } - if chomping == 1 { - s = append(s, trailing_breaks...) - } - - // Create a token. - *token = yaml_token_t{ - typ: yaml_SCALAR_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - value: s, - style: yaml_LITERAL_SCALAR_STYLE, - } - if !literal { - token.style = yaml_FOLDED_SCALAR_STYLE - } - return true -} - -// Scan indentation spaces and line breaks for a block scalar. Determine the -// indentation level if needed. -func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent *int, breaks *[]byte, start_mark yaml_mark_t, end_mark *yaml_mark_t) bool { - *end_mark = parser.mark - - // Eat the indentation spaces and line breaks. - max_indent := 0 - for { - // Eat the indentation spaces. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - for (*indent == 0 || parser.mark.column < *indent) && is_space(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - if parser.mark.column > max_indent { - max_indent = parser.mark.column - } - - // Check for a tab character messing the indentation. - if (*indent == 0 || parser.mark.column < *indent) && is_tab(parser.buffer, parser.buffer_pos) { - return yaml_parser_set_scanner_error(parser, "while scanning a block scalar", - start_mark, "found a tab character where an indentation space is expected") - } - - // Have we found a non-empty line? - if !is_break(parser.buffer, parser.buffer_pos) { - break - } - - // Consume the line break. - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - // [Go] Should really be returning breaks instead. - *breaks = read_line(parser, *breaks) - *end_mark = parser.mark - } - - // Determine the indentation level if needed. - if *indent == 0 { - *indent = max_indent - if *indent < parser.indent+1 { - *indent = parser.indent + 1 - } - if *indent < 1 { - *indent = 1 - } - } - return true -} - -// Scan a quoted scalar. -func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, single bool) bool { - // Eat the left quote. - start_mark := parser.mark - skip(parser) - - // Consume the content of the quoted scalar. - var s, leading_break, trailing_breaks, whitespaces []byte - for { - // Check that there are no document indicators at the beginning of the line. - if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { - return false - } - - if parser.mark.column == 0 && - ((parser.buffer[parser.buffer_pos+0] == '-' && - parser.buffer[parser.buffer_pos+1] == '-' && - parser.buffer[parser.buffer_pos+2] == '-') || - (parser.buffer[parser.buffer_pos+0] == '.' && - parser.buffer[parser.buffer_pos+1] == '.' && - parser.buffer[parser.buffer_pos+2] == '.')) && - is_blankz(parser.buffer, parser.buffer_pos+3) { - yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", - start_mark, "found unexpected document indicator") - return false - } - - // Check for EOF. - if is_z(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", - start_mark, "found unexpected end of stream") - return false - } - - // Consume non-blank characters. - leading_blanks := false - for !is_blankz(parser.buffer, parser.buffer_pos) { - if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' { - // Is is an escaped single quote. - s = append(s, '\'') - skip(parser) - skip(parser) - - } else if single && parser.buffer[parser.buffer_pos] == '\'' { - // It is a right single quote. - break - } else if !single && parser.buffer[parser.buffer_pos] == '"' { - // It is a right double quote. - break - - } else if !single && parser.buffer[parser.buffer_pos] == '\\' && is_break(parser.buffer, parser.buffer_pos+1) { - // It is an escaped line break. - if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { - return false - } - skip(parser) - skip_line(parser) - leading_blanks = true - break - - } else if !single && parser.buffer[parser.buffer_pos] == '\\' { - // It is an escape sequence. - code_length := 0 - - // Check the escape character. - switch parser.buffer[parser.buffer_pos+1] { - case '0': - s = append(s, 0) - case 'a': - s = append(s, '\x07') - case 'b': - s = append(s, '\x08') - case 't', '\t': - s = append(s, '\x09') - case 'n': - s = append(s, '\x0A') - case 'v': - s = append(s, '\x0B') - case 'f': - s = append(s, '\x0C') - case 'r': - s = append(s, '\x0D') - case 'e': - s = append(s, '\x1B') - case ' ': - s = append(s, '\x20') - case '"': - s = append(s, '"') - case '\'': - s = append(s, '\'') - case '\\': - s = append(s, '\\') - case 'N': // NEL (#x85) - s = append(s, '\xC2') - s = append(s, '\x85') - case '_': // #xA0 - s = append(s, '\xC2') - s = append(s, '\xA0') - case 'L': // LS (#x2028) - s = append(s, '\xE2') - s = append(s, '\x80') - s = append(s, '\xA8') - case 'P': // PS (#x2029) - s = append(s, '\xE2') - s = append(s, '\x80') - s = append(s, '\xA9') - case 'x': - code_length = 2 - case 'u': - code_length = 4 - case 'U': - code_length = 8 - default: - yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", - start_mark, "found unknown escape character") - return false - } - - skip(parser) - skip(parser) - - // Consume an arbitrary escape code. - if code_length > 0 { - var value int - - // Scan the character value. - if parser.unread < code_length && !yaml_parser_update_buffer(parser, code_length) { - return false - } - for k := 0; k < code_length; k++ { - if !is_hex(parser.buffer, parser.buffer_pos+k) { - yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", - start_mark, "did not find expected hexdecimal number") - return false - } - value = (value << 4) + as_hex(parser.buffer, parser.buffer_pos+k) - } - - // Check the value and write the character. - if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF { - yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", - start_mark, "found invalid Unicode character escape code") - return false - } - if value <= 0x7F { - s = append(s, byte(value)) - } else if value <= 0x7FF { - s = append(s, byte(0xC0+(value>>6))) - s = append(s, byte(0x80+(value&0x3F))) - } else if value <= 0xFFFF { - s = append(s, byte(0xE0+(value>>12))) - s = append(s, byte(0x80+((value>>6)&0x3F))) - s = append(s, byte(0x80+(value&0x3F))) - } else { - s = append(s, byte(0xF0+(value>>18))) - s = append(s, byte(0x80+((value>>12)&0x3F))) - s = append(s, byte(0x80+((value>>6)&0x3F))) - s = append(s, byte(0x80+(value&0x3F))) - } - - // Advance the pointer. - for k := 0; k < code_length; k++ { - skip(parser) - } - } - } else { - // It is a non-escaped non-blank character. - s = read(parser, s) - } - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - } - - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - // Check if we are at the end of the scalar. - if single { - if parser.buffer[parser.buffer_pos] == '\'' { - break - } - } else { - if parser.buffer[parser.buffer_pos] == '"' { - break - } - } - - // Consume blank characters. - for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { - if is_blank(parser.buffer, parser.buffer_pos) { - // Consume a space or a tab character. - if !leading_blanks { - whitespaces = read(parser, whitespaces) - } else { - skip(parser) - } - } else { - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - - // Check if it is a first line break. - if !leading_blanks { - whitespaces = whitespaces[:0] - leading_break = read_line(parser, leading_break) - leading_blanks = true - } else { - trailing_breaks = read_line(parser, trailing_breaks) - } - } - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Join the whitespaces or fold line breaks. - if leading_blanks { - // Do we need to fold line breaks? - if len(leading_break) > 0 && leading_break[0] == '\n' { - if len(trailing_breaks) == 0 { - s = append(s, ' ') - } else { - s = append(s, trailing_breaks...) - } - } else { - s = append(s, leading_break...) - s = append(s, trailing_breaks...) - } - trailing_breaks = trailing_breaks[:0] - leading_break = leading_break[:0] - } else { - s = append(s, whitespaces...) - whitespaces = whitespaces[:0] - } - } - - // Eat the right quote. - skip(parser) - end_mark := parser.mark - - // Create a token. - *token = yaml_token_t{ - typ: yaml_SCALAR_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - value: s, - style: yaml_SINGLE_QUOTED_SCALAR_STYLE, - } - if !single { - token.style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - return true -} - -// Scan a plain scalar. -func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) bool { - - var s, leading_break, trailing_breaks, whitespaces []byte - var leading_blanks bool - var indent = parser.indent + 1 - - start_mark := parser.mark - end_mark := parser.mark - - // Consume the content of the plain scalar. - for { - // Check for a document indicator. - if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { - return false - } - if parser.mark.column == 0 && - ((parser.buffer[parser.buffer_pos+0] == '-' && - parser.buffer[parser.buffer_pos+1] == '-' && - parser.buffer[parser.buffer_pos+2] == '-') || - (parser.buffer[parser.buffer_pos+0] == '.' && - parser.buffer[parser.buffer_pos+1] == '.' && - parser.buffer[parser.buffer_pos+2] == '.')) && - is_blankz(parser.buffer, parser.buffer_pos+3) { - break - } - - // Check for a comment. - if parser.buffer[parser.buffer_pos] == '#' { - break - } - - // Consume non-blank characters. - for !is_blankz(parser.buffer, parser.buffer_pos) { - - // Check for indicators that may end a plain scalar. - if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) || - (parser.flow_level > 0 && - (parser.buffer[parser.buffer_pos] == ',' || - parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' || - parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || - parser.buffer[parser.buffer_pos] == '}')) { - break - } - - // Check if we need to join whitespaces and breaks. - if leading_blanks || len(whitespaces) > 0 { - if leading_blanks { - // Do we need to fold line breaks? - if leading_break[0] == '\n' { - if len(trailing_breaks) == 0 { - s = append(s, ' ') - } else { - s = append(s, trailing_breaks...) - } - } else { - s = append(s, leading_break...) - s = append(s, trailing_breaks...) - } - trailing_breaks = trailing_breaks[:0] - leading_break = leading_break[:0] - leading_blanks = false - } else { - s = append(s, whitespaces...) - whitespaces = whitespaces[:0] - } - } - - // Copy the character. - s = read(parser, s) - - end_mark = parser.mark - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - } - - // Is it the end? - if !(is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos)) { - break - } - - // Consume blank characters. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { - if is_blank(parser.buffer, parser.buffer_pos) { - - // Check for tab characters that abuse indentation. - if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", - start_mark, "found a tab character that violates indentation") - return false - } - - // Consume a space or a tab character. - if !leading_blanks { - whitespaces = read(parser, whitespaces) - } else { - skip(parser) - } - } else { - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - - // Check if it is a first line break. - if !leading_blanks { - whitespaces = whitespaces[:0] - leading_break = read_line(parser, leading_break) - leading_blanks = true - } else { - trailing_breaks = read_line(parser, trailing_breaks) - } - } - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Check indentation level. - if parser.flow_level == 0 && parser.mark.column < indent { - break - } - } - - // Create a token. - *token = yaml_token_t{ - typ: yaml_SCALAR_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - value: s, - style: yaml_PLAIN_SCALAR_STYLE, - } - - // Note that we change the 'simple_key_allowed' flag. - if leading_blanks { - parser.simple_key_allowed = true - } - return true -} - -func yaml_parser_scan_line_comment(parser *yaml_parser_t, token_mark yaml_mark_t) bool { - if parser.newlines > 0 { - return true - } - - var start_mark yaml_mark_t - var text []byte - - for peek := 0; peek < 512; peek++ { - if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) { - break - } - if is_blank(parser.buffer, parser.buffer_pos+peek) { - continue - } - if parser.buffer[parser.buffer_pos+peek] == '#' { - seen := parser.mark.index + peek - for { - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if is_breakz(parser.buffer, parser.buffer_pos) { - if parser.mark.index >= seen { - break - } - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - skip_line(parser) - } else if parser.mark.index >= seen { - if len(text) == 0 { - start_mark = parser.mark - } - text = read(parser, text) - } else { - skip(parser) - } - } - } - break - } - if len(text) > 0 { - parser.comments = append(parser.comments, yaml_comment_t{ - token_mark: token_mark, - start_mark: start_mark, - line: text, - }) - } - return true -} - -func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) bool { - token := parser.tokens[len(parser.tokens)-1] - - if token.typ == yaml_FLOW_ENTRY_TOKEN && len(parser.tokens) > 1 { - token = parser.tokens[len(parser.tokens)-2] - } - - var token_mark = token.start_mark - var start_mark yaml_mark_t - var next_indent = parser.indent - if next_indent < 0 { - next_indent = 0 - } - - var recent_empty = false - var first_empty = parser.newlines <= 1 - - var line = parser.mark.line - var column = parser.mark.column - - var text []byte - - // The foot line is the place where a comment must start to - // still be considered as a foot of the prior content. - // If there's some content in the currently parsed line, then - // the foot is the line below it. - var foot_line = -1 - if scan_mark.line > 0 { - foot_line = parser.mark.line - parser.newlines + 1 - if parser.newlines == 0 && parser.mark.column > 1 { - foot_line++ - } - } - - var peek = 0 - for ; peek < 512; peek++ { - if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) { - break - } - column++ - if is_blank(parser.buffer, parser.buffer_pos+peek) { - continue - } - c := parser.buffer[parser.buffer_pos+peek] - var close_flow = parser.flow_level > 0 && (c == ']' || c == '}') - if close_flow || is_breakz(parser.buffer, parser.buffer_pos+peek) { - // Got line break or terminator. - if close_flow || !recent_empty { - if close_flow || first_empty && (start_mark.line == foot_line && token.typ != yaml_VALUE_TOKEN || start_mark.column-1 < next_indent) { - // This is the first empty line and there were no empty lines before, - // so this initial part of the comment is a foot of the prior token - // instead of being a head for the following one. Split it up. - // Alternatively, this might also be the last comment inside a flow - // scope, so it must be a footer. - if len(text) > 0 { - if start_mark.column-1 < next_indent { - // If dedented it's unrelated to the prior token. - token_mark = start_mark - } - parser.comments = append(parser.comments, yaml_comment_t{ - scan_mark: scan_mark, - token_mark: token_mark, - start_mark: start_mark, - end_mark: yaml_mark_t{parser.mark.index + peek, line, column}, - foot: text, - }) - scan_mark = yaml_mark_t{parser.mark.index + peek, line, column} - token_mark = scan_mark - text = nil - } - } else { - if len(text) > 0 && parser.buffer[parser.buffer_pos+peek] != 0 { - text = append(text, '\n') - } - } - } - if !is_break(parser.buffer, parser.buffer_pos+peek) { - break - } - first_empty = false - recent_empty = true - column = 0 - line++ - continue - } - - if len(text) > 0 && (close_flow || column-1 < next_indent && column != start_mark.column) { - // The comment at the different indentation is a foot of the - // preceding data rather than a head of the upcoming one. - parser.comments = append(parser.comments, yaml_comment_t{ - scan_mark: scan_mark, - token_mark: token_mark, - start_mark: start_mark, - end_mark: yaml_mark_t{parser.mark.index + peek, line, column}, - foot: text, - }) - scan_mark = yaml_mark_t{parser.mark.index + peek, line, column} - token_mark = scan_mark - text = nil - } - - if parser.buffer[parser.buffer_pos+peek] != '#' { - break - } - - if len(text) == 0 { - start_mark = yaml_mark_t{parser.mark.index + peek, line, column} - } else { - text = append(text, '\n') - } - - recent_empty = false - - // Consume until after the consumed comment line. - seen := parser.mark.index + peek - for { - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if is_breakz(parser.buffer, parser.buffer_pos) { - if parser.mark.index >= seen { - break - } - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - skip_line(parser) - } else if parser.mark.index >= seen { - text = read(parser, text) - } else { - skip(parser) - } - } - - peek = 0 - column = 0 - line = parser.mark.line - next_indent = parser.indent - if next_indent < 0 { - next_indent = 0 - } - } - - if len(text) > 0 { - parser.comments = append(parser.comments, yaml_comment_t{ - scan_mark: scan_mark, - token_mark: start_mark, - start_mark: start_mark, - end_mark: yaml_mark_t{parser.mark.index + peek - 1, line, column}, - head: text, - }) - } - return true -} diff --git a/go/sdk/vendor/gopkg.in/yaml.v3/sorter.go b/go/sdk/vendor/gopkg.in/yaml.v3/sorter.go deleted file mode 100644 index 9210ece..0000000 --- a/go/sdk/vendor/gopkg.in/yaml.v3/sorter.go +++ /dev/null @@ -1,134 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package yaml - -import ( - "reflect" - "unicode" -) - -type keyList []reflect.Value - -func (l keyList) Len() int { return len(l) } -func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } -func (l keyList) Less(i, j int) bool { - a := l[i] - b := l[j] - ak := a.Kind() - bk := b.Kind() - for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() { - a = a.Elem() - ak = a.Kind() - } - for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() { - b = b.Elem() - bk = b.Kind() - } - af, aok := keyFloat(a) - bf, bok := keyFloat(b) - if aok && bok { - if af != bf { - return af < bf - } - if ak != bk { - return ak < bk - } - return numLess(a, b) - } - if ak != reflect.String || bk != reflect.String { - return ak < bk - } - ar, br := []rune(a.String()), []rune(b.String()) - digits := false - for i := 0; i < len(ar) && i < len(br); i++ { - if ar[i] == br[i] { - digits = unicode.IsDigit(ar[i]) - continue - } - al := unicode.IsLetter(ar[i]) - bl := unicode.IsLetter(br[i]) - if al && bl { - return ar[i] < br[i] - } - if al || bl { - if digits { - return al - } else { - return bl - } - } - var ai, bi int - var an, bn int64 - if ar[i] == '0' || br[i] == '0' { - for j := i - 1; j >= 0 && unicode.IsDigit(ar[j]); j-- { - if ar[j] != '0' { - an = 1 - bn = 1 - break - } - } - } - for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { - an = an*10 + int64(ar[ai]-'0') - } - for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ { - bn = bn*10 + int64(br[bi]-'0') - } - if an != bn { - return an < bn - } - if ai != bi { - return ai < bi - } - return ar[i] < br[i] - } - return len(ar) < len(br) -} - -// keyFloat returns a float value for v if it is a number/bool -// and whether it is a number/bool or not. -func keyFloat(v reflect.Value) (f float64, ok bool) { - switch v.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return float64(v.Int()), true - case reflect.Float32, reflect.Float64: - return v.Float(), true - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return float64(v.Uint()), true - case reflect.Bool: - if v.Bool() { - return 1, true - } - return 0, true - } - return 0, false -} - -// numLess returns whether a < b. -// a and b must necessarily have the same kind. -func numLess(a, b reflect.Value) bool { - switch a.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return a.Int() < b.Int() - case reflect.Float32, reflect.Float64: - return a.Float() < b.Float() - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return a.Uint() < b.Uint() - case reflect.Bool: - return !a.Bool() && b.Bool() - } - panic("not a number") -} diff --git a/go/sdk/vendor/gopkg.in/yaml.v3/writerc.go b/go/sdk/vendor/gopkg.in/yaml.v3/writerc.go deleted file mode 100644 index 266d0b0..0000000 --- a/go/sdk/vendor/gopkg.in/yaml.v3/writerc.go +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -// of the Software, and to permit persons to whom the Software is furnished to do -// so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -package yaml - -// Set the writer error and return false. -func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool { - emitter.error = yaml_WRITER_ERROR - emitter.problem = problem - return false -} - -// Flush the output buffer. -func yaml_emitter_flush(emitter *yaml_emitter_t) bool { - if emitter.write_handler == nil { - panic("write handler not set") - } - - // Check if the buffer is empty. - if emitter.buffer_pos == 0 { - return true - } - - if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { - return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) - } - emitter.buffer_pos = 0 - return true -} diff --git a/go/sdk/vendor/gopkg.in/yaml.v3/yaml.go b/go/sdk/vendor/gopkg.in/yaml.v3/yaml.go deleted file mode 100644 index f0bedf3..0000000 --- a/go/sdk/vendor/gopkg.in/yaml.v3/yaml.go +++ /dev/null @@ -1,693 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package yaml implements YAML support for the Go language. -// -// Source code and other details for the project are available at GitHub: -// -// https://github.com/go-yaml/yaml -package yaml - -import ( - "errors" - "fmt" - "io" - "reflect" - "strings" - "sync" - "unicode/utf8" -) - -// The Unmarshaler interface may be implemented by types to customize their -// behavior when being unmarshaled from a YAML document. -type Unmarshaler interface { - UnmarshalYAML(value *Node) error -} - -type obsoleteUnmarshaler interface { - UnmarshalYAML(unmarshal func(interface{}) error) error -} - -// The Marshaler interface may be implemented by types to customize their -// behavior when being marshaled into a YAML document. The returned value -// is marshaled in place of the original value implementing Marshaler. -// -// If an error is returned by MarshalYAML, the marshaling procedure stops -// and returns with the provided error. -type Marshaler interface { - MarshalYAML() (interface{}, error) -} - -// Unmarshal decodes the first document found within the in byte slice -// and assigns decoded values into the out value. -// -// Maps and pointers (to a struct, string, int, etc) are accepted as out -// values. If an internal pointer within a struct is not initialized, -// the yaml package will initialize it if necessary for unmarshalling -// the provided data. The out parameter must not be nil. -// -// The type of the decoded values should be compatible with the respective -// values in out. If one or more values cannot be decoded due to a type -// mismatches, decoding continues partially until the end of the YAML -// content, and a *yaml.TypeError is returned with details for all -// missed values. -// -// Struct fields are only unmarshalled if they are exported (have an -// upper case first letter), and are unmarshalled using the field name -// lowercased as the default key. Custom keys may be defined via the -// "yaml" name in the field tag: the content preceding the first comma -// is used as the key, and the following comma-separated options are -// used to tweak the marshalling process (see Marshal). -// Conflicting names result in a runtime error. -// -// For example: -// -// type T struct { -// F int `yaml:"a,omitempty"` -// B int -// } -// var t T -// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t) -// -// See the documentation of Marshal for the format of tags and a list of -// supported tag options. -func Unmarshal(in []byte, out interface{}) (err error) { - return unmarshal(in, out, false) -} - -// A Decoder reads and decodes YAML values from an input stream. -type Decoder struct { - parser *parser - knownFields bool -} - -// NewDecoder returns a new decoder that reads from r. -// -// The decoder introduces its own buffering and may read -// data from r beyond the YAML values requested. -func NewDecoder(r io.Reader) *Decoder { - return &Decoder{ - parser: newParserFromReader(r), - } -} - -// KnownFields ensures that the keys in decoded mappings to -// exist as fields in the struct being decoded into. -func (dec *Decoder) KnownFields(enable bool) { - dec.knownFields = enable -} - -// Decode reads the next YAML-encoded value from its input -// and stores it in the value pointed to by v. -// -// See the documentation for Unmarshal for details about the -// conversion of YAML into a Go value. -func (dec *Decoder) Decode(v interface{}) (err error) { - d := newDecoder() - d.knownFields = dec.knownFields - defer handleErr(&err) - node := dec.parser.parse() - if node == nil { - return io.EOF - } - out := reflect.ValueOf(v) - if out.Kind() == reflect.Ptr && !out.IsNil() { - out = out.Elem() - } - d.unmarshal(node, out) - if len(d.terrors) > 0 { - return &TypeError{d.terrors} - } - return nil -} - -// Decode decodes the node and stores its data into the value pointed to by v. -// -// See the documentation for Unmarshal for details about the -// conversion of YAML into a Go value. -func (n *Node) Decode(v interface{}) (err error) { - d := newDecoder() - defer handleErr(&err) - out := reflect.ValueOf(v) - if out.Kind() == reflect.Ptr && !out.IsNil() { - out = out.Elem() - } - d.unmarshal(n, out) - if len(d.terrors) > 0 { - return &TypeError{d.terrors} - } - return nil -} - -func unmarshal(in []byte, out interface{}, strict bool) (err error) { - defer handleErr(&err) - d := newDecoder() - p := newParser(in) - defer p.destroy() - node := p.parse() - if node != nil { - v := reflect.ValueOf(out) - if v.Kind() == reflect.Ptr && !v.IsNil() { - v = v.Elem() - } - d.unmarshal(node, v) - } - if len(d.terrors) > 0 { - return &TypeError{d.terrors} - } - return nil -} - -// Marshal serializes the value provided into a YAML document. The structure -// of the generated document will reflect the structure of the value itself. -// Maps and pointers (to struct, string, int, etc) are accepted as the in value. -// -// Struct fields are only marshalled if they are exported (have an upper case -// first letter), and are marshalled using the field name lowercased as the -// default key. Custom keys may be defined via the "yaml" name in the field -// tag: the content preceding the first comma is used as the key, and the -// following comma-separated options are used to tweak the marshalling process. -// Conflicting names result in a runtime error. -// -// The field tag format accepted is: -// -// `(...) yaml:"[][,[,]]" (...)` -// -// The following flags are currently supported: -// -// omitempty Only include the field if it's not set to the zero -// value for the type or to empty slices or maps. -// Zero valued structs will be omitted if all their public -// fields are zero, unless they implement an IsZero -// method (see the IsZeroer interface type), in which -// case the field will be excluded if IsZero returns true. -// -// flow Marshal using a flow style (useful for structs, -// sequences and maps). -// -// inline Inline the field, which must be a struct or a map, -// causing all of its fields or keys to be processed as if -// they were part of the outer struct. For maps, keys must -// not conflict with the yaml keys of other struct fields. -// -// In addition, if the key is "-", the field is ignored. -// -// For example: -// -// type T struct { -// F int `yaml:"a,omitempty"` -// B int -// } -// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n" -// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n" -func Marshal(in interface{}) (out []byte, err error) { - defer handleErr(&err) - e := newEncoder() - defer e.destroy() - e.marshalDoc("", reflect.ValueOf(in)) - e.finish() - out = e.out - return -} - -// An Encoder writes YAML values to an output stream. -type Encoder struct { - encoder *encoder -} - -// NewEncoder returns a new encoder that writes to w. -// The Encoder should be closed after use to flush all data -// to w. -func NewEncoder(w io.Writer) *Encoder { - return &Encoder{ - encoder: newEncoderWithWriter(w), - } -} - -// Encode writes the YAML encoding of v to the stream. -// If multiple items are encoded to the stream, the -// second and subsequent document will be preceded -// with a "---" document separator, but the first will not. -// -// See the documentation for Marshal for details about the conversion of Go -// values to YAML. -func (e *Encoder) Encode(v interface{}) (err error) { - defer handleErr(&err) - e.encoder.marshalDoc("", reflect.ValueOf(v)) - return nil -} - -// Encode encodes value v and stores its representation in n. -// -// See the documentation for Marshal for details about the -// conversion of Go values into YAML. -func (n *Node) Encode(v interface{}) (err error) { - defer handleErr(&err) - e := newEncoder() - defer e.destroy() - e.marshalDoc("", reflect.ValueOf(v)) - e.finish() - p := newParser(e.out) - p.textless = true - defer p.destroy() - doc := p.parse() - *n = *doc.Content[0] - return nil -} - -// SetIndent changes the used indentation used when encoding. -func (e *Encoder) SetIndent(spaces int) { - if spaces < 0 { - panic("yaml: cannot indent to a negative number of spaces") - } - e.encoder.indent = spaces -} - -// Close closes the encoder by writing any remaining data. -// It does not write a stream terminating string "...". -func (e *Encoder) Close() (err error) { - defer handleErr(&err) - e.encoder.finish() - return nil -} - -func handleErr(err *error) { - if v := recover(); v != nil { - if e, ok := v.(yamlError); ok { - *err = e.err - } else { - panic(v) - } - } -} - -type yamlError struct { - err error -} - -func fail(err error) { - panic(yamlError{err}) -} - -func failf(format string, args ...interface{}) { - panic(yamlError{fmt.Errorf("yaml: "+format, args...)}) -} - -// A TypeError is returned by Unmarshal when one or more fields in -// the YAML document cannot be properly decoded into the requested -// types. When this error is returned, the value is still -// unmarshaled partially. -type TypeError struct { - Errors []string -} - -func (e *TypeError) Error() string { - return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n ")) -} - -type Kind uint32 - -const ( - DocumentNode Kind = 1 << iota - SequenceNode - MappingNode - ScalarNode - AliasNode -) - -type Style uint32 - -const ( - TaggedStyle Style = 1 << iota - DoubleQuotedStyle - SingleQuotedStyle - LiteralStyle - FoldedStyle - FlowStyle -) - -// Node represents an element in the YAML document hierarchy. While documents -// are typically encoded and decoded into higher level types, such as structs -// and maps, Node is an intermediate representation that allows detailed -// control over the content being decoded or encoded. -// -// It's worth noting that although Node offers access into details such as -// line numbers, colums, and comments, the content when re-encoded will not -// have its original textual representation preserved. An effort is made to -// render the data plesantly, and to preserve comments near the data they -// describe, though. -// -// Values that make use of the Node type interact with the yaml package in the -// same way any other type would do, by encoding and decoding yaml data -// directly or indirectly into them. -// -// For example: -// -// var person struct { -// Name string -// Address yaml.Node -// } -// err := yaml.Unmarshal(data, &person) -// -// Or by itself: -// -// var person Node -// err := yaml.Unmarshal(data, &person) -type Node struct { - // Kind defines whether the node is a document, a mapping, a sequence, - // a scalar value, or an alias to another node. The specific data type of - // scalar nodes may be obtained via the ShortTag and LongTag methods. - Kind Kind - - // Style allows customizing the apperance of the node in the tree. - Style Style - - // Tag holds the YAML tag defining the data type for the value. - // When decoding, this field will always be set to the resolved tag, - // even when it wasn't explicitly provided in the YAML content. - // When encoding, if this field is unset the value type will be - // implied from the node properties, and if it is set, it will only - // be serialized into the representation if TaggedStyle is used or - // the implicit tag diverges from the provided one. - Tag string - - // Value holds the unescaped and unquoted represenation of the value. - Value string - - // Anchor holds the anchor name for this node, which allows aliases to point to it. - Anchor string - - // Alias holds the node that this alias points to. Only valid when Kind is AliasNode. - Alias *Node - - // Content holds contained nodes for documents, mappings, and sequences. - Content []*Node - - // HeadComment holds any comments in the lines preceding the node and - // not separated by an empty line. - HeadComment string - - // LineComment holds any comments at the end of the line where the node is in. - LineComment string - - // FootComment holds any comments following the node and before empty lines. - FootComment string - - // Line and Column hold the node position in the decoded YAML text. - // These fields are not respected when encoding the node. - Line int - Column int -} - -// IsZero returns whether the node has all of its fields unset. -func (n *Node) IsZero() bool { - return n.Kind == 0 && n.Style == 0 && n.Tag == "" && n.Value == "" && n.Anchor == "" && n.Alias == nil && n.Content == nil && - n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0 -} - -// LongTag returns the long form of the tag that indicates the data type for -// the node. If the Tag field isn't explicitly defined, one will be computed -// based on the node properties. -func (n *Node) LongTag() string { - return longTag(n.ShortTag()) -} - -// ShortTag returns the short form of the YAML tag that indicates data type for -// the node. If the Tag field isn't explicitly defined, one will be computed -// based on the node properties. -func (n *Node) ShortTag() string { - if n.indicatedString() { - return strTag - } - if n.Tag == "" || n.Tag == "!" { - switch n.Kind { - case MappingNode: - return mapTag - case SequenceNode: - return seqTag - case AliasNode: - if n.Alias != nil { - return n.Alias.ShortTag() - } - case ScalarNode: - tag, _ := resolve("", n.Value) - return tag - case 0: - // Special case to make the zero value convenient. - if n.IsZero() { - return nullTag - } - } - return "" - } - return shortTag(n.Tag) -} - -func (n *Node) indicatedString() bool { - return n.Kind == ScalarNode && - (shortTag(n.Tag) == strTag || - (n.Tag == "" || n.Tag == "!") && n.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0) -} - -// SetString is a convenience function that sets the node to a string value -// and defines its style in a pleasant way depending on its content. -func (n *Node) SetString(s string) { - n.Kind = ScalarNode - if utf8.ValidString(s) { - n.Value = s - n.Tag = strTag - } else { - n.Value = encodeBase64(s) - n.Tag = binaryTag - } - if strings.Contains(n.Value, "\n") { - n.Style = LiteralStyle - } -} - -// -------------------------------------------------------------------------- -// Maintain a mapping of keys to structure field indexes - -// The code in this section was copied from mgo/bson. - -// structInfo holds details for the serialization of fields of -// a given struct. -type structInfo struct { - FieldsMap map[string]fieldInfo - FieldsList []fieldInfo - - // InlineMap is the number of the field in the struct that - // contains an ,inline map, or -1 if there's none. - InlineMap int - - // InlineUnmarshalers holds indexes to inlined fields that - // contain unmarshaler values. - InlineUnmarshalers [][]int -} - -type fieldInfo struct { - Key string - Num int - OmitEmpty bool - Flow bool - // Id holds the unique field identifier, so we can cheaply - // check for field duplicates without maintaining an extra map. - Id int - - // Inline holds the field index if the field is part of an inlined struct. - Inline []int -} - -var structMap = make(map[reflect.Type]*structInfo) -var fieldMapMutex sync.RWMutex -var unmarshalerType reflect.Type - -func init() { - var v Unmarshaler - unmarshalerType = reflect.ValueOf(&v).Elem().Type() -} - -func getStructInfo(st reflect.Type) (*structInfo, error) { - fieldMapMutex.RLock() - sinfo, found := structMap[st] - fieldMapMutex.RUnlock() - if found { - return sinfo, nil - } - - n := st.NumField() - fieldsMap := make(map[string]fieldInfo) - fieldsList := make([]fieldInfo, 0, n) - inlineMap := -1 - inlineUnmarshalers := [][]int(nil) - for i := 0; i != n; i++ { - field := st.Field(i) - if field.PkgPath != "" && !field.Anonymous { - continue // Private field - } - - info := fieldInfo{Num: i} - - tag := field.Tag.Get("yaml") - if tag == "" && strings.Index(string(field.Tag), ":") < 0 { - tag = string(field.Tag) - } - if tag == "-" { - continue - } - - inline := false - fields := strings.Split(tag, ",") - if len(fields) > 1 { - for _, flag := range fields[1:] { - switch flag { - case "omitempty": - info.OmitEmpty = true - case "flow": - info.Flow = true - case "inline": - inline = true - default: - return nil, errors.New(fmt.Sprintf("unsupported flag %q in tag %q of type %s", flag, tag, st)) - } - } - tag = fields[0] - } - - if inline { - switch field.Type.Kind() { - case reflect.Map: - if inlineMap >= 0 { - return nil, errors.New("multiple ,inline maps in struct " + st.String()) - } - if field.Type.Key() != reflect.TypeOf("") { - return nil, errors.New("option ,inline needs a map with string keys in struct " + st.String()) - } - inlineMap = info.Num - case reflect.Struct, reflect.Ptr: - ftype := field.Type - for ftype.Kind() == reflect.Ptr { - ftype = ftype.Elem() - } - if ftype.Kind() != reflect.Struct { - return nil, errors.New("option ,inline may only be used on a struct or map field") - } - if reflect.PtrTo(ftype).Implements(unmarshalerType) { - inlineUnmarshalers = append(inlineUnmarshalers, []int{i}) - } else { - sinfo, err := getStructInfo(ftype) - if err != nil { - return nil, err - } - for _, index := range sinfo.InlineUnmarshalers { - inlineUnmarshalers = append(inlineUnmarshalers, append([]int{i}, index...)) - } - for _, finfo := range sinfo.FieldsList { - if _, found := fieldsMap[finfo.Key]; found { - msg := "duplicated key '" + finfo.Key + "' in struct " + st.String() - return nil, errors.New(msg) - } - if finfo.Inline == nil { - finfo.Inline = []int{i, finfo.Num} - } else { - finfo.Inline = append([]int{i}, finfo.Inline...) - } - finfo.Id = len(fieldsList) - fieldsMap[finfo.Key] = finfo - fieldsList = append(fieldsList, finfo) - } - } - default: - return nil, errors.New("option ,inline may only be used on a struct or map field") - } - continue - } - - if tag != "" { - info.Key = tag - } else { - info.Key = strings.ToLower(field.Name) - } - - if _, found = fieldsMap[info.Key]; found { - msg := "duplicated key '" + info.Key + "' in struct " + st.String() - return nil, errors.New(msg) - } - - info.Id = len(fieldsList) - fieldsList = append(fieldsList, info) - fieldsMap[info.Key] = info - } - - sinfo = &structInfo{ - FieldsMap: fieldsMap, - FieldsList: fieldsList, - InlineMap: inlineMap, - InlineUnmarshalers: inlineUnmarshalers, - } - - fieldMapMutex.Lock() - structMap[st] = sinfo - fieldMapMutex.Unlock() - return sinfo, nil -} - -// IsZeroer is used to check whether an object is zero to -// determine whether it should be omitted when marshaling -// with the omitempty flag. One notable implementation -// is time.Time. -type IsZeroer interface { - IsZero() bool -} - -func isZero(v reflect.Value) bool { - kind := v.Kind() - if z, ok := v.Interface().(IsZeroer); ok { - if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() { - return true - } - return z.IsZero() - } - switch kind { - case reflect.String: - return len(v.String()) == 0 - case reflect.Interface, reflect.Ptr: - return v.IsNil() - case reflect.Slice: - return v.Len() == 0 - case reflect.Map: - return v.Len() == 0 - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return v.Int() == 0 - case reflect.Float32, reflect.Float64: - return v.Float() == 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return v.Uint() == 0 - case reflect.Bool: - return !v.Bool() - case reflect.Struct: - vt := v.Type() - for i := v.NumField() - 1; i >= 0; i-- { - if vt.Field(i).PkgPath != "" { - continue // Private field - } - if !isZero(v.Field(i)) { - return false - } - } - return true - } - return false -} diff --git a/go/sdk/vendor/gopkg.in/yaml.v3/yamlh.go b/go/sdk/vendor/gopkg.in/yaml.v3/yamlh.go deleted file mode 100644 index ddcd551..0000000 --- a/go/sdk/vendor/gopkg.in/yaml.v3/yamlh.go +++ /dev/null @@ -1,809 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -// of the Software, and to permit persons to whom the Software is furnished to do -// so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -package yaml - -import ( - "fmt" - "io" -) - -// The version directive data. -type yaml_version_directive_t struct { - major int8 // The major version number. - minor int8 // The minor version number. -} - -// The tag directive data. -type yaml_tag_directive_t struct { - handle []byte // The tag handle. - prefix []byte // The tag prefix. -} - -type yaml_encoding_t int - -// The stream encoding. -const ( - // Let the parser choose the encoding. - yaml_ANY_ENCODING yaml_encoding_t = iota - - yaml_UTF8_ENCODING // The default UTF-8 encoding. - yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM. - yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM. -) - -type yaml_break_t int - -// Line break types. -const ( - // Let the parser choose the break type. - yaml_ANY_BREAK yaml_break_t = iota - - yaml_CR_BREAK // Use CR for line breaks (Mac style). - yaml_LN_BREAK // Use LN for line breaks (Unix style). - yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style). -) - -type yaml_error_type_t int - -// Many bad things could happen with the parser and emitter. -const ( - // No error is produced. - yaml_NO_ERROR yaml_error_type_t = iota - - yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory. - yaml_READER_ERROR // Cannot read or decode the input stream. - yaml_SCANNER_ERROR // Cannot scan the input stream. - yaml_PARSER_ERROR // Cannot parse the input stream. - yaml_COMPOSER_ERROR // Cannot compose a YAML document. - yaml_WRITER_ERROR // Cannot write to the output stream. - yaml_EMITTER_ERROR // Cannot emit a YAML stream. -) - -// The pointer position. -type yaml_mark_t struct { - index int // The position index. - line int // The position line. - column int // The position column. -} - -// Node Styles - -type yaml_style_t int8 - -type yaml_scalar_style_t yaml_style_t - -// Scalar styles. -const ( - // Let the emitter choose the style. - yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = 0 - - yaml_PLAIN_SCALAR_STYLE yaml_scalar_style_t = 1 << iota // The plain scalar style. - yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style. - yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style. - yaml_LITERAL_SCALAR_STYLE // The literal scalar style. - yaml_FOLDED_SCALAR_STYLE // The folded scalar style. -) - -type yaml_sequence_style_t yaml_style_t - -// Sequence styles. -const ( - // Let the emitter choose the style. - yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota - - yaml_BLOCK_SEQUENCE_STYLE // The block sequence style. - yaml_FLOW_SEQUENCE_STYLE // The flow sequence style. -) - -type yaml_mapping_style_t yaml_style_t - -// Mapping styles. -const ( - // Let the emitter choose the style. - yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota - - yaml_BLOCK_MAPPING_STYLE // The block mapping style. - yaml_FLOW_MAPPING_STYLE // The flow mapping style. -) - -// Tokens - -type yaml_token_type_t int - -// Token types. -const ( - // An empty token. - yaml_NO_TOKEN yaml_token_type_t = iota - - yaml_STREAM_START_TOKEN // A STREAM-START token. - yaml_STREAM_END_TOKEN // A STREAM-END token. - - yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token. - yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token. - yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token. - yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token. - - yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token. - yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token. - yaml_BLOCK_END_TOKEN // A BLOCK-END token. - - yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token. - yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token. - yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token. - yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token. - - yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token. - yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token. - yaml_KEY_TOKEN // A KEY token. - yaml_VALUE_TOKEN // A VALUE token. - - yaml_ALIAS_TOKEN // An ALIAS token. - yaml_ANCHOR_TOKEN // An ANCHOR token. - yaml_TAG_TOKEN // A TAG token. - yaml_SCALAR_TOKEN // A SCALAR token. -) - -func (tt yaml_token_type_t) String() string { - switch tt { - case yaml_NO_TOKEN: - return "yaml_NO_TOKEN" - case yaml_STREAM_START_TOKEN: - return "yaml_STREAM_START_TOKEN" - case yaml_STREAM_END_TOKEN: - return "yaml_STREAM_END_TOKEN" - case yaml_VERSION_DIRECTIVE_TOKEN: - return "yaml_VERSION_DIRECTIVE_TOKEN" - case yaml_TAG_DIRECTIVE_TOKEN: - return "yaml_TAG_DIRECTIVE_TOKEN" - case yaml_DOCUMENT_START_TOKEN: - return "yaml_DOCUMENT_START_TOKEN" - case yaml_DOCUMENT_END_TOKEN: - return "yaml_DOCUMENT_END_TOKEN" - case yaml_BLOCK_SEQUENCE_START_TOKEN: - return "yaml_BLOCK_SEQUENCE_START_TOKEN" - case yaml_BLOCK_MAPPING_START_TOKEN: - return "yaml_BLOCK_MAPPING_START_TOKEN" - case yaml_BLOCK_END_TOKEN: - return "yaml_BLOCK_END_TOKEN" - case yaml_FLOW_SEQUENCE_START_TOKEN: - return "yaml_FLOW_SEQUENCE_START_TOKEN" - case yaml_FLOW_SEQUENCE_END_TOKEN: - return "yaml_FLOW_SEQUENCE_END_TOKEN" - case yaml_FLOW_MAPPING_START_TOKEN: - return "yaml_FLOW_MAPPING_START_TOKEN" - case yaml_FLOW_MAPPING_END_TOKEN: - return "yaml_FLOW_MAPPING_END_TOKEN" - case yaml_BLOCK_ENTRY_TOKEN: - return "yaml_BLOCK_ENTRY_TOKEN" - case yaml_FLOW_ENTRY_TOKEN: - return "yaml_FLOW_ENTRY_TOKEN" - case yaml_KEY_TOKEN: - return "yaml_KEY_TOKEN" - case yaml_VALUE_TOKEN: - return "yaml_VALUE_TOKEN" - case yaml_ALIAS_TOKEN: - return "yaml_ALIAS_TOKEN" - case yaml_ANCHOR_TOKEN: - return "yaml_ANCHOR_TOKEN" - case yaml_TAG_TOKEN: - return "yaml_TAG_TOKEN" - case yaml_SCALAR_TOKEN: - return "yaml_SCALAR_TOKEN" - } - return "" -} - -// The token structure. -type yaml_token_t struct { - // The token type. - typ yaml_token_type_t - - // The start/end of the token. - start_mark, end_mark yaml_mark_t - - // The stream encoding (for yaml_STREAM_START_TOKEN). - encoding yaml_encoding_t - - // The alias/anchor/scalar value or tag/tag directive handle - // (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN). - value []byte - - // The tag suffix (for yaml_TAG_TOKEN). - suffix []byte - - // The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN). - prefix []byte - - // The scalar style (for yaml_SCALAR_TOKEN). - style yaml_scalar_style_t - - // The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN). - major, minor int8 -} - -// Events - -type yaml_event_type_t int8 - -// Event types. -const ( - // An empty event. - yaml_NO_EVENT yaml_event_type_t = iota - - yaml_STREAM_START_EVENT // A STREAM-START event. - yaml_STREAM_END_EVENT // A STREAM-END event. - yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event. - yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event. - yaml_ALIAS_EVENT // An ALIAS event. - yaml_SCALAR_EVENT // A SCALAR event. - yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event. - yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event. - yaml_MAPPING_START_EVENT // A MAPPING-START event. - yaml_MAPPING_END_EVENT // A MAPPING-END event. - yaml_TAIL_COMMENT_EVENT -) - -var eventStrings = []string{ - yaml_NO_EVENT: "none", - yaml_STREAM_START_EVENT: "stream start", - yaml_STREAM_END_EVENT: "stream end", - yaml_DOCUMENT_START_EVENT: "document start", - yaml_DOCUMENT_END_EVENT: "document end", - yaml_ALIAS_EVENT: "alias", - yaml_SCALAR_EVENT: "scalar", - yaml_SEQUENCE_START_EVENT: "sequence start", - yaml_SEQUENCE_END_EVENT: "sequence end", - yaml_MAPPING_START_EVENT: "mapping start", - yaml_MAPPING_END_EVENT: "mapping end", - yaml_TAIL_COMMENT_EVENT: "tail comment", -} - -func (e yaml_event_type_t) String() string { - if e < 0 || int(e) >= len(eventStrings) { - return fmt.Sprintf("unknown event %d", e) - } - return eventStrings[e] -} - -// The event structure. -type yaml_event_t struct { - - // The event type. - typ yaml_event_type_t - - // The start and end of the event. - start_mark, end_mark yaml_mark_t - - // The document encoding (for yaml_STREAM_START_EVENT). - encoding yaml_encoding_t - - // The version directive (for yaml_DOCUMENT_START_EVENT). - version_directive *yaml_version_directive_t - - // The list of tag directives (for yaml_DOCUMENT_START_EVENT). - tag_directives []yaml_tag_directive_t - - // The comments - head_comment []byte - line_comment []byte - foot_comment []byte - tail_comment []byte - - // The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT). - anchor []byte - - // The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). - tag []byte - - // The scalar value (for yaml_SCALAR_EVENT). - value []byte - - // Is the document start/end indicator implicit, or the tag optional? - // (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT). - implicit bool - - // Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT). - quoted_implicit bool - - // The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). - style yaml_style_t -} - -func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) } -func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) } -func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) } - -// Nodes - -const ( - yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null. - yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false. - yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values. - yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values. - yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values. - yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values. - - yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences. - yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping. - - // Not in original libyaml. - yaml_BINARY_TAG = "tag:yaml.org,2002:binary" - yaml_MERGE_TAG = "tag:yaml.org,2002:merge" - - yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str. - yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq. - yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map. -) - -type yaml_node_type_t int - -// Node types. -const ( - // An empty node. - yaml_NO_NODE yaml_node_type_t = iota - - yaml_SCALAR_NODE // A scalar node. - yaml_SEQUENCE_NODE // A sequence node. - yaml_MAPPING_NODE // A mapping node. -) - -// An element of a sequence node. -type yaml_node_item_t int - -// An element of a mapping node. -type yaml_node_pair_t struct { - key int // The key of the element. - value int // The value of the element. -} - -// The node structure. -type yaml_node_t struct { - typ yaml_node_type_t // The node type. - tag []byte // The node tag. - - // The node data. - - // The scalar parameters (for yaml_SCALAR_NODE). - scalar struct { - value []byte // The scalar value. - length int // The length of the scalar value. - style yaml_scalar_style_t // The scalar style. - } - - // The sequence parameters (for YAML_SEQUENCE_NODE). - sequence struct { - items_data []yaml_node_item_t // The stack of sequence items. - style yaml_sequence_style_t // The sequence style. - } - - // The mapping parameters (for yaml_MAPPING_NODE). - mapping struct { - pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value). - pairs_start *yaml_node_pair_t // The beginning of the stack. - pairs_end *yaml_node_pair_t // The end of the stack. - pairs_top *yaml_node_pair_t // The top of the stack. - style yaml_mapping_style_t // The mapping style. - } - - start_mark yaml_mark_t // The beginning of the node. - end_mark yaml_mark_t // The end of the node. - -} - -// The document structure. -type yaml_document_t struct { - - // The document nodes. - nodes []yaml_node_t - - // The version directive. - version_directive *yaml_version_directive_t - - // The list of tag directives. - tag_directives_data []yaml_tag_directive_t - tag_directives_start int // The beginning of the tag directives list. - tag_directives_end int // The end of the tag directives list. - - start_implicit int // Is the document start indicator implicit? - end_implicit int // Is the document end indicator implicit? - - // The start/end of the document. - start_mark, end_mark yaml_mark_t -} - -// The prototype of a read handler. -// -// The read handler is called when the parser needs to read more bytes from the -// source. The handler should write not more than size bytes to the buffer. -// The number of written bytes should be set to the size_read variable. -// -// [in,out] data A pointer to an application data specified by -// -// yaml_parser_set_input(). -// -// [out] buffer The buffer to write the data from the source. -// [in] size The size of the buffer. -// [out] size_read The actual number of bytes read from the source. -// -// On success, the handler should return 1. If the handler failed, -// the returned value should be 0. On EOF, the handler should set the -// size_read to 0 and return 1. -type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error) - -// This structure holds information about a potential simple key. -type yaml_simple_key_t struct { - possible bool // Is a simple key possible? - required bool // Is a simple key required? - token_number int // The number of the token. - mark yaml_mark_t // The position mark. -} - -// The states of the parser. -type yaml_parser_state_t int - -const ( - yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota - - yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document. - yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START. - yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document. - yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END. - yaml_PARSE_BLOCK_NODE_STATE // Expect a block node. - yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence. - yaml_PARSE_FLOW_NODE_STATE // Expect a flow node. - yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence. - yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence. - yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence. - yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. - yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key. - yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value. - yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence. - yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence. - yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping. - yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping. - yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry. - yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. - yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. - yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. - yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping. - yaml_PARSE_END_STATE // Expect nothing. -) - -func (ps yaml_parser_state_t) String() string { - switch ps { - case yaml_PARSE_STREAM_START_STATE: - return "yaml_PARSE_STREAM_START_STATE" - case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: - return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE" - case yaml_PARSE_DOCUMENT_START_STATE: - return "yaml_PARSE_DOCUMENT_START_STATE" - case yaml_PARSE_DOCUMENT_CONTENT_STATE: - return "yaml_PARSE_DOCUMENT_CONTENT_STATE" - case yaml_PARSE_DOCUMENT_END_STATE: - return "yaml_PARSE_DOCUMENT_END_STATE" - case yaml_PARSE_BLOCK_NODE_STATE: - return "yaml_PARSE_BLOCK_NODE_STATE" - case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: - return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE" - case yaml_PARSE_FLOW_NODE_STATE: - return "yaml_PARSE_FLOW_NODE_STATE" - case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: - return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE" - case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: - return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE" - case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: - return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE" - case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: - return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE" - case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: - return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE" - case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: - return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE" - case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: - return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE" - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: - return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE" - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: - return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE" - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: - return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE" - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: - return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE" - case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: - return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE" - case yaml_PARSE_FLOW_MAPPING_KEY_STATE: - return "yaml_PARSE_FLOW_MAPPING_KEY_STATE" - case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: - return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE" - case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: - return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE" - case yaml_PARSE_END_STATE: - return "yaml_PARSE_END_STATE" - } - return "" -} - -// This structure holds aliases data. -type yaml_alias_data_t struct { - anchor []byte // The anchor. - index int // The node id. - mark yaml_mark_t // The anchor mark. -} - -// The parser structure. -// -// All members are internal. Manage the structure using the -// yaml_parser_ family of functions. -type yaml_parser_t struct { - - // Error handling - - error yaml_error_type_t // Error type. - - problem string // Error description. - - // The byte about which the problem occurred. - problem_offset int - problem_value int - problem_mark yaml_mark_t - - // The error context. - context string - context_mark yaml_mark_t - - // Reader stuff - - read_handler yaml_read_handler_t // Read handler. - - input_reader io.Reader // File input data. - input []byte // String input data. - input_pos int - - eof bool // EOF flag - - buffer []byte // The working buffer. - buffer_pos int // The current position of the buffer. - - unread int // The number of unread characters in the buffer. - - newlines int // The number of line breaks since last non-break/non-blank character - - raw_buffer []byte // The raw buffer. - raw_buffer_pos int // The current position of the buffer. - - encoding yaml_encoding_t // The input encoding. - - offset int // The offset of the current position (in bytes). - mark yaml_mark_t // The mark of the current position. - - // Comments - - head_comment []byte // The current head comments - line_comment []byte // The current line comments - foot_comment []byte // The current foot comments - tail_comment []byte // Foot comment that happens at the end of a block. - stem_comment []byte // Comment in item preceding a nested structure (list inside list item, etc) - - comments []yaml_comment_t // The folded comments for all parsed tokens - comments_head int - - // Scanner stuff - - stream_start_produced bool // Have we started to scan the input stream? - stream_end_produced bool // Have we reached the end of the input stream? - - flow_level int // The number of unclosed '[' and '{' indicators. - - tokens []yaml_token_t // The tokens queue. - tokens_head int // The head of the tokens queue. - tokens_parsed int // The number of tokens fetched from the queue. - token_available bool // Does the tokens queue contain a token ready for dequeueing. - - indent int // The current indentation level. - indents []int // The indentation levels stack. - - simple_key_allowed bool // May a simple key occur at the current position? - simple_keys []yaml_simple_key_t // The stack of simple keys. - simple_keys_by_tok map[int]int // possible simple_key indexes indexed by token_number - - // Parser stuff - - state yaml_parser_state_t // The current parser state. - states []yaml_parser_state_t // The parser states stack. - marks []yaml_mark_t // The stack of marks. - tag_directives []yaml_tag_directive_t // The list of TAG directives. - - // Dumper stuff - - aliases []yaml_alias_data_t // The alias data. - - document *yaml_document_t // The currently parsed document. -} - -type yaml_comment_t struct { - scan_mark yaml_mark_t // Position where scanning for comments started - token_mark yaml_mark_t // Position after which tokens will be associated with this comment - start_mark yaml_mark_t // Position of '#' comment mark - end_mark yaml_mark_t // Position where comment terminated - - head []byte - line []byte - foot []byte -} - -// Emitter Definitions - -// The prototype of a write handler. -// -// The write handler is called when the emitter needs to flush the accumulated -// characters to the output. The handler should write @a size bytes of the -// @a buffer to the output. -// -// @param[in,out] data A pointer to an application data specified by -// -// yaml_emitter_set_output(). -// -// @param[in] buffer The buffer with bytes to be written. -// @param[in] size The size of the buffer. -// -// @returns On success, the handler should return @c 1. If the handler failed, -// the returned value should be @c 0. -type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error - -type yaml_emitter_state_t int - -// The emitter states. -const ( - // Expect STREAM-START. - yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota - - yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END. - yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END. - yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document. - yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END. - yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence. - yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE // Expect the next item of a flow sequence, with the comma already written out - yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence. - yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. - yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE // Expect the next key of a flow mapping, with the comma already written out - yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. - yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping. - yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. - yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence. - yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence. - yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. - yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping. - yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping. - yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping. - yaml_EMIT_END_STATE // Expect nothing. -) - -// The emitter structure. -// -// All members are internal. Manage the structure using the @c yaml_emitter_ -// family of functions. -type yaml_emitter_t struct { - - // Error handling - - error yaml_error_type_t // Error type. - problem string // Error description. - - // Writer stuff - - write_handler yaml_write_handler_t // Write handler. - - output_buffer *[]byte // String output data. - output_writer io.Writer // File output data. - - buffer []byte // The working buffer. - buffer_pos int // The current position of the buffer. - - raw_buffer []byte // The raw buffer. - raw_buffer_pos int // The current position of the buffer. - - encoding yaml_encoding_t // The stream encoding. - - // Emitter stuff - - canonical bool // If the output is in the canonical style? - best_indent int // The number of indentation spaces. - best_width int // The preferred width of the output lines. - unicode bool // Allow unescaped non-ASCII characters? - line_break yaml_break_t // The preferred line break. - - state yaml_emitter_state_t // The current emitter state. - states []yaml_emitter_state_t // The stack of states. - - events []yaml_event_t // The event queue. - events_head int // The head of the event queue. - - indents []int // The stack of indentation levels. - - tag_directives []yaml_tag_directive_t // The list of tag directives. - - indent int // The current indentation level. - - flow_level int // The current flow level. - - root_context bool // Is it the document root context? - sequence_context bool // Is it a sequence context? - mapping_context bool // Is it a mapping context? - simple_key_context bool // Is it a simple mapping key context? - - line int // The current line. - column int // The current column. - whitespace bool // If the last character was a whitespace? - indention bool // If the last character was an indentation character (' ', '-', '?', ':')? - open_ended bool // If an explicit document end is required? - - space_above bool // Is there's an empty line above? - foot_indent int // The indent used to write the foot comment above, or -1 if none. - - // Anchor analysis. - anchor_data struct { - anchor []byte // The anchor value. - alias bool // Is it an alias? - } - - // Tag analysis. - tag_data struct { - handle []byte // The tag handle. - suffix []byte // The tag suffix. - } - - // Scalar analysis. - scalar_data struct { - value []byte // The scalar value. - multiline bool // Does the scalar contain line breaks? - flow_plain_allowed bool // Can the scalar be expessed in the flow plain style? - block_plain_allowed bool // Can the scalar be expressed in the block plain style? - single_quoted_allowed bool // Can the scalar be expressed in the single quoted style? - block_allowed bool // Can the scalar be expressed in the literal or folded styles? - style yaml_scalar_style_t // The output style. - } - - // Comments - head_comment []byte - line_comment []byte - foot_comment []byte - tail_comment []byte - - key_line_comment []byte - - // Dumper stuff - - opened bool // If the stream was already opened? - closed bool // If the stream was already closed? - - // The information associated with the document nodes. - anchors *struct { - references int // The number of references. - anchor int // The anchor id. - serialized bool // If the node has been emitted? - } - - last_anchor_id int // The last assigned anchor id. - - document *yaml_document_t // The currently emitted document. -} diff --git a/go/sdk/vendor/gopkg.in/yaml.v3/yamlprivateh.go b/go/sdk/vendor/gopkg.in/yaml.v3/yamlprivateh.go deleted file mode 100644 index dea1ba9..0000000 --- a/go/sdk/vendor/gopkg.in/yaml.v3/yamlprivateh.go +++ /dev/null @@ -1,198 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -// of the Software, and to permit persons to whom the Software is furnished to do -// so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -package yaml - -const ( - // The size of the input raw buffer. - input_raw_buffer_size = 512 - - // The size of the input buffer. - // It should be possible to decode the whole raw buffer. - input_buffer_size = input_raw_buffer_size * 3 - - // The size of the output buffer. - output_buffer_size = 128 - - // The size of the output raw buffer. - // It should be possible to encode the whole output buffer. - output_raw_buffer_size = (output_buffer_size*2 + 2) - - // The size of other stacks and queues. - initial_stack_size = 16 - initial_queue_size = 16 - initial_string_size = 16 -) - -// Check if the character at the specified position is an alphabetical -// character, a digit, '_', or '-'. -func is_alpha(b []byte, i int) bool { - return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-' -} - -// Check if the character at the specified position is a digit. -func is_digit(b []byte, i int) bool { - return b[i] >= '0' && b[i] <= '9' -} - -// Get the value of a digit. -func as_digit(b []byte, i int) int { - return int(b[i]) - '0' -} - -// Check if the character at the specified position is a hex-digit. -func is_hex(b []byte, i int) bool { - return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f' -} - -// Get the value of a hex-digit. -func as_hex(b []byte, i int) int { - bi := b[i] - if bi >= 'A' && bi <= 'F' { - return int(bi) - 'A' + 10 - } - if bi >= 'a' && bi <= 'f' { - return int(bi) - 'a' + 10 - } - return int(bi) - '0' -} - -// Check if the character is ASCII. -func is_ascii(b []byte, i int) bool { - return b[i] <= 0x7F -} - -// Check if the character at the start of the buffer can be printed unescaped. -func is_printable(b []byte, i int) bool { - return ((b[i] == 0x0A) || // . == #x0A - (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E - (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF - (b[i] > 0xC2 && b[i] < 0xED) || - (b[i] == 0xED && b[i+1] < 0xA0) || - (b[i] == 0xEE) || - (b[i] == 0xEF && // #xE000 <= . <= #xFFFD - !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF - !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF)))) -} - -// Check if the character at the specified position is NUL. -func is_z(b []byte, i int) bool { - return b[i] == 0x00 -} - -// Check if the beginning of the buffer is a BOM. -func is_bom(b []byte, i int) bool { - return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF -} - -// Check if the character at the specified position is space. -func is_space(b []byte, i int) bool { - return b[i] == ' ' -} - -// Check if the character at the specified position is tab. -func is_tab(b []byte, i int) bool { - return b[i] == '\t' -} - -// Check if the character at the specified position is blank (space or tab). -func is_blank(b []byte, i int) bool { - //return is_space(b, i) || is_tab(b, i) - return b[i] == ' ' || b[i] == '\t' -} - -// Check if the character at the specified position is a line break. -func is_break(b []byte, i int) bool { - return (b[i] == '\r' || // CR (#xD) - b[i] == '\n' || // LF (#xA) - b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029) -} - -func is_crlf(b []byte, i int) bool { - return b[i] == '\r' && b[i+1] == '\n' -} - -// Check if the character is a line break or NUL. -func is_breakz(b []byte, i int) bool { - //return is_break(b, i) || is_z(b, i) - return ( - // is_break: - b[i] == '\r' || // CR (#xD) - b[i] == '\n' || // LF (#xA) - b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) - // is_z: - b[i] == 0) -} - -// Check if the character is a line break, space, or NUL. -func is_spacez(b []byte, i int) bool { - //return is_space(b, i) || is_breakz(b, i) - return ( - // is_space: - b[i] == ' ' || - // is_breakz: - b[i] == '\r' || // CR (#xD) - b[i] == '\n' || // LF (#xA) - b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) - b[i] == 0) -} - -// Check if the character is a line break, space, tab, or NUL. -func is_blankz(b []byte, i int) bool { - //return is_blank(b, i) || is_breakz(b, i) - return ( - // is_blank: - b[i] == ' ' || b[i] == '\t' || - // is_breakz: - b[i] == '\r' || // CR (#xD) - b[i] == '\n' || // LF (#xA) - b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) - b[i] == 0) -} - -// Determine the width of the character. -func width(b byte) int { - // Don't replace these by a switch without first - // confirming that it is being inlined. - if b&0x80 == 0x00 { - return 1 - } - if b&0xE0 == 0xC0 { - return 2 - } - if b&0xF0 == 0xE0 { - return 3 - } - if b&0xF8 == 0xF0 { - return 4 - } - return 0 - -} diff --git a/go/sdk/vendor/modules.txt b/go/sdk/vendor/modules.txt deleted file mode 100644 index a08dd1c..0000000 --- a/go/sdk/vendor/modules.txt +++ /dev/null @@ -1,54 +0,0 @@ -# github.com/davecgh/go-spew v1.1.1 -## explicit -github.com/davecgh/go-spew/spew -# github.com/google/jsonschema-go v0.4.2 -## explicit; go 1.23.0 -github.com/google/jsonschema-go/jsonschema -# github.com/modelcontextprotocol/go-sdk v1.4.0 -## explicit; go 1.24.0 -github.com/modelcontextprotocol/go-sdk/auth -github.com/modelcontextprotocol/go-sdk/internal/json -github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2 -github.com/modelcontextprotocol/go-sdk/internal/mcpgodebug -github.com/modelcontextprotocol/go-sdk/internal/util -github.com/modelcontextprotocol/go-sdk/internal/xcontext -github.com/modelcontextprotocol/go-sdk/jsonrpc -github.com/modelcontextprotocol/go-sdk/mcp -github.com/modelcontextprotocol/go-sdk/oauthex -# github.com/pmezard/go-difflib v1.0.0 -## explicit -github.com/pmezard/go-difflib/difflib -# github.com/segmentio/asm v1.1.3 -## explicit; go 1.17 -github.com/segmentio/asm/ascii -github.com/segmentio/asm/base64 -github.com/segmentio/asm/cpu -github.com/segmentio/asm/cpu/arm -github.com/segmentio/asm/cpu/arm64 -github.com/segmentio/asm/cpu/cpuid -github.com/segmentio/asm/cpu/x86 -github.com/segmentio/asm/internal/unsafebytes -github.com/segmentio/asm/keyset -# github.com/segmentio/encoding v0.5.3 -## explicit; go 1.23 -github.com/segmentio/encoding/ascii -github.com/segmentio/encoding/iso8601 -github.com/segmentio/encoding/json -# github.com/stretchr/testify v1.11.1 -## explicit; go 1.17 -github.com/stretchr/testify/assert -github.com/stretchr/testify/assert/yaml -github.com/stretchr/testify/require -# github.com/yosida95/uritemplate/v3 v3.0.2 -## explicit; go 1.14 -github.com/yosida95/uritemplate/v3 -# golang.org/x/oauth2 v0.34.0 -## explicit; go 1.24.0 -golang.org/x/oauth2 -golang.org/x/oauth2/internal -# golang.org/x/sys v0.40.0 -## explicit; go 1.24.0 -golang.org/x/sys/cpu -# gopkg.in/yaml.v3 v3.0.1 -## explicit -gopkg.in/yaml.v3