├── .gitignore
├── .travis.yml
├── LICENSE
├── QuickTemplate.xml
├── README.md
├── bytebuffer.go
├── doc.go
├── examples
├── README.md
└── basicserver
│ ├── .gitignore
│ ├── Makefile
│ ├── README.md
│ ├── main.go
│ └── templates
│ ├── README.md
│ ├── basepage.qtpl
│ ├── basepage.qtpl.go
│ ├── errorpage.qtpl
│ ├── errorpage.qtpl.go
│ ├── mainpage.qtpl
│ ├── mainpage.qtpl.go
│ ├── tablepage.qtpl
│ └── tablepage.qtpl.go
├── go.mod
├── go.sum
├── htmlescapewriter.go
├── htmlescapewriter_test.go
├── htmlescapewriter_timing_test.go
├── jsonstring.go
├── jsonstring_test.go
├── jsonstring_timing_test.go
├── parser
├── functype.go
├── functype_test.go
├── parser.go
├── parser_test.go
├── scanner.go
├── scanner_test.go
└── util.go
├── qtc
├── LICENSE
├── README.md
└── main.go
├── testdata
├── qtc
│ ├── .gitignore
│ ├── test.qtpl
│ └── test.qtpl.expected
└── templates
│ ├── bench.qtpl
│ ├── bench.qtpl.go
│ ├── bench.tpl
│ ├── integration.qtpl
│ ├── integration.qtpl.go
│ ├── integration.qtpl.out
│ ├── marshal.qtpl
│ └── marshal.qtpl.go
├── tests
├── doc.go
├── integration_test.go
├── marshal_timing_test.go
└── templates_timing_test.go
├── urlencode.go
├── urlencode_test.go
├── util.go
├── util_appengine.go
├── util_noappengine.go
├── vendor
├── github.com
│ ├── andybalholm
│ │ └── brotli
│ │ │ ├── LICENSE
│ │ │ ├── README.md
│ │ │ ├── backward_references.go
│ │ │ ├── backward_references_hq.go
│ │ │ ├── bit_cost.go
│ │ │ ├── bit_reader.go
│ │ │ ├── bitwriter.go
│ │ │ ├── block_splitter.go
│ │ │ ├── block_splitter_command.go
│ │ │ ├── block_splitter_distance.go
│ │ │ ├── block_splitter_literal.go
│ │ │ ├── brotli_bit_stream.go
│ │ │ ├── cluster.go
│ │ │ ├── cluster_command.go
│ │ │ ├── cluster_distance.go
│ │ │ ├── cluster_literal.go
│ │ │ ├── command.go
│ │ │ ├── compress_fragment.go
│ │ │ ├── compress_fragment_two_pass.go
│ │ │ ├── constants.go
│ │ │ ├── context.go
│ │ │ ├── decode.go
│ │ │ ├── dictionary.go
│ │ │ ├── dictionary_hash.go
│ │ │ ├── encode.go
│ │ │ ├── encoder.go
│ │ │ ├── encoder_dict.go
│ │ │ ├── entropy_encode.go
│ │ │ ├── entropy_encode_static.go
│ │ │ ├── fast_log.go
│ │ │ ├── find_match_length.go
│ │ │ ├── h10.go
│ │ │ ├── h5.go
│ │ │ ├── h6.go
│ │ │ ├── hash.go
│ │ │ ├── hash_composite.go
│ │ │ ├── hash_forgetful_chain.go
│ │ │ ├── hash_longest_match_quickly.go
│ │ │ ├── hash_rolling.go
│ │ │ ├── histogram.go
│ │ │ ├── http.go
│ │ │ ├── huffman.go
│ │ │ ├── literal_cost.go
│ │ │ ├── matchfinder
│ │ │ ├── emitter.go
│ │ │ ├── m0.go
│ │ │ ├── m4.go
│ │ │ ├── matchfinder.go
│ │ │ └── textencoder.go
│ │ │ ├── memory.go
│ │ │ ├── metablock.go
│ │ │ ├── metablock_command.go
│ │ │ ├── metablock_distance.go
│ │ │ ├── metablock_literal.go
│ │ │ ├── params.go
│ │ │ ├── platform.go
│ │ │ ├── prefix.go
│ │ │ ├── prefix_dec.go
│ │ │ ├── quality.go
│ │ │ ├── reader.go
│ │ │ ├── ringbuffer.go
│ │ │ ├── state.go
│ │ │ ├── static_dict.go
│ │ │ ├── static_dict_lut.go
│ │ │ ├── symbol_list.go
│ │ │ ├── transform.go
│ │ │ ├── utf8_util.go
│ │ │ ├── util.go
│ │ │ ├── write_bits.go
│ │ │ └── writer.go
│ ├── klauspost
│ │ └── compress
│ │ │ ├── .gitattributes
│ │ │ ├── .gitignore
│ │ │ ├── .goreleaser.yml
│ │ │ ├── LICENSE
│ │ │ ├── README.md
│ │ │ ├── SECURITY.md
│ │ │ ├── compressible.go
│ │ │ ├── flate
│ │ │ ├── deflate.go
│ │ │ ├── dict_decoder.go
│ │ │ ├── fast_encoder.go
│ │ │ ├── huffman_bit_writer.go
│ │ │ ├── huffman_code.go
│ │ │ ├── huffman_sortByFreq.go
│ │ │ ├── huffman_sortByLiteral.go
│ │ │ ├── inflate.go
│ │ │ ├── inflate_gen.go
│ │ │ ├── level1.go
│ │ │ ├── level2.go
│ │ │ ├── level3.go
│ │ │ ├── level4.go
│ │ │ ├── level5.go
│ │ │ ├── level6.go
│ │ │ ├── matchlen_amd64.go
│ │ │ ├── matchlen_amd64.s
│ │ │ ├── matchlen_generic.go
│ │ │ ├── regmask_amd64.go
│ │ │ ├── regmask_other.go
│ │ │ ├── stateless.go
│ │ │ └── token.go
│ │ │ ├── fse
│ │ │ ├── README.md
│ │ │ ├── bitreader.go
│ │ │ ├── bitwriter.go
│ │ │ ├── bytereader.go
│ │ │ ├── compress.go
│ │ │ ├── decompress.go
│ │ │ └── fse.go
│ │ │ ├── gen.sh
│ │ │ ├── gzip
│ │ │ ├── gunzip.go
│ │ │ └── gzip.go
│ │ │ ├── huff0
│ │ │ ├── .gitignore
│ │ │ ├── README.md
│ │ │ ├── bitreader.go
│ │ │ ├── bitwriter.go
│ │ │ ├── compress.go
│ │ │ ├── decompress.go
│ │ │ ├── decompress_amd64.go
│ │ │ ├── decompress_amd64.s
│ │ │ ├── decompress_generic.go
│ │ │ └── huff0.go
│ │ │ ├── internal
│ │ │ ├── cpuinfo
│ │ │ │ ├── cpuinfo.go
│ │ │ │ ├── cpuinfo_amd64.go
│ │ │ │ └── cpuinfo_amd64.s
│ │ │ └── snapref
│ │ │ │ ├── LICENSE
│ │ │ │ ├── decode.go
│ │ │ │ ├── decode_other.go
│ │ │ │ ├── encode.go
│ │ │ │ ├── encode_other.go
│ │ │ │ └── snappy.go
│ │ │ ├── s2sx.mod
│ │ │ ├── s2sx.sum
│ │ │ ├── zlib
│ │ │ ├── reader.go
│ │ │ └── writer.go
│ │ │ └── zstd
│ │ │ ├── README.md
│ │ │ ├── bitreader.go
│ │ │ ├── bitwriter.go
│ │ │ ├── blockdec.go
│ │ │ ├── blockenc.go
│ │ │ ├── blocktype_string.go
│ │ │ ├── bytebuf.go
│ │ │ ├── bytereader.go
│ │ │ ├── decodeheader.go
│ │ │ ├── decoder.go
│ │ │ ├── decoder_options.go
│ │ │ ├── dict.go
│ │ │ ├── enc_base.go
│ │ │ ├── enc_best.go
│ │ │ ├── enc_better.go
│ │ │ ├── enc_dfast.go
│ │ │ ├── enc_fast.go
│ │ │ ├── encoder.go
│ │ │ ├── encoder_options.go
│ │ │ ├── framedec.go
│ │ │ ├── frameenc.go
│ │ │ ├── fse_decoder.go
│ │ │ ├── fse_decoder_amd64.go
│ │ │ ├── fse_decoder_amd64.s
│ │ │ ├── fse_decoder_generic.go
│ │ │ ├── fse_encoder.go
│ │ │ ├── fse_predefined.go
│ │ │ ├── hash.go
│ │ │ ├── history.go
│ │ │ ├── internal
│ │ │ └── xxhash
│ │ │ │ ├── LICENSE.txt
│ │ │ │ ├── README.md
│ │ │ │ ├── xxhash.go
│ │ │ │ ├── xxhash_amd64.s
│ │ │ │ ├── xxhash_arm64.s
│ │ │ │ ├── xxhash_asm.go
│ │ │ │ ├── xxhash_other.go
│ │ │ │ └── xxhash_safe.go
│ │ │ ├── matchlen_amd64.go
│ │ │ ├── matchlen_amd64.s
│ │ │ ├── matchlen_generic.go
│ │ │ ├── seqdec.go
│ │ │ ├── seqdec_amd64.go
│ │ │ ├── seqdec_amd64.s
│ │ │ ├── seqdec_generic.go
│ │ │ ├── seqenc.go
│ │ │ ├── snappy.go
│ │ │ ├── zip.go
│ │ │ └── zstd.go
│ └── valyala
│ │ ├── bytebufferpool
│ │ ├── .travis.yml
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── bytebuffer.go
│ │ ├── doc.go
│ │ └── pool.go
│ │ └── fasthttp
│ │ ├── .gitignore
│ │ ├── .golangci.yml
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── SECURITY.md
│ │ ├── TODO
│ │ ├── args.go
│ │ ├── b2s_new.go
│ │ ├── b2s_old.go
│ │ ├── brotli.go
│ │ ├── bytesconv.go
│ │ ├── bytesconv_32.go
│ │ ├── bytesconv_64.go
│ │ ├── bytesconv_table.go
│ │ ├── client.go
│ │ ├── coarsetime.go
│ │ ├── compress.go
│ │ ├── cookie.go
│ │ ├── doc.go
│ │ ├── examples
│ │ ├── README.md
│ │ ├── client
│ │ │ ├── Makefile
│ │ │ ├── README.md
│ │ │ └── client.go
│ │ ├── fileserver
│ │ │ ├── Makefile
│ │ │ ├── README.md
│ │ │ ├── fileserver.go
│ │ │ ├── ssl-cert-snakeoil.key
│ │ │ └── ssl-cert-snakeoil.pem
│ │ ├── helloworldserver
│ │ │ ├── Makefile
│ │ │ ├── README.md
│ │ │ └── helloworldserver.go
│ │ ├── host_client
│ │ │ ├── Makefile
│ │ │ ├── README.md
│ │ │ └── hostclient.go
│ │ ├── letsencrypt
│ │ │ └── letsencryptserver.go
│ │ └── multidomain
│ │ │ ├── Makefile
│ │ │ ├── README.md
│ │ │ └── multidomain.go
│ │ ├── fasthttputil
│ │ ├── doc.go
│ │ ├── inmemory_listener.go
│ │ ├── inmemory_listener_test.go
│ │ ├── inmemory_listener_timing_test.go
│ │ ├── pipeconns.go
│ │ └── pipeconns_test.go
│ │ ├── fs.go
│ │ ├── header.go
│ │ ├── headers.go
│ │ ├── http.go
│ │ ├── lbclient.go
│ │ ├── methods.go
│ │ ├── nocopy.go
│ │ ├── peripconn.go
│ │ ├── request_body.zst
│ │ ├── round2_32.go
│ │ ├── round2_64.go
│ │ ├── s2b_new.go
│ │ ├── s2b_old.go
│ │ ├── server.go
│ │ ├── stackless
│ │ ├── doc.go
│ │ ├── func.go
│ │ └── writer.go
│ │ ├── status.go
│ │ ├── stream.go
│ │ ├── streaming.go
│ │ ├── strings.go
│ │ ├── tcp.go
│ │ ├── tcp_windows.go
│ │ ├── tcpdialer.go
│ │ ├── testdata
│ │ └── test.png
│ │ ├── timer.go
│ │ ├── tls.go
│ │ ├── uri.go
│ │ ├── uri_unix.go
│ │ ├── uri_windows.go
│ │ ├── userdata.go
│ │ ├── workerpool.go
│ │ └── zstd.go
└── modules.txt
├── writer.go
├── writer_test.go
└── writer_timing_test.go
/.gitignore:
--------------------------------------------------------------------------------
1 | tags
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: go
2 |
3 | go:
4 | - 1.11.x
5 | - 1.12.x
6 | - 1.13.x
7 | - 1.14.x
8 | - tip
9 |
10 | before_install:
11 | - go get -u github.com/valyala/quicktemplate/qtc
12 | - go generate
13 |
14 | script:
15 | # build test for supported platforms
16 | - GOOS=linux go build
17 | - GOOS=darwin go build
18 | - GOOS=freebsd go build
19 |
20 | # run tests on a standard platform
21 | - go test -v ./...
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Aliaksandr Valialkin, VertaMedia
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/QuickTemplate.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/bytebuffer.go:
--------------------------------------------------------------------------------
1 | package quicktemplate
2 |
3 | import (
4 | "github.com/valyala/bytebufferpool"
5 | )
6 |
7 | // ByteBuffer implements io.Writer on top of byte slice.
8 | //
9 | // Recycle byte buffers via AcquireByteBuffer and ReleaseByteBuffer
10 | // in order to reduce memory allocations.
11 | //
12 | // Deprecated: use github.com/valyala/bytebufferpool instead.
13 | type ByteBuffer bytebufferpool.ByteBuffer
14 |
15 | // Write implements io.Writer.
16 | func (b *ByteBuffer) Write(p []byte) (int, error) {
17 | return bb(b).Write(p)
18 | }
19 |
20 | // Reset resets the byte buffer.
21 | func (b *ByteBuffer) Reset() {
22 | bb(b).Reset()
23 | }
24 |
25 | // AcquireByteBuffer returns new ByteBuffer from the pool.
26 | //
27 | // Return unneeded buffers to the pool by calling ReleaseByteBuffer
28 | // in order to reduce memory allocations.
29 | func AcquireByteBuffer() *ByteBuffer {
30 | return (*ByteBuffer)(byteBufferPool.Get())
31 | }
32 |
33 | // ReleaseByteBuffer retruns byte buffer to the pool.
34 | //
35 | // Do not access byte buffer after returning it to the pool,
36 | // otherwise data races may occur.
37 | func ReleaseByteBuffer(b *ByteBuffer) {
38 | byteBufferPool.Put(bb(b))
39 | }
40 |
41 | func bb(b *ByteBuffer) *bytebufferpool.ByteBuffer {
42 | return (*bytebufferpool.ByteBuffer)(b)
43 | }
44 |
45 | var byteBufferPool bytebufferpool.Pool
46 |
--------------------------------------------------------------------------------
/doc.go:
--------------------------------------------------------------------------------
1 | /*
2 | Package quicktemplate provides fast and powerful template engine.
3 |
4 | See https://github.com/valyala/quicktemplate for details.
5 | */
6 | package quicktemplate
7 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | [quicktemplate](https://github.com/valyala/quicktemplate) examples:
2 |
3 | * [basic usage](https://github.com/valyala/quicktemplate/tree/master/examples/basicserver)
4 |
--------------------------------------------------------------------------------
/examples/basicserver/.gitignore:
--------------------------------------------------------------------------------
1 | basicserver
2 |
--------------------------------------------------------------------------------
/examples/basicserver/Makefile:
--------------------------------------------------------------------------------
1 | run: build
2 | ./basicserver
3 |
4 | build: update
5 | go build -o basicserver
6 |
7 | update:
8 | go get -u github.com/valyala/fasthttp
9 | go get -u github.com/valyala/quicktemplate/qtc
10 |
11 | generate: update
12 | go generate
13 |
14 | all: update generate build run
15 |
--------------------------------------------------------------------------------
/examples/basicserver/README.md:
--------------------------------------------------------------------------------
1 | An example demonstrating basic usage of [quicktemplate](https://github.com/valyala/quicktemplate)
2 | as template engine and [fasthttp](https://github.com/valyala/fasthttp) as http server.
3 |
4 | Just run `make` to see the example in action.
5 | Run `make generate run` after modifying [template files](https://github.com/valyala/quicktemplate/tree/master/examples/basicserver/templates).
6 |
--------------------------------------------------------------------------------
/examples/basicserver/main.go:
--------------------------------------------------------------------------------
1 | // The following line is needed for generating go code from templates
2 | // with `go generate`.
3 | // See https://blog.golang.org/generate for more info.
4 | // Quicktemplate compiler (qtc) must be installed before running
5 | // `go generate`:
6 | //
7 | // go get -u github.com/valyala/quicktemplate/qtc
8 | //
9 | //go:generate qtc -dir=templates
10 | package main
11 |
12 | import (
13 | "fmt"
14 | "log"
15 | "math/rand"
16 |
17 | "github.com/valyala/fasthttp"
18 | "github.com/valyala/quicktemplate/examples/basicserver/templates"
19 | )
20 |
21 | func main() {
22 | log.Printf("starting the server at http://localhost:8080 ...")
23 | err := fasthttp.ListenAndServe("localhost:8080", requestHandler)
24 | if err != nil {
25 | log.Fatalf("unexpected error in server: %s", err)
26 | }
27 | }
28 |
29 | func requestHandler(ctx *fasthttp.RequestCtx) {
30 | switch string(ctx.Path()) {
31 | case "/":
32 | mainPageHandler(ctx)
33 | case "/table":
34 | tablePageHandler(ctx)
35 | default:
36 | errorPageHandler(ctx)
37 | }
38 | ctx.SetContentType("text/html; charset=utf-8")
39 | }
40 |
41 | func mainPageHandler(ctx *fasthttp.RequestCtx) {
42 | p := &templates.MainPage{
43 | CTX: ctx,
44 | }
45 | templates.WritePageTemplate(ctx, p)
46 | }
47 |
48 | func tablePageHandler(ctx *fasthttp.RequestCtx) {
49 | rowsCount := ctx.QueryArgs().GetUintOrZero("rowsCount")
50 | if rowsCount == 0 {
51 | rowsCount = 10
52 | }
53 | p := &templates.TablePage{
54 | Rows: generateRows(rowsCount),
55 | }
56 | templates.WritePageTemplate(ctx, p)
57 | }
58 |
59 | func errorPageHandler(ctx *fasthttp.RequestCtx) {
60 | p := &templates.ErrorPage{
61 | Path: ctx.Path(),
62 | }
63 | templates.WritePageTemplate(ctx, p)
64 | ctx.SetStatusCode(fasthttp.StatusBadRequest)
65 | }
66 |
67 | func generateRows(rowsCount int) []string {
68 | var rows []string
69 | for i := 0; i < rowsCount; i++ {
70 | r := fmt.Sprintf("row %d", i)
71 | if rand.Intn(20) == 0 {
72 | r = "bingo"
73 | }
74 | rows = append(rows, r)
75 | }
76 | return rows
77 | }
78 |
--------------------------------------------------------------------------------
/examples/basicserver/templates/README.md:
--------------------------------------------------------------------------------
1 | Template files with the corresponding compiled files.
2 |
3 | Compiled files are generated by [qtc](https://github.com/valyala/quicktemplate/tree/master/qtc).
4 |
--------------------------------------------------------------------------------
/examples/basicserver/templates/basepage.qtpl:
--------------------------------------------------------------------------------
1 | This is a base page template. All the other template pages implement this interface.
2 |
3 | {% interface
4 | Page {
5 | Title()
6 | Body()
7 | }
8 | %}
9 |
10 |
11 | Page prints a page implementing Page interface.
12 | {% func PageTemplate(p Page) %}
13 |
14 |
15 | {%= p.Title() %}
16 |
17 |
18 |
21 | {%= p.Body() %}
22 |
23 |
24 | {% endfunc %}
25 |
26 |
27 | Base page implementation. Other pages may inherit from it if they need
28 | overriding only certain Page methods
29 | {% code type BasePage struct {} %}
30 | {% func (p *BasePage) Title() %}This is a base title{% endfunc %}
31 | {% func (p *BasePage) Body() %}This is a base body{% endfunc %}
32 |
--------------------------------------------------------------------------------
/examples/basicserver/templates/errorpage.qtpl:
--------------------------------------------------------------------------------
1 | // Error page template. Implements BasePage methods.
2 |
3 | {% code
4 | type ErrorPage struct {
5 | // inherit from base page, so its' title is used in error page.
6 | BasePage
7 |
8 | // error path
9 | Path []byte
10 | }
11 | %}
12 |
13 |
14 | {% func (p *ErrorPage) Body() %}
15 | Error page
16 |
17 | Unsupported path {%z p.Path %}.
18 |
19 | Base page body: {%= p.BasePage.Body() %}
20 | {% endfunc %}
21 |
--------------------------------------------------------------------------------
/examples/basicserver/templates/errorpage.qtpl.go:
--------------------------------------------------------------------------------
1 | // Code generated by qtc from "errorpage.qtpl". DO NOT EDIT.
2 | // See https://github.com/valyala/quicktemplate for details.
3 |
4 | // Error page template. Implements BasePage methods.
5 | //
6 |
7 | //line examples/basicserver/templates/errorpage.qtpl:3
8 | package templates
9 |
10 | //line examples/basicserver/templates/errorpage.qtpl:3
11 | import (
12 | qtio422016 "io"
13 |
14 | qt422016 "github.com/valyala/quicktemplate"
15 | )
16 |
17 | //line examples/basicserver/templates/errorpage.qtpl:3
18 | var (
19 | _ = qtio422016.Copy
20 | _ = qt422016.AcquireByteBuffer
21 | )
22 |
23 | //line examples/basicserver/templates/errorpage.qtpl:4
24 | type ErrorPage struct {
25 | // inherit from base page, so its' title is used in error page.
26 | BasePage
27 |
28 | // error path
29 | Path []byte
30 | }
31 |
32 | //line examples/basicserver/templates/errorpage.qtpl:14
33 | func (p *ErrorPage) StreamBody(qw422016 *qt422016.Writer) {
34 | //line examples/basicserver/templates/errorpage.qtpl:14
35 | qw422016.N().S(`
36 | Error page
37 |
38 | Unsupported path `)
39 | //line examples/basicserver/templates/errorpage.qtpl:17
40 | qw422016.E().Z(p.Path)
41 | //line examples/basicserver/templates/errorpage.qtpl:17
42 | qw422016.N().S(`.
43 |
44 | Base page body: `)
45 | //line examples/basicserver/templates/errorpage.qtpl:19
46 | p.BasePage.StreamBody(qw422016)
47 | //line examples/basicserver/templates/errorpage.qtpl:19
48 | qw422016.N().S(`
49 | `)
50 | //line examples/basicserver/templates/errorpage.qtpl:20
51 | }
52 |
53 | //line examples/basicserver/templates/errorpage.qtpl:20
54 | func (p *ErrorPage) WriteBody(qq422016 qtio422016.Writer) {
55 | //line examples/basicserver/templates/errorpage.qtpl:20
56 | qw422016 := qt422016.AcquireWriter(qq422016)
57 | //line examples/basicserver/templates/errorpage.qtpl:20
58 | p.StreamBody(qw422016)
59 | //line examples/basicserver/templates/errorpage.qtpl:20
60 | qt422016.ReleaseWriter(qw422016)
61 | //line examples/basicserver/templates/errorpage.qtpl:20
62 | }
63 |
64 | //line examples/basicserver/templates/errorpage.qtpl:20
65 | func (p *ErrorPage) Body() string {
66 | //line examples/basicserver/templates/errorpage.qtpl:20
67 | qb422016 := qt422016.AcquireByteBuffer()
68 | //line examples/basicserver/templates/errorpage.qtpl:20
69 | p.WriteBody(qb422016)
70 | //line examples/basicserver/templates/errorpage.qtpl:20
71 | qs422016 := string(qb422016.B)
72 | //line examples/basicserver/templates/errorpage.qtpl:20
73 | qt422016.ReleaseByteBuffer(qb422016)
74 | //line examples/basicserver/templates/errorpage.qtpl:20
75 | return qs422016
76 | //line examples/basicserver/templates/errorpage.qtpl:20
77 | }
78 |
--------------------------------------------------------------------------------
/examples/basicserver/templates/mainpage.qtpl:
--------------------------------------------------------------------------------
1 | // Main page template. Implements BasePage methods.
2 |
3 | {% import "github.com/valyala/fasthttp" %}
4 |
5 | {% code
6 | type MainPage struct {
7 | CTX *fasthttp.RequestCtx
8 | }
9 | %}
10 |
11 |
12 | {% func (p *MainPage) Title() %}
13 | This is the main page
14 | {% endfunc %}
15 |
16 |
17 | {% func (p *MainPage) Body() %}
18 | Main page
19 |
20 | Click links below:
21 |
25 |
26 |
27 | Some info about you:
28 | IP: {%s p.CTX.RemoteIP().String() %}
29 | User-Agent: {%z p.CTX.UserAgent() %}
30 |
31 | {% endfunc %}
32 |
--------------------------------------------------------------------------------
/examples/basicserver/templates/tablepage.qtpl:
--------------------------------------------------------------------------------
1 | // Table page template. Implements BasePage methods.
2 |
3 | {% code
4 | type TablePage struct {
5 | Rows []string
6 | }
7 | %}
8 |
9 |
10 | {% func (p *TablePage) Title() %}
11 | This is table page
12 | {% endfunc %}
13 |
14 |
15 | {% func (p *TablePage) Body() %}
16 | Table page
17 |
18 | {%= p.form() %}
19 |
20 | {% if len(p.Rows) == 0 %}
21 | No rows. Click here.
22 | {% else %}
23 |
24 | {%= emitRows(p.Rows) %}
25 |
26 | {% endif %}
27 | {% endfunc %}
28 |
29 | {% func emitRows(rows []string) %}
30 |
31 | # |
32 | value |
33 |
34 |
35 | {% for n, r := range rows %}
36 | {% if r == "bingo" %}
37 | BINGO! |
38 | {% return %}
39 | {% elseif n == 42 %}
40 | 42 rows already generated |
41 | {% break %}
42 | {% endif %}
43 |
44 |
45 | {%d n+1 %} |
46 | {%s r %} |
47 |
48 | {% endfor %}
49 |
50 | No bingo found |
51 | {% endfunc %}
52 |
53 | {% func (p *TablePage) form() %}
54 |
58 | {% endfunc %}
59 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/valyala/quicktemplate
2 |
3 | go 1.17
4 |
5 | require (
6 | github.com/valyala/bytebufferpool v1.0.0
7 | github.com/valyala/fasthttp v1.55.0
8 | )
9 |
10 | require (
11 | github.com/andybalholm/brotli v1.1.0 // indirect
12 | github.com/klauspost/compress v1.17.9 // indirect
13 | )
14 |
--------------------------------------------------------------------------------
/htmlescapewriter.go:
--------------------------------------------------------------------------------
1 | package quicktemplate
2 |
3 | import (
4 | "bytes"
5 | "io"
6 | )
7 |
8 | type htmlEscapeWriter struct {
9 | w io.Writer
10 | }
11 |
12 | func (w *htmlEscapeWriter) Write(b []byte) (int, error) {
13 | if bytes.IndexByte(b, '<') < 0 &&
14 | bytes.IndexByte(b, '>') < 0 &&
15 | bytes.IndexByte(b, '"') < 0 &&
16 | bytes.IndexByte(b, '\'') < 0 &&
17 | bytes.IndexByte(b, '&') < 0 {
18 |
19 | // fast path - nothing to escape
20 | return w.w.Write(b)
21 | }
22 |
23 | // slow path
24 | write := w.w.Write
25 | j := 0
26 | for i, c := range b {
27 | switch c {
28 | case '<':
29 | write(b[j:i])
30 | write(strLT)
31 | j = i + 1
32 | case '>':
33 | write(b[j:i])
34 | write(strGT)
35 | j = i + 1
36 | case '"':
37 | write(b[j:i])
38 | write(strQuot)
39 | j = i + 1
40 | case '\'':
41 | write(b[j:i])
42 | write(strApos)
43 | j = i + 1
44 | case '&':
45 | write(b[j:i])
46 | write(strAmp)
47 | j = i + 1
48 | }
49 | }
50 | if n, err := write(b[j:]); err != nil {
51 | return j + n, err
52 | }
53 | return len(b), nil
54 | }
55 |
56 | var (
57 | strLT = []byte("<")
58 | strGT = []byte(">")
59 | strQuot = []byte(""")
60 | strApos = []byte("'")
61 | strAmp = []byte("&")
62 | )
63 |
--------------------------------------------------------------------------------
/htmlescapewriter_test.go:
--------------------------------------------------------------------------------
1 | package quicktemplate
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestHTMLEscapeWriter(t *testing.T) {
8 | testHTMLEscapeWriter(t, "", "")
9 | testHTMLEscapeWriter(t, "foobar", "foobar")
10 | testHTMLEscapeWriter(t, `fo'"bar&
`, "<h1>fo'"bar&</h1>")
11 | testHTMLEscapeWriter(t, "fobar привет\n\tbaz", "fo<b>bar привет\n\tbaz")
12 | }
13 |
14 | func testHTMLEscapeWriter(t *testing.T, s, expectedS string) {
15 | bb := AcquireByteBuffer()
16 | w := &htmlEscapeWriter{w: bb}
17 | n, err := w.Write([]byte(s))
18 | if err != nil {
19 | t.Fatalf("unexpected error when writing %q: %s", s, err)
20 | }
21 | if n != len(s) {
22 | t.Fatalf("unexpected n returned: %d. Expecting %d. s=%q", n, len(s), s)
23 | }
24 |
25 | if string(bb.B) != expectedS {
26 | t.Fatalf("unexpected result: %q. Expecting %q", bb.B, expectedS)
27 | }
28 | ReleaseByteBuffer(bb)
29 | }
30 |
--------------------------------------------------------------------------------
/htmlescapewriter_timing_test.go:
--------------------------------------------------------------------------------
1 | package quicktemplate
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func BenchmarkHTMLEscapeWriterNoHTML(b *testing.B) {
8 | s := "foobarbazabcdefghjkl"
9 | benchmarkHTMLEscapeWriter(b, s)
10 | }
11 |
12 | func BenchmarkHTMLEscapeWriterWithHTML(b *testing.B) {
13 | s := "foobazafghjkl"
14 | benchmarkHTMLEscapeWriter(b, s)
15 | }
16 |
17 | func benchmarkHTMLEscapeWriter(b *testing.B, s string) {
18 | sBytes := []byte(s)
19 | b.RunParallel(func(pb *testing.PB) {
20 | var err error
21 | bb := AcquireByteBuffer()
22 | w := &htmlEscapeWriter{w: bb}
23 | for pb.Next() {
24 | if _, err = w.Write(sBytes); err != nil {
25 | b.Fatalf("unexpected error: %s", err)
26 | }
27 | bb.Reset()
28 | }
29 | ReleaseByteBuffer(bb)
30 | })
31 | }
32 |
--------------------------------------------------------------------------------
/jsonstring.go:
--------------------------------------------------------------------------------
1 | package quicktemplate
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "strings"
7 | )
8 |
9 | func hasSpecialChars(s string) bool {
10 | if strings.IndexByte(s, '"') >= 0 || strings.IndexByte(s, '\\') >= 0 || strings.IndexByte(s, '<') >= 0 || strings.IndexByte(s, '\'') >= 0 {
11 | return true
12 | }
13 | for i := 0; i < len(s); i++ {
14 | if s[i] < 0x20 {
15 | return true
16 | }
17 | }
18 | return false
19 | }
20 |
21 | // AppendJSONString appends json-encoded string s to dst and returns the result.
22 | //
23 | // If addQuotes is true, then the appended json string is wrapped into double quotes.
24 | func AppendJSONString(dst []byte, s string, addQuotes bool) []byte {
25 | if !hasSpecialChars(s) {
26 | // Fast path - nothing to escape.
27 | if !addQuotes {
28 | return append(dst, s...)
29 | }
30 | dst = append(dst, '"')
31 | dst = append(dst, s...)
32 | dst = append(dst, '"')
33 | return dst
34 | }
35 |
36 | // Slow path - there are chars to escape.
37 | if addQuotes {
38 | dst = append(dst, '"')
39 | }
40 | dst = jsonReplacer.AppendReplace(dst, s)
41 | if addQuotes {
42 | dst = append(dst, '"')
43 | }
44 | return dst
45 | }
46 |
47 | var jsonReplacer = newByteReplacer(func() ([]byte, []string) {
48 | oldChars := []byte("\n\r\t\b\f\"\\<'")
49 | newStrings := []string{`\n`, `\r`, `\t`, `\b`, `\f`, `\"`, `\\`, `\u003c`, `\u0027`}
50 | for i := 0; i < 0x20; i++ {
51 | c := byte(i)
52 | if n := bytes.IndexByte(oldChars, c); n >= 0 {
53 | continue
54 | }
55 | oldChars = append(oldChars, byte(i))
56 | newStrings = append(newStrings, fmt.Sprintf(`\u%04x`, i))
57 | }
58 | return oldChars, newStrings
59 | }())
60 |
61 | type byteReplacer struct {
62 | m [256]byte
63 | newStrings []string
64 | }
65 |
66 | func newByteReplacer(oldChars []byte, newStrings []string) *byteReplacer {
67 | if len(oldChars) != len(newStrings) {
68 | panic(fmt.Errorf("len(oldChars)=%d must be equal to len(newStrings)=%d", len(oldChars), len(newStrings)))
69 | }
70 | if len(oldChars) >= 255 {
71 | panic(fmt.Errorf("len(oldChars)=%d must be smaller than 255", len(oldChars)))
72 | }
73 |
74 | var m [256]byte
75 | for i := range m[:] {
76 | m[i] = 255
77 | }
78 | for i, c := range oldChars {
79 | m[c] = byte(i)
80 | }
81 | return &byteReplacer{
82 | m: m,
83 | newStrings: newStrings,
84 | }
85 | }
86 |
87 | func (br *byteReplacer) AppendReplace(dst []byte, s string) []byte {
88 | m := br.m
89 | newStrings := br.newStrings
90 | for i := 0; i < len(s); i++ {
91 | c := s[i]
92 | n := m[c]
93 | if n == 255 {
94 | dst = append(dst, c)
95 | } else {
96 | dst = append(dst, newStrings[n]...)
97 | }
98 | }
99 | return dst
100 | }
101 |
--------------------------------------------------------------------------------
/jsonstring_test.go:
--------------------------------------------------------------------------------
1 | package quicktemplate
2 |
3 | import (
4 | "encoding/json"
5 | "strings"
6 | "testing"
7 | )
8 |
9 | func TestAppendJSONString(t *testing.T) {
10 | testAppendJSONString(t, ``)
11 | testAppendJSONString(t, `f`)
12 | testAppendJSONString(t, `"`)
13 | testAppendJSONString(t, `<`)
14 | testAppendJSONString(t, "\x00\n\r\t\b\f"+`"\`)
15 | testAppendJSONString(t, `"foobar`)
16 | testAppendJSONString(t, `foobar"`)
17 | testAppendJSONString(t, `foo "bar"
18 | baz`)
19 | testAppendJSONString(t, `this is a "тест"`)
20 | testAppendJSONString(t, `привет test ыва`)
21 |
22 | testAppendJSONString(t, ``)
23 | testAppendJSONString(t, "\u001b")
24 | }
25 |
26 | func testAppendJSONString(t *testing.T, s string) {
27 | expectedResult, err := json.Marshal(s)
28 | if err != nil {
29 | t.Fatalf("unexpected error when encoding string %q: %s", s, err)
30 | }
31 | expectedResult = expectedResult[1 : len(expectedResult)-1]
32 |
33 | bb := AcquireByteBuffer()
34 | bb.B = AppendJSONString(bb.B[:0], s, false)
35 | result := string(bb.B)
36 | ReleaseByteBuffer(bb)
37 |
38 | if strings.Contains(result, "'") {
39 | t.Fatalf("json string shouldn't contain single quote: %q, src %q", result, s)
40 | }
41 | result = strings.Replace(result, `\u0027`, "'", -1)
42 | result = strings.Replace(result, ">", `\u003e`, -1)
43 | if result != string(expectedResult) {
44 | t.Fatalf("unexpected result %q. Expecting %q. original string %q", result, expectedResult, s)
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/jsonstring_timing_test.go:
--------------------------------------------------------------------------------
1 | package quicktemplate
2 |
3 | import (
4 | "strconv"
5 | "testing"
6 | )
7 |
8 | func BenchmarkAppendJSONString(b *testing.B) {
9 | b.Run("no-special-chars", func(b *testing.B) {
10 | benchmarkAppendJSONString(b, "foo bar baz abc defkjlkj lkjdfs klsdjflfdjoqjo lkj ss")
11 | })
12 | b.Run("with-special-chars", func(b *testing.B) {
13 | benchmarkAppendJSONString(b, `foo bar baz abc defkjlkj lkjdf" klsdjflfdjoqjo\lkj ss`)
14 | })
15 | }
16 |
17 | func benchmarkAppendJSONString(b *testing.B, s string) {
18 | b.ReportAllocs()
19 | b.SetBytes(int64(len(s)))
20 | b.RunParallel(func(pb *testing.PB) {
21 | var buf []byte
22 | for pb.Next() {
23 | buf = AppendJSONString(buf[:0], s, true)
24 | }
25 | })
26 | }
27 |
28 | func BenchmarkAppendJSONStringViaStrconv(b *testing.B) {
29 | b.Run("no-special-chars", func(b *testing.B) {
30 | benchmarkAppendJSONStringViaStrconv(b, "foo bar baz abc defkjlkj lkjdfs klsdjflfdjoqjo lkj ss")
31 | })
32 | b.Run("with-special-chars", func(b *testing.B) {
33 | benchmarkAppendJSONStringViaStrconv(b, `foo bar baz abc defkjlkj lkjdf" klsdjflfdjoqjo\lkj ss`)
34 | })
35 | }
36 |
37 | func benchmarkAppendJSONStringViaStrconv(b *testing.B, s string) {
38 | b.ReportAllocs()
39 | b.SetBytes(int64(len(s)))
40 | b.RunParallel(func(pb *testing.PB) {
41 | var buf []byte
42 | for pb.Next() {
43 | buf = strconv.AppendQuote(buf[:0], s)
44 | }
45 | })
46 | }
47 |
--------------------------------------------------------------------------------
/parser/util.go:
--------------------------------------------------------------------------------
1 | package parser
2 |
3 | import (
4 | "bytes"
5 | "errors"
6 | "io/ioutil"
7 | "path/filepath"
8 | "unicode"
9 | )
10 |
11 | // mangleSuffix is used for mangling quicktemplate-specific names
12 | // in the generated code, so they don't clash with user-provided names.
13 | const mangleSuffix = "422016"
14 |
15 | func stripLeadingSpace(b []byte) []byte {
16 | for len(b) > 0 && isSpace(b[0]) {
17 | b = b[1:]
18 | }
19 | return b
20 | }
21 |
22 | func stripTrailingSpace(b []byte) []byte {
23 | for len(b) > 0 && isSpace(b[len(b)-1]) {
24 | b = b[:len(b)-1]
25 | }
26 | return b
27 | }
28 |
29 | func collapseSpace(b []byte) []byte {
30 | return stripSpaceExt(b, true)
31 | }
32 |
33 | func stripSpace(b []byte) []byte {
34 | return stripSpaceExt(b, false)
35 | }
36 |
37 | func stripSpaceExt(b []byte, isCollapse bool) []byte {
38 | if len(b) == 0 {
39 | return b
40 | }
41 |
42 | var dst []byte
43 | if isCollapse && isSpace(b[0]) {
44 | dst = append(dst, ' ')
45 | }
46 | isLastSpace := isSpace(b[len(b)-1])
47 | for len(b) > 0 {
48 | n := bytes.IndexByte(b, '\n')
49 | if n < 0 {
50 | n = len(b)
51 | }
52 | z := b[:n]
53 | if n == len(b) {
54 | b = b[n:]
55 | } else {
56 | b = b[n+1:]
57 | }
58 | z = stripLeadingSpace(z)
59 | z = stripTrailingSpace(z)
60 | if len(z) == 0 {
61 | continue
62 | }
63 | dst = append(dst, z...)
64 | if isCollapse {
65 | dst = append(dst, ' ')
66 | }
67 | }
68 | if isCollapse && !isLastSpace && len(dst) > 0 {
69 | dst = dst[:len(dst)-1]
70 | }
71 | return dst
72 | }
73 |
74 | func isSpace(c byte) bool {
75 | return unicode.IsSpace(rune(c))
76 | }
77 |
78 | func isUpper(c byte) bool {
79 | return unicode.IsUpper(rune(c))
80 | }
81 |
82 | func readFile(cwd, filename string) ([]byte, error) {
83 | if len(filename) == 0 {
84 | return nil, errors.New("filename cannot be empty")
85 | }
86 | if filename[0] != '/' {
87 | cwdAbs, err := filepath.Abs(cwd)
88 | if err != nil {
89 | return nil, err
90 | }
91 | dir, _ := filepath.Split(cwdAbs)
92 | filename = filepath.Join(dir, filename)
93 | }
94 |
95 | return ioutil.ReadFile(filename)
96 | }
97 |
--------------------------------------------------------------------------------
/qtc/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Aliaksandr Valialkin, VertaMedia
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/qtc/README.md:
--------------------------------------------------------------------------------
1 | # qtc
2 |
3 | Template compiler (converter) for [quicktemplate](https://github.com/valyala/quicktemplate).
4 | Converts quicktemplate files into Go code. By default these files
5 | have `.qtpl` extension.
6 |
7 | # Usage
8 |
9 | ```
10 | $ go get -u github.com/valyala/quicktemplate/qtc
11 | $ qtc -h
12 | ```
13 |
14 | `qtc` may be called either directly or via [go generate](https://blog.golang.org/generate).
15 | The latter case is preffered. Just put the following line near the `main` function:
16 |
17 | ```go
18 | package main
19 |
20 | //go:generate qtc -dir=path/to/directory/with/templates
21 |
22 | func main() {
23 | // main code here
24 | }
25 | ```
26 |
27 | Then run `go generate` whenever you need re-generating template code.
28 | Directory with templates may contain arbirary number of subdirectories -
29 | `qtc` generates template code recursively for each subdirectory.
30 |
31 | Directories with templates may also contain arbitrary `.go` files - contents
32 | of these files may be used inside templates. Such Go files usually contain
33 | various helper functions and structs.
34 |
--------------------------------------------------------------------------------
/testdata/qtc/.gitignore:
--------------------------------------------------------------------------------
1 | *.generated
2 |
--------------------------------------------------------------------------------
/testdata/templates/bench.qtpl:
--------------------------------------------------------------------------------
1 | {% code
2 |
3 | type BenchRow struct {
4 | ID int
5 | Message string
6 | Print bool
7 | }
8 |
9 | %}
10 |
11 | {% func BenchPage(rows []BenchRow) %}
12 | test
13 |
14 |
15 | {% for _, row := range rows %}
16 | {% if row.Print %}
17 | - ID={%d row.ID %}, Message={%s row.Message %}
18 | {% endif %}
19 | {% endfor %}
20 |
21 |
22 |
23 | {% endfunc %}
24 |
--------------------------------------------------------------------------------
/testdata/templates/bench.qtpl.go:
--------------------------------------------------------------------------------
1 | // Code generated by qtc from "bench.qtpl". DO NOT EDIT.
2 | // See https://github.com/valyala/quicktemplate for details.
3 |
4 | //line testdata/templates/bench.qtpl:1
5 | package templates
6 |
7 | //line testdata/templates/bench.qtpl:1
8 | import (
9 | qtio422016 "io"
10 |
11 | qt422016 "github.com/valyala/quicktemplate"
12 | )
13 |
14 | //line testdata/templates/bench.qtpl:1
15 | var (
16 | _ = qtio422016.Copy
17 | _ = qt422016.AcquireByteBuffer
18 | )
19 |
20 | //line testdata/templates/bench.qtpl:3
21 | type BenchRow struct {
22 | ID int
23 | Message string
24 | Print bool
25 | }
26 |
27 | //line testdata/templates/bench.qtpl:11
28 | func StreamBenchPage(qw422016 *qt422016.Writer, rows []BenchRow) {
29 | //line testdata/templates/bench.qtpl:11
30 | qw422016.N().S(`
31 | test
32 |
33 |
34 | `)
35 | //line testdata/templates/bench.qtpl:15
36 | for _, row := range rows {
37 | //line testdata/templates/bench.qtpl:15
38 | qw422016.N().S(`
39 | `)
40 | //line testdata/templates/bench.qtpl:16
41 | if row.Print {
42 | //line testdata/templates/bench.qtpl:16
43 | qw422016.N().S(`
44 | - ID=`)
45 | //line testdata/templates/bench.qtpl:17
46 | qw422016.N().D(row.ID)
47 | //line testdata/templates/bench.qtpl:17
48 | qw422016.N().S(`, Message=`)
49 | //line testdata/templates/bench.qtpl:17
50 | qw422016.E().S(row.Message)
51 | //line testdata/templates/bench.qtpl:17
52 | qw422016.N().S(`
53 | `)
54 | //line testdata/templates/bench.qtpl:18
55 | }
56 | //line testdata/templates/bench.qtpl:18
57 | qw422016.N().S(`
58 | `)
59 | //line testdata/templates/bench.qtpl:19
60 | }
61 | //line testdata/templates/bench.qtpl:19
62 | qw422016.N().S(`
63 |
64 |
65 |
66 | `)
67 | //line testdata/templates/bench.qtpl:23
68 | }
69 |
70 | //line testdata/templates/bench.qtpl:23
71 | func WriteBenchPage(qq422016 qtio422016.Writer, rows []BenchRow) {
72 | //line testdata/templates/bench.qtpl:23
73 | qw422016 := qt422016.AcquireWriter(qq422016)
74 | //line testdata/templates/bench.qtpl:23
75 | StreamBenchPage(qw422016, rows)
76 | //line testdata/templates/bench.qtpl:23
77 | qt422016.ReleaseWriter(qw422016)
78 | //line testdata/templates/bench.qtpl:23
79 | }
80 |
81 | //line testdata/templates/bench.qtpl:23
82 | func BenchPage(rows []BenchRow) string {
83 | //line testdata/templates/bench.qtpl:23
84 | qb422016 := qt422016.AcquireByteBuffer()
85 | //line testdata/templates/bench.qtpl:23
86 | WriteBenchPage(qb422016, rows)
87 | //line testdata/templates/bench.qtpl:23
88 | qs422016 := string(qb422016.B)
89 | //line testdata/templates/bench.qtpl:23
90 | qt422016.ReleaseByteBuffer(qb422016)
91 | //line testdata/templates/bench.qtpl:23
92 | return qs422016
93 | //line testdata/templates/bench.qtpl:23
94 | }
95 |
--------------------------------------------------------------------------------
/testdata/templates/bench.tpl:
--------------------------------------------------------------------------------
1 |
2 | test
3 |
4 |
5 | {{range .}}
6 | {{if .Print}}
7 | - ID={{.ID}}, Message={{.Message}}
8 | {{end}}
9 | {{end}}
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/testdata/templates/integration.qtpl:
--------------------------------------------------------------------------------
1 | This is a template for integration test.
2 | It should contains all the quicktemplate stuff.
3 |
4 | {% import "fmt" %}
5 |
6 | {% func Integration() %}
7 | Output tags` verification.
8 |
9 | {% code
10 | p := &integrationPage{
11 | S: "foobar",
12 | }
13 | %}
14 | Embedded func template:
15 | plain: {%= embeddedFunc(p) %}
16 | html-escaped: {%=h embeddedFunc(p) %}
17 | url-escaped: {%=u embeddedFunc(p) %}
18 | quoted json string: {%=q embeddedFunc(p) %}
19 | unquoted json string: {%=j embeddedFunc(p) %}
20 | html-escaped url-escaped: {%=uh embeddedFunc(p) %}
21 | html-escaped quoted json string: {%=qh embeddedFunc(p) %}
22 | html-escaped unquoted json string: {%=jh embeddedFunc(p) %}
23 |
24 | Html-escaped output tags:
25 |
26 | - {%s "html-escaped `string" %}
27 | - {%z []byte("html-escaped `byte slice") %}
28 | - Int: {%d 42 %}
29 | - Float: {%f 3.14 %}
30 | - {%q ` "json"
31 | string` %}
32 | - alert("foo {%j `"json"-safe
33 | ` %} aa" + 'bar {%j `';alert("evil")` %}')
34 | - test
35 | - {%v struct{ A string }{A: "foobar`"} %}
36 |
37 |
38 | Output tags without html escaping
39 |
40 | - {%s= "html-escaped `string" %}
41 | - {%z= []byte("html-escaped `byte slice") %}
42 | - Int: {%d= 42 %}
43 | - Float: {%f= 3.14 %}
44 | - {%q= ` "json"
45 | string` %}
46 | - alert("foo {%j= `"json"-safe
47 | ` %} aa" + 'bar {%j= `';alert("evil")` %}')
48 | - test
49 | - {%v= struct{ A string }{A: "foobar`"} %}
50 |
51 |
52 | {% stripspace %}
53 | Strip space {%space%}
54 | between lines and tags
55 | {%plain%}
56 | Tags aren't parsed {%inside %}
57 | plain
58 | {%endplain%}
59 | {% code // one-liner comment %}
60 | {% code
61 | // multi-line
62 | // comment
63 | %}
64 | {% code
65 | /*
66 | yet another
67 | multi-line comment
68 | */
69 | %}
70 | {% endstripspace %}
71 |
72 | {% collapsespace %}
73 | Collapse space {%space %}
74 | between {%newline%} lines and tags
75 | {%comment%}
76 | Comments {%are%}
77 | ignored
78 | {%endcomment%}
79 |
80 | {% for _, s := range []string{"foo","bar","baz"} %}
81 | {% if s == "bar" %}
82 | Bar
83 | {% elseif s == "baz" %}
84 | Baz
85 | {% break %}
86 | {% else %}
87 | {% if s == "never" %}
88 | {% return %}
89 | {% endif %}
90 |
91 | {% switch s %}
92 | {% case "foobar" %}
93 | s = foobar
94 | {% case "barbaz" %}
95 | s = barbaz
96 | {% default %}
97 | s = {%s s %}
98 | {% endswitch %}
99 |
100 | {% continue %}
101 | {% endif %}
102 | {% endfor %}
103 | {% endcollapsespace %}
104 |
105 | {% cat "integration.qtpl" %}
106 |
107 | Strip leading and trailing space:
108 | {%- for i := 0; i < 4; i++ -%}
109 | x += {%d i -%} + {%-d i+1 %}
110 | {%- endfor -%}
111 | end
112 |
113 | tail of the func
114 | {% endfunc %}
115 |
116 | {%
117 | interface Page {
118 | Header()
119 | Body()
120 | }
121 | %}
122 |
123 | {% func embeddedFunc(p Page) %}
124 | Page's header: {%= p.Header() %}
125 | Body: {%s= fmt.Sprintf("%s", p.Body()) %}
126 | {% endfunc %}
127 |
128 | {% code
129 | type integrationPage struct {
130 | S string
131 | }
132 | %}
133 |
134 | {% func (p *integrationPage) Header() %}Header{% endfunc %}
135 |
136 | {% func (p *integrationPage) Body() %}
137 | S={%q p.S %}
138 | {% endfunc %}
139 |
--------------------------------------------------------------------------------
/testdata/templates/marshal.qtpl:
--------------------------------------------------------------------------------
1 | Templates for marshal_timing_test.go
2 |
3 | {% code
4 | type MarshalRow struct {
5 | Msg string
6 | N int
7 | }
8 |
9 | type MarshalData struct {
10 | Foo int
11 | Bar string
12 | Rows []MarshalRow
13 | }
14 | %}
15 |
16 | // JSON marshaling
17 | {% stripspace %}
18 | {% func (d *MarshalData) JSON() %}
19 | {
20 | "Foo": {%d d.Foo %},
21 | "Bar": {%q= d.Bar %},
22 | "Rows":[
23 | {% for i, r := range d.Rows %}
24 | {
25 | "Msg": {%q= r.Msg %},
26 | "N": {%d r.N %}
27 | }
28 | {% if i + 1 < len(d.Rows) %},{% endif %}
29 | {% endfor %}
30 | ]
31 | }
32 | {% endfunc %}
33 | {% endstripspace %}
34 |
35 | // XML marshaling
36 | {% stripspace %}
37 | {% func (d *MarshalData) XML() %}
38 |
39 | {%d d.Foo %}
40 | {%s d.Bar %}
41 | {% for _, r := range d.Rows %}
42 |
43 | {%s r.Msg %}
44 | {%d r.N %}
45 |
46 | {% endfor %}
47 |
48 | {% endfunc %}
49 | {% endstripspace %}
50 |
--------------------------------------------------------------------------------
/tests/doc.go:
--------------------------------------------------------------------------------
1 | // Package tests contains tests for quicktemplate
2 | package tests
3 |
--------------------------------------------------------------------------------
/tests/integration_test.go:
--------------------------------------------------------------------------------
1 | package tests
2 |
3 | import (
4 | "io/ioutil"
5 | "testing"
6 |
7 | "github.com/valyala/quicktemplate/testdata/templates"
8 | )
9 |
10 | func TestIntegration(t *testing.T) {
11 | expectedS, err := ioutil.ReadFile("../testdata/templates/integration.qtpl.out")
12 | if err != nil {
13 | t.Fatalf("unexpected error: %s", err)
14 | }
15 | s := templates.Integration()
16 | if s != string(expectedS) {
17 | t.Fatalf("unexpected output\n%q\nExpecting\n%q\n", s, expectedS)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/tests/templates_timing_test.go:
--------------------------------------------------------------------------------
1 | package tests
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "html/template"
7 | "log"
8 | "testing"
9 | texttemplate "text/template"
10 |
11 | "github.com/valyala/quicktemplate"
12 | "github.com/valyala/quicktemplate/testdata/templates"
13 | )
14 |
15 | var tpl = template.Must(template.ParseFiles("../testdata/templates/bench.tpl"))
16 | var textTpl = texttemplate.Must(texttemplate.ParseFiles("../testdata/templates/bench.tpl"))
17 |
18 | func init() {
19 | // make sure that both template engines generate the same result
20 | rows := getBenchRows(3)
21 |
22 | bb1 := &quicktemplate.ByteBuffer{}
23 | if err := tpl.Execute(bb1, rows); err != nil {
24 | log.Fatalf("unexpected error: %s", err)
25 | }
26 |
27 | bb2 := &quicktemplate.ByteBuffer{}
28 | templates.WriteBenchPage(bb2, rows)
29 |
30 | if !bytes.Equal(bb1.B, bb2.B) {
31 | log.Fatalf("results mismatch:\n%q\n%q", bb1, bb2)
32 | }
33 | }
34 |
35 | func BenchmarkQuickTemplate1(b *testing.B) {
36 | benchmarkQuickTemplate(b, 1)
37 | }
38 |
39 | func BenchmarkQuickTemplate10(b *testing.B) {
40 | benchmarkQuickTemplate(b, 10)
41 | }
42 |
43 | func BenchmarkQuickTemplate100(b *testing.B) {
44 | benchmarkQuickTemplate(b, 100)
45 | }
46 |
47 | func benchmarkQuickTemplate(b *testing.B, rowsCount int) {
48 | rows := getBenchRows(rowsCount)
49 | b.RunParallel(func(pb *testing.PB) {
50 | bb := quicktemplate.AcquireByteBuffer()
51 | for pb.Next() {
52 | templates.WriteBenchPage(bb, rows)
53 | bb.Reset()
54 | }
55 | quicktemplate.ReleaseByteBuffer(bb)
56 | })
57 | }
58 |
59 | func BenchmarkHTMLTemplate1(b *testing.B) {
60 | benchmarkHTMLTemplate(b, 1)
61 | }
62 |
63 | func BenchmarkHTMLTemplate10(b *testing.B) {
64 | benchmarkHTMLTemplate(b, 10)
65 | }
66 |
67 | func BenchmarkHTMLTemplate100(b *testing.B) {
68 | benchmarkHTMLTemplate(b, 100)
69 | }
70 |
71 | func benchmarkHTMLTemplate(b *testing.B, rowsCount int) {
72 | rows := getBenchRows(rowsCount)
73 | b.RunParallel(func(pb *testing.PB) {
74 | bb := quicktemplate.AcquireByteBuffer()
75 | for pb.Next() {
76 | if err := tpl.Execute(bb, rows); err != nil {
77 | b.Fatalf("unexpected error: %s", err)
78 | }
79 | bb.Reset()
80 | }
81 | quicktemplate.ReleaseByteBuffer(bb)
82 | })
83 | }
84 |
85 | func BenchmarkTextTemplate1(b *testing.B) {
86 | benchmarkTextTemplate(b, 1)
87 | }
88 |
89 | func BenchmarkTextTemplate10(b *testing.B) {
90 | benchmarkTextTemplate(b, 10)
91 | }
92 |
93 | func BenchmarkTextTemplate100(b *testing.B) {
94 | benchmarkTextTemplate(b, 100)
95 | }
96 |
97 | func benchmarkTextTemplate(b *testing.B, rowsCount int) {
98 | rows := getBenchRows(rowsCount)
99 | b.RunParallel(func(pb *testing.PB) {
100 | bb := quicktemplate.AcquireByteBuffer()
101 | for pb.Next() {
102 | if err := textTpl.Execute(bb, rows); err != nil {
103 | b.Fatalf("unexpected error: %s", err)
104 | }
105 | bb.Reset()
106 | }
107 | quicktemplate.ReleaseByteBuffer(bb)
108 | })
109 | }
110 |
111 | func getBenchRows(n int) []templates.BenchRow {
112 | rows := make([]templates.BenchRow, n)
113 | for i := 0; i < n; i++ {
114 | rows[i] = templates.BenchRow{
115 | ID: i,
116 | Message: fmt.Sprintf("message %d", i),
117 | Print: ((i & 1) == 0),
118 | }
119 | }
120 | return rows
121 | }
122 |
--------------------------------------------------------------------------------
/urlencode.go:
--------------------------------------------------------------------------------
1 | package quicktemplate
2 |
3 | func appendURLEncode(dst []byte, src string) []byte {
4 | n := len(src)
5 | if n > 0 {
6 | // Hint the compiler to remove bounds checks in the loop below.
7 | _ = src[n-1]
8 | }
9 | for i := 0; i < n; i++ {
10 | c := src[i]
11 |
12 | // See http://www.w3.org/TR/html5/forms.html#form-submission-algorithm
13 | if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' ||
14 | c == '-' || c == '.' || c == '_' {
15 | dst = append(dst, c)
16 | } else {
17 | if c == ' ' {
18 | dst = append(dst, '+')
19 | } else {
20 | dst = append(dst, '%', hexCharUpper(c>>4), hexCharUpper(c&15))
21 | }
22 | }
23 | }
24 | return dst
25 | }
26 |
27 | func hexCharUpper(c byte) byte {
28 | if c < 10 {
29 | return '0' + c
30 | }
31 | return c - 10 + 'A'
32 | }
33 |
--------------------------------------------------------------------------------
/urlencode_test.go:
--------------------------------------------------------------------------------
1 | package quicktemplate
2 |
3 | import (
4 | "net/url"
5 | "testing"
6 | )
7 |
8 | func TestAppendURLEncode(t *testing.T) {
9 | testAppendURLEncode(t, "")
10 | testAppendURLEncode(t, "f")
11 | testAppendURLEncode(t, " ")
12 | testAppendURLEncode(t, ".-_")
13 | testAppendURLEncode(t, "тест+this/&=;?\n\t\rabc")
14 | }
15 |
16 | func testAppendURLEncode(t *testing.T, s string) {
17 | expectedResult := url.QueryEscape(s)
18 | result := appendURLEncode(nil, s)
19 | if string(result) != expectedResult {
20 | t.Fatalf("unexpected result %q. Expecting %q. str=%q", result, expectedResult, s)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/util.go:
--------------------------------------------------------------------------------
1 | package quicktemplate
2 |
3 | //go:generate qtc -dir=testdata/templates
4 |
--------------------------------------------------------------------------------
/util_appengine.go:
--------------------------------------------------------------------------------
1 | //go:build appengine || appenginevm
2 | // +build appengine appenginevm
3 |
4 | package quicktemplate
5 |
6 | func unsafeStrToBytes(s string) []byte {
7 | return []byte(s)
8 | }
9 |
10 | func unsafeBytesToStr(z []byte) string {
11 | return string(z)
12 | }
13 |
--------------------------------------------------------------------------------
/util_noappengine.go:
--------------------------------------------------------------------------------
1 | //go:build !appengine && !appenginevm
2 | // +build !appengine,!appenginevm
3 |
4 | package quicktemplate
5 |
6 | import (
7 | "reflect"
8 | "unsafe"
9 | )
10 |
11 | func unsafeStrToBytes(s string) (b []byte) {
12 | sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
13 | bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
14 | bh.Data = sh.Data
15 | bh.Len = sh.Len
16 | bh.Cap = sh.Len
17 | return b
18 | }
19 |
20 | func unsafeBytesToStr(z []byte) string {
21 | return *(*string)(unsafe.Pointer(&z))
22 | }
23 |
--------------------------------------------------------------------------------
/vendor/github.com/andybalholm/brotli/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors.
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/vendor/github.com/andybalholm/brotli/README.md:
--------------------------------------------------------------------------------
1 | This package is a brotli compressor and decompressor implemented in Go.
2 | It was translated from the reference implementation (https://github.com/google/brotli)
3 | with the `c2go` tool at https://github.com/andybalholm/c2go.
4 |
5 | I have been working on new compression algorithms (not translated from C)
6 | in the matchfinder package.
7 | You can use them with the NewWriterV2 function.
8 | Currently they give better results than the old implementation
9 | (at least for compressing my test file, Newton’s *Opticks*)
10 | on levels 2 to 6.
11 |
12 | I am using it in production with https://github.com/andybalholm/redwood.
13 |
14 | API documentation is found at https://pkg.go.dev/github.com/andybalholm/brotli?tab=doc.
15 |
--------------------------------------------------------------------------------
/vendor/github.com/andybalholm/brotli/bitwriter.go:
--------------------------------------------------------------------------------
1 | package brotli
2 |
3 | /* Copyright 2010 Google Inc. All Rights Reserved.
4 |
5 | Distributed under MIT license.
6 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
7 | */
8 |
9 | /* Write bits into a byte array. */
10 |
11 | type bitWriter struct {
12 | dst []byte
13 |
14 | // Data waiting to be written is the low nbits of bits.
15 | bits uint64
16 | nbits uint
17 | }
18 |
19 | func (w *bitWriter) writeBits(nb uint, b uint64) {
20 | w.bits |= b << w.nbits
21 | w.nbits += nb
22 | if w.nbits >= 32 {
23 | bits := w.bits
24 | w.bits >>= 32
25 | w.nbits -= 32
26 | w.dst = append(w.dst,
27 | byte(bits),
28 | byte(bits>>8),
29 | byte(bits>>16),
30 | byte(bits>>24),
31 | )
32 | }
33 | }
34 |
35 | func (w *bitWriter) writeSingleBit(bit bool) {
36 | if bit {
37 | w.writeBits(1, 1)
38 | } else {
39 | w.writeBits(1, 0)
40 | }
41 | }
42 |
43 | func (w *bitWriter) jumpToByteBoundary() {
44 | dst := w.dst
45 | for w.nbits != 0 {
46 | dst = append(dst, byte(w.bits))
47 | w.bits >>= 8
48 | if w.nbits > 8 { // Avoid underflow
49 | w.nbits -= 8
50 | } else {
51 | w.nbits = 0
52 | }
53 | }
54 | w.bits = 0
55 | w.dst = dst
56 | }
57 |
--------------------------------------------------------------------------------
/vendor/github.com/andybalholm/brotli/cluster.go:
--------------------------------------------------------------------------------
1 | package brotli
2 |
3 | /* Copyright 2013 Google Inc. All Rights Reserved.
4 |
5 | Distributed under MIT license.
6 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
7 | */
8 |
9 | /* Functions for clustering similar histograms together. */
10 |
11 | type histogramPair struct {
12 | idx1 uint32
13 | idx2 uint32
14 | cost_combo float64
15 | cost_diff float64
16 | }
17 |
18 | func histogramPairIsLess(p1 *histogramPair, p2 *histogramPair) bool {
19 | if p1.cost_diff != p2.cost_diff {
20 | return p1.cost_diff > p2.cost_diff
21 | }
22 |
23 | return (p1.idx2 - p1.idx1) > (p2.idx2 - p2.idx1)
24 | }
25 |
26 | /* Returns entropy reduction of the context map when we combine two clusters. */
27 | func clusterCostDiff(size_a uint, size_b uint) float64 {
28 | var size_c uint = size_a + size_b
29 | return float64(size_a)*fastLog2(size_a) + float64(size_b)*fastLog2(size_b) - float64(size_c)*fastLog2(size_c)
30 | }
31 |
--------------------------------------------------------------------------------
/vendor/github.com/andybalholm/brotli/constants.go:
--------------------------------------------------------------------------------
1 | package brotli
2 |
3 | /* Copyright 2016 Google Inc. All Rights Reserved.
4 |
5 | Distributed under MIT license.
6 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
7 | */
8 |
9 | /* Specification: 7.3. Encoding of the context map */
10 | const contextMapMaxRle = 16
11 |
12 | /* Specification: 2. Compressed representation overview */
13 | const maxNumberOfBlockTypes = 256
14 |
15 | /* Specification: 3.3. Alphabet sizes: insert-and-copy length */
16 | const numLiteralSymbols = 256
17 |
18 | const numCommandSymbols = 704
19 |
20 | const numBlockLenSymbols = 26
21 |
22 | const maxContextMapSymbols = (maxNumberOfBlockTypes + contextMapMaxRle)
23 |
24 | const maxBlockTypeSymbols = (maxNumberOfBlockTypes + 2)
25 |
26 | /* Specification: 3.5. Complex prefix codes */
27 | const repeatPreviousCodeLength = 16
28 |
29 | const repeatZeroCodeLength = 17
30 |
31 | const codeLengthCodes = (repeatZeroCodeLength + 1)
32 |
33 | /* "code length of 8 is repeated" */
34 | const initialRepeatedCodeLength = 8
35 |
36 | /* "Large Window Brotli" */
37 | const largeMaxDistanceBits = 62
38 |
39 | const largeMinWbits = 10
40 |
41 | const largeMaxWbits = 30
42 |
43 | /* Specification: 4. Encoding of distances */
44 | const numDistanceShortCodes = 16
45 |
46 | const maxNpostfix = 3
47 |
48 | const maxNdirect = 120
49 |
50 | const maxDistanceBits = 24
51 |
52 | func distanceAlphabetSize(NPOSTFIX uint, NDIRECT uint, MAXNBITS uint) uint {
53 | return numDistanceShortCodes + NDIRECT + uint(MAXNBITS<<(NPOSTFIX+1))
54 | }
55 |
56 | /* numDistanceSymbols == 1128 */
57 | const numDistanceSymbols = 1128
58 |
59 | const maxDistance = 0x3FFFFFC
60 |
61 | const maxAllowedDistance = 0x7FFFFFFC
62 |
63 | /* 7.1. Context modes and context ID lookup for literals */
64 | /* "context IDs for literals are in the range of 0..63" */
65 | const literalContextBits = 6
66 |
67 | /* 7.2. Context ID for distances */
68 | const distanceContextBits = 2
69 |
70 | /* 9.1. Format of the Stream Header */
71 | /* Number of slack bytes for window size. Don't confuse
72 | with BROTLI_NUM_DISTANCE_SHORT_CODES. */
73 | const windowGap = 16
74 |
75 | func maxBackwardLimit(W uint) uint {
76 | return (uint(1) << W) - windowGap
77 | }
78 |
--------------------------------------------------------------------------------
/vendor/github.com/andybalholm/brotli/encoder_dict.go:
--------------------------------------------------------------------------------
1 | package brotli
2 |
3 | /* Dictionary data (words and transforms) for 1 possible context */
4 | type encoderDictionary struct {
5 | words *dictionary
6 | cutoffTransformsCount uint32
7 | cutoffTransforms uint64
8 | hash_table []uint16
9 | buckets []uint16
10 | dict_words []dictWord
11 | }
12 |
13 | func initEncoderDictionary(dict *encoderDictionary) {
14 | dict.words = getDictionary()
15 |
16 | dict.hash_table = kStaticDictionaryHash[:]
17 | dict.buckets = kStaticDictionaryBuckets[:]
18 | dict.dict_words = kStaticDictionaryWords[:]
19 |
20 | dict.cutoffTransformsCount = kCutoffTransformsCount
21 | dict.cutoffTransforms = kCutoffTransforms
22 | }
23 |
--------------------------------------------------------------------------------
/vendor/github.com/andybalholm/brotli/find_match_length.go:
--------------------------------------------------------------------------------
1 | package brotli
2 |
3 | import (
4 | "encoding/binary"
5 | "math/bits"
6 | "runtime"
7 | )
8 |
9 | /* Copyright 2010 Google Inc. All Rights Reserved.
10 |
11 | Distributed under MIT license.
12 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
13 | */
14 |
15 | /* Function to find maximal matching prefixes of strings. */
16 | func findMatchLengthWithLimit(s1 []byte, s2 []byte, limit uint) uint {
17 | var matched uint = 0
18 | _, _ = s1[limit-1], s2[limit-1] // bounds check
19 | switch runtime.GOARCH {
20 | case "amd64":
21 | // Compare 8 bytes at at time.
22 | for matched+8 <= limit {
23 | w1 := binary.LittleEndian.Uint64(s1[matched:])
24 | w2 := binary.LittleEndian.Uint64(s2[matched:])
25 | if w1 != w2 {
26 | return matched + uint(bits.TrailingZeros64(w1^w2)>>3)
27 | }
28 | matched += 8
29 | }
30 | case "386":
31 | // Compare 4 bytes at at time.
32 | for matched+4 <= limit {
33 | w1 := binary.LittleEndian.Uint32(s1[matched:])
34 | w2 := binary.LittleEndian.Uint32(s2[matched:])
35 | if w1 != w2 {
36 | return matched + uint(bits.TrailingZeros32(w1^w2)>>3)
37 | }
38 | matched += 4
39 | }
40 | }
41 | for matched < limit && s1[matched] == s2[matched] {
42 | matched++
43 | }
44 | return matched
45 | }
46 |
--------------------------------------------------------------------------------
/vendor/github.com/andybalholm/brotli/hash_composite.go:
--------------------------------------------------------------------------------
1 | package brotli
2 |
3 | /* Copyright 2018 Google Inc. All Rights Reserved.
4 |
5 | Distributed under MIT license.
6 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
7 | */
8 |
9 | func (h *hashComposite) HashTypeLength() uint {
10 | var a uint = h.ha.HashTypeLength()
11 | var b uint = h.hb.HashTypeLength()
12 | if a > b {
13 | return a
14 | } else {
15 | return b
16 | }
17 | }
18 |
19 | func (h *hashComposite) StoreLookahead() uint {
20 | var a uint = h.ha.StoreLookahead()
21 | var b uint = h.hb.StoreLookahead()
22 | if a > b {
23 | return a
24 | } else {
25 | return b
26 | }
27 | }
28 |
29 | /* Composite hasher: This hasher allows to combine two other hashers, HASHER_A
30 | and HASHER_B. */
31 | type hashComposite struct {
32 | hasherCommon
33 | ha hasherHandle
34 | hb hasherHandle
35 | params *encoderParams
36 | }
37 |
38 | func (h *hashComposite) Initialize(params *encoderParams) {
39 | h.params = params
40 | }
41 |
42 | /* TODO: Initialize of the hashers is defered to Prepare (and params
43 | remembered here) because we don't get the one_shot and input_size params
44 | here that are needed to know the memory size of them. Instead provide
45 | those params to all hashers InitializehashComposite */
46 | func (h *hashComposite) Prepare(one_shot bool, input_size uint, data []byte) {
47 | if h.ha == nil {
48 | var common_a *hasherCommon
49 | var common_b *hasherCommon
50 |
51 | common_a = h.ha.Common()
52 | common_a.params = h.params.hasher
53 | common_a.is_prepared_ = false
54 | common_a.dict_num_lookups = 0
55 | common_a.dict_num_matches = 0
56 | h.ha.Initialize(h.params)
57 |
58 | common_b = h.hb.Common()
59 | common_b.params = h.params.hasher
60 | common_b.is_prepared_ = false
61 | common_b.dict_num_lookups = 0
62 | common_b.dict_num_matches = 0
63 | h.hb.Initialize(h.params)
64 | }
65 |
66 | h.ha.Prepare(one_shot, input_size, data)
67 | h.hb.Prepare(one_shot, input_size, data)
68 | }
69 |
70 | func (h *hashComposite) Store(data []byte, mask uint, ix uint) {
71 | h.ha.Store(data, mask, ix)
72 | h.hb.Store(data, mask, ix)
73 | }
74 |
75 | func (h *hashComposite) StoreRange(data []byte, mask uint, ix_start uint, ix_end uint) {
76 | h.ha.StoreRange(data, mask, ix_start, ix_end)
77 | h.hb.StoreRange(data, mask, ix_start, ix_end)
78 | }
79 |
80 | func (h *hashComposite) StitchToPreviousBlock(num_bytes uint, position uint, ringbuffer []byte, ring_buffer_mask uint) {
81 | h.ha.StitchToPreviousBlock(num_bytes, position, ringbuffer, ring_buffer_mask)
82 | h.hb.StitchToPreviousBlock(num_bytes, position, ringbuffer, ring_buffer_mask)
83 | }
84 |
85 | func (h *hashComposite) PrepareDistanceCache(distance_cache []int) {
86 | h.ha.PrepareDistanceCache(distance_cache)
87 | h.hb.PrepareDistanceCache(distance_cache)
88 | }
89 |
90 | func (h *hashComposite) FindLongestMatch(dictionary *encoderDictionary, data []byte, ring_buffer_mask uint, distance_cache []int, cur_ix uint, max_length uint, max_backward uint, gap uint, max_distance uint, out *hasherSearchResult) {
91 | h.ha.FindLongestMatch(dictionary, data, ring_buffer_mask, distance_cache, cur_ix, max_length, max_backward, gap, max_distance, out)
92 | h.hb.FindLongestMatch(dictionary, data, ring_buffer_mask, distance_cache, cur_ix, max_length, max_backward, gap, max_distance, out)
93 | }
94 |
--------------------------------------------------------------------------------
/vendor/github.com/andybalholm/brotli/matchfinder/emitter.go:
--------------------------------------------------------------------------------
1 | package matchfinder
2 |
3 | // An absoluteMatch is like a Match, but it stores indexes into the byte
4 | // stream instead of lengths.
5 | type absoluteMatch struct {
6 | // Start is the index of the first byte.
7 | Start int
8 |
9 | // End is the index of the byte after the last byte
10 | // (so that End - Start = Length).
11 | End int
12 |
13 | // Match is the index of the previous data that matches
14 | // (Start - Match = Distance).
15 | Match int
16 | }
17 |
18 | // A matchEmitter manages the output of matches for a MatchFinder.
19 | type matchEmitter struct {
20 | // Dst is the destination slice that Matches are added to.
21 | Dst []Match
22 |
23 | // NextEmit is the index of the next byte to emit.
24 | NextEmit int
25 | }
26 |
27 | func (e *matchEmitter) emit(m absoluteMatch) {
28 | e.Dst = append(e.Dst, Match{
29 | Unmatched: m.Start - e.NextEmit,
30 | Length: m.End - m.Start,
31 | Distance: m.Start - m.Match,
32 | })
33 | e.NextEmit = m.End
34 | }
35 |
36 | // trim shortens m if it extends past maxEnd. Then if the length is at least
37 | // minLength, the match is emitted.
38 | func (e *matchEmitter) trim(m absoluteMatch, maxEnd int, minLength int) {
39 | if m.End > maxEnd {
40 | m.End = maxEnd
41 | }
42 | if m.End-m.Start >= minLength {
43 | e.emit(m)
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/vendor/github.com/andybalholm/brotli/matchfinder/matchfinder.go:
--------------------------------------------------------------------------------
1 | // The matchfinder package defines reusable components for data compression.
2 | //
3 | // Many compression libraries have two main parts:
4 | // - Something that looks for repeated sequences of bytes
5 | // - An encoder for the compressed data format (often an entropy coder)
6 | //
7 | // Although these are logically two separate steps, the implementations are
8 | // usually closely tied together. You can't use flate's matcher with snappy's
9 | // encoder, for example. This package defines interfaces and an intermediate
10 | // representation to allow mixing and matching compression components.
11 | package matchfinder
12 |
13 | import "io"
14 |
15 | // A Match is the basic unit of LZ77 compression.
16 | type Match struct {
17 | Unmatched int // the number of unmatched bytes since the previous match
18 | Length int // the number of bytes in the matched string; it may be 0 at the end of the input
19 | Distance int // how far back in the stream to copy from
20 | }
21 |
22 | // A MatchFinder performs the LZ77 stage of compression, looking for matches.
23 | type MatchFinder interface {
24 | // FindMatches looks for matches in src, appends them to dst, and returns dst.
25 | FindMatches(dst []Match, src []byte) []Match
26 |
27 | // Reset clears any internal state, preparing the MatchFinder to be used with
28 | // a new stream.
29 | Reset()
30 | }
31 |
32 | // An Encoder encodes the data in its final format.
33 | type Encoder interface {
34 | // Encode appends the encoded format of src to dst, using the match
35 | // information from matches.
36 | Encode(dst []byte, src []byte, matches []Match, lastBlock bool) []byte
37 |
38 | // Reset clears any internal state, preparing the Encoder to be used with
39 | // a new stream.
40 | Reset()
41 | }
42 |
43 | // A Writer uses MatchFinder and Encoder to write compressed data to Dest.
44 | type Writer struct {
45 | Dest io.Writer
46 | MatchFinder MatchFinder
47 | Encoder Encoder
48 |
49 | // BlockSize is the number of bytes to compress at a time. If it is zero,
50 | // each Write operation will be treated as one block.
51 | BlockSize int
52 |
53 | err error
54 | inBuf []byte
55 | outBuf []byte
56 | matches []Match
57 | }
58 |
59 | func (w *Writer) Write(p []byte) (n int, err error) {
60 | if w.err != nil {
61 | return 0, w.err
62 | }
63 |
64 | if w.BlockSize == 0 {
65 | return w.writeBlock(p, false)
66 | }
67 |
68 | w.inBuf = append(w.inBuf, p...)
69 | var pos int
70 | for pos = 0; pos+w.BlockSize <= len(w.inBuf) && w.err == nil; pos += w.BlockSize {
71 | w.writeBlock(w.inBuf[pos:pos+w.BlockSize], false)
72 | }
73 | if pos > 0 {
74 | n := copy(w.inBuf, w.inBuf[pos:])
75 | w.inBuf = w.inBuf[:n]
76 | }
77 |
78 | return len(p), w.err
79 | }
80 |
81 | func (w *Writer) writeBlock(p []byte, lastBlock bool) (n int, err error) {
82 | w.outBuf = w.outBuf[:0]
83 | w.matches = w.MatchFinder.FindMatches(w.matches[:0], p)
84 | w.outBuf = w.Encoder.Encode(w.outBuf, p, w.matches, lastBlock)
85 | _, w.err = w.Dest.Write(w.outBuf)
86 | return len(p), w.err
87 | }
88 |
89 | func (w *Writer) Close() error {
90 | w.writeBlock(w.inBuf, true)
91 | w.inBuf = w.inBuf[:0]
92 | return w.err
93 | }
94 |
95 | func (w *Writer) Reset(newDest io.Writer) {
96 | w.MatchFinder.Reset()
97 | w.Encoder.Reset()
98 | w.err = nil
99 | w.inBuf = w.inBuf[:0]
100 | w.outBuf = w.outBuf[:0]
101 | w.matches = w.matches[:0]
102 | w.Dest = newDest
103 | }
104 |
--------------------------------------------------------------------------------
/vendor/github.com/andybalholm/brotli/matchfinder/textencoder.go:
--------------------------------------------------------------------------------
1 | package matchfinder
2 |
3 | import "fmt"
4 |
5 | // A TextEncoder is an Encoder that produces a human-readable representation of
6 | // the LZ77 compression. Matches are replaced with symbols.
7 | type TextEncoder struct{}
8 |
9 | func (t TextEncoder) Reset() {}
10 |
11 | func (t TextEncoder) Encode(dst []byte, src []byte, matches []Match, lastBlock bool) []byte {
12 | pos := 0
13 | for _, m := range matches {
14 | if m.Unmatched > 0 {
15 | dst = append(dst, src[pos:pos+m.Unmatched]...)
16 | pos += m.Unmatched
17 | }
18 | if m.Length > 0 {
19 | dst = append(dst, []byte(fmt.Sprintf("<%d,%d>", m.Length, m.Distance))...)
20 | pos += m.Length
21 | }
22 | }
23 | if pos < len(src) {
24 | dst = append(dst, src[pos:]...)
25 | }
26 | return dst
27 | }
28 |
29 | // A NoMatchFinder implements MatchFinder, but doesn't find any matches.
30 | // It can be used to implement the equivalent of the standard library flate package's
31 | // HuffmanOnly setting.
32 | type NoMatchFinder struct{}
33 |
34 | func (n NoMatchFinder) Reset() {}
35 |
36 | func (n NoMatchFinder) FindMatches(dst []Match, src []byte) []Match {
37 | return append(dst, Match{
38 | Unmatched: len(src),
39 | })
40 | }
41 |
42 | // AutoReset wraps a MatchFinder that can return references to data in previous
43 | // blocks, and calls Reset before each block. It is useful for (e.g.) using a
44 | // snappy Encoder with a MatchFinder designed for flate. (Snappy doesn't
45 | // support references between blocks.)
46 | type AutoReset struct {
47 | MatchFinder
48 | }
49 |
50 | func (a AutoReset) FindMatches(dst []Match, src []byte) []Match {
51 | a.Reset()
52 | return a.MatchFinder.FindMatches(dst, src)
53 | }
54 |
--------------------------------------------------------------------------------
/vendor/github.com/andybalholm/brotli/memory.go:
--------------------------------------------------------------------------------
1 | package brotli
2 |
3 | /* Copyright 2016 Google Inc. All Rights Reserved.
4 |
5 | Distributed under MIT license.
6 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
7 | */
8 |
9 | /*
10 | Dynamically grows array capacity to at least the requested size
11 | T: data type
12 | A: array
13 | C: capacity
14 | R: requested size
15 | */
16 | func brotli_ensure_capacity_uint8_t(a *[]byte, c *uint, r uint) {
17 | if *c < r {
18 | var new_size uint = *c
19 | if new_size == 0 {
20 | new_size = r
21 | }
22 |
23 | for new_size < r {
24 | new_size *= 2
25 | }
26 |
27 | if cap(*a) < int(new_size) {
28 | var new_array []byte = make([]byte, new_size)
29 | if *c != 0 {
30 | copy(new_array, (*a)[:*c])
31 | }
32 |
33 | *a = new_array
34 | } else {
35 | *a = (*a)[:new_size]
36 | }
37 |
38 | *c = new_size
39 | }
40 | }
41 |
42 | func brotli_ensure_capacity_uint32_t(a *[]uint32, c *uint, r uint) {
43 | var new_array []uint32
44 | if *c < r {
45 | var new_size uint = *c
46 | if new_size == 0 {
47 | new_size = r
48 | }
49 |
50 | for new_size < r {
51 | new_size *= 2
52 | }
53 |
54 | if cap(*a) < int(new_size) {
55 | new_array = make([]uint32, new_size)
56 | if *c != 0 {
57 | copy(new_array, (*a)[:*c])
58 | }
59 |
60 | *a = new_array
61 | } else {
62 | *a = (*a)[:new_size]
63 | }
64 | *c = new_size
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/vendor/github.com/andybalholm/brotli/params.go:
--------------------------------------------------------------------------------
1 | package brotli
2 |
3 | /* Copyright 2017 Google Inc. All Rights Reserved.
4 |
5 | Distributed under MIT license.
6 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
7 | */
8 |
9 | /* Parameters for the Brotli encoder with chosen quality levels. */
10 | type hasherParams struct {
11 | type_ int
12 | bucket_bits int
13 | block_bits int
14 | hash_len int
15 | num_last_distances_to_check int
16 | }
17 |
18 | type distanceParams struct {
19 | distance_postfix_bits uint32
20 | num_direct_distance_codes uint32
21 | alphabet_size uint32
22 | max_distance uint
23 | }
24 |
25 | /* Encoding parameters */
26 | type encoderParams struct {
27 | mode int
28 | quality int
29 | lgwin uint
30 | lgblock int
31 | size_hint uint
32 | disable_literal_context_modeling bool
33 | large_window bool
34 | hasher hasherParams
35 | dist distanceParams
36 | dictionary encoderDictionary
37 | }
38 |
--------------------------------------------------------------------------------
/vendor/github.com/andybalholm/brotli/platform.go:
--------------------------------------------------------------------------------
1 | package brotli
2 |
3 | /* Copyright 2013 Google Inc. All Rights Reserved.
4 |
5 | Distributed under MIT license.
6 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
7 | */
8 |
9 | func brotli_min_double(a float64, b float64) float64 {
10 | if a < b {
11 | return a
12 | } else {
13 | return b
14 | }
15 | }
16 |
17 | func brotli_max_double(a float64, b float64) float64 {
18 | if a > b {
19 | return a
20 | } else {
21 | return b
22 | }
23 | }
24 |
25 | func brotli_min_float(a float32, b float32) float32 {
26 | if a < b {
27 | return a
28 | } else {
29 | return b
30 | }
31 | }
32 |
33 | func brotli_max_float(a float32, b float32) float32 {
34 | if a > b {
35 | return a
36 | } else {
37 | return b
38 | }
39 | }
40 |
41 | func brotli_min_int(a int, b int) int {
42 | if a < b {
43 | return a
44 | } else {
45 | return b
46 | }
47 | }
48 |
49 | func brotli_max_int(a int, b int) int {
50 | if a > b {
51 | return a
52 | } else {
53 | return b
54 | }
55 | }
56 |
57 | func brotli_min_size_t(a uint, b uint) uint {
58 | if a < b {
59 | return a
60 | } else {
61 | return b
62 | }
63 | }
64 |
65 | func brotli_max_size_t(a uint, b uint) uint {
66 | if a > b {
67 | return a
68 | } else {
69 | return b
70 | }
71 | }
72 |
73 | func brotli_min_uint32_t(a uint32, b uint32) uint32 {
74 | if a < b {
75 | return a
76 | } else {
77 | return b
78 | }
79 | }
80 |
81 | func brotli_max_uint32_t(a uint32, b uint32) uint32 {
82 | if a > b {
83 | return a
84 | } else {
85 | return b
86 | }
87 | }
88 |
89 | func brotli_min_uint8_t(a byte, b byte) byte {
90 | if a < b {
91 | return a
92 | } else {
93 | return b
94 | }
95 | }
96 |
97 | func brotli_max_uint8_t(a byte, b byte) byte {
98 | if a > b {
99 | return a
100 | } else {
101 | return b
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/vendor/github.com/andybalholm/brotli/prefix.go:
--------------------------------------------------------------------------------
1 | package brotli
2 |
3 | /* Copyright 2013 Google Inc. All Rights Reserved.
4 |
5 | Distributed under MIT license.
6 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
7 | */
8 |
9 | /* Functions for encoding of integers into prefix codes the amount of extra
10 | bits, and the actual values of the extra bits. */
11 |
12 | /* Here distance_code is an intermediate code, i.e. one of the special codes or
13 | the actual distance increased by BROTLI_NUM_DISTANCE_SHORT_CODES - 1. */
14 | func prefixEncodeCopyDistance(distance_code uint, num_direct_codes uint, postfix_bits uint, code *uint16, extra_bits *uint32) {
15 | if distance_code < numDistanceShortCodes+num_direct_codes {
16 | *code = uint16(distance_code)
17 | *extra_bits = 0
18 | return
19 | } else {
20 | var dist uint = (uint(1) << (postfix_bits + 2)) + (distance_code - numDistanceShortCodes - num_direct_codes)
21 | var bucket uint = uint(log2FloorNonZero(dist) - 1)
22 | var postfix_mask uint = (1 << postfix_bits) - 1
23 | var postfix uint = dist & postfix_mask
24 | var prefix uint = (dist >> bucket) & 1
25 | var offset uint = (2 + prefix) << bucket
26 | var nbits uint = bucket - postfix_bits
27 | *code = uint16(nbits<<10 | (numDistanceShortCodes + num_direct_codes + ((2*(nbits-1) + prefix) << postfix_bits) + postfix))
28 | *extra_bits = uint32((dist - offset) >> postfix_bits)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/vendor/github.com/andybalholm/brotli/reader.go:
--------------------------------------------------------------------------------
1 | package brotli
2 |
3 | import (
4 | "errors"
5 | "io"
6 | )
7 |
8 | type decodeError int
9 |
10 | func (err decodeError) Error() string {
11 | return "brotli: " + string(decoderErrorString(int(err)))
12 | }
13 |
14 | var errExcessiveInput = errors.New("brotli: excessive input")
15 | var errInvalidState = errors.New("brotli: invalid state")
16 |
17 | // readBufSize is a "good" buffer size that avoids excessive round-trips
18 | // between C and Go but doesn't waste too much memory on buffering.
19 | // It is arbitrarily chosen to be equal to the constant used in io.Copy.
20 | const readBufSize = 32 * 1024
21 |
22 | // NewReader creates a new Reader reading the given reader.
23 | func NewReader(src io.Reader) *Reader {
24 | r := new(Reader)
25 | r.Reset(src)
26 | return r
27 | }
28 |
29 | // Reset discards the Reader's state and makes it equivalent to the result of
30 | // its original state from NewReader, but reading from src instead.
31 | // This permits reusing a Reader rather than allocating a new one.
32 | // Error is always nil
33 | func (r *Reader) Reset(src io.Reader) error {
34 | if r.error_code < 0 {
35 | // There was an unrecoverable error, leaving the Reader's state
36 | // undefined. Clear out everything but the buffer.
37 | *r = Reader{buf: r.buf}
38 | }
39 |
40 | decoderStateInit(r)
41 | r.src = src
42 | if r.buf == nil {
43 | r.buf = make([]byte, readBufSize)
44 | }
45 | return nil
46 | }
47 |
48 | func (r *Reader) Read(p []byte) (n int, err error) {
49 | if !decoderHasMoreOutput(r) && len(r.in) == 0 {
50 | m, readErr := r.src.Read(r.buf)
51 | if m == 0 {
52 | // If readErr is `nil`, we just proxy underlying stream behavior.
53 | return 0, readErr
54 | }
55 | r.in = r.buf[:m]
56 | }
57 |
58 | if len(p) == 0 {
59 | return 0, nil
60 | }
61 |
62 | for {
63 | var written uint
64 | in_len := uint(len(r.in))
65 | out_len := uint(len(p))
66 | in_remaining := in_len
67 | out_remaining := out_len
68 | result := decoderDecompressStream(r, &in_remaining, &r.in, &out_remaining, &p)
69 | written = out_len - out_remaining
70 | n = int(written)
71 |
72 | switch result {
73 | case decoderResultSuccess:
74 | if len(r.in) > 0 {
75 | return n, errExcessiveInput
76 | }
77 | return n, nil
78 | case decoderResultError:
79 | return n, decodeError(decoderGetErrorCode(r))
80 | case decoderResultNeedsMoreOutput:
81 | if n == 0 {
82 | return 0, io.ErrShortBuffer
83 | }
84 | return n, nil
85 | case decoderNeedsMoreInput:
86 | }
87 |
88 | if len(r.in) != 0 {
89 | return 0, errInvalidState
90 | }
91 |
92 | // Calling r.src.Read may block. Don't block if we have data to return.
93 | if n > 0 {
94 | return n, nil
95 | }
96 |
97 | // Top off the buffer.
98 | encN, err := r.src.Read(r.buf)
99 | if encN == 0 {
100 | // Not enough data to complete decoding.
101 | if err == io.EOF {
102 | return 0, io.ErrUnexpectedEOF
103 | }
104 | return 0, err
105 | }
106 | r.in = r.buf[:encN]
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/vendor/github.com/andybalholm/brotli/symbol_list.go:
--------------------------------------------------------------------------------
1 | package brotli
2 |
3 | /* Copyright 2013 Google Inc. All Rights Reserved.
4 |
5 | Distributed under MIT license.
6 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
7 | */
8 |
9 | /* Utilities for building Huffman decoding tables. */
10 |
11 | type symbolList struct {
12 | storage []uint16
13 | offset int
14 | }
15 |
16 | func symbolListGet(sl symbolList, i int) uint16 {
17 | return sl.storage[i+sl.offset]
18 | }
19 |
20 | func symbolListPut(sl symbolList, i int, val uint16) {
21 | sl.storage[i+sl.offset] = val
22 | }
23 |
--------------------------------------------------------------------------------
/vendor/github.com/andybalholm/brotli/utf8_util.go:
--------------------------------------------------------------------------------
1 | package brotli
2 |
3 | /* Copyright 2013 Google Inc. All Rights Reserved.
4 |
5 | Distributed under MIT license.
6 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
7 | */
8 |
9 | /* Heuristics for deciding about the UTF8-ness of strings. */
10 |
11 | const kMinUTF8Ratio float64 = 0.75
12 |
13 | /* Returns 1 if at least min_fraction of the bytes between pos and
14 | pos + length in the (data, mask) ring-buffer is UTF8-encoded, otherwise
15 | returns 0. */
16 | func parseAsUTF8(symbol *int, input []byte, size uint) uint {
17 | /* ASCII */
18 | if input[0]&0x80 == 0 {
19 | *symbol = int(input[0])
20 | if *symbol > 0 {
21 | return 1
22 | }
23 | }
24 |
25 | /* 2-byte UTF8 */
26 | if size > 1 && input[0]&0xE0 == 0xC0 && input[1]&0xC0 == 0x80 {
27 | *symbol = (int(input[0])&0x1F)<<6 | int(input[1])&0x3F
28 | if *symbol > 0x7F {
29 | return 2
30 | }
31 | }
32 |
33 | /* 3-byte UFT8 */
34 | if size > 2 && input[0]&0xF0 == 0xE0 && input[1]&0xC0 == 0x80 && input[2]&0xC0 == 0x80 {
35 | *symbol = (int(input[0])&0x0F)<<12 | (int(input[1])&0x3F)<<6 | int(input[2])&0x3F
36 | if *symbol > 0x7FF {
37 | return 3
38 | }
39 | }
40 |
41 | /* 4-byte UFT8 */
42 | if size > 3 && input[0]&0xF8 == 0xF0 && input[1]&0xC0 == 0x80 && input[2]&0xC0 == 0x80 && input[3]&0xC0 == 0x80 {
43 | *symbol = (int(input[0])&0x07)<<18 | (int(input[1])&0x3F)<<12 | (int(input[2])&0x3F)<<6 | int(input[3])&0x3F
44 | if *symbol > 0xFFFF && *symbol <= 0x10FFFF {
45 | return 4
46 | }
47 | }
48 |
49 | /* Not UTF8, emit a special symbol above the UTF8-code space */
50 | *symbol = 0x110000 | int(input[0])
51 |
52 | return 1
53 | }
54 |
55 | /* Returns 1 if at least min_fraction of the data is UTF8-encoded.*/
56 | func isMostlyUTF8(data []byte, pos uint, mask uint, length uint, min_fraction float64) bool {
57 | var size_utf8 uint = 0
58 | var i uint = 0
59 | for i < length {
60 | var symbol int
61 | current_data := data[(pos+i)&mask:]
62 | var bytes_read uint = parseAsUTF8(&symbol, current_data, length-i)
63 | i += bytes_read
64 | if symbol < 0x110000 {
65 | size_utf8 += bytes_read
66 | }
67 | }
68 |
69 | return float64(size_utf8) > min_fraction*float64(length)
70 | }
71 |
--------------------------------------------------------------------------------
/vendor/github.com/andybalholm/brotli/util.go:
--------------------------------------------------------------------------------
1 | package brotli
2 |
3 | func assert(cond bool) {
4 | if !cond {
5 | panic("assertion failure")
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/vendor/github.com/andybalholm/brotli/write_bits.go:
--------------------------------------------------------------------------------
1 | package brotli
2 |
3 | import "encoding/binary"
4 |
5 | /* Copyright 2010 Google Inc. All Rights Reserved.
6 |
7 | Distributed under MIT license.
8 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
9 | */
10 |
11 | /* Write bits into a byte array. */
12 |
13 | /* This function writes bits into bytes in increasing addresses, and within
14 | a byte least-significant-bit first.
15 |
16 | The function can write up to 56 bits in one go with WriteBits
17 | Example: let's assume that 3 bits (Rs below) have been written already:
18 |
19 | BYTE-0 BYTE+1 BYTE+2
20 |
21 | 0000 0RRR 0000 0000 0000 0000
22 |
23 | Now, we could write 5 or less bits in MSB by just sifting by 3
24 | and OR'ing to BYTE-0.
25 |
26 | For n bits, we take the last 5 bits, OR that with high bits in BYTE-0,
27 | and locate the rest in BYTE+1, BYTE+2, etc. */
28 | func writeBits(n_bits uint, bits uint64, pos *uint, array []byte) {
29 | /* This branch of the code can write up to 56 bits at a time,
30 | 7 bits are lost by being perhaps already in *p and at least
31 | 1 bit is needed to initialize the bit-stream ahead (i.e. if 7
32 | bits are in *p and we write 57 bits, then the next write will
33 | access a byte that was never initialized). */
34 | p := array[*pos>>3:]
35 | v := uint64(p[0])
36 | v |= bits << (*pos & 7)
37 | binary.LittleEndian.PutUint64(p, v)
38 | *pos += n_bits
39 | }
40 |
41 | func writeSingleBit(bit bool, pos *uint, array []byte) {
42 | if bit {
43 | writeBits(1, 1, pos, array)
44 | } else {
45 | writeBits(1, 0, pos, array)
46 | }
47 | }
48 |
49 | func writeBitsPrepareStorage(pos uint, array []byte) {
50 | assert(pos&7 == 0)
51 | array[pos>>3] = 0
52 | }
53 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/.gitattributes:
--------------------------------------------------------------------------------
1 | * -text
2 | *.bin -text -diff
3 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files, Static and Dynamic libs (Shared Objects)
2 | *.o
3 | *.a
4 | *.so
5 |
6 | # Folders
7 | _obj
8 | _test
9 |
10 | # Architecture specific extensions/prefixes
11 | *.[568vq]
12 | [568vq].out
13 |
14 | *.cgo1.go
15 | *.cgo2.c
16 | _cgo_defun.c
17 | _cgo_gotypes.go
18 | _cgo_export.*
19 |
20 | _testmain.go
21 |
22 | *.exe
23 | *.test
24 | *.prof
25 | /s2/cmd/_s2sx/sfx-exe
26 |
27 | # Linux perf files
28 | perf.data
29 | perf.data.old
30 |
31 | # gdb history
32 | .gdb_history
33 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/.goreleaser.yml:
--------------------------------------------------------------------------------
1 | # This is an example goreleaser.yaml file with some sane defaults.
2 | # Make sure to check the documentation at http://goreleaser.com
3 | before:
4 | hooks:
5 | - ./gen.sh
6 |
7 | builds:
8 | -
9 | id: "s2c"
10 | binary: s2c
11 | main: ./s2/cmd/s2c/main.go
12 | flags:
13 | - -trimpath
14 | env:
15 | - CGO_ENABLED=0
16 | goos:
17 | - aix
18 | - linux
19 | - freebsd
20 | - netbsd
21 | - windows
22 | - darwin
23 | goarch:
24 | - 386
25 | - amd64
26 | - arm
27 | - arm64
28 | - ppc64
29 | - ppc64le
30 | - mips64
31 | - mips64le
32 | goarm:
33 | - 7
34 | -
35 | id: "s2d"
36 | binary: s2d
37 | main: ./s2/cmd/s2d/main.go
38 | flags:
39 | - -trimpath
40 | env:
41 | - CGO_ENABLED=0
42 | goos:
43 | - aix
44 | - linux
45 | - freebsd
46 | - netbsd
47 | - windows
48 | - darwin
49 | goarch:
50 | - 386
51 | - amd64
52 | - arm
53 | - arm64
54 | - ppc64
55 | - ppc64le
56 | - mips64
57 | - mips64le
58 | goarm:
59 | - 7
60 | -
61 | id: "s2sx"
62 | binary: s2sx
63 | main: ./s2/cmd/_s2sx/main.go
64 | flags:
65 | - -modfile=s2sx.mod
66 | - -trimpath
67 | env:
68 | - CGO_ENABLED=0
69 | goos:
70 | - aix
71 | - linux
72 | - freebsd
73 | - netbsd
74 | - windows
75 | - darwin
76 | goarch:
77 | - 386
78 | - amd64
79 | - arm
80 | - arm64
81 | - ppc64
82 | - ppc64le
83 | - mips64
84 | - mips64le
85 | goarm:
86 | - 7
87 |
88 | archives:
89 | -
90 | id: s2-binaries
91 | name_template: "s2-{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
92 | format_overrides:
93 | - goos: windows
94 | format: zip
95 | files:
96 | - unpack/*
97 | - s2/LICENSE
98 | - s2/README.md
99 | checksum:
100 | name_template: 'checksums.txt'
101 | snapshot:
102 | name_template: "{{ .Tag }}-next"
103 | changelog:
104 | sort: asc
105 | filters:
106 | exclude:
107 | - '^doc:'
108 | - '^docs:'
109 | - '^test:'
110 | - '^tests:'
111 | - '^Update\sREADME.md'
112 |
113 | nfpms:
114 | -
115 | file_name_template: "s2_package__{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
116 | vendor: Klaus Post
117 | homepage: https://github.com/klauspost/compress
118 | maintainer: Klaus Post
119 | description: S2 Compression Tool
120 | license: BSD 3-Clause
121 | formats:
122 | - deb
123 | - rpm
124 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions
4 |
5 | Security updates are applied only to the latest release.
6 |
7 | ## Vulnerability Definition
8 |
9 | A security vulnerability is a bug that with certain input triggers a crash or an infinite loop. Most calls will have varying execution time and only in rare cases will slow operation be considered a security vulnerability.
10 |
11 | Corrupted output generally is not considered a security vulnerability, unless independent operations are able to affect each other. Note that not all functionality is re-entrant and safe to use concurrently.
12 |
13 | Out-of-memory crashes only applies if the en/decoder uses an abnormal amount of memory, with appropriate options applied, to limit maximum window size, concurrency, etc. However, if you are in doubt you are welcome to file a security issue.
14 |
15 | It is assumed that all callers are trusted, meaning internal data exposed through reflection or inspection of returned data structures is not considered a vulnerability.
16 |
17 | Vulnerabilities resulting from compiler/assembler errors should be reported upstream. Depending on the severity this package may or may not implement a workaround.
18 |
19 | ## Reporting a Vulnerability
20 |
21 | If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released.
22 |
23 | Please disclose it at [security advisory](https://github.com/klauspost/compress/security/advisories/new). If possible please provide a minimal reproducer. If the issue only applies to a single platform, it would be helpful to provide access to that.
24 |
25 | This project is maintained by a team of volunteers on a reasonable-effort basis. As such, vulnerabilities will be disclosed in a best effort base.
26 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/compressible.go:
--------------------------------------------------------------------------------
1 | package compress
2 |
3 | import "math"
4 |
5 | // Estimate returns a normalized compressibility estimate of block b.
6 | // Values close to zero are likely uncompressible.
7 | // Values above 0.1 are likely to be compressible.
8 | // Values above 0.5 are very compressible.
9 | // Very small lengths will return 0.
10 | func Estimate(b []byte) float64 {
11 | if len(b) < 16 {
12 | return 0
13 | }
14 |
15 | // Correctly predicted order 1
16 | hits := 0
17 | lastMatch := false
18 | var o1 [256]byte
19 | var hist [256]int
20 | c1 := byte(0)
21 | for _, c := range b {
22 | if c == o1[c1] {
23 | // We only count a hit if there was two correct predictions in a row.
24 | if lastMatch {
25 | hits++
26 | }
27 | lastMatch = true
28 | } else {
29 | lastMatch = false
30 | }
31 | o1[c1] = c
32 | c1 = c
33 | hist[c]++
34 | }
35 |
36 | // Use x^0.6 to give better spread
37 | prediction := math.Pow(float64(hits)/float64(len(b)), 0.6)
38 |
39 | // Calculate histogram distribution
40 | variance := float64(0)
41 | avg := float64(len(b)) / 256
42 |
43 | for _, v := range hist {
44 | Δ := float64(v) - avg
45 | variance += Δ * Δ
46 | }
47 |
48 | stddev := math.Sqrt(float64(variance)) / float64(len(b))
49 | exp := math.Sqrt(1 / float64(len(b)))
50 |
51 | // Subtract expected stddev
52 | stddev -= exp
53 | if stddev < 0 {
54 | stddev = 0
55 | }
56 | stddev *= 1 + exp
57 |
58 | // Use x^0.4 to give better spread
59 | entropy := math.Pow(stddev, 0.4)
60 |
61 | // 50/50 weight between prediction and histogram distribution
62 | return math.Pow((prediction+entropy)/2, 0.9)
63 | }
64 |
65 | // ShannonEntropyBits returns the number of bits minimum required to represent
66 | // an entropy encoding of the input bytes.
67 | // https://en.wiktionary.org/wiki/Shannon_entropy
68 | func ShannonEntropyBits(b []byte) int {
69 | if len(b) == 0 {
70 | return 0
71 | }
72 | var hist [256]int
73 | for _, c := range b {
74 | hist[c]++
75 | }
76 | shannon := float64(0)
77 | invTotal := 1.0 / float64(len(b))
78 | for _, v := range hist[:] {
79 | if v > 0 {
80 | n := float64(v)
81 | shannon += math.Ceil(-math.Log2(n*invTotal) * n)
82 | }
83 | }
84 | return int(math.Ceil(shannon))
85 | }
86 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/flate/matchlen_amd64.go:
--------------------------------------------------------------------------------
1 | //go:build amd64 && !appengine && !noasm && gc
2 | // +build amd64,!appengine,!noasm,gc
3 |
4 | // Copyright 2019+ Klaus Post. All rights reserved.
5 | // License information can be found in the LICENSE file.
6 |
7 | package flate
8 |
9 | // matchLen returns how many bytes match in a and b
10 | //
11 | // It assumes that:
12 | //
13 | // len(a) <= len(b) and len(a) > 0
14 | //
15 | //go:noescape
16 | func matchLen(a []byte, b []byte) int
17 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/flate/matchlen_amd64.s:
--------------------------------------------------------------------------------
1 | // Copied from S2 implementation.
2 |
3 | //go:build !appengine && !noasm && gc && !noasm
4 |
5 | #include "textflag.h"
6 |
7 | // func matchLen(a []byte, b []byte) int
8 | TEXT ·matchLen(SB), NOSPLIT, $0-56
9 | MOVQ a_base+0(FP), AX
10 | MOVQ b_base+24(FP), CX
11 | MOVQ a_len+8(FP), DX
12 |
13 | // matchLen
14 | XORL SI, SI
15 | CMPL DX, $0x08
16 | JB matchlen_match4_standalone
17 |
18 | matchlen_loopback_standalone:
19 | MOVQ (AX)(SI*1), BX
20 | XORQ (CX)(SI*1), BX
21 | JZ matchlen_loop_standalone
22 |
23 | #ifdef GOAMD64_v3
24 | TZCNTQ BX, BX
25 | #else
26 | BSFQ BX, BX
27 | #endif
28 | SHRL $0x03, BX
29 | LEAL (SI)(BX*1), SI
30 | JMP gen_match_len_end
31 |
32 | matchlen_loop_standalone:
33 | LEAL -8(DX), DX
34 | LEAL 8(SI), SI
35 | CMPL DX, $0x08
36 | JAE matchlen_loopback_standalone
37 |
38 | matchlen_match4_standalone:
39 | CMPL DX, $0x04
40 | JB matchlen_match2_standalone
41 | MOVL (AX)(SI*1), BX
42 | CMPL (CX)(SI*1), BX
43 | JNE matchlen_match2_standalone
44 | LEAL -4(DX), DX
45 | LEAL 4(SI), SI
46 |
47 | matchlen_match2_standalone:
48 | CMPL DX, $0x02
49 | JB matchlen_match1_standalone
50 | MOVW (AX)(SI*1), BX
51 | CMPW (CX)(SI*1), BX
52 | JNE matchlen_match1_standalone
53 | LEAL -2(DX), DX
54 | LEAL 2(SI), SI
55 |
56 | matchlen_match1_standalone:
57 | CMPL DX, $0x01
58 | JB gen_match_len_end
59 | MOVB (AX)(SI*1), BL
60 | CMPB (CX)(SI*1), BL
61 | JNE gen_match_len_end
62 | INCL SI
63 |
64 | gen_match_len_end:
65 | MOVQ SI, ret+48(FP)
66 | RET
67 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/flate/matchlen_generic.go:
--------------------------------------------------------------------------------
1 | //go:build !amd64 || appengine || !gc || noasm
2 | // +build !amd64 appengine !gc noasm
3 |
4 | // Copyright 2019+ Klaus Post. All rights reserved.
5 | // License information can be found in the LICENSE file.
6 |
7 | package flate
8 |
9 | import (
10 | "encoding/binary"
11 | "math/bits"
12 | )
13 |
14 | // matchLen returns the maximum common prefix length of a and b.
15 | // a must be the shortest of the two.
16 | func matchLen(a, b []byte) (n int) {
17 | for ; len(a) >= 8 && len(b) >= 8; a, b = a[8:], b[8:] {
18 | diff := binary.LittleEndian.Uint64(a) ^ binary.LittleEndian.Uint64(b)
19 | if diff != 0 {
20 | return n + bits.TrailingZeros64(diff)>>3
21 | }
22 | n += 8
23 | }
24 |
25 | for i := range a {
26 | if a[i] != b[i] {
27 | break
28 | }
29 | n++
30 | }
31 | return n
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/flate/regmask_amd64.go:
--------------------------------------------------------------------------------
1 | package flate
2 |
3 | const (
4 | // Masks for shifts with register sizes of the shift value.
5 | // This can be used to work around the x86 design of shifting by mod register size.
6 | // It can be used when a variable shift is always smaller than the register size.
7 |
8 | // reg8SizeMaskX - shift value is 8 bits, shifted is X
9 | reg8SizeMask8 = 7
10 | reg8SizeMask16 = 15
11 | reg8SizeMask32 = 31
12 | reg8SizeMask64 = 63
13 |
14 | // reg16SizeMaskX - shift value is 16 bits, shifted is X
15 | reg16SizeMask8 = reg8SizeMask8
16 | reg16SizeMask16 = reg8SizeMask16
17 | reg16SizeMask32 = reg8SizeMask32
18 | reg16SizeMask64 = reg8SizeMask64
19 |
20 | // reg32SizeMaskX - shift value is 32 bits, shifted is X
21 | reg32SizeMask8 = reg8SizeMask8
22 | reg32SizeMask16 = reg8SizeMask16
23 | reg32SizeMask32 = reg8SizeMask32
24 | reg32SizeMask64 = reg8SizeMask64
25 |
26 | // reg64SizeMaskX - shift value is 64 bits, shifted is X
27 | reg64SizeMask8 = reg8SizeMask8
28 | reg64SizeMask16 = reg8SizeMask16
29 | reg64SizeMask32 = reg8SizeMask32
30 | reg64SizeMask64 = reg8SizeMask64
31 |
32 | // regSizeMaskUintX - shift value is uint, shifted is X
33 | regSizeMaskUint8 = reg8SizeMask8
34 | regSizeMaskUint16 = reg8SizeMask16
35 | regSizeMaskUint32 = reg8SizeMask32
36 | regSizeMaskUint64 = reg8SizeMask64
37 | )
38 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/flate/regmask_other.go:
--------------------------------------------------------------------------------
1 | //go:build !amd64
2 | // +build !amd64
3 |
4 | package flate
5 |
6 | const (
7 | // Masks for shifts with register sizes of the shift value.
8 | // This can be used to work around the x86 design of shifting by mod register size.
9 | // It can be used when a variable shift is always smaller than the register size.
10 |
11 | // reg8SizeMaskX - shift value is 8 bits, shifted is X
12 | reg8SizeMask8 = 0xff
13 | reg8SizeMask16 = 0xff
14 | reg8SizeMask32 = 0xff
15 | reg8SizeMask64 = 0xff
16 |
17 | // reg16SizeMaskX - shift value is 16 bits, shifted is X
18 | reg16SizeMask8 = 0xffff
19 | reg16SizeMask16 = 0xffff
20 | reg16SizeMask32 = 0xffff
21 | reg16SizeMask64 = 0xffff
22 |
23 | // reg32SizeMaskX - shift value is 32 bits, shifted is X
24 | reg32SizeMask8 = 0xffffffff
25 | reg32SizeMask16 = 0xffffffff
26 | reg32SizeMask32 = 0xffffffff
27 | reg32SizeMask64 = 0xffffffff
28 |
29 | // reg64SizeMaskX - shift value is 64 bits, shifted is X
30 | reg64SizeMask8 = 0xffffffffffffffff
31 | reg64SizeMask16 = 0xffffffffffffffff
32 | reg64SizeMask32 = 0xffffffffffffffff
33 | reg64SizeMask64 = 0xffffffffffffffff
34 |
35 | // regSizeMaskUintX - shift value is uint, shifted is X
36 | regSizeMaskUint8 = ^uint(0)
37 | regSizeMaskUint16 = ^uint(0)
38 | regSizeMaskUint32 = ^uint(0)
39 | regSizeMaskUint64 = ^uint(0)
40 | )
41 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/fse/bitreader.go:
--------------------------------------------------------------------------------
1 | // Copyright 2018 Klaus Post. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 | // Based on work Copyright (c) 2013, Yann Collet, released under BSD License.
5 |
6 | package fse
7 |
8 | import (
9 | "encoding/binary"
10 | "errors"
11 | "io"
12 | )
13 |
14 | // bitReader reads a bitstream in reverse.
15 | // The last set bit indicates the start of the stream and is used
16 | // for aligning the input.
17 | type bitReader struct {
18 | in []byte
19 | off uint // next byte to read is at in[off - 1]
20 | value uint64
21 | bitsRead uint8
22 | }
23 |
24 | // init initializes and resets the bit reader.
25 | func (b *bitReader) init(in []byte) error {
26 | if len(in) < 1 {
27 | return errors.New("corrupt stream: too short")
28 | }
29 | b.in = in
30 | b.off = uint(len(in))
31 | // The highest bit of the last byte indicates where to start
32 | v := in[len(in)-1]
33 | if v == 0 {
34 | return errors.New("corrupt stream, did not find end of stream")
35 | }
36 | b.bitsRead = 64
37 | b.value = 0
38 | if len(in) >= 8 {
39 | b.fillFastStart()
40 | } else {
41 | b.fill()
42 | b.fill()
43 | }
44 | b.bitsRead += 8 - uint8(highBits(uint32(v)))
45 | return nil
46 | }
47 |
48 | // getBits will return n bits. n can be 0.
49 | func (b *bitReader) getBits(n uint8) uint16 {
50 | if n == 0 || b.bitsRead >= 64 {
51 | return 0
52 | }
53 | return b.getBitsFast(n)
54 | }
55 |
56 | // getBitsFast requires that at least one bit is requested every time.
57 | // There are no checks if the buffer is filled.
58 | func (b *bitReader) getBitsFast(n uint8) uint16 {
59 | const regMask = 64 - 1
60 | v := uint16((b.value << (b.bitsRead & regMask)) >> ((regMask + 1 - n) & regMask))
61 | b.bitsRead += n
62 | return v
63 | }
64 |
65 | // fillFast() will make sure at least 32 bits are available.
66 | // There must be at least 4 bytes available.
67 | func (b *bitReader) fillFast() {
68 | if b.bitsRead < 32 {
69 | return
70 | }
71 | // 2 bounds checks.
72 | v := b.in[b.off-4:]
73 | v = v[:4]
74 | low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24)
75 | b.value = (b.value << 32) | uint64(low)
76 | b.bitsRead -= 32
77 | b.off -= 4
78 | }
79 |
80 | // fill() will make sure at least 32 bits are available.
81 | func (b *bitReader) fill() {
82 | if b.bitsRead < 32 {
83 | return
84 | }
85 | if b.off > 4 {
86 | v := b.in[b.off-4:]
87 | v = v[:4]
88 | low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24)
89 | b.value = (b.value << 32) | uint64(low)
90 | b.bitsRead -= 32
91 | b.off -= 4
92 | return
93 | }
94 | for b.off > 0 {
95 | b.value = (b.value << 8) | uint64(b.in[b.off-1])
96 | b.bitsRead -= 8
97 | b.off--
98 | }
99 | }
100 |
101 | // fillFastStart() assumes the bitreader is empty and there is at least 8 bytes to read.
102 | func (b *bitReader) fillFastStart() {
103 | // Do single re-slice to avoid bounds checks.
104 | b.value = binary.LittleEndian.Uint64(b.in[b.off-8:])
105 | b.bitsRead = 0
106 | b.off -= 8
107 | }
108 |
109 | // finished returns true if all bits have been read from the bit stream.
110 | func (b *bitReader) finished() bool {
111 | return b.bitsRead >= 64 && b.off == 0
112 | }
113 |
114 | // close the bitstream and returns an error if out-of-buffer reads occurred.
115 | func (b *bitReader) close() error {
116 | // Release reference.
117 | b.in = nil
118 | if b.bitsRead > 64 {
119 | return io.ErrUnexpectedEOF
120 | }
121 | return nil
122 | }
123 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/fse/bytereader.go:
--------------------------------------------------------------------------------
1 | // Copyright 2018 Klaus Post. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 | // Based on work Copyright (c) 2013, Yann Collet, released under BSD License.
5 |
6 | package fse
7 |
8 | // byteReader provides a byte reader that reads
9 | // little endian values from a byte stream.
10 | // The input stream is manually advanced.
11 | // The reader performs no bounds checks.
12 | type byteReader struct {
13 | b []byte
14 | off int
15 | }
16 |
17 | // init will initialize the reader and set the input.
18 | func (b *byteReader) init(in []byte) {
19 | b.b = in
20 | b.off = 0
21 | }
22 |
23 | // advance the stream b n bytes.
24 | func (b *byteReader) advance(n uint) {
25 | b.off += int(n)
26 | }
27 |
28 | // Uint32 returns a little endian uint32 starting at current offset.
29 | func (b byteReader) Uint32() uint32 {
30 | b2 := b.b[b.off:]
31 | b2 = b2[:4]
32 | v3 := uint32(b2[3])
33 | v2 := uint32(b2[2])
34 | v1 := uint32(b2[1])
35 | v0 := uint32(b2[0])
36 | return v0 | (v1 << 8) | (v2 << 16) | (v3 << 24)
37 | }
38 |
39 | // unread returns the unread portion of the input.
40 | func (b byteReader) unread() []byte {
41 | return b.b[b.off:]
42 | }
43 |
44 | // remain will return the number of bytes remaining.
45 | func (b byteReader) remain() int {
46 | return len(b.b) - b.off
47 | }
48 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/gen.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | cd s2/cmd/_s2sx/ || exit 1
4 | go generate .
5 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/huff0/.gitignore:
--------------------------------------------------------------------------------
1 | /huff0-fuzz.zip
2 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/huff0/bitwriter.go:
--------------------------------------------------------------------------------
1 | // Copyright 2018 Klaus Post. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 | // Based on work Copyright (c) 2013, Yann Collet, released under BSD License.
5 |
6 | package huff0
7 |
8 | // bitWriter will write bits.
9 | // First bit will be LSB of the first byte of output.
10 | type bitWriter struct {
11 | bitContainer uint64
12 | nBits uint8
13 | out []byte
14 | }
15 |
16 | // addBits16Clean will add up to 16 bits. value may not contain more set bits than indicated.
17 | // It will not check if there is space for them, so the caller must ensure that it has flushed recently.
18 | func (b *bitWriter) addBits16Clean(value uint16, bits uint8) {
19 | b.bitContainer |= uint64(value) << (b.nBits & 63)
20 | b.nBits += bits
21 | }
22 |
23 | // encSymbol will add up to 16 bits. value may not contain more set bits than indicated.
24 | // It will not check if there is space for them, so the caller must ensure that it has flushed recently.
25 | func (b *bitWriter) encSymbol(ct cTable, symbol byte) {
26 | enc := ct[symbol]
27 | b.bitContainer |= uint64(enc.val) << (b.nBits & 63)
28 | if false {
29 | if enc.nBits == 0 {
30 | panic("nbits 0")
31 | }
32 | }
33 | b.nBits += enc.nBits
34 | }
35 |
36 | // encTwoSymbols will add up to 32 bits. value may not contain more set bits than indicated.
37 | // It will not check if there is space for them, so the caller must ensure that it has flushed recently.
38 | func (b *bitWriter) encTwoSymbols(ct cTable, av, bv byte) {
39 | encA := ct[av]
40 | encB := ct[bv]
41 | sh := b.nBits & 63
42 | combined := uint64(encA.val) | (uint64(encB.val) << (encA.nBits & 63))
43 | b.bitContainer |= combined << sh
44 | if false {
45 | if encA.nBits == 0 {
46 | panic("nbitsA 0")
47 | }
48 | if encB.nBits == 0 {
49 | panic("nbitsB 0")
50 | }
51 | }
52 | b.nBits += encA.nBits + encB.nBits
53 | }
54 |
55 | // encFourSymbols adds up to 32 bits from four symbols.
56 | // It will not check if there is space for them,
57 | // so the caller must ensure that b has been flushed recently.
58 | func (b *bitWriter) encFourSymbols(encA, encB, encC, encD cTableEntry) {
59 | bitsA := encA.nBits
60 | bitsB := bitsA + encB.nBits
61 | bitsC := bitsB + encC.nBits
62 | bitsD := bitsC + encD.nBits
63 | combined := uint64(encA.val) |
64 | (uint64(encB.val) << (bitsA & 63)) |
65 | (uint64(encC.val) << (bitsB & 63)) |
66 | (uint64(encD.val) << (bitsC & 63))
67 | b.bitContainer |= combined << (b.nBits & 63)
68 | b.nBits += bitsD
69 | }
70 |
71 | // flush32 will flush out, so there are at least 32 bits available for writing.
72 | func (b *bitWriter) flush32() {
73 | if b.nBits < 32 {
74 | return
75 | }
76 | b.out = append(b.out,
77 | byte(b.bitContainer),
78 | byte(b.bitContainer>>8),
79 | byte(b.bitContainer>>16),
80 | byte(b.bitContainer>>24))
81 | b.nBits -= 32
82 | b.bitContainer >>= 32
83 | }
84 |
85 | // flushAlign will flush remaining full bytes and align to next byte boundary.
86 | func (b *bitWriter) flushAlign() {
87 | nbBytes := (b.nBits + 7) >> 3
88 | for i := uint8(0); i < nbBytes; i++ {
89 | b.out = append(b.out, byte(b.bitContainer>>(i*8)))
90 | }
91 | b.nBits = 0
92 | b.bitContainer = 0
93 | }
94 |
95 | // close will write the alignment bit and write the final byte(s)
96 | // to the output.
97 | func (b *bitWriter) close() {
98 | // End mark
99 | b.addBits16Clean(1, 1)
100 | // flush until next byte.
101 | b.flushAlign()
102 | }
103 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/internal/cpuinfo/cpuinfo.go:
--------------------------------------------------------------------------------
1 | // Package cpuinfo gives runtime info about the current CPU.
2 | //
3 | // This is a very limited module meant for use internally
4 | // in this project. For more versatile solution check
5 | // https://github.com/klauspost/cpuid.
6 | package cpuinfo
7 |
8 | // HasBMI1 checks whether an x86 CPU supports the BMI1 extension.
9 | func HasBMI1() bool {
10 | return hasBMI1
11 | }
12 |
13 | // HasBMI2 checks whether an x86 CPU supports the BMI2 extension.
14 | func HasBMI2() bool {
15 | return hasBMI2
16 | }
17 |
18 | // DisableBMI2 will disable BMI2, for testing purposes.
19 | // Call returned function to restore previous state.
20 | func DisableBMI2() func() {
21 | old := hasBMI2
22 | hasBMI2 = false
23 | return func() {
24 | hasBMI2 = old
25 | }
26 | }
27 |
28 | // HasBMI checks whether an x86 CPU supports both BMI1 and BMI2 extensions.
29 | func HasBMI() bool {
30 | return HasBMI1() && HasBMI2()
31 | }
32 |
33 | var hasBMI1 bool
34 | var hasBMI2 bool
35 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/internal/cpuinfo/cpuinfo_amd64.go:
--------------------------------------------------------------------------------
1 | //go:build amd64 && !appengine && !noasm && gc
2 | // +build amd64,!appengine,!noasm,gc
3 |
4 | package cpuinfo
5 |
6 | // go:noescape
7 | func x86extensions() (bmi1, bmi2 bool)
8 |
9 | func init() {
10 | hasBMI1, hasBMI2 = x86extensions()
11 | }
12 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/internal/cpuinfo/cpuinfo_amd64.s:
--------------------------------------------------------------------------------
1 | // +build !appengine
2 | // +build gc
3 | // +build !noasm
4 |
5 | #include "textflag.h"
6 | #include "funcdata.h"
7 | #include "go_asm.h"
8 |
9 | TEXT ·x86extensions(SB), NOSPLIT, $0
10 | // 1. determine max EAX value
11 | XORQ AX, AX
12 | CPUID
13 |
14 | CMPQ AX, $7
15 | JB unsupported
16 |
17 | // 2. EAX = 7, ECX = 0 --- see Table 3-8 "Information Returned by CPUID Instruction"
18 | MOVQ $7, AX
19 | MOVQ $0, CX
20 | CPUID
21 |
22 | BTQ $3, BX // bit 3 = BMI1
23 | SETCS AL
24 |
25 | BTQ $8, BX // bit 8 = BMI2
26 | SETCS AH
27 |
28 | MOVB AL, bmi1+0(FP)
29 | MOVB AH, bmi2+1(FP)
30 | RET
31 |
32 | unsupported:
33 | XORQ AX, AX
34 | MOVB AL, bmi1+0(FP)
35 | MOVB AL, bmi2+1(FP)
36 | RET
37 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/internal/snapref/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011 The Snappy-Go Authors. All rights reserved.
2 |
3 | Redistribution and use in source and binary forms, with or without
4 | modification, are permitted provided that the following conditions are
5 | met:
6 |
7 | * Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above
10 | copyright notice, this list of conditions and the following disclaimer
11 | in the documentation and/or other materials provided with the
12 | distribution.
13 | * Neither the name of Google Inc. nor the names of its
14 | contributors may be used to endorse or promote products derived from
15 | this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/internal/snapref/decode_other.go:
--------------------------------------------------------------------------------
1 | // Copyright 2016 The Snappy-Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package snapref
6 |
7 | // decode writes the decoding of src to dst. It assumes that the varint-encoded
8 | // length of the decompressed bytes has already been read, and that len(dst)
9 | // equals that length.
10 | //
11 | // It returns 0 on success or a decodeErrCodeXxx error code on failure.
12 | func decode(dst, src []byte) int {
13 | var d, s, offset, length int
14 | for s < len(src) {
15 | switch src[s] & 0x03 {
16 | case tagLiteral:
17 | x := uint32(src[s] >> 2)
18 | switch {
19 | case x < 60:
20 | s++
21 | case x == 60:
22 | s += 2
23 | if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line.
24 | return decodeErrCodeCorrupt
25 | }
26 | x = uint32(src[s-1])
27 | case x == 61:
28 | s += 3
29 | if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line.
30 | return decodeErrCodeCorrupt
31 | }
32 | x = uint32(src[s-2]) | uint32(src[s-1])<<8
33 | case x == 62:
34 | s += 4
35 | if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line.
36 | return decodeErrCodeCorrupt
37 | }
38 | x = uint32(src[s-3]) | uint32(src[s-2])<<8 | uint32(src[s-1])<<16
39 | case x == 63:
40 | s += 5
41 | if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line.
42 | return decodeErrCodeCorrupt
43 | }
44 | x = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24
45 | }
46 | length = int(x) + 1
47 | if length <= 0 {
48 | return decodeErrCodeUnsupportedLiteralLength
49 | }
50 | if length > len(dst)-d || length > len(src)-s {
51 | return decodeErrCodeCorrupt
52 | }
53 | copy(dst[d:], src[s:s+length])
54 | d += length
55 | s += length
56 | continue
57 |
58 | case tagCopy1:
59 | s += 2
60 | if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line.
61 | return decodeErrCodeCorrupt
62 | }
63 | length = 4 + int(src[s-2])>>2&0x7
64 | offset = int(uint32(src[s-2])&0xe0<<3 | uint32(src[s-1]))
65 |
66 | case tagCopy2:
67 | s += 3
68 | if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line.
69 | return decodeErrCodeCorrupt
70 | }
71 | length = 1 + int(src[s-3])>>2
72 | offset = int(uint32(src[s-2]) | uint32(src[s-1])<<8)
73 |
74 | case tagCopy4:
75 | s += 5
76 | if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line.
77 | return decodeErrCodeCorrupt
78 | }
79 | length = 1 + int(src[s-5])>>2
80 | offset = int(uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24)
81 | }
82 |
83 | if offset <= 0 || d < offset || length > len(dst)-d {
84 | return decodeErrCodeCorrupt
85 | }
86 | // Copy from an earlier sub-slice of dst to a later sub-slice.
87 | // If no overlap, use the built-in copy:
88 | if offset >= length {
89 | copy(dst[d:d+length], dst[d-offset:])
90 | d += length
91 | continue
92 | }
93 |
94 | // Unlike the built-in copy function, this byte-by-byte copy always runs
95 | // forwards, even if the slices overlap. Conceptually, this is:
96 | //
97 | // d += forwardCopy(dst[d:d+length], dst[d-offset:])
98 | //
99 | // We align the slices into a and b and show the compiler they are the same size.
100 | // This allows the loop to run without bounds checks.
101 | a := dst[d : d+length]
102 | b := dst[d-offset:]
103 | b = b[:len(a)]
104 | for i := range a {
105 | a[i] = b[i]
106 | }
107 | d += length
108 | }
109 | if d != len(dst) {
110 | return decodeErrCodeCorrupt
111 | }
112 | return 0
113 | }
114 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/s2sx.mod:
--------------------------------------------------------------------------------
1 | module github.com/klauspost/compress
2 |
3 | go 1.19
4 |
5 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/s2sx.sum:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/valyala/quicktemplate/4d619e27ca723c29dcecf9844b193ee20df2322a/vendor/github.com/klauspost/compress/s2sx.sum
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/zstd/bitwriter.go:
--------------------------------------------------------------------------------
1 | // Copyright 2018 Klaus Post. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 | // Based on work Copyright (c) 2013, Yann Collet, released under BSD License.
5 |
6 | package zstd
7 |
8 | // bitWriter will write bits.
9 | // First bit will be LSB of the first byte of output.
10 | type bitWriter struct {
11 | bitContainer uint64
12 | nBits uint8
13 | out []byte
14 | }
15 |
16 | // bitMask16 is bitmasks. Has extra to avoid bounds check.
17 | var bitMask16 = [32]uint16{
18 | 0, 1, 3, 7, 0xF, 0x1F,
19 | 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF,
20 | 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0xFFFF,
21 | 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
22 | 0xFFFF, 0xFFFF} /* up to 16 bits */
23 |
24 | var bitMask32 = [32]uint32{
25 | 0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF,
26 | 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF,
27 | 0x1ffff, 0x3ffff, 0x7FFFF, 0xfFFFF, 0x1fFFFF, 0x3fFFFF, 0x7fFFFF, 0xffFFFF,
28 | 0x1ffFFFF, 0x3ffFFFF, 0x7ffFFFF, 0xfffFFFF, 0x1fffFFFF, 0x3fffFFFF, 0x7fffFFFF,
29 | } // up to 32 bits
30 |
31 | // addBits16NC will add up to 16 bits.
32 | // It will not check if there is space for them,
33 | // so the caller must ensure that it has flushed recently.
34 | func (b *bitWriter) addBits16NC(value uint16, bits uint8) {
35 | b.bitContainer |= uint64(value&bitMask16[bits&31]) << (b.nBits & 63)
36 | b.nBits += bits
37 | }
38 |
39 | // addBits32NC will add up to 31 bits.
40 | // It will not check if there is space for them,
41 | // so the caller must ensure that it has flushed recently.
42 | func (b *bitWriter) addBits32NC(value uint32, bits uint8) {
43 | b.bitContainer |= uint64(value&bitMask32[bits&31]) << (b.nBits & 63)
44 | b.nBits += bits
45 | }
46 |
47 | // addBits64NC will add up to 64 bits.
48 | // There must be space for 32 bits.
49 | func (b *bitWriter) addBits64NC(value uint64, bits uint8) {
50 | if bits <= 31 {
51 | b.addBits32Clean(uint32(value), bits)
52 | return
53 | }
54 | b.addBits32Clean(uint32(value), 32)
55 | b.flush32()
56 | b.addBits32Clean(uint32(value>>32), bits-32)
57 | }
58 |
59 | // addBits32Clean will add up to 32 bits.
60 | // It will not check if there is space for them.
61 | // The input must not contain more bits than specified.
62 | func (b *bitWriter) addBits32Clean(value uint32, bits uint8) {
63 | b.bitContainer |= uint64(value) << (b.nBits & 63)
64 | b.nBits += bits
65 | }
66 |
67 | // addBits16Clean will add up to 16 bits. value may not contain more set bits than indicated.
68 | // It will not check if there is space for them, so the caller must ensure that it has flushed recently.
69 | func (b *bitWriter) addBits16Clean(value uint16, bits uint8) {
70 | b.bitContainer |= uint64(value) << (b.nBits & 63)
71 | b.nBits += bits
72 | }
73 |
74 | // flush32 will flush out, so there are at least 32 bits available for writing.
75 | func (b *bitWriter) flush32() {
76 | if b.nBits < 32 {
77 | return
78 | }
79 | b.out = append(b.out,
80 | byte(b.bitContainer),
81 | byte(b.bitContainer>>8),
82 | byte(b.bitContainer>>16),
83 | byte(b.bitContainer>>24))
84 | b.nBits -= 32
85 | b.bitContainer >>= 32
86 | }
87 |
88 | // flushAlign will flush remaining full bytes and align to next byte boundary.
89 | func (b *bitWriter) flushAlign() {
90 | nbBytes := (b.nBits + 7) >> 3
91 | for i := uint8(0); i < nbBytes; i++ {
92 | b.out = append(b.out, byte(b.bitContainer>>(i*8)))
93 | }
94 | b.nBits = 0
95 | b.bitContainer = 0
96 | }
97 |
98 | // close will write the alignment bit and write the final byte(s)
99 | // to the output.
100 | func (b *bitWriter) close() {
101 | // End mark
102 | b.addBits16Clean(1, 1)
103 | // flush until next byte.
104 | b.flushAlign()
105 | }
106 |
107 | // reset and continue writing by appending to out.
108 | func (b *bitWriter) reset(out []byte) {
109 | b.bitContainer = 0
110 | b.nBits = 0
111 | b.out = out
112 | }
113 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/zstd/blocktype_string.go:
--------------------------------------------------------------------------------
1 | // Code generated by "stringer -type=blockType,literalsBlockType,seqCompMode,tableIndex"; DO NOT EDIT.
2 |
3 | package zstd
4 |
5 | import "strconv"
6 |
7 | func _() {
8 | // An "invalid array index" compiler error signifies that the constant values have changed.
9 | // Re-run the stringer command to generate them again.
10 | var x [1]struct{}
11 | _ = x[blockTypeRaw-0]
12 | _ = x[blockTypeRLE-1]
13 | _ = x[blockTypeCompressed-2]
14 | _ = x[blockTypeReserved-3]
15 | }
16 |
17 | const _blockType_name = "blockTypeRawblockTypeRLEblockTypeCompressedblockTypeReserved"
18 |
19 | var _blockType_index = [...]uint8{0, 12, 24, 43, 60}
20 |
21 | func (i blockType) String() string {
22 | if i >= blockType(len(_blockType_index)-1) {
23 | return "blockType(" + strconv.FormatInt(int64(i), 10) + ")"
24 | }
25 | return _blockType_name[_blockType_index[i]:_blockType_index[i+1]]
26 | }
27 | func _() {
28 | // An "invalid array index" compiler error signifies that the constant values have changed.
29 | // Re-run the stringer command to generate them again.
30 | var x [1]struct{}
31 | _ = x[literalsBlockRaw-0]
32 | _ = x[literalsBlockRLE-1]
33 | _ = x[literalsBlockCompressed-2]
34 | _ = x[literalsBlockTreeless-3]
35 | }
36 |
37 | const _literalsBlockType_name = "literalsBlockRawliteralsBlockRLEliteralsBlockCompressedliteralsBlockTreeless"
38 |
39 | var _literalsBlockType_index = [...]uint8{0, 16, 32, 55, 76}
40 |
41 | func (i literalsBlockType) String() string {
42 | if i >= literalsBlockType(len(_literalsBlockType_index)-1) {
43 | return "literalsBlockType(" + strconv.FormatInt(int64(i), 10) + ")"
44 | }
45 | return _literalsBlockType_name[_literalsBlockType_index[i]:_literalsBlockType_index[i+1]]
46 | }
47 | func _() {
48 | // An "invalid array index" compiler error signifies that the constant values have changed.
49 | // Re-run the stringer command to generate them again.
50 | var x [1]struct{}
51 | _ = x[compModePredefined-0]
52 | _ = x[compModeRLE-1]
53 | _ = x[compModeFSE-2]
54 | _ = x[compModeRepeat-3]
55 | }
56 |
57 | const _seqCompMode_name = "compModePredefinedcompModeRLEcompModeFSEcompModeRepeat"
58 |
59 | var _seqCompMode_index = [...]uint8{0, 18, 29, 40, 54}
60 |
61 | func (i seqCompMode) String() string {
62 | if i >= seqCompMode(len(_seqCompMode_index)-1) {
63 | return "seqCompMode(" + strconv.FormatInt(int64(i), 10) + ")"
64 | }
65 | return _seqCompMode_name[_seqCompMode_index[i]:_seqCompMode_index[i+1]]
66 | }
67 | func _() {
68 | // An "invalid array index" compiler error signifies that the constant values have changed.
69 | // Re-run the stringer command to generate them again.
70 | var x [1]struct{}
71 | _ = x[tableLiteralLengths-0]
72 | _ = x[tableOffsets-1]
73 | _ = x[tableMatchLengths-2]
74 | }
75 |
76 | const _tableIndex_name = "tableLiteralLengthstableOffsetstableMatchLengths"
77 |
78 | var _tableIndex_index = [...]uint8{0, 19, 31, 48}
79 |
80 | func (i tableIndex) String() string {
81 | if i >= tableIndex(len(_tableIndex_index)-1) {
82 | return "tableIndex(" + strconv.FormatInt(int64(i), 10) + ")"
83 | }
84 | return _tableIndex_name[_tableIndex_index[i]:_tableIndex_index[i+1]]
85 | }
86 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/zstd/bytebuf.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019+ Klaus Post. All rights reserved.
2 | // License information can be found in the LICENSE file.
3 | // Based on work by Yann Collet, released under BSD License.
4 |
5 | package zstd
6 |
7 | import (
8 | "fmt"
9 | "io"
10 | )
11 |
12 | type byteBuffer interface {
13 | // Read up to 8 bytes.
14 | // Returns io.ErrUnexpectedEOF if this cannot be satisfied.
15 | readSmall(n int) ([]byte, error)
16 |
17 | // Read >8 bytes.
18 | // MAY use the destination slice.
19 | readBig(n int, dst []byte) ([]byte, error)
20 |
21 | // Read a single byte.
22 | readByte() (byte, error)
23 |
24 | // Skip n bytes.
25 | skipN(n int64) error
26 | }
27 |
28 | // in-memory buffer
29 | type byteBuf []byte
30 |
31 | func (b *byteBuf) readSmall(n int) ([]byte, error) {
32 | if debugAsserts && n > 8 {
33 | panic(fmt.Errorf("small read > 8 (%d). use readBig", n))
34 | }
35 | bb := *b
36 | if len(bb) < n {
37 | return nil, io.ErrUnexpectedEOF
38 | }
39 | r := bb[:n]
40 | *b = bb[n:]
41 | return r, nil
42 | }
43 |
44 | func (b *byteBuf) readBig(n int, dst []byte) ([]byte, error) {
45 | bb := *b
46 | if len(bb) < n {
47 | return nil, io.ErrUnexpectedEOF
48 | }
49 | r := bb[:n]
50 | *b = bb[n:]
51 | return r, nil
52 | }
53 |
54 | func (b *byteBuf) readByte() (byte, error) {
55 | bb := *b
56 | if len(bb) < 1 {
57 | return 0, io.ErrUnexpectedEOF
58 | }
59 | r := bb[0]
60 | *b = bb[1:]
61 | return r, nil
62 | }
63 |
64 | func (b *byteBuf) skipN(n int64) error {
65 | bb := *b
66 | if n < 0 {
67 | return fmt.Errorf("negative skip (%d) requested", n)
68 | }
69 | if int64(len(bb)) < n {
70 | return io.ErrUnexpectedEOF
71 | }
72 | *b = bb[n:]
73 | return nil
74 | }
75 |
76 | // wrapper around a reader.
77 | type readerWrapper struct {
78 | r io.Reader
79 | tmp [8]byte
80 | }
81 |
82 | func (r *readerWrapper) readSmall(n int) ([]byte, error) {
83 | if debugAsserts && n > 8 {
84 | panic(fmt.Errorf("small read > 8 (%d). use readBig", n))
85 | }
86 | n2, err := io.ReadFull(r.r, r.tmp[:n])
87 | // We only really care about the actual bytes read.
88 | if err != nil {
89 | if err == io.EOF {
90 | return nil, io.ErrUnexpectedEOF
91 | }
92 | if debugDecoder {
93 | println("readSmall: got", n2, "want", n, "err", err)
94 | }
95 | return nil, err
96 | }
97 | return r.tmp[:n], nil
98 | }
99 |
100 | func (r *readerWrapper) readBig(n int, dst []byte) ([]byte, error) {
101 | if cap(dst) < n {
102 | dst = make([]byte, n)
103 | }
104 | n2, err := io.ReadFull(r.r, dst[:n])
105 | if err == io.EOF && n > 0 {
106 | err = io.ErrUnexpectedEOF
107 | }
108 | return dst[:n2], err
109 | }
110 |
111 | func (r *readerWrapper) readByte() (byte, error) {
112 | n2, err := io.ReadFull(r.r, r.tmp[:1])
113 | if err != nil {
114 | if err == io.EOF {
115 | err = io.ErrUnexpectedEOF
116 | }
117 | return 0, err
118 | }
119 | if n2 != 1 {
120 | return 0, io.ErrUnexpectedEOF
121 | }
122 | return r.tmp[0], nil
123 | }
124 |
125 | func (r *readerWrapper) skipN(n int64) error {
126 | n2, err := io.CopyN(io.Discard, r.r, n)
127 | if n2 != n {
128 | err = io.ErrUnexpectedEOF
129 | }
130 | return err
131 | }
132 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/zstd/bytereader.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019+ Klaus Post. All rights reserved.
2 | // License information can be found in the LICENSE file.
3 | // Based on work by Yann Collet, released under BSD License.
4 |
5 | package zstd
6 |
7 | // byteReader provides a byte reader that reads
8 | // little endian values from a byte stream.
9 | // The input stream is manually advanced.
10 | // The reader performs no bounds checks.
11 | type byteReader struct {
12 | b []byte
13 | off int
14 | }
15 |
16 | // advance the stream b n bytes.
17 | func (b *byteReader) advance(n uint) {
18 | b.off += int(n)
19 | }
20 |
21 | // overread returns whether we have advanced too far.
22 | func (b *byteReader) overread() bool {
23 | return b.off > len(b.b)
24 | }
25 |
26 | // Int32 returns a little endian int32 starting at current offset.
27 | func (b byteReader) Int32() int32 {
28 | b2 := b.b[b.off:]
29 | b2 = b2[:4]
30 | v3 := int32(b2[3])
31 | v2 := int32(b2[2])
32 | v1 := int32(b2[1])
33 | v0 := int32(b2[0])
34 | return v0 | (v1 << 8) | (v2 << 16) | (v3 << 24)
35 | }
36 |
37 | // Uint8 returns the next byte
38 | func (b *byteReader) Uint8() uint8 {
39 | v := b.b[b.off]
40 | return v
41 | }
42 |
43 | // Uint32 returns a little endian uint32 starting at current offset.
44 | func (b byteReader) Uint32() uint32 {
45 | if r := b.remain(); r < 4 {
46 | // Very rare
47 | v := uint32(0)
48 | for i := 1; i <= r; i++ {
49 | v = (v << 8) | uint32(b.b[len(b.b)-i])
50 | }
51 | return v
52 | }
53 | b2 := b.b[b.off:]
54 | b2 = b2[:4]
55 | v3 := uint32(b2[3])
56 | v2 := uint32(b2[2])
57 | v1 := uint32(b2[1])
58 | v0 := uint32(b2[0])
59 | return v0 | (v1 << 8) | (v2 << 16) | (v3 << 24)
60 | }
61 |
62 | // Uint32NC returns a little endian uint32 starting at current offset.
63 | // The caller must be sure if there are at least 4 bytes left.
64 | func (b byteReader) Uint32NC() uint32 {
65 | b2 := b.b[b.off:]
66 | b2 = b2[:4]
67 | v3 := uint32(b2[3])
68 | v2 := uint32(b2[2])
69 | v1 := uint32(b2[1])
70 | v0 := uint32(b2[0])
71 | return v0 | (v1 << 8) | (v2 << 16) | (v3 << 24)
72 | }
73 |
74 | // unread returns the unread portion of the input.
75 | func (b byteReader) unread() []byte {
76 | return b.b[b.off:]
77 | }
78 |
79 | // remain will return the number of bytes remaining.
80 | func (b byteReader) remain() int {
81 | return len(b.b) - b.off
82 | }
83 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/zstd/frameenc.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019+ Klaus Post. All rights reserved.
2 | // License information can be found in the LICENSE file.
3 | // Based on work by Yann Collet, released under BSD License.
4 |
5 | package zstd
6 |
7 | import (
8 | "encoding/binary"
9 | "fmt"
10 | "io"
11 | "math"
12 | "math/bits"
13 | )
14 |
15 | type frameHeader struct {
16 | ContentSize uint64
17 | WindowSize uint32
18 | SingleSegment bool
19 | Checksum bool
20 | DictID uint32
21 | }
22 |
23 | const maxHeaderSize = 14
24 |
25 | func (f frameHeader) appendTo(dst []byte) []byte {
26 | dst = append(dst, frameMagic...)
27 | var fhd uint8
28 | if f.Checksum {
29 | fhd |= 1 << 2
30 | }
31 | if f.SingleSegment {
32 | fhd |= 1 << 5
33 | }
34 |
35 | var dictIDContent []byte
36 | if f.DictID > 0 {
37 | var tmp [4]byte
38 | if f.DictID < 256 {
39 | fhd |= 1
40 | tmp[0] = uint8(f.DictID)
41 | dictIDContent = tmp[:1]
42 | } else if f.DictID < 1<<16 {
43 | fhd |= 2
44 | binary.LittleEndian.PutUint16(tmp[:2], uint16(f.DictID))
45 | dictIDContent = tmp[:2]
46 | } else {
47 | fhd |= 3
48 | binary.LittleEndian.PutUint32(tmp[:4], f.DictID)
49 | dictIDContent = tmp[:4]
50 | }
51 | }
52 | var fcs uint8
53 | if f.ContentSize >= 256 {
54 | fcs++
55 | }
56 | if f.ContentSize >= 65536+256 {
57 | fcs++
58 | }
59 | if f.ContentSize >= 0xffffffff {
60 | fcs++
61 | }
62 |
63 | fhd |= fcs << 6
64 |
65 | dst = append(dst, fhd)
66 | if !f.SingleSegment {
67 | const winLogMin = 10
68 | windowLog := (bits.Len32(f.WindowSize-1) - winLogMin) << 3
69 | dst = append(dst, uint8(windowLog))
70 | }
71 | if f.DictID > 0 {
72 | dst = append(dst, dictIDContent...)
73 | }
74 | switch fcs {
75 | case 0:
76 | if f.SingleSegment {
77 | dst = append(dst, uint8(f.ContentSize))
78 | }
79 | // Unless SingleSegment is set, framessizes < 256 are not stored.
80 | case 1:
81 | f.ContentSize -= 256
82 | dst = append(dst, uint8(f.ContentSize), uint8(f.ContentSize>>8))
83 | case 2:
84 | dst = append(dst, uint8(f.ContentSize), uint8(f.ContentSize>>8), uint8(f.ContentSize>>16), uint8(f.ContentSize>>24))
85 | case 3:
86 | dst = append(dst, uint8(f.ContentSize), uint8(f.ContentSize>>8), uint8(f.ContentSize>>16), uint8(f.ContentSize>>24),
87 | uint8(f.ContentSize>>32), uint8(f.ContentSize>>40), uint8(f.ContentSize>>48), uint8(f.ContentSize>>56))
88 | default:
89 | panic("invalid fcs")
90 | }
91 | return dst
92 | }
93 |
94 | const skippableFrameHeader = 4 + 4
95 |
96 | // calcSkippableFrame will return a total size to be added for written
97 | // to be divisible by multiple.
98 | // The value will always be > skippableFrameHeader.
99 | // The function will panic if written < 0 or wantMultiple <= 0.
100 | func calcSkippableFrame(written, wantMultiple int64) int {
101 | if wantMultiple <= 0 {
102 | panic("wantMultiple <= 0")
103 | }
104 | if written < 0 {
105 | panic("written < 0")
106 | }
107 | leftOver := written % wantMultiple
108 | if leftOver == 0 {
109 | return 0
110 | }
111 | toAdd := wantMultiple - leftOver
112 | for toAdd < skippableFrameHeader {
113 | toAdd += wantMultiple
114 | }
115 | return int(toAdd)
116 | }
117 |
118 | // skippableFrame will add a skippable frame with a total size of bytes.
119 | // total should be >= skippableFrameHeader and < math.MaxUint32.
120 | func skippableFrame(dst []byte, total int, r io.Reader) ([]byte, error) {
121 | if total == 0 {
122 | return dst, nil
123 | }
124 | if total < skippableFrameHeader {
125 | return dst, fmt.Errorf("requested skippable frame (%d) < 8", total)
126 | }
127 | if int64(total) > math.MaxUint32 {
128 | return dst, fmt.Errorf("requested skippable frame (%d) > max uint32", total)
129 | }
130 | dst = append(dst, 0x50, 0x2a, 0x4d, 0x18)
131 | f := uint32(total - skippableFrameHeader)
132 | dst = append(dst, uint8(f), uint8(f>>8), uint8(f>>16), uint8(f>>24))
133 | start := len(dst)
134 | dst = append(dst, make([]byte, f)...)
135 | _, err := io.ReadFull(r, dst[start:])
136 | return dst, err
137 | }
138 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/zstd/fse_decoder_amd64.go:
--------------------------------------------------------------------------------
1 | //go:build amd64 && !appengine && !noasm && gc
2 | // +build amd64,!appengine,!noasm,gc
3 |
4 | package zstd
5 |
6 | import (
7 | "fmt"
8 | )
9 |
10 | type buildDtableAsmContext struct {
11 | // inputs
12 | stateTable *uint16
13 | norm *int16
14 | dt *uint64
15 |
16 | // outputs --- set by the procedure in the case of error;
17 | // for interpretation please see the error handling part below
18 | errParam1 uint64
19 | errParam2 uint64
20 | }
21 |
22 | // buildDtable_asm is an x86 assembly implementation of fseDecoder.buildDtable.
23 | // Function returns non-zero exit code on error.
24 | //
25 | //go:noescape
26 | func buildDtable_asm(s *fseDecoder, ctx *buildDtableAsmContext) int
27 |
28 | // please keep in sync with _generate/gen_fse.go
29 | const (
30 | errorCorruptedNormalizedCounter = 1
31 | errorNewStateTooBig = 2
32 | errorNewStateNoBits = 3
33 | )
34 |
35 | // buildDtable will build the decoding table.
36 | func (s *fseDecoder) buildDtable() error {
37 | ctx := buildDtableAsmContext{
38 | stateTable: &s.stateTable[0],
39 | norm: &s.norm[0],
40 | dt: (*uint64)(&s.dt[0]),
41 | }
42 | code := buildDtable_asm(s, &ctx)
43 |
44 | if code != 0 {
45 | switch code {
46 | case errorCorruptedNormalizedCounter:
47 | position := ctx.errParam1
48 | return fmt.Errorf("corrupted input (position=%d, expected 0)", position)
49 |
50 | case errorNewStateTooBig:
51 | newState := decSymbol(ctx.errParam1)
52 | size := ctx.errParam2
53 | return fmt.Errorf("newState (%d) outside table size (%d)", newState, size)
54 |
55 | case errorNewStateNoBits:
56 | newState := decSymbol(ctx.errParam1)
57 | oldState := decSymbol(ctx.errParam2)
58 | return fmt.Errorf("newState (%d) == oldState (%d) and no bits", newState, oldState)
59 |
60 | default:
61 | return fmt.Errorf("buildDtable_asm returned unhandled nonzero code = %d", code)
62 | }
63 | }
64 | return nil
65 | }
66 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/zstd/fse_decoder_amd64.s:
--------------------------------------------------------------------------------
1 | // Code generated by command: go run gen_fse.go -out ../fse_decoder_amd64.s -pkg=zstd. DO NOT EDIT.
2 |
3 | //go:build !appengine && !noasm && gc && !noasm
4 |
5 | // func buildDtable_asm(s *fseDecoder, ctx *buildDtableAsmContext) int
6 | TEXT ·buildDtable_asm(SB), $0-24
7 | MOVQ ctx+8(FP), CX
8 | MOVQ s+0(FP), DI
9 |
10 | // Load values
11 | MOVBQZX 4098(DI), DX
12 | XORQ AX, AX
13 | BTSQ DX, AX
14 | MOVQ (CX), BX
15 | MOVQ 16(CX), SI
16 | LEAQ -1(AX), R8
17 | MOVQ 8(CX), CX
18 | MOVWQZX 4096(DI), DI
19 |
20 | // End load values
21 | // Init, lay down lowprob symbols
22 | XORQ R9, R9
23 | JMP init_main_loop_condition
24 |
25 | init_main_loop:
26 | MOVWQSX (CX)(R9*2), R10
27 | CMPW R10, $-1
28 | JNE do_not_update_high_threshold
29 | MOVB R9, 1(SI)(R8*8)
30 | DECQ R8
31 | MOVQ $0x0000000000000001, R10
32 |
33 | do_not_update_high_threshold:
34 | MOVW R10, (BX)(R9*2)
35 | INCQ R9
36 |
37 | init_main_loop_condition:
38 | CMPQ R9, DI
39 | JL init_main_loop
40 |
41 | // Spread symbols
42 | // Calculate table step
43 | MOVQ AX, R9
44 | SHRQ $0x01, R9
45 | MOVQ AX, R10
46 | SHRQ $0x03, R10
47 | LEAQ 3(R9)(R10*1), R9
48 |
49 | // Fill add bits values
50 | LEAQ -1(AX), R10
51 | XORQ R11, R11
52 | XORQ R12, R12
53 | JMP spread_main_loop_condition
54 |
55 | spread_main_loop:
56 | XORQ R13, R13
57 | MOVWQSX (CX)(R12*2), R14
58 | JMP spread_inner_loop_condition
59 |
60 | spread_inner_loop:
61 | MOVB R12, 1(SI)(R11*8)
62 |
63 | adjust_position:
64 | ADDQ R9, R11
65 | ANDQ R10, R11
66 | CMPQ R11, R8
67 | JG adjust_position
68 | INCQ R13
69 |
70 | spread_inner_loop_condition:
71 | CMPQ R13, R14
72 | JL spread_inner_loop
73 | INCQ R12
74 |
75 | spread_main_loop_condition:
76 | CMPQ R12, DI
77 | JL spread_main_loop
78 | TESTQ R11, R11
79 | JZ spread_check_ok
80 | MOVQ ctx+8(FP), AX
81 | MOVQ R11, 24(AX)
82 | MOVQ $+1, ret+16(FP)
83 | RET
84 |
85 | spread_check_ok:
86 | // Build Decoding table
87 | XORQ DI, DI
88 |
89 | build_table_main_table:
90 | MOVBQZX 1(SI)(DI*8), CX
91 | MOVWQZX (BX)(CX*2), R8
92 | LEAQ 1(R8), R9
93 | MOVW R9, (BX)(CX*2)
94 | MOVQ R8, R9
95 | BSRQ R9, R9
96 | MOVQ DX, CX
97 | SUBQ R9, CX
98 | SHLQ CL, R8
99 | SUBQ AX, R8
100 | MOVB CL, (SI)(DI*8)
101 | MOVW R8, 2(SI)(DI*8)
102 | CMPQ R8, AX
103 | JLE build_table_check1_ok
104 | MOVQ ctx+8(FP), CX
105 | MOVQ R8, 24(CX)
106 | MOVQ AX, 32(CX)
107 | MOVQ $+2, ret+16(FP)
108 | RET
109 |
110 | build_table_check1_ok:
111 | TESTB CL, CL
112 | JNZ build_table_check2_ok
113 | CMPW R8, DI
114 | JNE build_table_check2_ok
115 | MOVQ ctx+8(FP), AX
116 | MOVQ R8, 24(AX)
117 | MOVQ DI, 32(AX)
118 | MOVQ $+3, ret+16(FP)
119 | RET
120 |
121 | build_table_check2_ok:
122 | INCQ DI
123 | CMPQ DI, AX
124 | JL build_table_main_table
125 | MOVQ $+0, ret+16(FP)
126 | RET
127 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/zstd/fse_decoder_generic.go:
--------------------------------------------------------------------------------
1 | //go:build !amd64 || appengine || !gc || noasm
2 | // +build !amd64 appengine !gc noasm
3 |
4 | package zstd
5 |
6 | import (
7 | "errors"
8 | "fmt"
9 | )
10 |
11 | // buildDtable will build the decoding table.
12 | func (s *fseDecoder) buildDtable() error {
13 | tableSize := uint32(1 << s.actualTableLog)
14 | highThreshold := tableSize - 1
15 | symbolNext := s.stateTable[:256]
16 |
17 | // Init, lay down lowprob symbols
18 | {
19 | for i, v := range s.norm[:s.symbolLen] {
20 | if v == -1 {
21 | s.dt[highThreshold].setAddBits(uint8(i))
22 | highThreshold--
23 | v = 1
24 | }
25 | symbolNext[i] = uint16(v)
26 | }
27 | }
28 |
29 | // Spread symbols
30 | {
31 | tableMask := tableSize - 1
32 | step := tableStep(tableSize)
33 | position := uint32(0)
34 | for ss, v := range s.norm[:s.symbolLen] {
35 | for i := 0; i < int(v); i++ {
36 | s.dt[position].setAddBits(uint8(ss))
37 | for {
38 | // lowprob area
39 | position = (position + step) & tableMask
40 | if position <= highThreshold {
41 | break
42 | }
43 | }
44 | }
45 | }
46 | if position != 0 {
47 | // position must reach all cells once, otherwise normalizedCounter is incorrect
48 | return errors.New("corrupted input (position != 0)")
49 | }
50 | }
51 |
52 | // Build Decoding table
53 | {
54 | tableSize := uint16(1 << s.actualTableLog)
55 | for u, v := range s.dt[:tableSize] {
56 | symbol := v.addBits()
57 | nextState := symbolNext[symbol]
58 | symbolNext[symbol] = nextState + 1
59 | nBits := s.actualTableLog - byte(highBits(uint32(nextState)))
60 | s.dt[u&maxTableMask].setNBits(nBits)
61 | newState := (nextState << nBits) - tableSize
62 | if newState > tableSize {
63 | return fmt.Errorf("newState (%d) outside table size (%d)", newState, tableSize)
64 | }
65 | if newState == uint16(u) && nBits == 0 {
66 | // Seems weird that this is possible with nbits > 0.
67 | return fmt.Errorf("newState (%d) == oldState (%d) and no bits", newState, u)
68 | }
69 | s.dt[u&maxTableMask].setNewState(newState)
70 | }
71 | }
72 | return nil
73 | }
74 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/zstd/hash.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019+ Klaus Post. All rights reserved.
2 | // License information can be found in the LICENSE file.
3 | // Based on work by Yann Collet, released under BSD License.
4 |
5 | package zstd
6 |
7 | const (
8 | prime3bytes = 506832829
9 | prime4bytes = 2654435761
10 | prime5bytes = 889523592379
11 | prime6bytes = 227718039650203
12 | prime7bytes = 58295818150454627
13 | prime8bytes = 0xcf1bbcdcb7a56463
14 | )
15 |
16 | // hashLen returns a hash of the lowest mls bytes of with length output bits.
17 | // mls must be >=3 and <=8. Any other value will return hash for 4 bytes.
18 | // length should always be < 32.
19 | // Preferably length and mls should be a constant for inlining.
20 | func hashLen(u uint64, length, mls uint8) uint32 {
21 | switch mls {
22 | case 3:
23 | return (uint32(u<<8) * prime3bytes) >> (32 - length)
24 | case 5:
25 | return uint32(((u << (64 - 40)) * prime5bytes) >> (64 - length))
26 | case 6:
27 | return uint32(((u << (64 - 48)) * prime6bytes) >> (64 - length))
28 | case 7:
29 | return uint32(((u << (64 - 56)) * prime7bytes) >> (64 - length))
30 | case 8:
31 | return uint32((u * prime8bytes) >> (64 - length))
32 | default:
33 | return (uint32(u) * prime4bytes) >> (32 - length)
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/zstd/history.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019+ Klaus Post. All rights reserved.
2 | // License information can be found in the LICENSE file.
3 | // Based on work by Yann Collet, released under BSD License.
4 |
5 | package zstd
6 |
7 | import (
8 | "github.com/klauspost/compress/huff0"
9 | )
10 |
11 | // history contains the information transferred between blocks.
12 | type history struct {
13 | // Literal decompression
14 | huffTree *huff0.Scratch
15 |
16 | // Sequence decompression
17 | decoders sequenceDecs
18 | recentOffsets [3]int
19 |
20 | // History buffer...
21 | b []byte
22 |
23 | // ignoreBuffer is meant to ignore a number of bytes
24 | // when checking for matches in history
25 | ignoreBuffer int
26 |
27 | windowSize int
28 | allocFrameBuffer int // needed?
29 | error bool
30 | dict *dict
31 | }
32 |
33 | // reset will reset the history to initial state of a frame.
34 | // The history must already have been initialized to the desired size.
35 | func (h *history) reset() {
36 | h.b = h.b[:0]
37 | h.ignoreBuffer = 0
38 | h.error = false
39 | h.recentOffsets = [3]int{1, 4, 8}
40 | h.decoders.freeDecoders()
41 | h.decoders = sequenceDecs{br: h.decoders.br}
42 | h.freeHuffDecoder()
43 | h.huffTree = nil
44 | h.dict = nil
45 | //printf("history created: %+v (l: %d, c: %d)", *h, len(h.b), cap(h.b))
46 | }
47 |
48 | func (h *history) freeHuffDecoder() {
49 | if h.huffTree != nil {
50 | if h.dict == nil || h.dict.litEnc != h.huffTree {
51 | huffDecoderPool.Put(h.huffTree)
52 | h.huffTree = nil
53 | }
54 | }
55 | }
56 |
57 | func (h *history) setDict(dict *dict) {
58 | if dict == nil {
59 | return
60 | }
61 | h.dict = dict
62 | h.decoders.litLengths = dict.llDec
63 | h.decoders.offsets = dict.ofDec
64 | h.decoders.matchLengths = dict.mlDec
65 | h.decoders.dict = dict.content
66 | h.recentOffsets = dict.offsets
67 | h.huffTree = dict.litEnc
68 | }
69 |
70 | // append bytes to history.
71 | // This function will make sure there is space for it,
72 | // if the buffer has been allocated with enough extra space.
73 | func (h *history) append(b []byte) {
74 | if len(b) >= h.windowSize {
75 | // Discard all history by simply overwriting
76 | h.b = h.b[:h.windowSize]
77 | copy(h.b, b[len(b)-h.windowSize:])
78 | return
79 | }
80 |
81 | // If there is space, append it.
82 | if len(b) < cap(h.b)-len(h.b) {
83 | h.b = append(h.b, b...)
84 | return
85 | }
86 |
87 | // Move data down so we only have window size left.
88 | // We know we have less than window size in b at this point.
89 | discard := len(b) + len(h.b) - h.windowSize
90 | copy(h.b, h.b[discard:])
91 | h.b = h.b[:h.windowSize]
92 | copy(h.b[h.windowSize-len(b):], b)
93 | }
94 |
95 | // ensureBlock will ensure there is space for at least one block...
96 | func (h *history) ensureBlock() {
97 | if cap(h.b) < h.allocFrameBuffer {
98 | h.b = make([]byte, 0, h.allocFrameBuffer)
99 | return
100 | }
101 |
102 | avail := cap(h.b) - len(h.b)
103 | if avail >= h.windowSize || avail > maxCompressedBlockSize {
104 | return
105 | }
106 | // Move data down so we only have window size left.
107 | // We know we have less than window size in b at this point.
108 | discard := len(h.b) - h.windowSize
109 | copy(h.b, h.b[discard:])
110 | h.b = h.b[:h.windowSize]
111 | }
112 |
113 | // append bytes to history without ever discarding anything.
114 | func (h *history) appendKeep(b []byte) {
115 | h.b = append(h.b, b...)
116 | }
117 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/zstd/internal/xxhash/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016 Caleb Spare
2 |
3 | MIT License
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | "Software"), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/zstd/internal/xxhash/README.md:
--------------------------------------------------------------------------------
1 | # xxhash
2 |
3 | VENDORED: Go to [github.com/cespare/xxhash](https://github.com/cespare/xxhash) for original package.
4 |
5 | xxhash is a Go implementation of the 64-bit [xxHash] algorithm, XXH64. This is a
6 | high-quality hashing algorithm that is much faster than anything in the Go
7 | standard library.
8 |
9 | This package provides a straightforward API:
10 |
11 | ```
12 | func Sum64(b []byte) uint64
13 | func Sum64String(s string) uint64
14 | type Digest struct{ ... }
15 | func New() *Digest
16 | ```
17 |
18 | The `Digest` type implements hash.Hash64. Its key methods are:
19 |
20 | ```
21 | func (*Digest) Write([]byte) (int, error)
22 | func (*Digest) WriteString(string) (int, error)
23 | func (*Digest) Sum64() uint64
24 | ```
25 |
26 | The package is written with optimized pure Go and also contains even faster
27 | assembly implementations for amd64 and arm64. If desired, the `purego` build tag
28 | opts into using the Go code even on those architectures.
29 |
30 | [xxHash]: http://cyan4973.github.io/xxHash/
31 |
32 | ## Compatibility
33 |
34 | This package is in a module and the latest code is in version 2 of the module.
35 | You need a version of Go with at least "minimal module compatibility" to use
36 | github.com/cespare/xxhash/v2:
37 |
38 | * 1.9.7+ for Go 1.9
39 | * 1.10.3+ for Go 1.10
40 | * Go 1.11 or later
41 |
42 | I recommend using the latest release of Go.
43 |
44 | ## Benchmarks
45 |
46 | Here are some quick benchmarks comparing the pure-Go and assembly
47 | implementations of Sum64.
48 |
49 | | input size | purego | asm |
50 | | ---------- | --------- | --------- |
51 | | 4 B | 1.3 GB/s | 1.2 GB/s |
52 | | 16 B | 2.9 GB/s | 3.5 GB/s |
53 | | 100 B | 6.9 GB/s | 8.1 GB/s |
54 | | 4 KB | 11.7 GB/s | 16.7 GB/s |
55 | | 10 MB | 12.0 GB/s | 17.3 GB/s |
56 |
57 | These numbers were generated on Ubuntu 20.04 with an Intel Xeon Platinum 8252C
58 | CPU using the following commands under Go 1.19.2:
59 |
60 | ```
61 | benchstat <(go test -tags purego -benchtime 500ms -count 15 -bench 'Sum64$')
62 | benchstat <(go test -benchtime 500ms -count 15 -bench 'Sum64$')
63 | ```
64 |
65 | ## Projects using this package
66 |
67 | - [InfluxDB](https://github.com/influxdata/influxdb)
68 | - [Prometheus](https://github.com/prometheus/prometheus)
69 | - [VictoriaMetrics](https://github.com/VictoriaMetrics/VictoriaMetrics)
70 | - [FreeCache](https://github.com/coocood/freecache)
71 | - [FastCache](https://github.com/VictoriaMetrics/fastcache)
72 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_asm.go:
--------------------------------------------------------------------------------
1 | //go:build (amd64 || arm64) && !appengine && gc && !purego && !noasm
2 | // +build amd64 arm64
3 | // +build !appengine
4 | // +build gc
5 | // +build !purego
6 | // +build !noasm
7 |
8 | package xxhash
9 |
10 | // Sum64 computes the 64-bit xxHash digest of b.
11 | //
12 | //go:noescape
13 | func Sum64(b []byte) uint64
14 |
15 | //go:noescape
16 | func writeBlocks(s *Digest, b []byte) int
17 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_other.go:
--------------------------------------------------------------------------------
1 | //go:build (!amd64 && !arm64) || appengine || !gc || purego || noasm
2 | // +build !amd64,!arm64 appengine !gc purego noasm
3 |
4 | package xxhash
5 |
6 | // Sum64 computes the 64-bit xxHash digest of b.
7 | func Sum64(b []byte) uint64 {
8 | // A simpler version would be
9 | // d := New()
10 | // d.Write(b)
11 | // return d.Sum64()
12 | // but this is faster, particularly for small inputs.
13 |
14 | n := len(b)
15 | var h uint64
16 |
17 | if n >= 32 {
18 | v1 := primes[0] + prime2
19 | v2 := prime2
20 | v3 := uint64(0)
21 | v4 := -primes[0]
22 | for len(b) >= 32 {
23 | v1 = round(v1, u64(b[0:8:len(b)]))
24 | v2 = round(v2, u64(b[8:16:len(b)]))
25 | v3 = round(v3, u64(b[16:24:len(b)]))
26 | v4 = round(v4, u64(b[24:32:len(b)]))
27 | b = b[32:len(b):len(b)]
28 | }
29 | h = rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4)
30 | h = mergeRound(h, v1)
31 | h = mergeRound(h, v2)
32 | h = mergeRound(h, v3)
33 | h = mergeRound(h, v4)
34 | } else {
35 | h = prime5
36 | }
37 |
38 | h += uint64(n)
39 |
40 | for ; len(b) >= 8; b = b[8:] {
41 | k1 := round(0, u64(b[:8]))
42 | h ^= k1
43 | h = rol27(h)*prime1 + prime4
44 | }
45 | if len(b) >= 4 {
46 | h ^= uint64(u32(b[:4])) * prime1
47 | h = rol23(h)*prime2 + prime3
48 | b = b[4:]
49 | }
50 | for ; len(b) > 0; b = b[1:] {
51 | h ^= uint64(b[0]) * prime5
52 | h = rol11(h) * prime1
53 | }
54 |
55 | h ^= h >> 33
56 | h *= prime2
57 | h ^= h >> 29
58 | h *= prime3
59 | h ^= h >> 32
60 |
61 | return h
62 | }
63 |
64 | func writeBlocks(d *Digest, b []byte) int {
65 | v1, v2, v3, v4 := d.v1, d.v2, d.v3, d.v4
66 | n := len(b)
67 | for len(b) >= 32 {
68 | v1 = round(v1, u64(b[0:8:len(b)]))
69 | v2 = round(v2, u64(b[8:16:len(b)]))
70 | v3 = round(v3, u64(b[16:24:len(b)]))
71 | v4 = round(v4, u64(b[24:32:len(b)]))
72 | b = b[32:len(b):len(b)]
73 | }
74 | d.v1, d.v2, d.v3, d.v4 = v1, v2, v3, v4
75 | return n - len(b)
76 | }
77 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_safe.go:
--------------------------------------------------------------------------------
1 | package xxhash
2 |
3 | // Sum64String computes the 64-bit xxHash digest of s.
4 | func Sum64String(s string) uint64 {
5 | return Sum64([]byte(s))
6 | }
7 |
8 | // WriteString adds more data to d. It always returns len(s), nil.
9 | func (d *Digest) WriteString(s string) (n int, err error) {
10 | return d.Write([]byte(s))
11 | }
12 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/zstd/matchlen_amd64.go:
--------------------------------------------------------------------------------
1 | //go:build amd64 && !appengine && !noasm && gc
2 | // +build amd64,!appengine,!noasm,gc
3 |
4 | // Copyright 2019+ Klaus Post. All rights reserved.
5 | // License information can be found in the LICENSE file.
6 |
7 | package zstd
8 |
9 | // matchLen returns how many bytes match in a and b
10 | //
11 | // It assumes that:
12 | //
13 | // len(a) <= len(b) and len(a) > 0
14 | //
15 | //go:noescape
16 | func matchLen(a []byte, b []byte) int
17 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/zstd/matchlen_amd64.s:
--------------------------------------------------------------------------------
1 | // Copied from S2 implementation.
2 |
3 | //go:build !appengine && !noasm && gc && !noasm
4 |
5 | #include "textflag.h"
6 |
7 | // func matchLen(a []byte, b []byte) int
8 | TEXT ·matchLen(SB), NOSPLIT, $0-56
9 | MOVQ a_base+0(FP), AX
10 | MOVQ b_base+24(FP), CX
11 | MOVQ a_len+8(FP), DX
12 |
13 | // matchLen
14 | XORL SI, SI
15 | CMPL DX, $0x08
16 | JB matchlen_match4_standalone
17 |
18 | matchlen_loopback_standalone:
19 | MOVQ (AX)(SI*1), BX
20 | XORQ (CX)(SI*1), BX
21 | JZ matchlen_loop_standalone
22 |
23 | #ifdef GOAMD64_v3
24 | TZCNTQ BX, BX
25 | #else
26 | BSFQ BX, BX
27 | #endif
28 | SHRL $0x03, BX
29 | LEAL (SI)(BX*1), SI
30 | JMP gen_match_len_end
31 |
32 | matchlen_loop_standalone:
33 | LEAL -8(DX), DX
34 | LEAL 8(SI), SI
35 | CMPL DX, $0x08
36 | JAE matchlen_loopback_standalone
37 |
38 | matchlen_match4_standalone:
39 | CMPL DX, $0x04
40 | JB matchlen_match2_standalone
41 | MOVL (AX)(SI*1), BX
42 | CMPL (CX)(SI*1), BX
43 | JNE matchlen_match2_standalone
44 | LEAL -4(DX), DX
45 | LEAL 4(SI), SI
46 |
47 | matchlen_match2_standalone:
48 | CMPL DX, $0x02
49 | JB matchlen_match1_standalone
50 | MOVW (AX)(SI*1), BX
51 | CMPW (CX)(SI*1), BX
52 | JNE matchlen_match1_standalone
53 | LEAL -2(DX), DX
54 | LEAL 2(SI), SI
55 |
56 | matchlen_match1_standalone:
57 | CMPL DX, $0x01
58 | JB gen_match_len_end
59 | MOVB (AX)(SI*1), BL
60 | CMPB (CX)(SI*1), BL
61 | JNE gen_match_len_end
62 | INCL SI
63 |
64 | gen_match_len_end:
65 | MOVQ SI, ret+48(FP)
66 | RET
67 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/zstd/matchlen_generic.go:
--------------------------------------------------------------------------------
1 | //go:build !amd64 || appengine || !gc || noasm
2 | // +build !amd64 appengine !gc noasm
3 |
4 | // Copyright 2019+ Klaus Post. All rights reserved.
5 | // License information can be found in the LICENSE file.
6 |
7 | package zstd
8 |
9 | import (
10 | "encoding/binary"
11 | "math/bits"
12 | )
13 |
14 | // matchLen returns the maximum common prefix length of a and b.
15 | // a must be the shortest of the two.
16 | func matchLen(a, b []byte) (n int) {
17 | for ; len(a) >= 8 && len(b) >= 8; a, b = a[8:], b[8:] {
18 | diff := binary.LittleEndian.Uint64(a) ^ binary.LittleEndian.Uint64(b)
19 | if diff != 0 {
20 | return n + bits.TrailingZeros64(diff)>>3
21 | }
22 | n += 8
23 | }
24 |
25 | for i := range a {
26 | if a[i] != b[i] {
27 | break
28 | }
29 | n++
30 | }
31 | return n
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/vendor/github.com/klauspost/compress/zstd/seqenc.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019+ Klaus Post. All rights reserved.
2 | // License information can be found in the LICENSE file.
3 | // Based on work by Yann Collet, released under BSD License.
4 |
5 | package zstd
6 |
7 | import "math/bits"
8 |
9 | type seqCoders struct {
10 | llEnc, ofEnc, mlEnc *fseEncoder
11 | llPrev, ofPrev, mlPrev *fseEncoder
12 | }
13 |
14 | // swap coders with another (block).
15 | func (s *seqCoders) swap(other *seqCoders) {
16 | *s, *other = *other, *s
17 | }
18 |
19 | // setPrev will update the previous encoders to the actually used ones
20 | // and make sure a fresh one is in the main slot.
21 | func (s *seqCoders) setPrev(ll, ml, of *fseEncoder) {
22 | compareSwap := func(used *fseEncoder, current, prev **fseEncoder) {
23 | // We used the new one, more current to history and reuse the previous history
24 | if *current == used {
25 | *prev, *current = *current, *prev
26 | c := *current
27 | p := *prev
28 | c.reUsed = false
29 | p.reUsed = true
30 | return
31 | }
32 | if used == *prev {
33 | return
34 | }
35 | // Ensure we cannot reuse by accident
36 | prevEnc := *prev
37 | prevEnc.symbolLen = 0
38 | }
39 | compareSwap(ll, &s.llEnc, &s.llPrev)
40 | compareSwap(ml, &s.mlEnc, &s.mlPrev)
41 | compareSwap(of, &s.ofEnc, &s.ofPrev)
42 | }
43 |
44 | func highBit(val uint32) (n uint32) {
45 | return uint32(bits.Len32(val) - 1)
46 | }
47 |
48 | var llCodeTable = [64]byte{0, 1, 2, 3, 4, 5, 6, 7,
49 | 8, 9, 10, 11, 12, 13, 14, 15,
50 | 16, 16, 17, 17, 18, 18, 19, 19,
51 | 20, 20, 20, 20, 21, 21, 21, 21,
52 | 22, 22, 22, 22, 22, 22, 22, 22,
53 | 23, 23, 23, 23, 23, 23, 23, 23,
54 | 24, 24, 24, 24, 24, 24, 24, 24,
55 | 24, 24, 24, 24, 24, 24, 24, 24}
56 |
57 | // Up to 6 bits
58 | const maxLLCode = 35
59 |
60 | // llBitsTable translates from ll code to number of bits.
61 | var llBitsTable = [maxLLCode + 1]byte{
62 | 0, 0, 0, 0, 0, 0, 0, 0,
63 | 0, 0, 0, 0, 0, 0, 0, 0,
64 | 1, 1, 1, 1, 2, 2, 3, 3,
65 | 4, 6, 7, 8, 9, 10, 11, 12,
66 | 13, 14, 15, 16}
67 |
68 | // llCode returns the code that represents the literal length requested.
69 | func llCode(litLength uint32) uint8 {
70 | const llDeltaCode = 19
71 | if litLength <= 63 {
72 | // Compiler insists on bounds check (Go 1.12)
73 | return llCodeTable[litLength&63]
74 | }
75 | return uint8(highBit(litLength)) + llDeltaCode
76 | }
77 |
78 | var mlCodeTable = [128]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
79 | 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
80 | 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37,
81 | 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39,
82 | 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
83 | 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
84 | 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
85 | 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42}
86 |
87 | // Up to 6 bits
88 | const maxMLCode = 52
89 |
90 | // mlBitsTable translates from ml code to number of bits.
91 | var mlBitsTable = [maxMLCode + 1]byte{
92 | 0, 0, 0, 0, 0, 0, 0, 0,
93 | 0, 0, 0, 0, 0, 0, 0, 0,
94 | 0, 0, 0, 0, 0, 0, 0, 0,
95 | 0, 0, 0, 0, 0, 0, 0, 0,
96 | 1, 1, 1, 1, 2, 2, 3, 3,
97 | 4, 4, 5, 7, 8, 9, 10, 11,
98 | 12, 13, 14, 15, 16}
99 |
100 | // note : mlBase = matchLength - MINMATCH;
101 | // because it's the format it's stored in seqStore->sequences
102 | func mlCode(mlBase uint32) uint8 {
103 | const mlDeltaCode = 36
104 | if mlBase <= 127 {
105 | // Compiler insists on bounds check (Go 1.12)
106 | return mlCodeTable[mlBase&127]
107 | }
108 | return uint8(highBit(mlBase)) + mlDeltaCode
109 | }
110 |
111 | func ofCode(offset uint32) uint8 {
112 | // A valid offset will always be > 0.
113 | return uint8(bits.Len32(offset) - 1)
114 | }
115 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/bytebufferpool/.travis.yml:
--------------------------------------------------------------------------------
1 | language: go
2 |
3 | go:
4 | - 1.6
5 |
6 | script:
7 | # build test for supported platforms
8 | - GOOS=linux go build
9 | - GOOS=darwin go build
10 | - GOOS=freebsd go build
11 | - GOOS=windows go build
12 | - GOARCH=386 go build
13 |
14 | # run tests on a standard platform
15 | - go test -v ./...
16 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/bytebufferpool/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Aliaksandr Valialkin, VertaMedia
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/bytebufferpool/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/valyala/bytebufferpool)
2 | [](http://godoc.org/github.com/valyala/bytebufferpool)
3 | [](http://goreportcard.com/report/valyala/bytebufferpool)
4 |
5 | # bytebufferpool
6 |
7 | An implementation of a pool of byte buffers with anti-memory-waste protection.
8 |
9 | The pool may waste limited amount of memory due to fragmentation.
10 | This amount equals to the maximum total size of the byte buffers
11 | in concurrent use.
12 |
13 | # Benchmark results
14 | Currently bytebufferpool is fastest and most effective buffer pool written in Go.
15 |
16 | You can find results [here](https://omgnull.github.io/go-benchmark/buffer/).
17 |
18 | # bytebufferpool users
19 |
20 | * [fasthttp](https://github.com/valyala/fasthttp)
21 | * [quicktemplate](https://github.com/valyala/quicktemplate)
22 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/bytebufferpool/bytebuffer.go:
--------------------------------------------------------------------------------
1 | package bytebufferpool
2 |
3 | import "io"
4 |
5 | // ByteBuffer provides byte buffer, which can be used for minimizing
6 | // memory allocations.
7 | //
8 | // ByteBuffer may be used with functions appending data to the given []byte
9 | // slice. See example code for details.
10 | //
11 | // Use Get for obtaining an empty byte buffer.
12 | type ByteBuffer struct {
13 |
14 | // B is a byte buffer to use in append-like workloads.
15 | // See example code for details.
16 | B []byte
17 | }
18 |
19 | // Len returns the size of the byte buffer.
20 | func (b *ByteBuffer) Len() int {
21 | return len(b.B)
22 | }
23 |
24 | // ReadFrom implements io.ReaderFrom.
25 | //
26 | // The function appends all the data read from r to b.
27 | func (b *ByteBuffer) ReadFrom(r io.Reader) (int64, error) {
28 | p := b.B
29 | nStart := int64(len(p))
30 | nMax := int64(cap(p))
31 | n := nStart
32 | if nMax == 0 {
33 | nMax = 64
34 | p = make([]byte, nMax)
35 | } else {
36 | p = p[:nMax]
37 | }
38 | for {
39 | if n == nMax {
40 | nMax *= 2
41 | bNew := make([]byte, nMax)
42 | copy(bNew, p)
43 | p = bNew
44 | }
45 | nn, err := r.Read(p[n:])
46 | n += int64(nn)
47 | if err != nil {
48 | b.B = p[:n]
49 | n -= nStart
50 | if err == io.EOF {
51 | return n, nil
52 | }
53 | return n, err
54 | }
55 | }
56 | }
57 |
58 | // WriteTo implements io.WriterTo.
59 | func (b *ByteBuffer) WriteTo(w io.Writer) (int64, error) {
60 | n, err := w.Write(b.B)
61 | return int64(n), err
62 | }
63 |
64 | // Bytes returns b.B, i.e. all the bytes accumulated in the buffer.
65 | //
66 | // The purpose of this function is bytes.Buffer compatibility.
67 | func (b *ByteBuffer) Bytes() []byte {
68 | return b.B
69 | }
70 |
71 | // Write implements io.Writer - it appends p to ByteBuffer.B
72 | func (b *ByteBuffer) Write(p []byte) (int, error) {
73 | b.B = append(b.B, p...)
74 | return len(p), nil
75 | }
76 |
77 | // WriteByte appends the byte c to the buffer.
78 | //
79 | // The purpose of this function is bytes.Buffer compatibility.
80 | //
81 | // The function always returns nil.
82 | func (b *ByteBuffer) WriteByte(c byte) error {
83 | b.B = append(b.B, c)
84 | return nil
85 | }
86 |
87 | // WriteString appends s to ByteBuffer.B.
88 | func (b *ByteBuffer) WriteString(s string) (int, error) {
89 | b.B = append(b.B, s...)
90 | return len(s), nil
91 | }
92 |
93 | // Set sets ByteBuffer.B to p.
94 | func (b *ByteBuffer) Set(p []byte) {
95 | b.B = append(b.B[:0], p...)
96 | }
97 |
98 | // SetString sets ByteBuffer.B to s.
99 | func (b *ByteBuffer) SetString(s string) {
100 | b.B = append(b.B[:0], s...)
101 | }
102 |
103 | // String returns string representation of ByteBuffer.B.
104 | func (b *ByteBuffer) String() string {
105 | return string(b.B)
106 | }
107 |
108 | // Reset makes ByteBuffer.B empty.
109 | func (b *ByteBuffer) Reset() {
110 | b.B = b.B[:0]
111 | }
112 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/bytebufferpool/doc.go:
--------------------------------------------------------------------------------
1 | // Package bytebufferpool implements a pool of byte buffers
2 | // with anti-fragmentation protection.
3 | //
4 | // The pool may waste limited amount of memory due to fragmentation.
5 | // This amount equals to the maximum total size of the byte buffers
6 | // in concurrent use.
7 | package bytebufferpool
8 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/bytebufferpool/pool.go:
--------------------------------------------------------------------------------
1 | package bytebufferpool
2 |
3 | import (
4 | "sort"
5 | "sync"
6 | "sync/atomic"
7 | )
8 |
9 | const (
10 | minBitSize = 6 // 2**6=64 is a CPU cache line size
11 | steps = 20
12 |
13 | minSize = 1 << minBitSize
14 | maxSize = 1 << (minBitSize + steps - 1)
15 |
16 | calibrateCallsThreshold = 42000
17 | maxPercentile = 0.95
18 | )
19 |
20 | // Pool represents byte buffer pool.
21 | //
22 | // Distinct pools may be used for distinct types of byte buffers.
23 | // Properly determined byte buffer types with their own pools may help reducing
24 | // memory waste.
25 | type Pool struct {
26 | calls [steps]uint64
27 | calibrating uint64
28 |
29 | defaultSize uint64
30 | maxSize uint64
31 |
32 | pool sync.Pool
33 | }
34 |
35 | var defaultPool Pool
36 |
37 | // Get returns an empty byte buffer from the pool.
38 | //
39 | // Got byte buffer may be returned to the pool via Put call.
40 | // This reduces the number of memory allocations required for byte buffer
41 | // management.
42 | func Get() *ByteBuffer { return defaultPool.Get() }
43 |
44 | // Get returns new byte buffer with zero length.
45 | //
46 | // The byte buffer may be returned to the pool via Put after the use
47 | // in order to minimize GC overhead.
48 | func (p *Pool) Get() *ByteBuffer {
49 | v := p.pool.Get()
50 | if v != nil {
51 | return v.(*ByteBuffer)
52 | }
53 | return &ByteBuffer{
54 | B: make([]byte, 0, atomic.LoadUint64(&p.defaultSize)),
55 | }
56 | }
57 |
58 | // Put returns byte buffer to the pool.
59 | //
60 | // ByteBuffer.B mustn't be touched after returning it to the pool.
61 | // Otherwise data races will occur.
62 | func Put(b *ByteBuffer) { defaultPool.Put(b) }
63 |
64 | // Put releases byte buffer obtained via Get to the pool.
65 | //
66 | // The buffer mustn't be accessed after returning to the pool.
67 | func (p *Pool) Put(b *ByteBuffer) {
68 | idx := index(len(b.B))
69 |
70 | if atomic.AddUint64(&p.calls[idx], 1) > calibrateCallsThreshold {
71 | p.calibrate()
72 | }
73 |
74 | maxSize := int(atomic.LoadUint64(&p.maxSize))
75 | if maxSize == 0 || cap(b.B) <= maxSize {
76 | b.Reset()
77 | p.pool.Put(b)
78 | }
79 | }
80 |
81 | func (p *Pool) calibrate() {
82 | if !atomic.CompareAndSwapUint64(&p.calibrating, 0, 1) {
83 | return
84 | }
85 |
86 | a := make(callSizes, 0, steps)
87 | var callsSum uint64
88 | for i := uint64(0); i < steps; i++ {
89 | calls := atomic.SwapUint64(&p.calls[i], 0)
90 | callsSum += calls
91 | a = append(a, callSize{
92 | calls: calls,
93 | size: minSize << i,
94 | })
95 | }
96 | sort.Sort(a)
97 |
98 | defaultSize := a[0].size
99 | maxSize := defaultSize
100 |
101 | maxSum := uint64(float64(callsSum) * maxPercentile)
102 | callsSum = 0
103 | for i := 0; i < steps; i++ {
104 | if callsSum > maxSum {
105 | break
106 | }
107 | callsSum += a[i].calls
108 | size := a[i].size
109 | if size > maxSize {
110 | maxSize = size
111 | }
112 | }
113 |
114 | atomic.StoreUint64(&p.defaultSize, defaultSize)
115 | atomic.StoreUint64(&p.maxSize, maxSize)
116 |
117 | atomic.StoreUint64(&p.calibrating, 0)
118 | }
119 |
120 | type callSize struct {
121 | calls uint64
122 | size uint64
123 | }
124 |
125 | type callSizes []callSize
126 |
127 | func (ci callSizes) Len() int {
128 | return len(ci)
129 | }
130 |
131 | func (ci callSizes) Less(i, j int) bool {
132 | return ci[i].calls > ci[j].calls
133 | }
134 |
135 | func (ci callSizes) Swap(i, j int) {
136 | ci[i], ci[j] = ci[j], ci[i]
137 | }
138 |
139 | func index(n int) int {
140 | n--
141 | n >>= minBitSize
142 | idx := 0
143 | for n > 0 {
144 | n >>= 1
145 | idx++
146 | }
147 | if idx >= steps {
148 | idx = steps - 1
149 | }
150 | return idx
151 | }
152 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/.gitignore:
--------------------------------------------------------------------------------
1 | tags
2 | *.pprof
3 | *.fasthttp.gz
4 | *.fasthttp.br
5 | .idea
6 | .vscode
7 | .DS_Store
8 | vendor/
9 | testdata/fuzz
10 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/.golangci.yml:
--------------------------------------------------------------------------------
1 | # This file contains configuration options for golangci-lint.
2 | # https://github.com/golangci/golangci-lint/blob/master/.golangci.reference.yml
3 |
4 | run:
5 | # Timeout for analysis.
6 | timeout: 5m
7 |
8 | linters:
9 | enable-all: true
10 | disable:
11 | - cyclop
12 | - depguard
13 | - dupl
14 | - errname
15 | - errorlint
16 | - exhaustive
17 | - exhaustruct
18 | - forcetypeassert
19 | - funlen
20 | - gochecknoglobals
21 | - gocognit
22 | - goconst
23 | - gocyclo
24 | - goerr113
25 | - gomnd
26 | - gosec
27 | - inamedparam
28 | - ireturn
29 | - maintidx
30 | - nakedret
31 | - nestif
32 | - nlreturn
33 | - noctx
34 | - nonamedreturns
35 | - paralleltest
36 | - testableexamples
37 | - testpackage
38 | - thelper
39 | - tparallel
40 | - unparam
41 | - usestdlibvars
42 | - varnamelen
43 | - wrapcheck
44 | - wsl
45 |
46 | # Deprecated linters
47 | - deadcode
48 | - exhaustivestruct
49 | - golint
50 | - ifshort
51 | - interfacer
52 | - maligned
53 | - nosnakecase
54 | - scopelint
55 | - structcheck
56 | - varcheck
57 |
58 | linters-settings:
59 | revive:
60 | # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md
61 | rules:
62 | - name: use-any
63 | lll:
64 | line-length: 130
65 | stylecheck:
66 | checks: [
67 | "all",
68 | "-ST1000", # at least one file in a package should have a package comment
69 | ]
70 | gocritic:
71 | enabled-tags:
72 | - diagnostic
73 | - experimental
74 | - opinionated
75 | - performance
76 | - style
77 | disabled-checks:
78 | - deferInLoop
79 | - importShadow
80 | - sloppyReassign
81 | - unnamedResult
82 | - whyNoLint
83 | govet:
84 | enable-all: true
85 | disable:
86 | - fieldalignment
87 | - shadow
88 |
89 | issues:
90 | # Show all issues from a linter.
91 | max-issues-per-linter: 0
92 |
93 | # Show all issues with the same text.
94 | max-same-issues: 0
95 |
96 | include:
97 | - EXC0011 # include issues about comments from `stylecheck`
98 |
99 | exclude-rules:
100 | # Exclude some linters from running on tests files.
101 | - path: _test\.go
102 | linters:
103 | - lll
104 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015-present Aliaksandr Valialkin, VertaMedia, Kirill Danshin, Erik Dubbelboer, FastHTTP Authors
4 |
5 | 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:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | 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.
10 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/SECURITY.md:
--------------------------------------------------------------------------------
1 | ### TL;DR
2 |
3 | We use a simplified version of [Golang Security Policy](https://go.dev/security).
4 | For example, for now we skip CVE assignment.
5 |
6 | ### Reporting a Security Bug
7 |
8 | Please report to us any issues you find. This document explains how to do that and what to expect in return.
9 |
10 | All security bugs in our releases should be reported by email to erik@dubbelboer.com
11 | Your email will be acknowledged within 24 hours, and you'll receive a more detailed response
12 | to your email within 72 hours indicating the next steps in handling your report.
13 | Please use a descriptive subject line for your report email.
14 |
15 | ### Flagging Existing Issues as Security-related
16 |
17 | If you believe that an existing issue is security-related, we ask that you send an email to erik@dubbelboer.com
18 | The email should include the issue ID and a short description of why it should be handled according to this security policy.
19 |
20 | ### Disclosure Process
21 |
22 | Our project uses the following disclosure process:
23 |
24 | - Once the security report is received it is assigned a primary handler. This person coordinates the fix and release process.
25 | - The issue is confirmed and a list of affected software is determined.
26 | - Code is audited to find any potential similar problems.
27 | - Fixes are prepared for the two most recent major releases and the head/master revision. These fixes are not yet committed to the public repository.
28 | - To notify users, a new issue without security details is submitted to our GitHub repository.
29 | - Three working days following this notification, the fixes are applied to the public repository and a new release is issued.
30 | - On the date that the fixes are applied, announcement is published in the issue.
31 |
32 | This process can take some time, especially when coordination is required with maintainers of other projects.
33 | Every effort will be made to handle the bug in as timely a manner as possible, however it's important that we follow
34 | the process described above to ensure that disclosures are handled consistently.
35 |
36 | ### Receiving Security Updates
37 | The best way to receive security announcements is to subscribe ("Watch") to our repository.
38 | Any GitHub issues pertaining to a security issue will be prefixed with [security].
39 |
40 | ### Comments on This Policy
41 | If you have any suggestions to improve this policy, please send an email to erik@dubbelboer.com for discussion.
42 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/TODO:
--------------------------------------------------------------------------------
1 | - SessionClient with referer and cookies support.
2 | - ProxyHandler similar to FSHandler.
3 | - WebSockets. See https://tools.ietf.org/html/rfc6455 .
4 | - HTTP/2.0. See https://tools.ietf.org/html/rfc7540 .
5 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/b2s_new.go:
--------------------------------------------------------------------------------
1 | //go:build go1.20
2 |
3 | package fasthttp
4 |
5 | import "unsafe"
6 |
7 | // b2s converts byte slice to a string without memory allocation.
8 | // See https://groups.google.com/forum/#!msg/Golang-Nuts/ENgbUzYvCuU/90yGx7GUAgAJ .
9 | func b2s(b []byte) string {
10 | return unsafe.String(unsafe.SliceData(b), len(b))
11 | }
12 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/b2s_old.go:
--------------------------------------------------------------------------------
1 | //go:build !go1.20
2 |
3 | package fasthttp
4 |
5 | import "unsafe"
6 |
7 | // b2s converts byte slice to a string without memory allocation.
8 | // See https://groups.google.com/forum/#!msg/Golang-Nuts/ENgbUzYvCuU/90yGx7GUAgAJ .
9 | //
10 | // Note it may break if string and/or slice header will change
11 | // in the future go versions.
12 | func b2s(b []byte) string {
13 | return *(*string)(unsafe.Pointer(&b))
14 | }
15 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/bytesconv_32.go:
--------------------------------------------------------------------------------
1 | //go:build !amd64 && !arm64 && !ppc64 && !ppc64le && !riscv64 && !s390x
2 |
3 | package fasthttp
4 |
5 | const (
6 | maxHexIntChars = 7
7 | )
8 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/bytesconv_64.go:
--------------------------------------------------------------------------------
1 | //go:build amd64 || arm64 || ppc64 || ppc64le || riscv64 || s390x
2 |
3 | package fasthttp
4 |
5 | const (
6 | maxHexIntChars = 15
7 | )
8 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/coarsetime.go:
--------------------------------------------------------------------------------
1 | package fasthttp
2 |
3 | import (
4 | "time"
5 | )
6 |
7 | // CoarseTimeNow returns the current time truncated to the nearest second.
8 | //
9 | // Deprecated: This is slower than calling time.Now() directly.
10 | // This is now time.Now().Truncate(time.Second) shortcut.
11 | func CoarseTimeNow() time.Time {
12 | return time.Now().Truncate(time.Second)
13 | }
14 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/doc.go:
--------------------------------------------------------------------------------
1 | /*
2 | Package fasthttp provides fast HTTP server and client API.
3 |
4 | Fasthttp provides the following features:
5 |
6 | 1. Optimized for speed. Easily handles more than 100K qps and more than 1M
7 | concurrent keep-alive connections on modern hardware.
8 |
9 | 2. Optimized for low memory usage.
10 |
11 | 3. Easy 'Connection: Upgrade' support via RequestCtx.Hijack.
12 |
13 | 4. Server provides the following anti-DoS limits:
14 |
15 | - The number of concurrent connections.
16 |
17 | - The number of concurrent connections per client IP.
18 |
19 | - The number of requests per connection.
20 |
21 | - Request read timeout.
22 |
23 | - Response write timeout.
24 |
25 | - Maximum request header size.
26 |
27 | - Maximum request body size.
28 |
29 | - Maximum request execution time.
30 |
31 | - Maximum keep-alive connection lifetime.
32 |
33 | - Early filtering out non-GET requests.
34 |
35 | 5. A lot of additional useful info is exposed to request handler:
36 |
37 | - Server and client address.
38 |
39 | - Per-request logger.
40 |
41 | - Unique request id.
42 |
43 | - Request start time.
44 |
45 | - Connection start time.
46 |
47 | - Request sequence number for the current connection.
48 |
49 | 6. Client supports automatic retry on idempotent requests' failure.
50 |
51 | 7. Fasthttp API is designed with the ability to extend existing client
52 | and server implementations or to write custom client and server
53 | implementations from scratch.
54 | */
55 | package fasthttp
56 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/examples/README.md:
--------------------------------------------------------------------------------
1 | # Code examples
2 |
3 | * [HelloWorld server](helloworldserver)
4 | * [Static file server](fileserver)
5 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/examples/client/Makefile:
--------------------------------------------------------------------------------
1 | client: clean
2 | go get -u github.com/valyala/fasthttp
3 | go build
4 |
5 | clean:
6 | rm -f client
7 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/examples/client/README.md:
--------------------------------------------------------------------------------
1 | # Client Example
2 |
3 | The Client is useful when working with multiple hostnames.
4 |
5 | See the simplest `sendGetRequest()` for GET and more advanced `sendPostRequest()` for a POST request.
6 |
7 | The `sendPostRequest()` also shows:
8 | * Per-request timeout with `DoTimeout()`
9 | * Send a body as bytes slice with `SetBodyRaw()`. This is useful if you generated a request body. Otherwise, prefer `SetBody()` which copies it.
10 | * Parse JSON from response
11 | * Gracefully show error messages i.e. timeouts as warnings and other errors as a failures with detailed error messages.
12 |
13 | ## How to build and run
14 | Start a web server on localhost:8080 then execute:
15 |
16 | make
17 | ./client
18 |
19 | ## Client vs HostClient
20 | Internally the Client creates a dedicated HostClient for each domain/IP address and cleans unused after period of time.
21 | So if you have a single heavily loaded API endpoint it's better to use HostClient. See an example in the [examples/host_client](../host_client/)
22 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/examples/client/client.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "encoding/json"
5 | "errors"
6 | "fmt"
7 | "io"
8 | "net/http"
9 | "os"
10 | "reflect"
11 | "time"
12 |
13 | "github.com/valyala/fasthttp"
14 | )
15 |
16 | var headerContentTypeJson = []byte("application/json")
17 |
18 | var client *fasthttp.Client
19 |
20 | type Entity struct {
21 | Id int
22 | Name string
23 | }
24 |
25 | func main() {
26 | // You may read the timeouts from some config
27 | readTimeout, _ := time.ParseDuration("500ms")
28 | writeTimeout, _ := time.ParseDuration("500ms")
29 | maxIdleConnDuration, _ := time.ParseDuration("1h")
30 | client = &fasthttp.Client{
31 | ReadTimeout: readTimeout,
32 | WriteTimeout: writeTimeout,
33 | MaxIdleConnDuration: maxIdleConnDuration,
34 | NoDefaultUserAgentHeader: true, // Don't send: User-Agent: fasthttp
35 | DisableHeaderNamesNormalizing: true, // If you set the case on your headers correctly you can enable this
36 | DisablePathNormalizing: true,
37 | // increase DNS cache time to an hour instead of default minute
38 | Dial: (&fasthttp.TCPDialer{
39 | Concurrency: 4096,
40 | DNSCacheDuration: time.Hour,
41 | }).Dial,
42 | }
43 | sendGetRequest()
44 | sendPostRequest()
45 | }
46 |
47 | func sendGetRequest() {
48 | req := fasthttp.AcquireRequest()
49 | req.SetRequestURI("http://localhost:8080/")
50 | req.Header.SetMethod(fasthttp.MethodGet)
51 | resp := fasthttp.AcquireResponse()
52 | err := client.Do(req, resp)
53 | fasthttp.ReleaseRequest(req)
54 | if err == nil {
55 | fmt.Printf("DEBUG Response: %s\n", resp.Body())
56 | } else {
57 | fmt.Fprintf(os.Stderr, "ERR Connection error: %v\n", err)
58 | }
59 | fasthttp.ReleaseResponse(resp)
60 | }
61 |
62 | func sendPostRequest() {
63 | // per-request timeout
64 | reqTimeout := time.Duration(100) * time.Millisecond
65 |
66 | reqEntity := &Entity{
67 | Name: "New entity",
68 | }
69 | reqEntityBytes, _ := json.Marshal(reqEntity)
70 |
71 | req := fasthttp.AcquireRequest()
72 | req.SetRequestURI("http://localhost:8080/")
73 | req.Header.SetMethod(fasthttp.MethodPost)
74 | req.Header.SetContentTypeBytes(headerContentTypeJson)
75 | req.SetBodyRaw(reqEntityBytes)
76 |
77 | resp := fasthttp.AcquireResponse()
78 | err := client.DoTimeout(req, resp, reqTimeout)
79 | fasthttp.ReleaseRequest(req)
80 | defer fasthttp.ReleaseResponse(resp)
81 |
82 | if err != nil {
83 | errName, known := httpConnError(err)
84 | if known {
85 | fmt.Fprintf(os.Stderr, "WARN conn error: %v\n", errName)
86 | } else {
87 | fmt.Fprintf(os.Stderr, "ERR conn failure: %v %v\n", errName, err)
88 | }
89 |
90 | return
91 | }
92 |
93 | statusCode := resp.StatusCode()
94 | respBody := resp.Body()
95 | fmt.Printf("DEBUG Response: %s\n", respBody)
96 |
97 | if statusCode != http.StatusOK {
98 | fmt.Fprintf(os.Stderr, "ERR invalid HTTP response code: %d\n", statusCode)
99 |
100 | return
101 | }
102 |
103 | respEntity := &Entity{}
104 | err = json.Unmarshal(respBody, respEntity)
105 | if err == nil || errors.Is(err, io.EOF) {
106 | fmt.Printf("DEBUG Parsed Response: %v\n", respEntity)
107 | } else {
108 | fmt.Fprintf(os.Stderr, "ERR failed to parse response: %v\n", err)
109 | }
110 | }
111 |
112 | func httpConnError(err error) (string, bool) {
113 | var (
114 | errName string
115 | known = true
116 | )
117 |
118 | switch {
119 | case errors.Is(err, fasthttp.ErrTimeout):
120 | errName = "timeout"
121 | case errors.Is(err, fasthttp.ErrNoFreeConns):
122 | errName = "conn_limit"
123 | case errors.Is(err, fasthttp.ErrConnectionClosed):
124 | errName = "conn_close"
125 | case reflect.TypeOf(err).String() == "*net.OpError":
126 | errName = "timeout"
127 | default:
128 | known = false
129 | }
130 |
131 | return errName, known
132 | }
133 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/examples/fileserver/Makefile:
--------------------------------------------------------------------------------
1 | fileserver: clean
2 | go get -u github.com/valyala/fasthttp
3 | go get -u github.com/valyala/fasthttp/expvarhandler
4 | go build
5 |
6 | clean:
7 | rm -f fileserver
8 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/examples/fileserver/README.md:
--------------------------------------------------------------------------------
1 | # Static file server example
2 |
3 | * Serves files from the given directory.
4 | * Supports transparent response compression.
5 | * Supports byte range responses.
6 | * Generates directory index pages.
7 | * Supports TLS (aka SSL or HTTPS).
8 | * Supports virtual hosts.
9 | * Exports various stats on /stats path.
10 |
11 | # How to build
12 |
13 | ```
14 | make
15 | ```
16 |
17 | # How to run
18 |
19 | ```
20 | ./fileserver -h
21 | ./fileserver -addr=tcp.addr.to.listen:to -dir=/path/to/directory/to/serve
22 | ```
23 |
24 | # fileserver vs nginx performance comparison
25 |
26 | Serving default nginx path (`/usr/share/nginx/html` on ubuntu).
27 |
28 | * nginx
29 |
30 | ```
31 | $ ./wrk -t 4 -c 16 -d 10 http://localhost:80
32 | Running 10s test @ http://localhost:80
33 | 4 threads and 16 connections
34 | Thread Stats Avg Stdev Max +/- Stdev
35 | Latency 397.76us 1.08ms 20.23ms 95.19%
36 | Req/Sec 21.20k 2.49k 31.34k 79.65%
37 | 850220 requests in 10.10s, 695.65MB read
38 | Requests/sec: 84182.71
39 | Transfer/sec: 68.88MB
40 | ```
41 |
42 | * fileserver
43 |
44 | ```
45 | $ ./wrk -t 4 -c 16 -d 10 http://localhost:8080
46 | Running 10s test @ http://localhost:8080
47 | 4 threads and 16 connections
48 | Thread Stats Avg Stdev Max +/- Stdev
49 | Latency 447.99us 1.59ms 27.20ms 94.79%
50 | Req/Sec 37.13k 3.99k 47.86k 76.00%
51 | 1478457 requests in 10.02s, 1.03GB read
52 | Requests/sec: 147597.06
53 | Transfer/sec: 105.15MB
54 | ```
55 |
56 | 8 pipelined requests
57 |
58 | * nginx
59 |
60 | ```
61 | $ ./wrk -s pipeline.lua -t 4 -c 16 -d 10 http://localhost:80 -- 8
62 | Running 10s test @ http://localhost:80
63 | 4 threads and 16 connections
64 | Thread Stats Avg Stdev Max +/- Stdev
65 | Latency 1.34ms 2.15ms 30.91ms 92.16%
66 | Req/Sec 33.54k 7.36k 108.12k 76.81%
67 | 1339908 requests in 10.10s, 1.07GB read
68 | Requests/sec: 132705.81
69 | Transfer/sec: 108.58MB
70 | ```
71 |
72 | * fileserver
73 |
74 | ```
75 | $ ./wrk -s pipeline.lua -t 4 -c 16 -d 10 http://localhost:8080 -- 8
76 | Running 10s test @ http://localhost:8080
77 | 4 threads and 16 connections
78 | Thread Stats Avg Stdev Max +/- Stdev
79 | Latency 2.08ms 6.33ms 88.26ms 92.83%
80 | Req/Sec 116.54k 14.66k 167.98k 69.00%
81 | 4642226 requests in 10.03s, 3.23GB read
82 | Requests/sec: 462769.41
83 | Transfer/sec: 329.67MB
84 | ```
85 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/examples/fileserver/ssl-cert-snakeoil.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQD4IQusAs8PJdnG
3 | 3mURt/AXtgC+ceqLOatJ49JJE1VPTkMAy+oE1f1XvkMrYsHqmDf6GWVzgVXryL4U
4 | wq2/nJSm56ddhN55nI8oSN3dtywUB8/ShelEN73nlN77PeD9tl6NksPwWaKrqxq0
5 | FlabRPZSQCfmgZbhDV8Sa8mfCkFU0G0lit6kLGceCKMvmW+9Bz7ebsYmVdmVMxmf
6 | IJStFD44lWFTdUc65WISKEdW2ELcUefb0zOLw+0PCbXFGJH5x5ktksW8+BBk2Hkg
7 | GeQRL/qPCccthbScO0VgNj3zJ3ZZL0ObSDAbvNDG85joeNjDNq5DT/BAZ0bOSbEF
8 | sh+f9BAzAgMBAAECggEBAJWv2cq7Jw6MVwSRxYca38xuD6TUNBopgBvjREixURW2
9 | sNUaLuMb9Omp7fuOaE2N5rcJ+xnjPGIxh/oeN5MQctz9gwn3zf6vY+15h97pUb4D
10 | uGvYPRDaT8YVGS+X9NMZ4ZCmqW2lpWzKnCFoGHcy8yZLbcaxBsRdvKzwOYGoPiFb
11 | K2QuhXZ/1UPmqK9i2DFKtj40X6vBszTNboFxOVpXrPu0FJwLVSDf2hSZ4fMM0DH3
12 | YqwKcYf5te+hxGKgrqRA3tn0NCWii0in6QIwXMC+kMw1ebg/tZKqyDLMNptAK8J+
13 | DVw9m5X1seUHS5ehU/g2jrQrtK5WYn7MrFK4lBzlRwECgYEA/d1TeANYECDWRRDk
14 | B0aaRZs87Rwl/J9PsvbsKvtU/bX+OfSOUjOa9iQBqn0LmU8GqusEET/QVUfocVwV
15 | Bggf/5qDLxz100Rj0ags/yE/kNr0Bb31kkkKHFMnCT06YasR7qKllwrAlPJvQv9x
16 | IzBKq+T/Dx08Wep9bCRSFhzRCnsCgYEA+jdeZXTDr/Vz+D2B3nAw1frqYFfGnEVY
17 | wqmoK3VXMDkGuxsloO2rN+SyiUo3JNiQNPDub/t7175GH5pmKtZOlftePANsUjBj
18 | wZ1D0rI5Bxu/71ibIUYIRVmXsTEQkh/ozoh3jXCZ9+bLgYiYx7789IUZZSokFQ3D
19 | FICUT9KJ36kCgYAGoq9Y1rWJjmIrYfqj2guUQC+CfxbbGIrrwZqAsRsSmpwvhZ3m
20 | tiSZxG0quKQB+NfSxdvQW5ulbwC7Xc3K35F+i9pb8+TVBdeaFkw+yu6vaZmxQLrX
21 | fQM/pEjD7A7HmMIaO7QaU5SfEAsqdCTP56Y8AftMuNXn/8IRfo2KuGwaWwKBgFpU
22 | ILzJoVdlad9E/Rw7LjYhZfkv1uBVXIyxyKcfrkEXZSmozDXDdxsvcZCEfVHM6Ipk
23 | K/+7LuMcqp4AFEAEq8wTOdq6daFaHLkpt/FZK6M4TlruhtpFOPkoNc3e45eM83OT
24 | 6mziKINJC1CQ6m65sQHpBtjxlKMRG8rL/D6wx9s5AoGBAMRlqNPMwglT3hvDmsAt
25 | 9Lf9pdmhERUlHhD8bj8mDaBj2Aqv7f6VRJaYZqP403pKKQexuqcn80mtjkSAPFkN
26 | Cj7BVt/RXm5uoxDTnfi26RF9F6yNDEJ7UU9+peBr99aazF/fTgW/1GcMkQnum8uV
27 | c257YgaWmjK9uB0Y2r2VxS0G
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/examples/fileserver/ssl-cert-snakeoil.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIICujCCAaKgAwIBAgIJAMbXnKZ/cikUMA0GCSqGSIb3DQEBCwUAMBUxEzARBgNV
3 | BAMTCnVidW50dS5uYW4wHhcNMTUwMjA0MDgwMTM5WhcNMjUwMjAxMDgwMTM5WjAV
4 | MRMwEQYDVQQDEwp1YnVudHUubmFuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
5 | CgKCAQEA+CELrALPDyXZxt5lEbfwF7YAvnHqizmrSePSSRNVT05DAMvqBNX9V75D
6 | K2LB6pg3+hllc4FV68i+FMKtv5yUpuenXYTeeZyPKEjd3bcsFAfP0oXpRDe955Te
7 | +z3g/bZejZLD8Fmiq6satBZWm0T2UkAn5oGW4Q1fEmvJnwpBVNBtJYrepCxnHgij
8 | L5lvvQc+3m7GJlXZlTMZnyCUrRQ+OJVhU3VHOuViEihHVthC3FHn29Mzi8PtDwm1
9 | xRiR+ceZLZLFvPgQZNh5IBnkES/6jwnHLYW0nDtFYDY98yd2WS9Dm0gwG7zQxvOY
10 | 6HjYwzauQ0/wQGdGzkmxBbIfn/QQMwIDAQABow0wCzAJBgNVHRMEAjAAMA0GCSqG
11 | SIb3DQEBCwUAA4IBAQBQjKm/4KN/iTgXbLTL3i7zaxYXFLXsnT1tF+ay4VA8aj98
12 | L3JwRTciZ3A5iy/W4VSCt3eASwOaPWHKqDBB5RTtL73LoAqsWmO3APOGQAbixcQ2
13 | 45GXi05OKeyiYRi1Nvq7Unv9jUkRDHUYVPZVSAjCpsXzPhFkmZoTRxmx5l0ZF7Li
14 | K91lI5h+eFq0dwZwrmlPambyh1vQUi70VHv8DNToVU29kel7YLbxGbuqETfhrcy6
15 | X+Mha6RYITkAn5FqsZcKMsc9eYGEF4l3XV+oS7q6xfTxktYJMFTI18J0lQ2Lv/CI
16 | whdMnYGntDQBE/iFCrJEGNsKGc38796GBOb5j+zd
17 | -----END CERTIFICATE-----
18 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/examples/helloworldserver/Makefile:
--------------------------------------------------------------------------------
1 | helloworldserver: clean
2 | go get -u github.com/valyala/fasthttp
3 | go build
4 |
5 | clean:
6 | rm -f helloworldserver
7 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/examples/helloworldserver/README.md:
--------------------------------------------------------------------------------
1 | # HelloWorld server example
2 |
3 | * Displays various request info.
4 | * Sets response headers and cookies.
5 | * Supports transparent compression.
6 |
7 | # How to build
8 |
9 | ```
10 | make
11 | ```
12 |
13 | # How to run
14 |
15 | ```
16 | ./helloworldserver -addr=tcp.addr.to.listen:to
17 | ```
18 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/examples/helloworldserver/helloworldserver.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 | "log"
7 |
8 | "github.com/valyala/fasthttp"
9 | )
10 |
11 | var (
12 | addr = flag.String("addr", ":8080", "TCP address to listen to")
13 | compress = flag.Bool("compress", false, "Whether to enable transparent response compression")
14 | )
15 |
16 | func main() {
17 | flag.Parse()
18 |
19 | h := requestHandler
20 | if *compress {
21 | h = fasthttp.CompressHandler(h)
22 | }
23 |
24 | if err := fasthttp.ListenAndServe(*addr, h); err != nil {
25 | log.Fatalf("Error in ListenAndServe: %v", err)
26 | }
27 | }
28 |
29 | func requestHandler(ctx *fasthttp.RequestCtx) {
30 | fmt.Fprintf(ctx, "Hello, world!\n\n")
31 |
32 | fmt.Fprintf(ctx, "Request method is %q\n", ctx.Method())
33 | fmt.Fprintf(ctx, "RequestURI is %q\n", ctx.RequestURI())
34 | fmt.Fprintf(ctx, "Requested path is %q\n", ctx.Path())
35 | fmt.Fprintf(ctx, "Host is %q\n", ctx.Host())
36 | fmt.Fprintf(ctx, "Query string is %q\n", ctx.QueryArgs())
37 | fmt.Fprintf(ctx, "User-Agent is %q\n", ctx.UserAgent())
38 | fmt.Fprintf(ctx, "Connection has been established at %s\n", ctx.ConnTime())
39 | fmt.Fprintf(ctx, "Request has been started at %s\n", ctx.Time())
40 | fmt.Fprintf(ctx, "Serial request number for the current connection is %d\n", ctx.ConnRequestNum())
41 | fmt.Fprintf(ctx, "Your ip is %q\n\n", ctx.RemoteIP())
42 |
43 | fmt.Fprintf(ctx, "Raw request is:\n---CUT---\n%s\n---CUT---", &ctx.Request)
44 |
45 | ctx.SetContentType("text/plain; charset=utf8")
46 |
47 | // Set arbitrary headers
48 | ctx.Response.Header.Set("X-My-Header", "my-header-value")
49 |
50 | // Set cookies
51 | var c fasthttp.Cookie
52 | c.SetKey("cookie-name")
53 | c.SetValue("cookie-value")
54 | ctx.Response.Header.SetCookie(&c)
55 | }
56 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/examples/host_client/Makefile:
--------------------------------------------------------------------------------
1 | host_client: clean
2 | go get -u github.com/valyala/fasthttp
3 | go build
4 |
5 | clean:
6 | rm -f host_client
7 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/examples/host_client/README.md:
--------------------------------------------------------------------------------
1 | # Host Client Example
2 |
3 | The HostClient is useful when calling an API from a single host.
4 | The example also shows how to use URI.
5 | You may create the parsed URI once and reuse it in many requests.
6 | The URI has a username and password for Basic Auth but you may also set other parts i.e. `SetPath()`, `SetQueryString()`.
7 |
8 | # How to build and run
9 | Start a web server on localhost:8080 then execute:
10 |
11 | make
12 | ./host_client
13 |
14 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/examples/host_client/hostclient.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "os"
6 |
7 | "github.com/valyala/fasthttp"
8 | )
9 |
10 | func main() {
11 | // Get URI from a pool
12 | url := fasthttp.AcquireURI()
13 | url.Parse(nil, []byte("http://localhost:8080/"))
14 | url.SetUsername("Aladdin")
15 | url.SetPassword("Open Sesame")
16 |
17 | hc := &fasthttp.HostClient{
18 | Addr: "localhost:8080", // The host address and port must be set explicitly
19 | }
20 |
21 | req := fasthttp.AcquireRequest()
22 | req.SetURI(url) // copy url into request
23 | fasthttp.ReleaseURI(url) // now you may release the URI
24 |
25 | req.Header.SetMethod(fasthttp.MethodGet)
26 | resp := fasthttp.AcquireResponse()
27 | err := hc.Do(req, resp)
28 | fasthttp.ReleaseRequest(req)
29 | if err == nil {
30 | fmt.Printf("Response: %s\n", resp.Body())
31 | } else {
32 | fmt.Fprintf(os.Stderr, "Connection error: %v\n", err)
33 | }
34 | fasthttp.ReleaseResponse(resp)
35 | }
36 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/examples/letsencrypt/letsencryptserver.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "crypto/tls"
5 | "net"
6 |
7 | "github.com/valyala/fasthttp"
8 | "golang.org/x/crypto/acme"
9 | "golang.org/x/crypto/acme/autocert"
10 | )
11 |
12 | func requestHandler(ctx *fasthttp.RequestCtx) {
13 | ctx.SetBodyString("hello from https!")
14 | }
15 |
16 | func main() {
17 | m := &autocert.Manager{
18 | Prompt: autocert.AcceptTOS,
19 | HostPolicy: autocert.HostWhitelist("example.com"), // Replace with your domain.
20 | Cache: autocert.DirCache("./certs"),
21 | }
22 |
23 | cfg := &tls.Config{
24 | GetCertificate: m.GetCertificate,
25 | NextProtos: []string{
26 | "http/1.1", acme.ALPNProto,
27 | },
28 | }
29 |
30 | // Let's Encrypt tls-alpn-01 only works on port 443.
31 | ln, err := net.Listen("tcp4", "0.0.0.0:443") /* #nosec G102 */
32 | if err != nil {
33 | panic(err)
34 | }
35 |
36 | lnTls := tls.NewListener(ln, cfg)
37 |
38 | if err := fasthttp.Serve(lnTls, requestHandler); err != nil {
39 | panic(err)
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/examples/multidomain/Makefile:
--------------------------------------------------------------------------------
1 | writer: clean
2 | go get -u github.com/valyala/fasthttp
3 | go build
4 |
5 | clean:
6 | rm -f multidomain
7 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/examples/multidomain/README.md:
--------------------------------------------------------------------------------
1 | # Multidomain using SSL certs example
2 |
3 | * Prints two messages depending on visited host.
4 |
5 | # How to build
6 |
7 | ```
8 | make
9 | ```
10 |
11 | # How to run
12 |
13 | ```
14 | ./multidomain
15 | ```
16 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/examples/multidomain/multidomain.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/valyala/fasthttp"
7 | )
8 |
9 | var domains = make(map[string]fasthttp.RequestHandler)
10 |
11 | func main() {
12 | server := &fasthttp.Server{
13 | // You can check the access using openssl command:
14 | // $ openssl s_client -connect localhost:8080 << EOF
15 | // > GET /
16 | // > Host: localhost
17 | // > EOF
18 | //
19 | // $ openssl s_client -connect localhost:8080 << EOF
20 | // > GET /
21 | // > Host: 127.0.0.1:8080
22 | // > EOF
23 | //
24 | Handler: func(ctx *fasthttp.RequestCtx) {
25 | h, ok := domains[string(ctx.Host())]
26 | if !ok {
27 | ctx.NotFound()
28 | return
29 | }
30 | h(ctx)
31 | },
32 | }
33 |
34 | // preparing first host
35 | cert, priv, err := fasthttp.GenerateTestCertificate("localhost:8080")
36 | if err != nil {
37 | panic(err)
38 | }
39 | domains["localhost:8080"] = func(ctx *fasthttp.RequestCtx) {
40 | ctx.WriteString("You are accessing to localhost:8080\n")
41 | }
42 |
43 | err = server.AppendCertEmbed(cert, priv)
44 | if err != nil {
45 | panic(err)
46 | }
47 |
48 | // preparing second host
49 | cert, priv, err = fasthttp.GenerateTestCertificate("127.0.0.1")
50 | if err != nil {
51 | panic(err)
52 | }
53 | domains["127.0.0.1:8080"] = func(ctx *fasthttp.RequestCtx) {
54 | ctx.WriteString("You are accessing to 127.0.0.1:8080\n")
55 | }
56 |
57 | err = server.AppendCertEmbed(cert, priv)
58 | if err != nil {
59 | panic(err)
60 | }
61 |
62 | fmt.Println(server.ListenAndServeTLS(":8080", "", ""))
63 | }
64 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/fasthttputil/doc.go:
--------------------------------------------------------------------------------
1 | // Package fasthttputil provides utility functions for fasthttp.
2 | package fasthttputil
3 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/fasthttputil/inmemory_listener.go:
--------------------------------------------------------------------------------
1 | package fasthttputil
2 |
3 | import (
4 | "errors"
5 | "net"
6 | "sync"
7 | )
8 |
9 | // ErrInmemoryListenerClosed indicates that the InmemoryListener is already closed.
10 | var ErrInmemoryListenerClosed = errors.New("InmemoryListener is already closed: use of closed network connection")
11 |
12 | // InmemoryListener provides in-memory dialer<->net.Listener implementation.
13 | //
14 | // It may be used either for fast in-process client<->server communications
15 | // without network stack overhead or for client<->server tests.
16 | type InmemoryListener struct {
17 | lock sync.Mutex
18 | closed bool
19 | conns chan acceptConn
20 | listenerAddr net.Addr
21 | addrLock sync.RWMutex
22 | }
23 |
24 | type acceptConn struct {
25 | conn net.Conn
26 | accepted chan struct{}
27 | }
28 |
29 | // NewInmemoryListener returns new in-memory dialer<->net.Listener.
30 | func NewInmemoryListener() *InmemoryListener {
31 | return &InmemoryListener{
32 | conns: make(chan acceptConn, 1024),
33 | }
34 | }
35 |
36 | // SetLocalAddr sets the (simulated) local address for the listener.
37 | func (ln *InmemoryListener) SetLocalAddr(localAddr net.Addr) {
38 | ln.addrLock.Lock()
39 | defer ln.addrLock.Unlock()
40 |
41 | ln.listenerAddr = localAddr
42 | }
43 |
44 | // Accept implements net.Listener's Accept.
45 | //
46 | // It is safe calling Accept from concurrently running goroutines.
47 | //
48 | // Accept returns new connection per each Dial call.
49 | func (ln *InmemoryListener) Accept() (net.Conn, error) {
50 | c, ok := <-ln.conns
51 | if !ok {
52 | return nil, ErrInmemoryListenerClosed
53 | }
54 | close(c.accepted)
55 | return c.conn, nil
56 | }
57 |
58 | // Close implements net.Listener's Close.
59 | func (ln *InmemoryListener) Close() error {
60 | var err error
61 |
62 | ln.lock.Lock()
63 | if !ln.closed {
64 | close(ln.conns)
65 | ln.closed = true
66 | } else {
67 | err = ErrInmemoryListenerClosed
68 | }
69 | ln.lock.Unlock()
70 | return err
71 | }
72 |
73 | type inmemoryAddr int
74 |
75 | func (inmemoryAddr) Network() string {
76 | return "inmemory"
77 | }
78 |
79 | func (inmemoryAddr) String() string {
80 | return "InmemoryListener"
81 | }
82 |
83 | // Addr implements net.Listener's Addr.
84 | func (ln *InmemoryListener) Addr() net.Addr {
85 | ln.addrLock.RLock()
86 | defer ln.addrLock.RUnlock()
87 |
88 | if ln.listenerAddr != nil {
89 | return ln.listenerAddr
90 | }
91 |
92 | return inmemoryAddr(0)
93 | }
94 |
95 | // Dial creates new client<->server connection.
96 | // Just like a real Dial it only returns once the server
97 | // has accepted the connection.
98 | //
99 | // It is safe calling Dial from concurrently running goroutines.
100 | func (ln *InmemoryListener) Dial() (net.Conn, error) {
101 | return ln.DialWithLocalAddr(nil)
102 | }
103 |
104 | // DialWithLocalAddr creates new client<->server connection.
105 | // Just like a real Dial it only returns once the server
106 | // has accepted the connection. The local address of the
107 | // client connection can be set with local.
108 | //
109 | // It is safe calling Dial from concurrently running goroutines.
110 | func (ln *InmemoryListener) DialWithLocalAddr(local net.Addr) (net.Conn, error) {
111 | pc := NewPipeConns()
112 |
113 | pc.SetAddresses(local, ln.Addr(), ln.Addr(), local)
114 |
115 | cConn := pc.Conn1()
116 | sConn := pc.Conn2()
117 | ln.lock.Lock()
118 | accepted := make(chan struct{})
119 | if !ln.closed {
120 | ln.conns <- acceptConn{sConn, accepted}
121 | // Wait until the connection has been accepted.
122 | <-accepted
123 | } else {
124 | _ = sConn.Close()
125 | _ = cConn.Close()
126 | cConn = nil
127 | }
128 | ln.lock.Unlock()
129 |
130 | if cConn == nil {
131 | return nil, ErrInmemoryListenerClosed
132 | }
133 | return cConn, nil
134 | }
135 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/methods.go:
--------------------------------------------------------------------------------
1 | package fasthttp
2 |
3 | // HTTP methods were copied from net/http.
4 | const (
5 | MethodGet = "GET" // RFC 7231, 4.3.1
6 | MethodHead = "HEAD" // RFC 7231, 4.3.2
7 | MethodPost = "POST" // RFC 7231, 4.3.3
8 | MethodPut = "PUT" // RFC 7231, 4.3.4
9 | MethodPatch = "PATCH" // RFC 5789
10 | MethodDelete = "DELETE" // RFC 7231, 4.3.5
11 | MethodConnect = "CONNECT" // RFC 7231, 4.3.6
12 | MethodOptions = "OPTIONS" // RFC 7231, 4.3.7
13 | MethodTrace = "TRACE" // RFC 7231, 4.3.8
14 | )
15 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/nocopy.go:
--------------------------------------------------------------------------------
1 | package fasthttp
2 |
3 | // Embed this type into a struct, which mustn't be copied,
4 | // so `go vet` gives a warning if this struct is copied.
5 | //
6 | // See https://github.com/golang/go/issues/8005#issuecomment-190753527 for details.
7 | // and also: https://stackoverflow.com/questions/52494458/nocopy-minimal-example
8 | type noCopy struct{}
9 |
10 | func (*noCopy) Lock() {}
11 | func (*noCopy) Unlock() {}
12 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/peripconn.go:
--------------------------------------------------------------------------------
1 | package fasthttp
2 |
3 | import (
4 | "crypto/tls"
5 | "net"
6 | "sync"
7 | )
8 |
9 | type perIPConnCounter struct {
10 | perIPConnPool sync.Pool
11 | perIPTLSConnPool sync.Pool
12 | lock sync.Mutex
13 | m map[uint32]int
14 | }
15 |
16 | func (cc *perIPConnCounter) Register(ip uint32) int {
17 | cc.lock.Lock()
18 | if cc.m == nil {
19 | cc.m = make(map[uint32]int)
20 | }
21 | n := cc.m[ip] + 1
22 | cc.m[ip] = n
23 | cc.lock.Unlock()
24 | return n
25 | }
26 |
27 | func (cc *perIPConnCounter) Unregister(ip uint32) {
28 | cc.lock.Lock()
29 | defer cc.lock.Unlock()
30 | if cc.m == nil {
31 | // developer safeguard
32 | panic("BUG: perIPConnCounter.Register() wasn't called")
33 | }
34 | n := cc.m[ip] - 1
35 | if n < 0 {
36 | n = 0
37 | }
38 | cc.m[ip] = n
39 | }
40 |
41 | type perIPConn struct {
42 | net.Conn
43 |
44 | ip uint32
45 | perIPConnCounter *perIPConnCounter
46 | }
47 |
48 | type perIPTLSConn struct {
49 | *tls.Conn
50 |
51 | ip uint32
52 | perIPConnCounter *perIPConnCounter
53 | }
54 |
55 | func acquirePerIPConn(conn net.Conn, ip uint32, counter *perIPConnCounter) net.Conn {
56 | if tlcConn, ok := conn.(*tls.Conn); ok {
57 | v := counter.perIPTLSConnPool.Get()
58 | if v == nil {
59 | return &perIPTLSConn{
60 | perIPConnCounter: counter,
61 | Conn: tlcConn,
62 | ip: ip,
63 | }
64 | }
65 | c := v.(*perIPConn)
66 | c.Conn = conn
67 | c.ip = ip
68 | return c
69 | }
70 |
71 | v := counter.perIPConnPool.Get()
72 | if v == nil {
73 | return &perIPConn{
74 | perIPConnCounter: counter,
75 | Conn: conn,
76 | ip: ip,
77 | }
78 | }
79 | c := v.(*perIPConn)
80 | c.Conn = conn
81 | c.ip = ip
82 | return c
83 | }
84 |
85 | func (c *perIPConn) Close() error {
86 | err := c.Conn.Close()
87 | c.perIPConnCounter.Unregister(c.ip)
88 | c.Conn = nil
89 | c.perIPConnCounter.perIPConnPool.Put(c)
90 | return err
91 | }
92 |
93 | func (c *perIPTLSConn) Close() error {
94 | err := c.Conn.Close()
95 | c.perIPConnCounter.Unregister(c.ip)
96 | c.Conn = nil
97 | c.perIPConnCounter.perIPTLSConnPool.Put(c)
98 | return err
99 | }
100 |
101 | func getUint32IP(c net.Conn) uint32 {
102 | return ip2uint32(getConnIP4(c))
103 | }
104 |
105 | func getConnIP4(c net.Conn) net.IP {
106 | addr := c.RemoteAddr()
107 | ipAddr, ok := addr.(*net.TCPAddr)
108 | if !ok {
109 | return net.IPv4zero
110 | }
111 | return ipAddr.IP.To4()
112 | }
113 |
114 | func ip2uint32(ip net.IP) uint32 {
115 | if len(ip) != 4 {
116 | return 0
117 | }
118 | return uint32(ip[0])<<24 | uint32(ip[1])<<16 | uint32(ip[2])<<8 | uint32(ip[3])
119 | }
120 |
121 | func uint322ip(ip uint32) net.IP {
122 | b := make([]byte, 4)
123 | b[0] = byte(ip >> 24)
124 | b[1] = byte(ip >> 16)
125 | b[2] = byte(ip >> 8)
126 | b[3] = byte(ip)
127 | return b
128 | }
129 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/request_body.zst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/valyala/quicktemplate/4d619e27ca723c29dcecf9844b193ee20df2322a/vendor/github.com/valyala/fasthttp/request_body.zst
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/round2_32.go:
--------------------------------------------------------------------------------
1 | //go:build !amd64 && !arm64 && !ppc64 && !ppc64le && !riscv64 && !s390x
2 |
3 | package fasthttp
4 |
5 | import "math"
6 |
7 | func roundUpForSliceCap(n int) int {
8 | if n <= 0 {
9 | return 0
10 | }
11 |
12 | // Above 100MB, we don't round up as the overhead is too large.
13 | if n > 100*1024*1024 {
14 | return n
15 | }
16 |
17 | x := uint32(n - 1)
18 | x |= x >> 1
19 | x |= x >> 2
20 | x |= x >> 4
21 | x |= x >> 8
22 | x |= x >> 16
23 |
24 | // Make sure we don't return 0 due to overflow, even on 32 bit systems
25 | if x >= uint32(math.MaxInt32) {
26 | return math.MaxInt32
27 | }
28 |
29 | return int(x + 1)
30 | }
31 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/round2_64.go:
--------------------------------------------------------------------------------
1 | //go:build amd64 || arm64 || ppc64 || ppc64le || riscv64 || s390x
2 |
3 | package fasthttp
4 |
5 | func roundUpForSliceCap(n int) int {
6 | if n <= 0 {
7 | return 0
8 | }
9 |
10 | // Above 100MB, we don't round up as the overhead is too large.
11 | if n > 100*1024*1024 {
12 | return n
13 | }
14 |
15 | x := uint64(n - 1)
16 | x |= x >> 1
17 | x |= x >> 2
18 | x |= x >> 4
19 | x |= x >> 8
20 | x |= x >> 16
21 |
22 | return int(x + 1)
23 | }
24 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/s2b_new.go:
--------------------------------------------------------------------------------
1 | //go:build go1.20
2 |
3 | package fasthttp
4 |
5 | import "unsafe"
6 |
7 | // s2b converts string to a byte slice without memory allocation.
8 | func s2b(s string) []byte {
9 | return unsafe.Slice(unsafe.StringData(s), len(s))
10 | }
11 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/s2b_old.go:
--------------------------------------------------------------------------------
1 | //go:build !go1.20
2 |
3 | package fasthttp
4 |
5 | import (
6 | "reflect"
7 | "unsafe"
8 | )
9 |
10 | // s2b converts string to a byte slice without memory allocation.
11 | //
12 | // Note it may break if string and/or slice header will change
13 | // in the future go versions.
14 | func s2b(s string) (b []byte) {
15 | bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
16 | sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
17 | bh.Data = sh.Data
18 | bh.Cap = sh.Len
19 | bh.Len = sh.Len
20 | return b
21 | }
22 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/stackless/doc.go:
--------------------------------------------------------------------------------
1 | // Package stackless provides functionality that may save stack space
2 | // for high number of concurrently running goroutines.
3 | package stackless
4 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/stackless/func.go:
--------------------------------------------------------------------------------
1 | package stackless
2 |
3 | import (
4 | "runtime"
5 | "sync"
6 | )
7 |
8 | // NewFunc returns stackless wrapper for the function f.
9 | //
10 | // Unlike f, the returned stackless wrapper doesn't use stack space
11 | // on the goroutine that calls it.
12 | // The wrapper may save a lot of stack space if the following conditions
13 | // are met:
14 | //
15 | // - f doesn't contain blocking calls on network, I/O or channels;
16 | // - f uses a lot of stack space;
17 | // - the wrapper is called from high number of concurrent goroutines.
18 | //
19 | // The stackless wrapper returns false if the call cannot be processed
20 | // at the moment due to high load.
21 | func NewFunc(f func(ctx any)) func(ctx any) bool {
22 | if f == nil {
23 | // developer sanity-check
24 | panic("BUG: f cannot be nil")
25 | }
26 |
27 | funcWorkCh := make(chan *funcWork, runtime.GOMAXPROCS(-1)*2048)
28 | onceInit := func() {
29 | n := runtime.GOMAXPROCS(-1)
30 | for i := 0; i < n; i++ {
31 | go funcWorker(funcWorkCh, f)
32 | }
33 | }
34 | var once sync.Once
35 |
36 | return func(ctx any) bool {
37 | once.Do(onceInit)
38 | fw := getFuncWork()
39 | fw.ctx = ctx
40 |
41 | select {
42 | case funcWorkCh <- fw:
43 | default:
44 | putFuncWork(fw)
45 | return false
46 | }
47 | <-fw.done
48 | putFuncWork(fw)
49 | return true
50 | }
51 | }
52 |
53 | func funcWorker(funcWorkCh <-chan *funcWork, f func(ctx any)) {
54 | for fw := range funcWorkCh {
55 | f(fw.ctx)
56 | fw.done <- struct{}{}
57 | }
58 | }
59 |
60 | func getFuncWork() *funcWork {
61 | v := funcWorkPool.Get()
62 | if v == nil {
63 | v = &funcWork{
64 | done: make(chan struct{}, 1),
65 | }
66 | }
67 | return v.(*funcWork)
68 | }
69 |
70 | func putFuncWork(fw *funcWork) {
71 | fw.ctx = nil
72 | funcWorkPool.Put(fw)
73 | }
74 |
75 | var funcWorkPool sync.Pool
76 |
77 | type funcWork struct {
78 | ctx any
79 | done chan struct{}
80 | }
81 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/stackless/writer.go:
--------------------------------------------------------------------------------
1 | package stackless
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 | "io"
7 | "sync"
8 |
9 | "github.com/valyala/bytebufferpool"
10 | )
11 |
12 | // Writer is an interface stackless writer must conform to.
13 | //
14 | // The interface contains common subset for Writers from compress/* packages.
15 | type Writer interface {
16 | Write(p []byte) (int, error)
17 | Flush() error
18 | Close() error
19 | Reset(w io.Writer)
20 | }
21 |
22 | // NewWriterFunc must return new writer that will be wrapped into
23 | // stackless writer.
24 | type NewWriterFunc func(w io.Writer) Writer
25 |
26 | // NewWriter creates a stackless writer around a writer returned
27 | // from newWriter.
28 | //
29 | // The returned writer writes data to dstW.
30 | //
31 | // Writers that use a lot of stack space may be wrapped into stackless writer,
32 | // thus saving stack space for high number of concurrently running goroutines.
33 | func NewWriter(dstW io.Writer, newWriter NewWriterFunc) Writer {
34 | w := &writer{
35 | dstW: dstW,
36 | }
37 | w.zw = newWriter(&w.xw)
38 | return w
39 | }
40 |
41 | type writer struct {
42 | dstW io.Writer
43 | zw Writer
44 | xw xWriter
45 |
46 | err error
47 | n int
48 |
49 | p []byte
50 | op op
51 | }
52 |
53 | type op int
54 |
55 | const (
56 | opWrite op = iota
57 | opFlush
58 | opClose
59 | opReset
60 | )
61 |
62 | func (w *writer) Write(p []byte) (int, error) {
63 | w.p = p
64 | err := w.do(opWrite)
65 | w.p = nil
66 | return w.n, err
67 | }
68 |
69 | func (w *writer) Flush() error {
70 | return w.do(opFlush)
71 | }
72 |
73 | func (w *writer) Close() error {
74 | return w.do(opClose)
75 | }
76 |
77 | func (w *writer) Reset(dstW io.Writer) {
78 | w.xw.Reset()
79 | w.do(opReset) //nolint:errcheck
80 | w.dstW = dstW
81 | }
82 |
83 | func (w *writer) do(op op) error {
84 | w.op = op
85 | if !stacklessWriterFunc(w) {
86 | return errHighLoad
87 | }
88 | err := w.err
89 | if err != nil {
90 | return err
91 | }
92 | if w.xw.bb != nil && len(w.xw.bb.B) > 0 {
93 | _, err = w.dstW.Write(w.xw.bb.B)
94 | }
95 | w.xw.Reset()
96 |
97 | return err
98 | }
99 |
100 | var errHighLoad = errors.New("cannot compress data due to high load")
101 |
102 | var (
103 | stacklessWriterFuncOnce sync.Once
104 | stacklessWriterFuncFunc func(ctx any) bool
105 | )
106 |
107 | func stacklessWriterFunc(ctx any) bool {
108 | stacklessWriterFuncOnce.Do(func() {
109 | stacklessWriterFuncFunc = NewFunc(writerFunc)
110 | })
111 | return stacklessWriterFuncFunc(ctx)
112 | }
113 |
114 | func writerFunc(ctx any) {
115 | w := ctx.(*writer)
116 | switch w.op {
117 | case opWrite:
118 | w.n, w.err = w.zw.Write(w.p)
119 | case opFlush:
120 | w.err = w.zw.Flush()
121 | case opClose:
122 | w.err = w.zw.Close()
123 | case opReset:
124 | w.zw.Reset(&w.xw)
125 | w.err = nil
126 | default:
127 | panic(fmt.Sprintf("BUG: unexpected op: %d", w.op))
128 | }
129 | }
130 |
131 | type xWriter struct {
132 | bb *bytebufferpool.ByteBuffer
133 | }
134 |
135 | func (w *xWriter) Write(p []byte) (int, error) {
136 | if w.bb == nil {
137 | w.bb = bufferPool.Get()
138 | }
139 | return w.bb.Write(p)
140 | }
141 |
142 | func (w *xWriter) Reset() {
143 | if w.bb != nil {
144 | bufferPool.Put(w.bb)
145 | w.bb = nil
146 | }
147 | }
148 |
149 | var bufferPool bytebufferpool.Pool
150 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/stream.go:
--------------------------------------------------------------------------------
1 | package fasthttp
2 |
3 | import (
4 | "bufio"
5 | "io"
6 | "sync"
7 |
8 | "github.com/valyala/fasthttp/fasthttputil"
9 | )
10 |
11 | // StreamWriter must write data to w.
12 | //
13 | // Usually StreamWriter writes data to w in a loop (aka 'data streaming').
14 | //
15 | // StreamWriter must return immediately if w returns error.
16 | //
17 | // Since the written data is buffered, do not forget calling w.Flush
18 | // when the data must be propagated to reader.
19 | type StreamWriter func(w *bufio.Writer)
20 |
21 | // NewStreamReader returns a reader, which replays all the data generated by sw.
22 | //
23 | // The returned reader may be passed to Response.SetBodyStream.
24 | //
25 | // Close must be called on the returned reader after all the required data
26 | // has been read. Otherwise goroutine leak may occur.
27 | //
28 | // See also Response.SetBodyStreamWriter.
29 | func NewStreamReader(sw StreamWriter) io.ReadCloser {
30 | pc := fasthttputil.NewPipeConns()
31 | pw := pc.Conn1()
32 | pr := pc.Conn2()
33 |
34 | var bw *bufio.Writer
35 | v := streamWriterBufPool.Get()
36 | if v == nil {
37 | bw = bufio.NewWriter(pw)
38 | } else {
39 | bw = v.(*bufio.Writer)
40 | bw.Reset(pw)
41 | }
42 |
43 | go func() {
44 | sw(bw)
45 | bw.Flush()
46 | pw.Close()
47 |
48 | streamWriterBufPool.Put(bw)
49 | }()
50 |
51 | return pr
52 | }
53 |
54 | var streamWriterBufPool sync.Pool
55 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/streaming.go:
--------------------------------------------------------------------------------
1 | package fasthttp
2 |
3 | import (
4 | "bufio"
5 | "bytes"
6 | "io"
7 | "sync"
8 |
9 | "github.com/valyala/bytebufferpool"
10 | )
11 |
12 | type headerInterface interface {
13 | ContentLength() int
14 | ReadTrailer(r *bufio.Reader) error
15 | }
16 |
17 | type requestStream struct {
18 | header headerInterface
19 | prefetchedBytes *bytes.Reader
20 | reader *bufio.Reader
21 | totalBytesRead int
22 | chunkLeft int
23 | }
24 |
25 | func (rs *requestStream) Read(p []byte) (int, error) {
26 | var (
27 | n int
28 | err error
29 | )
30 | if rs.header.ContentLength() == -1 {
31 | if rs.chunkLeft == 0 {
32 | chunkSize, err := parseChunkSize(rs.reader)
33 | if err != nil {
34 | return 0, err
35 | }
36 | if chunkSize == 0 {
37 | err = rs.header.ReadTrailer(rs.reader)
38 | if err != nil && err != io.EOF {
39 | return 0, err
40 | }
41 | return 0, io.EOF
42 | }
43 | rs.chunkLeft = chunkSize
44 | }
45 | bytesToRead := len(p)
46 | if rs.chunkLeft < len(p) {
47 | bytesToRead = rs.chunkLeft
48 | }
49 | n, err = rs.reader.Read(p[:bytesToRead])
50 | rs.totalBytesRead += n
51 | rs.chunkLeft -= n
52 | if err == io.EOF {
53 | err = io.ErrUnexpectedEOF
54 | }
55 | if err == nil && rs.chunkLeft == 0 {
56 | err = readCrLf(rs.reader)
57 | }
58 | return n, err
59 | }
60 | if rs.totalBytesRead == rs.header.ContentLength() {
61 | return 0, io.EOF
62 | }
63 | prefetchedSize := int(rs.prefetchedBytes.Size())
64 | if prefetchedSize > rs.totalBytesRead {
65 | left := prefetchedSize - rs.totalBytesRead
66 | if len(p) > left {
67 | p = p[:left]
68 | }
69 | n, err := rs.prefetchedBytes.Read(p)
70 | rs.totalBytesRead += n
71 | if n == rs.header.ContentLength() {
72 | return n, io.EOF
73 | }
74 | return n, err
75 | }
76 | left := rs.header.ContentLength() - rs.totalBytesRead
77 | if len(p) > left {
78 | p = p[:left]
79 | }
80 | n, err = rs.reader.Read(p)
81 | rs.totalBytesRead += n
82 | if err != nil {
83 | return n, err
84 | }
85 |
86 | if rs.totalBytesRead == rs.header.ContentLength() {
87 | err = io.EOF
88 | }
89 | return n, err
90 | }
91 |
92 | func acquireRequestStream(b *bytebufferpool.ByteBuffer, r *bufio.Reader, h headerInterface) *requestStream {
93 | rs := requestStreamPool.Get().(*requestStream)
94 | rs.prefetchedBytes = bytes.NewReader(b.B)
95 | rs.reader = r
96 | rs.header = h
97 | return rs
98 | }
99 |
100 | func releaseRequestStream(rs *requestStream) {
101 | rs.prefetchedBytes = nil
102 | rs.totalBytesRead = 0
103 | rs.chunkLeft = 0
104 | rs.reader = nil
105 | rs.header = nil
106 | requestStreamPool.Put(rs)
107 | }
108 |
109 | var requestStreamPool = sync.Pool{
110 | New: func() any {
111 | return &requestStream{}
112 | },
113 | }
114 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/tcp.go:
--------------------------------------------------------------------------------
1 | //go:build !windows
2 |
3 | package fasthttp
4 |
5 | import (
6 | "errors"
7 | "syscall"
8 | )
9 |
10 | func isConnectionReset(err error) bool {
11 | return errors.Is(err, syscall.ECONNRESET)
12 | }
13 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/tcp_windows.go:
--------------------------------------------------------------------------------
1 | package fasthttp
2 |
3 | import (
4 | "errors"
5 | "syscall"
6 | )
7 |
8 | func isConnectionReset(err error) bool {
9 | return errors.Is(err, syscall.WSAECONNRESET)
10 | }
11 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/testdata/test.png:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/timer.go:
--------------------------------------------------------------------------------
1 | package fasthttp
2 |
3 | import (
4 | "sync"
5 | "time"
6 | )
7 |
8 | func initTimer(t *time.Timer, timeout time.Duration) *time.Timer {
9 | if t == nil {
10 | return time.NewTimer(timeout)
11 | }
12 | if t.Reset(timeout) {
13 | // developer sanity-check
14 | panic("BUG: active timer trapped into initTimer()")
15 | }
16 | return t
17 | }
18 |
19 | func stopTimer(t *time.Timer) {
20 | if !t.Stop() {
21 | // Collect possibly added time from the channel
22 | // if timer has been stopped and nobody collected its value.
23 | select {
24 | case <-t.C:
25 | default:
26 | }
27 | }
28 | }
29 |
30 | // AcquireTimer returns a time.Timer from the pool and updates it to
31 | // send the current time on its channel after at least timeout.
32 | //
33 | // The returned Timer may be returned to the pool with ReleaseTimer
34 | // when no longer needed. This allows reducing GC load.
35 | func AcquireTimer(timeout time.Duration) *time.Timer {
36 | v := timerPool.Get()
37 | if v == nil {
38 | return time.NewTimer(timeout)
39 | }
40 | t := v.(*time.Timer)
41 | initTimer(t, timeout)
42 | return t
43 | }
44 |
45 | // ReleaseTimer returns the time.Timer acquired via AcquireTimer to the pool
46 | // and prevents the Timer from firing.
47 | //
48 | // Do not access the released time.Timer or read from its channel otherwise
49 | // data races may occur.
50 | func ReleaseTimer(t *time.Timer) {
51 | stopTimer(t)
52 | timerPool.Put(t)
53 | }
54 |
55 | var timerPool sync.Pool
56 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/tls.go:
--------------------------------------------------------------------------------
1 | package fasthttp
2 |
3 | import (
4 | "crypto/rand"
5 | "crypto/rsa"
6 | "crypto/x509"
7 | "crypto/x509/pkix"
8 | "encoding/pem"
9 | "math/big"
10 | "time"
11 | )
12 |
13 | // GenerateTestCertificate generates a test certificate and private key based on the given host.
14 | func GenerateTestCertificate(host string) ([]byte, []byte, error) {
15 | priv, err := rsa.GenerateKey(rand.Reader, 2048)
16 | if err != nil {
17 | return nil, nil, err
18 | }
19 |
20 | serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
21 | serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
22 | if err != nil {
23 | return nil, nil, err
24 | }
25 |
26 | cert := &x509.Certificate{
27 | SerialNumber: serialNumber,
28 | Subject: pkix.Name{
29 | Organization: []string{"fasthttp test"},
30 | },
31 | NotBefore: time.Now(),
32 | NotAfter: time.Now().Add(365 * 24 * time.Hour),
33 | KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageDigitalSignature,
34 | ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
35 | SignatureAlgorithm: x509.SHA256WithRSA,
36 | DNSNames: []string{host},
37 | BasicConstraintsValid: true,
38 | IsCA: true,
39 | }
40 |
41 | certBytes, err := x509.CreateCertificate(
42 | rand.Reader, cert, cert, &priv.PublicKey, priv,
43 | )
44 |
45 | p := pem.EncodeToMemory(
46 | &pem.Block{
47 | Type: "PRIVATE KEY",
48 | Bytes: x509.MarshalPKCS1PrivateKey(priv),
49 | },
50 | )
51 |
52 | b := pem.EncodeToMemory(
53 | &pem.Block{
54 | Type: "CERTIFICATE",
55 | Bytes: certBytes,
56 | },
57 | )
58 |
59 | return b, p, err
60 | }
61 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/uri_unix.go:
--------------------------------------------------------------------------------
1 | //go:build !windows
2 |
3 | package fasthttp
4 |
5 | func addLeadingSlash(dst, src []byte) []byte {
6 | // add leading slash for unix paths
7 | if len(src) == 0 || src[0] != '/' {
8 | dst = append(dst, '/')
9 | }
10 |
11 | return dst
12 | }
13 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/uri_windows.go:
--------------------------------------------------------------------------------
1 | package fasthttp
2 |
3 | func addLeadingSlash(dst, src []byte) []byte {
4 | // zero length 、"C:/" and "a" case
5 | isDisk := len(src) > 2 && src[1] == ':'
6 | if len(src) == 0 || (!isDisk && src[0] != '/') {
7 | dst = append(dst, '/')
8 | }
9 |
10 | return dst
11 | }
12 |
--------------------------------------------------------------------------------
/vendor/github.com/valyala/fasthttp/userdata.go:
--------------------------------------------------------------------------------
1 | package fasthttp
2 |
3 | import (
4 | "io"
5 | )
6 |
7 | type userDataKV struct {
8 | key any
9 | value any
10 | }
11 |
12 | type userData []userDataKV
13 |
14 | func (d *userData) Set(key, value any) {
15 | if b, ok := key.([]byte); ok {
16 | key = string(b)
17 | }
18 | args := *d
19 | n := len(args)
20 | for i := 0; i < n; i++ {
21 | kv := &args[i]
22 | if kv.key == key {
23 | kv.value = value
24 | return
25 | }
26 | }
27 |
28 | if value == nil {
29 | return
30 | }
31 |
32 | c := cap(args)
33 | if c > n {
34 | args = args[:n+1]
35 | kv := &args[n]
36 | kv.key = key
37 | kv.value = value
38 | *d = args
39 | return
40 | }
41 |
42 | kv := userDataKV{}
43 | kv.key = key
44 | kv.value = value
45 | args = append(args, kv)
46 | *d = args
47 | }
48 |
49 | func (d *userData) SetBytes(key []byte, value any) {
50 | d.Set(key, value)
51 | }
52 |
53 | func (d *userData) Get(key any) any {
54 | if b, ok := key.([]byte); ok {
55 | key = b2s(b)
56 | }
57 | args := *d
58 | n := len(args)
59 | for i := 0; i < n; i++ {
60 | kv := &args[i]
61 | if kv.key == key {
62 | return kv.value
63 | }
64 | }
65 | return nil
66 | }
67 |
68 | func (d *userData) GetBytes(key []byte) any {
69 | return d.Get(key)
70 | }
71 |
72 | func (d *userData) Reset() {
73 | args := *d
74 | n := len(args)
75 | for i := 0; i < n; i++ {
76 | v := args[i].value
77 | if vc, ok := v.(io.Closer); ok {
78 | vc.Close()
79 | }
80 | }
81 | *d = (*d)[:0]
82 | }
83 |
84 | func (d *userData) Remove(key any) {
85 | if b, ok := key.([]byte); ok {
86 | key = b2s(b)
87 | }
88 | args := *d
89 | n := len(args)
90 | for i := 0; i < n; i++ {
91 | kv := &args[i]
92 | if kv.key == key {
93 | n--
94 | args[i], args[n] = args[n], args[i]
95 | args[n].value = nil
96 | args = args[:n]
97 | *d = args
98 | return
99 | }
100 | }
101 | }
102 |
103 | func (d *userData) RemoveBytes(key []byte) {
104 | d.Remove(key)
105 | }
106 |
--------------------------------------------------------------------------------
/vendor/modules.txt:
--------------------------------------------------------------------------------
1 | # github.com/andybalholm/brotli v1.1.0
2 | ## explicit; go 1.13
3 | github.com/andybalholm/brotli
4 | github.com/andybalholm/brotli/matchfinder
5 | # github.com/klauspost/compress v1.17.9
6 | ## explicit; go 1.20
7 | github.com/klauspost/compress
8 | github.com/klauspost/compress/flate
9 | github.com/klauspost/compress/fse
10 | github.com/klauspost/compress/gzip
11 | github.com/klauspost/compress/huff0
12 | github.com/klauspost/compress/internal/cpuinfo
13 | github.com/klauspost/compress/internal/snapref
14 | github.com/klauspost/compress/zlib
15 | github.com/klauspost/compress/zstd
16 | github.com/klauspost/compress/zstd/internal/xxhash
17 | # github.com/valyala/bytebufferpool v1.0.0
18 | ## explicit
19 | github.com/valyala/bytebufferpool
20 | # github.com/valyala/fasthttp v1.55.0
21 | ## explicit; go 1.20
22 | github.com/valyala/fasthttp
23 | github.com/valyala/fasthttp/fasthttputil
24 | github.com/valyala/fasthttp/stackless
25 |
--------------------------------------------------------------------------------