Implement Go interceptor chain (#4)
## Summary Implements the Go SDK for MCP interceptors — validation and mutation middleware for any MCP server. The framework treats interceptors as first-class MCP primitives: they are registered on an MCP server, discoverable via `interceptors/list`, and invocable via `interceptor/invoke` — the same JSON-RPC pattern as tools, prompts, and resources. A chain engine orchestrates execution across one or more interceptor servers, and an optional go-sdk middleware integration applies interceptors automatically on every matching request/response. ## Architecture **Three-layer design:** 1. **`interceptors`** — Protocol-agnostic core. Defines interceptor types (validators, mutators), metadata, invocation, wire types, and results. Zero MCP dependencies. 2. **`interceptors/mcpserver`** — MCP server integration. Wraps `mcp.Server` to register `interceptors/list` and `interceptor/invoke` as custom JSON-RPC methods and advertise interceptor capabilities during `initialize`. 3. **`interceptors/chain`** — Chain engine. Orchestrates execution across N interceptor servers with trust-boundary-aware ordering, priority-based mutation sequencing, parallel validation, audit-mode isolation, and fail-open/fail-closed semantics. 4. **`interceptors/integrations/gomiddleware`** — Optional go-sdk middleware. Installs on `mcp.Server` via `AddReceivingMiddleware()` to automatically run the interceptor chain on every matching request/response. **Key design decisions:** - **Trust-boundary ordering** — request phase: validate → mutate; response phase: mutate → validate. Validation always guards the boundary crossing. - **Wire-level invocation** — the chain calls `interceptor/invoke` over the MCP transport (even in-process via `LocalChain()`), so local and remote interceptor servers use the same interface. - **Audit-mode isolation** — audit-mode mutators compute transformations without applying them. Only audit mutators pay the serialization cost. - **Concurrency** — validators run in parallel; mutators run sequentially in priority order. ### Package Structure | Package | File | Responsibility | |---------|------|----------------| | `interceptors` | `interceptor.go` | Enums, Metadata, Interceptor interface, Validator/Mutator structs, handler types, Invocation | | `interceptors` | `wire.go` | Wire types: ListParams/Result, InvokeParams/Result, InterceptorInfo, event/method constants | | `interceptors` | `priority.go` | Priority with phase-aware resolution and JSON marshaling | | `interceptors` | `doc.go` | Package documentation with examples | | `interceptors/chain` | `chain.go` | Chain engine: discovery, filtering, sorting, execution orchestration | | `interceptors/chain` | `result.go` | ExecutionResult, AbortInfo | | `interceptors/chain` | `doc.go` | Sub-package documentation | | `interceptors/mcpserver` | `server.go` | MCP server wrapper, interceptor registry, capability advertisement, `LocalChain()` | | `interceptors/mcpserver` | `rpc.go` | `interceptors/list` and `interceptor/invoke` JSON-RPC handlers | | `interceptors/mcpserver` | `doc.go` | Sub-package documentation | | `integrations/gomiddleware` | `middleware.go` | go-sdk `Middleware` that runs the chain on every request/response | | `integrations/gomiddleware` | `errors.go` | Abort-to-JSONRPC error conversion | | `integrations/gomiddleware` | `doc.go` | Sub-package documentation | ### Documentation - `doc/DESIGN.md` — architecture, execution model, integration with go-sdk - `doc/CONFORMANCE.md` — SEP conformance status - `doc/PERFORMANCE.md` — per-request cost model ### Examples - `examples/validator` — blocks dangerous tool calls, demonstrates `WithContextProvider` - `examples/mutator` — tags tool responses with audit trail ## Vendor: go-sdk v1.4.0 with custom method support Vendors `go-sdk` with minimal extensions for custom JSON-RPC methods: - `Server.AddCustomMethod` — registers a handler that bypasses the typed pipeline - `ClientSession.CallCustom` — sends raw JSON-RPC calls for custom methods These changes are generic (not interceptor-specific) and enable any MCP extension to define its own JSON-RPC methods. ## TODO - More integration tests - Unit tests - Support wildcards for event interception (separate PR) --------- Signed-off-by: Kurt Degiorgio <kdegiorgio@bloomberg.net>
This commit is contained in:
parent
45f9e0ef27
commit
c9900f02ab
33 changed files with 62908 additions and 19 deletions
21
go/sdk/vendor/github.com/segmentio/asm/LICENSE
generated
vendored
Normal file
21
go/sdk/vendor/github.com/segmentio/asm/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
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.
|
||||
53
go/sdk/vendor/github.com/segmentio/asm/ascii/ascii.go
generated
vendored
Normal file
53
go/sdk/vendor/github.com/segmentio/asm/ascii/ascii.go
generated
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
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,
|
||||
}
|
||||
30
go/sdk/vendor/github.com/segmentio/asm/ascii/equal_fold.go
generated
vendored
Normal file
30
go/sdk/vendor/github.com/segmentio/asm/ascii/equal_fold.go
generated
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
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)
|
||||
}
|
||||
13
go/sdk/vendor/github.com/segmentio/asm/ascii/equal_fold_amd64.go
generated
vendored
Normal file
13
go/sdk/vendor/github.com/segmentio/asm/ascii/equal_fold_amd64.go
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// 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
|
||||
304
go/sdk/vendor/github.com/segmentio/asm/ascii/equal_fold_amd64.s
generated
vendored
Normal file
304
go/sdk/vendor/github.com/segmentio/asm/ascii/equal_fold_amd64.s
generated
vendored
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
// 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
|
||||
60
go/sdk/vendor/github.com/segmentio/asm/ascii/equal_fold_default.go
generated
vendored
Normal file
60
go/sdk/vendor/github.com/segmentio/asm/ascii/equal_fold_default.go
generated
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
//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
|
||||
}
|
||||
18
go/sdk/vendor/github.com/segmentio/asm/ascii/valid.go
generated
vendored
Normal file
18
go/sdk/vendor/github.com/segmentio/asm/ascii/valid.go
generated
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
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
|
||||
}
|
||||
9
go/sdk/vendor/github.com/segmentio/asm/ascii/valid_amd64.go
generated
vendored
Normal file
9
go/sdk/vendor/github.com/segmentio/asm/ascii/valid_amd64.go
generated
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
// 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
|
||||
132
go/sdk/vendor/github.com/segmentio/asm/ascii/valid_amd64.s
generated
vendored
Normal file
132
go/sdk/vendor/github.com/segmentio/asm/ascii/valid_amd64.s
generated
vendored
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
// 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
|
||||
48
go/sdk/vendor/github.com/segmentio/asm/ascii/valid_default.go
generated
vendored
Normal file
48
go/sdk/vendor/github.com/segmentio/asm/ascii/valid_default.go
generated
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
//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
|
||||
}
|
||||
18
go/sdk/vendor/github.com/segmentio/asm/ascii/valid_print.go
generated
vendored
Normal file
18
go/sdk/vendor/github.com/segmentio/asm/ascii/valid_print.go
generated
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
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
|
||||
}
|
||||
9
go/sdk/vendor/github.com/segmentio/asm/ascii/valid_print_amd64.go
generated
vendored
Normal file
9
go/sdk/vendor/github.com/segmentio/asm/ascii/valid_print_amd64.go
generated
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
// 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
|
||||
185
go/sdk/vendor/github.com/segmentio/asm/ascii/valid_print_amd64.s
generated
vendored
Normal file
185
go/sdk/vendor/github.com/segmentio/asm/ascii/valid_print_amd64.s
generated
vendored
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
// 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
|
||||
46
go/sdk/vendor/github.com/segmentio/asm/ascii/valid_print_default.go
generated
vendored
Normal file
46
go/sdk/vendor/github.com/segmentio/asm/ascii/valid_print_default.go
generated
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
//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))
|
||||
}
|
||||
68
go/sdk/vendor/github.com/segmentio/asm/base64/base64.go
generated
vendored
Normal file
68
go/sdk/vendor/github.com/segmentio/asm/base64/base64.go
generated
vendored
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
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: {},
|
||||
}
|
||||
160
go/sdk/vendor/github.com/segmentio/asm/base64/base64_amd64.go
generated
vendored
Normal file
160
go/sdk/vendor/github.com/segmentio/asm/base64/base64_amd64.go
generated
vendored
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
//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)
|
||||
}
|
||||
14
go/sdk/vendor/github.com/segmentio/asm/base64/base64_default.go
generated
vendored
Normal file
14
go/sdk/vendor/github.com/segmentio/asm/base64/base64_default.go
generated
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
//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)
|
||||
}
|
||||
10
go/sdk/vendor/github.com/segmentio/asm/base64/decode_amd64.go
generated
vendored
Normal file
10
go/sdk/vendor/github.com/segmentio/asm/base64/decode_amd64.go
generated
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
// 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)
|
||||
144
go/sdk/vendor/github.com/segmentio/asm/base64/decode_amd64.s
generated
vendored
Normal file
144
go/sdk/vendor/github.com/segmentio/asm/base64/decode_amd64.s
generated
vendored
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
// 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
|
||||
8
go/sdk/vendor/github.com/segmentio/asm/base64/encode_amd64.go
generated
vendored
Normal file
8
go/sdk/vendor/github.com/segmentio/asm/base64/encode_amd64.go
generated
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
// 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)
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue