├── .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 | 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 |
19 | return to main page 20 |
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 |
55 | Rows:
56 | 57 |
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 | 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 | 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 | 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 | 37 | 38 | Output tags without html escaping 39 | 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 | [![Build Status](https://travis-ci.org/valyala/bytebufferpool.svg)](https://travis-ci.org/valyala/bytebufferpool) 2 | [![GoDoc](https://godoc.org/github.com/valyala/bytebufferpool?status.svg)](http://godoc.org/github.com/valyala/bytebufferpool) 3 | [![Go Report](http://goreportcard.com/badge/valyala/bytebufferpool)](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 | --------------------------------------------------------------------------------