forked from lug/matterbridge
		
	Update dependencies (#1851)
This commit is contained in:
		
							
								
								
									
										3
									
								
								vendor/github.com/SevereCloud/vksdk/v2/.golangci.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/SevereCloud/vksdk/v2/.golangci.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -57,6 +57,8 @@ linters:
 | 
			
		||||
    - grouper
 | 
			
		||||
    - decorder
 | 
			
		||||
    - containedctx
 | 
			
		||||
    # - execinquery # FIXME: panic in 1.46.0
 | 
			
		||||
    - nosprintfhostport
 | 
			
		||||
 | 
			
		||||
# - wrapcheck # TODO: v3 Fix
 | 
			
		||||
# - testpackage # TODO: Fix testpackage
 | 
			
		||||
@@ -87,6 +89,7 @@ linters:
 | 
			
		||||
# - varnamelen
 | 
			
		||||
# - errchkjson
 | 
			
		||||
# - maintidx
 | 
			
		||||
# - nonamedreturns
 | 
			
		||||
 | 
			
		||||
# depricated
 | 
			
		||||
# - maligned
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/SevereCloud/vksdk/v2/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/SevereCloud/vksdk/v2/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -7,6 +7,6 @@ package vksdk
 | 
			
		||||
 | 
			
		||||
// Module constants.
 | 
			
		||||
const (
 | 
			
		||||
	Version = "2.14.0"
 | 
			
		||||
	Version = "2.14.1"
 | 
			
		||||
	API     = "5.131"
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								vendor/github.com/SevereCloud/vksdk/v2/object/groups.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								vendor/github.com/SevereCloud/vksdk/v2/object/groups.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -210,7 +210,7 @@ type GroupsGroup struct {
 | 
			
		||||
	MainSection     int                  `json:"main_section,omitempty"`
 | 
			
		||||
	OnlineStatus    GroupsOnlineStatus   `json:"online_status,omitempty"` // Status of replies in community messages
 | 
			
		||||
	AgeLimits       int                  `json:"age_limits,omitempty"`    // Information whether age limit
 | 
			
		||||
	BanInfo         GroupsGroupBanInfo   `json:"ban_info,omitempty"`      // User ban info
 | 
			
		||||
	BanInfo         *GroupsGroupBanInfo  `json:"ban_info,omitempty"`      // User ban info
 | 
			
		||||
	Addresses       GroupsAddressesInfo  `json:"addresses,omitempty"`     // Info about addresses in Groups
 | 
			
		||||
	LiveCovers      GroupsLiveCovers     `json:"live_covers,omitempty"`
 | 
			
		||||
	CropPhoto       UsersCropPhoto       `json:"crop_photo,omitempty"`
 | 
			
		||||
@@ -963,10 +963,10 @@ type GroupsOnlineStatus struct {
 | 
			
		||||
 | 
			
		||||
// GroupsOwnerXtrBanInfo struct.
 | 
			
		||||
type GroupsOwnerXtrBanInfo struct {
 | 
			
		||||
	BanInfo GroupsBanInfo `json:"ban_info"`
 | 
			
		||||
	Group   GroupsGroup   `json:"group"`
 | 
			
		||||
	Profile UsersUser     `json:"profile"`
 | 
			
		||||
	Type    string        `json:"type"`
 | 
			
		||||
	BanInfo *GroupsBanInfo `json:"ban_info"`
 | 
			
		||||
	Group   GroupsGroup    `json:"group"`
 | 
			
		||||
	Profile UsersUser      `json:"profile"`
 | 
			
		||||
	Type    string         `json:"type"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GroupsSubjectItem struct.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/SevereCloud/vksdk/v2/object/video.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/SevereCloud/vksdk/v2/object/video.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -31,7 +31,7 @@ type VideoVideo struct {
 | 
			
		||||
	CanLike BaseBoolInt `json:"can_like"`
 | 
			
		||||
 | 
			
		||||
	// Information whether current user can download the video.
 | 
			
		||||
	CanDownload BaseBoolInt `json:"can_download"`
 | 
			
		||||
	CanDownload int `json:"can_download"`
 | 
			
		||||
 | 
			
		||||
	// Information whether current user can repost this video.
 | 
			
		||||
	CanRepost         BaseBoolInt       `json:"can_repost"`
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								vendor/github.com/d5/tengo/v2/compiler.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/d5/tengo/v2/compiler.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1220,14 +1220,14 @@ func (c *Compiler) optimizeFunc(node parser.Node) {
 | 
			
		||||
	iterateInstructions(c.scopes[c.scopeIndex].Instructions,
 | 
			
		||||
		func(pos int, opcode parser.Opcode, operands []int) bool {
 | 
			
		||||
			switch {
 | 
			
		||||
			case dsts[pos]:
 | 
			
		||||
				dstIdx++
 | 
			
		||||
				deadCode = false
 | 
			
		||||
			case opcode == parser.OpReturn:
 | 
			
		||||
				if deadCode {
 | 
			
		||||
					return true
 | 
			
		||||
				}
 | 
			
		||||
				deadCode = true
 | 
			
		||||
			case dsts[pos]:
 | 
			
		||||
				dstIdx++
 | 
			
		||||
				deadCode = false
 | 
			
		||||
			case deadCode:
 | 
			
		||||
				return true
 | 
			
		||||
			}
 | 
			
		||||
@@ -1242,6 +1242,7 @@ func (c *Compiler) optimizeFunc(node parser.Node) {
 | 
			
		||||
	var appendReturn bool
 | 
			
		||||
	endPos := len(c.scopes[c.scopeIndex].Instructions)
 | 
			
		||||
	newEndPost := len(newInsts)
 | 
			
		||||
 | 
			
		||||
	iterateInstructions(newInsts,
 | 
			
		||||
		func(pos int, opcode parser.Opcode, operands []int) bool {
 | 
			
		||||
			switch opcode {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								vendor/github.com/d5/tengo/v2/parser/parser.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								vendor/github.com/d5/tengo/v2/parser/parser.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -375,7 +375,12 @@ func (p *Parser) parseOperand() Expr {
 | 
			
		||||
	case token.Ident:
 | 
			
		||||
		return p.parseIdent()
 | 
			
		||||
	case token.Int:
 | 
			
		||||
		v, _ := strconv.ParseInt(p.tokenLit, 10, 64)
 | 
			
		||||
		v, err := strconv.ParseInt(p.tokenLit, 0, 64)
 | 
			
		||||
		if err == strconv.ErrRange {
 | 
			
		||||
			p.error(p.pos, "number out of range")
 | 
			
		||||
		} else if err != nil {
 | 
			
		||||
			p.error(p.pos, "invalid integer")
 | 
			
		||||
		}
 | 
			
		||||
		x := &IntLit{
 | 
			
		||||
			Value:    v,
 | 
			
		||||
			ValuePos: p.pos,
 | 
			
		||||
@@ -383,8 +388,14 @@ func (p *Parser) parseOperand() Expr {
 | 
			
		||||
		}
 | 
			
		||||
		p.next()
 | 
			
		||||
		return x
 | 
			
		||||
 | 
			
		||||
	case token.Float:
 | 
			
		||||
		v, _ := strconv.ParseFloat(p.tokenLit, 64)
 | 
			
		||||
		v, err := strconv.ParseFloat(p.tokenLit, 64)
 | 
			
		||||
		if err == strconv.ErrRange {
 | 
			
		||||
			p.error(p.pos, "number out of range")
 | 
			
		||||
		} else if err != nil {
 | 
			
		||||
			p.error(p.pos, "invalid float")
 | 
			
		||||
		}
 | 
			
		||||
		x := &FloatLit{
 | 
			
		||||
			Value:    v,
 | 
			
		||||
			ValuePos: p.pos,
 | 
			
		||||
@@ -447,10 +458,11 @@ func (p *Parser) parseOperand() Expr {
 | 
			
		||||
		return p.parseErrorExpr()
 | 
			
		||||
	case token.Immutable: // immutable expression
 | 
			
		||||
		return p.parseImmutableExpr()
 | 
			
		||||
	default:
 | 
			
		||||
		p.errorExpected(p.pos, "operand")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pos := p.pos
 | 
			
		||||
	p.errorExpected(pos, "operand")
 | 
			
		||||
	p.advance(stmtStart)
 | 
			
		||||
	return &BadExpr{From: pos, To: p.pos}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										113
									
								
								vendor/github.com/d5/tengo/v2/parser/scanner.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										113
									
								
								vendor/github.com/d5/tengo/v2/parser/scanner.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -93,9 +93,9 @@ func (s *Scanner) Scan() (
 | 
			
		||||
			token.Export, token.True, token.False, token.Undefined:
 | 
			
		||||
			insertSemi = true
 | 
			
		||||
		}
 | 
			
		||||
	case '0' <= ch && ch <= '9':
 | 
			
		||||
	case ('0' <= ch && ch <= '9') || (ch == '.' && '0' <= s.peek() && s.peek() <= '9'):
 | 
			
		||||
		insertSemi = true
 | 
			
		||||
		tok, literal = s.scanNumber(false)
 | 
			
		||||
		tok, literal = s.scanNumber()
 | 
			
		||||
	default:
 | 
			
		||||
		s.next() // always make progress
 | 
			
		||||
 | 
			
		||||
@@ -125,16 +125,11 @@ func (s *Scanner) Scan() (
 | 
			
		||||
		case ':':
 | 
			
		||||
			tok = s.switch2(token.Colon, token.Define)
 | 
			
		||||
		case '.':
 | 
			
		||||
			if '0' <= s.ch && s.ch <= '9' {
 | 
			
		||||
				insertSemi = true
 | 
			
		||||
				tok, literal = s.scanNumber(true)
 | 
			
		||||
			} else {
 | 
			
		||||
				tok = token.Period
 | 
			
		||||
				if s.ch == '.' && s.peek() == '.' {
 | 
			
		||||
					s.next()
 | 
			
		||||
					s.next() // consume last '.'
 | 
			
		||||
					tok = token.Ellipsis
 | 
			
		||||
				}
 | 
			
		||||
			tok = token.Period
 | 
			
		||||
			if s.ch == '.' && s.peek() == '.' {
 | 
			
		||||
				s.next()
 | 
			
		||||
				s.next() // consume last '.'
 | 
			
		||||
				tok = token.Ellipsis
 | 
			
		||||
			}
 | 
			
		||||
		case ',':
 | 
			
		||||
			tok = token.Comma
 | 
			
		||||
@@ -379,86 +374,58 @@ func (s *Scanner) scanIdentifier() string {
 | 
			
		||||
	return string(s.src[offs:s.offset])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Scanner) scanMantissa(base int) {
 | 
			
		||||
	for digitVal(s.ch) < base {
 | 
			
		||||
func (s *Scanner) scanDigits(base int) {
 | 
			
		||||
	for s.ch == '_' || digitVal(s.ch) < base {
 | 
			
		||||
		s.next()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Scanner) scanNumber(
 | 
			
		||||
	seenDecimalPoint bool,
 | 
			
		||||
) (tok token.Token, lit string) {
 | 
			
		||||
	// digitVal(s.ch) < 10
 | 
			
		||||
func (s *Scanner) scanNumber() (token.Token, string) {
 | 
			
		||||
	offs := s.offset
 | 
			
		||||
	tok = token.Int
 | 
			
		||||
	tok := token.Int
 | 
			
		||||
	base := 10
 | 
			
		||||
 | 
			
		||||
	defer func() {
 | 
			
		||||
		lit = string(s.src[offs:s.offset])
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	if seenDecimalPoint {
 | 
			
		||||
		offs--
 | 
			
		||||
		tok = token.Float
 | 
			
		||||
		s.scanMantissa(10)
 | 
			
		||||
		goto exponent
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if s.ch == '0' {
 | 
			
		||||
		// int or float
 | 
			
		||||
		offs := s.offset
 | 
			
		||||
	// Determine base
 | 
			
		||||
	switch {
 | 
			
		||||
	case s.ch == '0' && lower(s.peek()) == 'b':
 | 
			
		||||
		base = 2
 | 
			
		||||
		s.next()
 | 
			
		||||
		s.next()
 | 
			
		||||
	case s.ch == '0' && lower(s.peek()) == 'o':
 | 
			
		||||
		base = 8
 | 
			
		||||
		s.next()
 | 
			
		||||
		s.next()
 | 
			
		||||
	case s.ch == '0' && lower(s.peek()) == 'x':
 | 
			
		||||
		base = 16
 | 
			
		||||
		s.next()
 | 
			
		||||
		s.next()
 | 
			
		||||
		if s.ch == 'x' || s.ch == 'X' {
 | 
			
		||||
			// hexadecimal int
 | 
			
		||||
			s.next()
 | 
			
		||||
			s.scanMantissa(16)
 | 
			
		||||
			if s.offset-offs <= 2 {
 | 
			
		||||
				// only scanned "0x" or "0X"
 | 
			
		||||
				s.error(offs, "illegal hexadecimal number")
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			// octal int or float
 | 
			
		||||
			seenDecimalDigit := false
 | 
			
		||||
			s.scanMantissa(8)
 | 
			
		||||
			if s.ch == '8' || s.ch == '9' {
 | 
			
		||||
				// illegal octal int or float
 | 
			
		||||
				seenDecimalDigit = true
 | 
			
		||||
				s.scanMantissa(10)
 | 
			
		||||
			}
 | 
			
		||||
			if s.ch == '.' || s.ch == 'e' || s.ch == 'E' || s.ch == 'i' {
 | 
			
		||||
				goto fraction
 | 
			
		||||
			}
 | 
			
		||||
			// octal int
 | 
			
		||||
			if seenDecimalDigit {
 | 
			
		||||
				s.error(offs, "illegal octal number")
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// decimal int or float
 | 
			
		||||
	s.scanMantissa(10)
 | 
			
		||||
	// Scan whole number
 | 
			
		||||
	s.scanDigits(base)
 | 
			
		||||
 | 
			
		||||
fraction:
 | 
			
		||||
	if s.ch == '.' {
 | 
			
		||||
	// Scan fractional part
 | 
			
		||||
	if s.ch == '.' && (base == 10 || base == 16) {
 | 
			
		||||
		tok = token.Float
 | 
			
		||||
		s.next()
 | 
			
		||||
		s.scanMantissa(10)
 | 
			
		||||
		s.scanDigits(base)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
exponent:
 | 
			
		||||
	if s.ch == 'e' || s.ch == 'E' {
 | 
			
		||||
	// Scan exponent
 | 
			
		||||
	if s.ch == 'e' || s.ch == 'E' || s.ch == 'p' || s.ch == 'P' {
 | 
			
		||||
		tok = token.Float
 | 
			
		||||
		s.next()
 | 
			
		||||
		if s.ch == '-' || s.ch == '+' {
 | 
			
		||||
			s.next()
 | 
			
		||||
		}
 | 
			
		||||
		if digitVal(s.ch) < 10 {
 | 
			
		||||
			s.scanMantissa(10)
 | 
			
		||||
		} else {
 | 
			
		||||
			s.error(offs, "illegal floating-point exponent")
 | 
			
		||||
		offs := s.offset
 | 
			
		||||
		s.scanDigits(10)
 | 
			
		||||
		if offs == s.offset {
 | 
			
		||||
			s.error(offs, "exponent has no digits")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
 | 
			
		||||
	return tok, string(s.src[offs:s.offset])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Scanner) scanEscape(quote rune) bool {
 | 
			
		||||
@@ -687,3 +654,7 @@ func digitVal(ch rune) int {
 | 
			
		||||
	}
 | 
			
		||||
	return 16 // larger than any legal digit val
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func lower(c byte) byte {
 | 
			
		||||
	return c | ('x' - 'X')
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								vendor/github.com/gomarkdown/markdown/.gitpod.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								vendor/github.com/gomarkdown/markdown/.gitpod.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
# This configuration file was automatically generated by Gitpod.
 | 
			
		||||
# Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file)
 | 
			
		||||
# and commit this file to your remote git repository to share the goodness with others.
 | 
			
		||||
 | 
			
		||||
tasks:
 | 
			
		||||
  - init: go get && go build ./... && go test ./...
 | 
			
		||||
    command: go run
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										6
									
								
								vendor/github.com/gomarkdown/markdown/parser/block.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/gomarkdown/markdown/parser/block.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1675,6 +1675,12 @@ func (p *Parser) paragraph(data []byte) int {
 | 
			
		||||
			return i
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// if there's a block quote, paragraph is over
 | 
			
		||||
		if p.quotePrefix(current) > 0 {
 | 
			
		||||
			p.renderParagraph(data[:i])
 | 
			
		||||
			return i
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// if there's a fenced code block, paragraph is over
 | 
			
		||||
		if p.extensions&FencedCode != 0 {
 | 
			
		||||
			if p.fencedCodeBlock(current, false) > 0 {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								vendor/github.com/klauspost/compress/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/klauspost/compress/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -23,3 +23,10 @@ _testmain.go
 | 
			
		||||
*.test
 | 
			
		||||
*.prof
 | 
			
		||||
/s2/cmd/_s2sx/sfx-exe
 | 
			
		||||
 | 
			
		||||
# Linux perf files
 | 
			
		||||
perf.data
 | 
			
		||||
perf.data.old
 | 
			
		||||
 | 
			
		||||
# gdb history
 | 
			
		||||
.gdb_history
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								vendor/github.com/klauspost/compress/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										40
									
								
								vendor/github.com/klauspost/compress/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -17,6 +17,41 @@ This package provides various compression algorithms.
 | 
			
		||||
 | 
			
		||||
# changelog
 | 
			
		||||
 | 
			
		||||
* May 25, 2022 (v1.15.5)
 | 
			
		||||
	* s2: Add concurrent stream decompression https://github.com/klauspost/compress/pull/602
 | 
			
		||||
	* s2: Fix final emit oob read crash on amd64 https://github.com/klauspost/compress/pull/601
 | 
			
		||||
	* huff0: asm implementation of Decompress1X by @WojciechMula https://github.com/klauspost/compress/pull/596
 | 
			
		||||
	* zstd: Use 1 less goroutine for stream decoding https://github.com/klauspost/compress/pull/588
 | 
			
		||||
	* zstd: Copy literal in 16 byte blocks when possible https://github.com/klauspost/compress/pull/592
 | 
			
		||||
	* zstd: Speed up when WithDecoderLowmem(false) https://github.com/klauspost/compress/pull/599
 | 
			
		||||
	* zstd: faster next state update in BMI2 version of decode by @WojciechMula in https://github.com/klauspost/compress/pull/593
 | 
			
		||||
	* huff0: Do not check max size when reading table. https://github.com/klauspost/compress/pull/586
 | 
			
		||||
	* flate: Inplace hashing for level 7-9 by @klauspost in https://github.com/klauspost/compress/pull/590
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
* May 11, 2022 (v1.15.4)
 | 
			
		||||
	* huff0: decompress directly into output by @WojciechMula in [#577](https://github.com/klauspost/compress/pull/577)
 | 
			
		||||
	* inflate: Keep dict on stack [#581](https://github.com/klauspost/compress/pull/581)
 | 
			
		||||
	* zstd: Faster decoding memcopy in asm [#583](https://github.com/klauspost/compress/pull/583)
 | 
			
		||||
	* zstd: Fix ignored crc [#580](https://github.com/klauspost/compress/pull/580)
 | 
			
		||||
 | 
			
		||||
* May 5, 2022 (v1.15.3)
 | 
			
		||||
	* zstd: Allow to ignore checksum checking by @WojciechMula [#572](https://github.com/klauspost/compress/pull/572)
 | 
			
		||||
	* s2: Fix incorrect seek for io.SeekEnd in [#575](https://github.com/klauspost/compress/pull/575)
 | 
			
		||||
 | 
			
		||||
* Apr 26, 2022 (v1.15.2)
 | 
			
		||||
	* zstd: Add x86-64 assembly for decompression on streams and blocks. Contributed by [@WojciechMula](https://github.com/WojciechMula). Typically 2x faster.  [#528](https://github.com/klauspost/compress/pull/528) [#531](https://github.com/klauspost/compress/pull/531) [#545](https://github.com/klauspost/compress/pull/545) [#537](https://github.com/klauspost/compress/pull/537)
 | 
			
		||||
	* zstd: Add options to ZipDecompressor and fixes [#539](https://github.com/klauspost/compress/pull/539)
 | 
			
		||||
	* s2: Use sorted search for index [#555](https://github.com/klauspost/compress/pull/555)
 | 
			
		||||
	* Minimum version is Go 1.16, added CI test on 1.18.
 | 
			
		||||
 | 
			
		||||
* Mar 11, 2022 (v1.15.1)
 | 
			
		||||
	* huff0: Add x86 assembly of Decode4X by @WojciechMula in [#512](https://github.com/klauspost/compress/pull/512)
 | 
			
		||||
	* zstd: Reuse zip decoders in [#514](https://github.com/klauspost/compress/pull/514)
 | 
			
		||||
	* zstd: Detect extra block data and report as corrupted in [#520](https://github.com/klauspost/compress/pull/520)
 | 
			
		||||
	* zstd: Handle zero sized frame content size stricter in [#521](https://github.com/klauspost/compress/pull/521)
 | 
			
		||||
	* zstd: Add stricter block size checks in [#523](https://github.com/klauspost/compress/pull/523)
 | 
			
		||||
 | 
			
		||||
* Mar 3, 2022 (v1.15.0)
 | 
			
		||||
	* zstd: Refactor decoder by @klauspost in [#498](https://github.com/klauspost/compress/pull/498)
 | 
			
		||||
	* zstd: Add stream encoding without goroutines by @klauspost in [#505](https://github.com/klauspost/compress/pull/505)
 | 
			
		||||
@@ -60,6 +95,9 @@ While the release has been extensively tested, it is recommended to testing when
 | 
			
		||||
	* zstd: add arm64 xxhash assembly in [#464](https://github.com/klauspost/compress/pull/464)
 | 
			
		||||
	* Add garbled for binaries for s2 in [#445](https://github.com/klauspost/compress/pull/445)
 | 
			
		||||
 | 
			
		||||
<details>
 | 
			
		||||
	<summary>See changes to v1.13.x</summary>
 | 
			
		||||
	
 | 
			
		||||
* Aug 30, 2021 (v1.13.5)
 | 
			
		||||
	* gz/zlib/flate: Alias stdlib errors [#425](https://github.com/klauspost/compress/pull/425)
 | 
			
		||||
	* s2: Add block support to commandline tools [#413](https://github.com/klauspost/compress/pull/413)
 | 
			
		||||
@@ -88,6 +126,8 @@ While the release has been extensively tested, it is recommended to testing when
 | 
			
		||||
	* Added [gzhttp](https://github.com/klauspost/compress/tree/master/gzhttp#gzip-handler) which allows wrapping HTTP servers and clients with GZIP compressors.
 | 
			
		||||
	* zstd: Detect short invalid signatures [#382](https://github.com/klauspost/compress/pull/382)
 | 
			
		||||
	* zstd: Spawn decoder goroutine only if needed. [#380](https://github.com/klauspost/compress/pull/380)
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<details>
 | 
			
		||||
	<summary>See changes to v1.12.x</summary>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								vendor/github.com/klauspost/compress/huff0/autogen.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/klauspost/compress/huff0/autogen.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,5 +0,0 @@
 | 
			
		||||
package huff0
 | 
			
		||||
 | 
			
		||||
//go:generate go run generate.go
 | 
			
		||||
//go:generate asmfmt -w decompress_amd64.s
 | 
			
		||||
//go:generate asmfmt -w decompress_8b_amd64.s
 | 
			
		||||
							
								
								
									
										10
									
								
								vendor/github.com/klauspost/compress/huff0/bitreader.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								vendor/github.com/klauspost/compress/huff0/bitreader.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -165,11 +165,6 @@ func (b *bitReaderShifted) peekBitsFast(n uint8) uint16 {
 | 
			
		||||
	return uint16(b.value >> ((64 - n) & 63))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// peekTopBits(n) is equvialent to peekBitFast(64 - n)
 | 
			
		||||
func (b *bitReaderShifted) peekTopBits(n uint8) uint16 {
 | 
			
		||||
	return uint16(b.value >> n)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *bitReaderShifted) advance(n uint8) {
 | 
			
		||||
	b.bitsRead += n
 | 
			
		||||
	b.value <<= n & 63
 | 
			
		||||
@@ -220,11 +215,6 @@ func (b *bitReaderShifted) fill() {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// finished returns true if all bits have been read from the bit stream.
 | 
			
		||||
func (b *bitReaderShifted) finished() bool {
 | 
			
		||||
	return b.off == 0 && b.bitsRead >= 64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *bitReaderShifted) remaining() uint {
 | 
			
		||||
	return b.off*8 + uint(64-b.bitsRead)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										115
									
								
								vendor/github.com/klauspost/compress/huff0/bitwriter.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										115
									
								
								vendor/github.com/klauspost/compress/huff0/bitwriter.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -5,8 +5,6 @@
 | 
			
		||||
 | 
			
		||||
package huff0
 | 
			
		||||
 | 
			
		||||
import "fmt"
 | 
			
		||||
 | 
			
		||||
// bitWriter will write bits.
 | 
			
		||||
// First bit will be LSB of the first byte of output.
 | 
			
		||||
type bitWriter struct {
 | 
			
		||||
@@ -23,14 +21,6 @@ var bitMask16 = [32]uint16{
 | 
			
		||||
	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
 | 
			
		||||
	0xFFFF, 0xFFFF} /* up to 16 bits */
 | 
			
		||||
 | 
			
		||||
// addBits16NC will add up to 16 bits.
 | 
			
		||||
// It will not check if there is space for them,
 | 
			
		||||
// so the caller must ensure that it has flushed recently.
 | 
			
		||||
func (b *bitWriter) addBits16NC(value uint16, bits uint8) {
 | 
			
		||||
	b.bitContainer |= uint64(value&bitMask16[bits&31]) << (b.nBits & 63)
 | 
			
		||||
	b.nBits += bits
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// addBits16Clean will add up to 16 bits. value may not contain more set bits than indicated.
 | 
			
		||||
// It will not check if there is space for them, so the caller must ensure that it has flushed recently.
 | 
			
		||||
func (b *bitWriter) addBits16Clean(value uint16, bits uint8) {
 | 
			
		||||
@@ -70,104 +60,6 @@ func (b *bitWriter) encTwoSymbols(ct cTable, av, bv byte) {
 | 
			
		||||
	b.nBits += encA.nBits + encB.nBits
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// addBits16ZeroNC will add up to 16 bits.
 | 
			
		||||
// It will not check if there is space for them,
 | 
			
		||||
// so the caller must ensure that it has flushed recently.
 | 
			
		||||
// This is fastest if bits can be zero.
 | 
			
		||||
func (b *bitWriter) addBits16ZeroNC(value uint16, bits uint8) {
 | 
			
		||||
	if bits == 0 {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	value <<= (16 - bits) & 15
 | 
			
		||||
	value >>= (16 - bits) & 15
 | 
			
		||||
	b.bitContainer |= uint64(value) << (b.nBits & 63)
 | 
			
		||||
	b.nBits += bits
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// flush will flush all pending full bytes.
 | 
			
		||||
// There will be at least 56 bits available for writing when this has been called.
 | 
			
		||||
// Using flush32 is faster, but leaves less space for writing.
 | 
			
		||||
func (b *bitWriter) flush() {
 | 
			
		||||
	v := b.nBits >> 3
 | 
			
		||||
	switch v {
 | 
			
		||||
	case 0:
 | 
			
		||||
		return
 | 
			
		||||
	case 1:
 | 
			
		||||
		b.out = append(b.out,
 | 
			
		||||
			byte(b.bitContainer),
 | 
			
		||||
		)
 | 
			
		||||
		b.bitContainer >>= 1 << 3
 | 
			
		||||
	case 2:
 | 
			
		||||
		b.out = append(b.out,
 | 
			
		||||
			byte(b.bitContainer),
 | 
			
		||||
			byte(b.bitContainer>>8),
 | 
			
		||||
		)
 | 
			
		||||
		b.bitContainer >>= 2 << 3
 | 
			
		||||
	case 3:
 | 
			
		||||
		b.out = append(b.out,
 | 
			
		||||
			byte(b.bitContainer),
 | 
			
		||||
			byte(b.bitContainer>>8),
 | 
			
		||||
			byte(b.bitContainer>>16),
 | 
			
		||||
		)
 | 
			
		||||
		b.bitContainer >>= 3 << 3
 | 
			
		||||
	case 4:
 | 
			
		||||
		b.out = append(b.out,
 | 
			
		||||
			byte(b.bitContainer),
 | 
			
		||||
			byte(b.bitContainer>>8),
 | 
			
		||||
			byte(b.bitContainer>>16),
 | 
			
		||||
			byte(b.bitContainer>>24),
 | 
			
		||||
		)
 | 
			
		||||
		b.bitContainer >>= 4 << 3
 | 
			
		||||
	case 5:
 | 
			
		||||
		b.out = append(b.out,
 | 
			
		||||
			byte(b.bitContainer),
 | 
			
		||||
			byte(b.bitContainer>>8),
 | 
			
		||||
			byte(b.bitContainer>>16),
 | 
			
		||||
			byte(b.bitContainer>>24),
 | 
			
		||||
			byte(b.bitContainer>>32),
 | 
			
		||||
		)
 | 
			
		||||
		b.bitContainer >>= 5 << 3
 | 
			
		||||
	case 6:
 | 
			
		||||
		b.out = append(b.out,
 | 
			
		||||
			byte(b.bitContainer),
 | 
			
		||||
			byte(b.bitContainer>>8),
 | 
			
		||||
			byte(b.bitContainer>>16),
 | 
			
		||||
			byte(b.bitContainer>>24),
 | 
			
		||||
			byte(b.bitContainer>>32),
 | 
			
		||||
			byte(b.bitContainer>>40),
 | 
			
		||||
		)
 | 
			
		||||
		b.bitContainer >>= 6 << 3
 | 
			
		||||
	case 7:
 | 
			
		||||
		b.out = append(b.out,
 | 
			
		||||
			byte(b.bitContainer),
 | 
			
		||||
			byte(b.bitContainer>>8),
 | 
			
		||||
			byte(b.bitContainer>>16),
 | 
			
		||||
			byte(b.bitContainer>>24),
 | 
			
		||||
			byte(b.bitContainer>>32),
 | 
			
		||||
			byte(b.bitContainer>>40),
 | 
			
		||||
			byte(b.bitContainer>>48),
 | 
			
		||||
		)
 | 
			
		||||
		b.bitContainer >>= 7 << 3
 | 
			
		||||
	case 8:
 | 
			
		||||
		b.out = append(b.out,
 | 
			
		||||
			byte(b.bitContainer),
 | 
			
		||||
			byte(b.bitContainer>>8),
 | 
			
		||||
			byte(b.bitContainer>>16),
 | 
			
		||||
			byte(b.bitContainer>>24),
 | 
			
		||||
			byte(b.bitContainer>>32),
 | 
			
		||||
			byte(b.bitContainer>>40),
 | 
			
		||||
			byte(b.bitContainer>>48),
 | 
			
		||||
			byte(b.bitContainer>>56),
 | 
			
		||||
		)
 | 
			
		||||
		b.bitContainer = 0
 | 
			
		||||
		b.nBits = 0
 | 
			
		||||
		return
 | 
			
		||||
	default:
 | 
			
		||||
		panic(fmt.Errorf("bits (%d) > 64", b.nBits))
 | 
			
		||||
	}
 | 
			
		||||
	b.nBits &= 7
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// flush32 will flush out, so there are at least 32 bits available for writing.
 | 
			
		||||
func (b *bitWriter) flush32() {
 | 
			
		||||
	if b.nBits < 32 {
 | 
			
		||||
@@ -201,10 +93,3 @@ func (b *bitWriter) close() error {
 | 
			
		||||
	b.flushAlign()
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// reset and continue writing by appending to out.
 | 
			
		||||
func (b *bitWriter) reset(out []byte) {
 | 
			
		||||
	b.bitContainer = 0
 | 
			
		||||
	b.nBits = 0
 | 
			
		||||
	b.out = out
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								vendor/github.com/klauspost/compress/huff0/bytereader.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								vendor/github.com/klauspost/compress/huff0/bytereader.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -20,11 +20,6 @@ func (b *byteReader) init(in []byte) {
 | 
			
		||||
	b.off = 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// advance the stream b n bytes.
 | 
			
		||||
func (b *byteReader) advance(n uint) {
 | 
			
		||||
	b.off += int(n)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int32 returns a little endian int32 starting at current offset.
 | 
			
		||||
func (b byteReader) Int32() int32 {
 | 
			
		||||
	v3 := int32(b.b[b.off+3])
 | 
			
		||||
@@ -43,11 +38,6 @@ func (b byteReader) Uint32() uint32 {
 | 
			
		||||
	return (v3 << 24) | (v2 << 16) | (v1 << 8) | v0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// unread returns the unread portion of the input.
 | 
			
		||||
func (b byteReader) unread() []byte {
 | 
			
		||||
	return b.b[b.off:]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// remain will return the number of bytes remaining.
 | 
			
		||||
func (b byteReader) remain() int {
 | 
			
		||||
	return len(b.b) - b.off
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								vendor/github.com/klauspost/compress/huff0/compress.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/klauspost/compress/huff0/compress.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -404,6 +404,7 @@ func (s *Scratch) canUseTable(c cTable) bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//lint:ignore U1000 used for debugging
 | 
			
		||||
func (s *Scratch) validateTable(c cTable) bool {
 | 
			
		||||
	if len(c) < int(s.symbolLen) {
 | 
			
		||||
		return false
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										113
									
								
								vendor/github.com/klauspost/compress/huff0/decompress.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										113
									
								
								vendor/github.com/klauspost/compress/huff0/decompress.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -11,7 +11,6 @@ import (
 | 
			
		||||
 | 
			
		||||
type dTable struct {
 | 
			
		||||
	single []dEntrySingle
 | 
			
		||||
	double []dEntryDouble
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// single-symbols decoding
 | 
			
		||||
@@ -19,13 +18,6 @@ type dEntrySingle struct {
 | 
			
		||||
	entry uint16
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// double-symbols decoding
 | 
			
		||||
type dEntryDouble struct {
 | 
			
		||||
	seq   [4]byte
 | 
			
		||||
	nBits uint8
 | 
			
		||||
	len   uint8
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Uses special code for all tables that are < 8 bits.
 | 
			
		||||
const use8BitTables = true
 | 
			
		||||
 | 
			
		||||
@@ -35,7 +27,7 @@ const use8BitTables = true
 | 
			
		||||
// If no Scratch is provided a new one is allocated.
 | 
			
		||||
// The returned Scratch can be used for encoding or decoding input using this table.
 | 
			
		||||
func ReadTable(in []byte, s *Scratch) (s2 *Scratch, remain []byte, err error) {
 | 
			
		||||
	s, err = s.prepare(in)
 | 
			
		||||
	s, err = s.prepare(nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return s, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -236,108 +228,6 @@ func (d *Decoder) buffer() *[4][256]byte {
 | 
			
		||||
	return &[4][256]byte{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decompress1X will decompress a 1X encoded stream.
 | 
			
		||||
// The cap of the output buffer will be the maximum decompressed size.
 | 
			
		||||
// The length of the supplied input must match the end of a block exactly.
 | 
			
		||||
func (d *Decoder) Decompress1X(dst, src []byte) ([]byte, error) {
 | 
			
		||||
	if len(d.dt.single) == 0 {
 | 
			
		||||
		return nil, errors.New("no table loaded")
 | 
			
		||||
	}
 | 
			
		||||
	if use8BitTables && d.actualTableLog <= 8 {
 | 
			
		||||
		return d.decompress1X8Bit(dst, src)
 | 
			
		||||
	}
 | 
			
		||||
	var br bitReaderShifted
 | 
			
		||||
	err := br.init(src)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return dst, err
 | 
			
		||||
	}
 | 
			
		||||
	maxDecodedSize := cap(dst)
 | 
			
		||||
	dst = dst[:0]
 | 
			
		||||
 | 
			
		||||
	// Avoid bounds check by always having full sized table.
 | 
			
		||||
	const tlSize = 1 << tableLogMax
 | 
			
		||||
	const tlMask = tlSize - 1
 | 
			
		||||
	dt := d.dt.single[:tlSize]
 | 
			
		||||
 | 
			
		||||
	// Use temp table to avoid bound checks/append penalty.
 | 
			
		||||
	bufs := d.buffer()
 | 
			
		||||
	buf := &bufs[0]
 | 
			
		||||
	var off uint8
 | 
			
		||||
 | 
			
		||||
	for br.off >= 8 {
 | 
			
		||||
		br.fillFast()
 | 
			
		||||
		v := dt[br.peekBitsFast(d.actualTableLog)&tlMask]
 | 
			
		||||
		br.advance(uint8(v.entry))
 | 
			
		||||
		buf[off+0] = uint8(v.entry >> 8)
 | 
			
		||||
 | 
			
		||||
		v = dt[br.peekBitsFast(d.actualTableLog)&tlMask]
 | 
			
		||||
		br.advance(uint8(v.entry))
 | 
			
		||||
		buf[off+1] = uint8(v.entry >> 8)
 | 
			
		||||
 | 
			
		||||
		// Refill
 | 
			
		||||
		br.fillFast()
 | 
			
		||||
 | 
			
		||||
		v = dt[br.peekBitsFast(d.actualTableLog)&tlMask]
 | 
			
		||||
		br.advance(uint8(v.entry))
 | 
			
		||||
		buf[off+2] = uint8(v.entry >> 8)
 | 
			
		||||
 | 
			
		||||
		v = dt[br.peekBitsFast(d.actualTableLog)&tlMask]
 | 
			
		||||
		br.advance(uint8(v.entry))
 | 
			
		||||
		buf[off+3] = uint8(v.entry >> 8)
 | 
			
		||||
 | 
			
		||||
		off += 4
 | 
			
		||||
		if off == 0 {
 | 
			
		||||
			if len(dst)+256 > maxDecodedSize {
 | 
			
		||||
				br.close()
 | 
			
		||||
				d.bufs.Put(bufs)
 | 
			
		||||
				return nil, ErrMaxDecodedSizeExceeded
 | 
			
		||||
			}
 | 
			
		||||
			dst = append(dst, buf[:]...)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(dst)+int(off) > maxDecodedSize {
 | 
			
		||||
		d.bufs.Put(bufs)
 | 
			
		||||
		br.close()
 | 
			
		||||
		return nil, ErrMaxDecodedSizeExceeded
 | 
			
		||||
	}
 | 
			
		||||
	dst = append(dst, buf[:off]...)
 | 
			
		||||
 | 
			
		||||
	// br < 8, so uint8 is fine
 | 
			
		||||
	bitsLeft := uint8(br.off)*8 + 64 - br.bitsRead
 | 
			
		||||
	for bitsLeft > 0 {
 | 
			
		||||
		br.fill()
 | 
			
		||||
		if false && br.bitsRead >= 32 {
 | 
			
		||||
			if br.off >= 4 {
 | 
			
		||||
				v := br.in[br.off-4:]
 | 
			
		||||
				v = v[:4]
 | 
			
		||||
				low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24)
 | 
			
		||||
				br.value = (br.value << 32) | uint64(low)
 | 
			
		||||
				br.bitsRead -= 32
 | 
			
		||||
				br.off -= 4
 | 
			
		||||
			} else {
 | 
			
		||||
				for br.off > 0 {
 | 
			
		||||
					br.value = (br.value << 8) | uint64(br.in[br.off-1])
 | 
			
		||||
					br.bitsRead -= 8
 | 
			
		||||
					br.off--
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if len(dst) >= maxDecodedSize {
 | 
			
		||||
			d.bufs.Put(bufs)
 | 
			
		||||
			br.close()
 | 
			
		||||
			return nil, ErrMaxDecodedSizeExceeded
 | 
			
		||||
		}
 | 
			
		||||
		v := d.dt.single[br.peekBitsFast(d.actualTableLog)&tlMask]
 | 
			
		||||
		nBits := uint8(v.entry)
 | 
			
		||||
		br.advance(nBits)
 | 
			
		||||
		bitsLeft -= nBits
 | 
			
		||||
		dst = append(dst, uint8(v.entry>>8))
 | 
			
		||||
	}
 | 
			
		||||
	d.bufs.Put(bufs)
 | 
			
		||||
	return dst, br.close()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// decompress1X8Bit will decompress a 1X encoded stream with tablelog <= 8.
 | 
			
		||||
// The cap of the output buffer will be the maximum decompressed size.
 | 
			
		||||
// The length of the supplied input must match the end of a block exactly.
 | 
			
		||||
@@ -995,7 +885,6 @@ func (d *Decoder) decompress4X8bitExactly(dst, src []byte) ([]byte, error) {
 | 
			
		||||
 | 
			
		||||
	const shift = 56
 | 
			
		||||
	const tlSize = 1 << 8
 | 
			
		||||
	const tlMask = tlSize - 1
 | 
			
		||||
	single := d.dt.single[:tlSize]
 | 
			
		||||
 | 
			
		||||
	// Use temp table to avoid bound checks/append penalty.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										488
									
								
								vendor/github.com/klauspost/compress/huff0/decompress_8b_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										488
									
								
								vendor/github.com/klauspost/compress/huff0/decompress_8b_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,488 +0,0 @@
 | 
			
		||||
// +build !appengine
 | 
			
		||||
// +build gc
 | 
			
		||||
// +build !noasm
 | 
			
		||||
 | 
			
		||||
#include "textflag.h"
 | 
			
		||||
#include "funcdata.h"
 | 
			
		||||
#include "go_asm.h"
 | 
			
		||||
 | 
			
		||||
#define bufoff      256 // see decompress.go, we're using [4][256]byte table
 | 
			
		||||
 | 
			
		||||
// func decompress4x_main_loop_x86(pbr0, pbr1, pbr2, pbr3 *bitReaderShifted,
 | 
			
		||||
//	peekBits uint8, buf *byte, tbl *dEntrySingle) (int, bool)
 | 
			
		||||
TEXT ·decompress4x_8b_loop_x86(SB), NOSPLIT, $8
 | 
			
		||||
#define off             R8
 | 
			
		||||
#define buffer          DI
 | 
			
		||||
#define table           SI
 | 
			
		||||
 | 
			
		||||
#define br_bits_read    R9
 | 
			
		||||
#define br_value        R10
 | 
			
		||||
#define br_offset       R11
 | 
			
		||||
#define peek_bits       R12
 | 
			
		||||
#define exhausted       DX
 | 
			
		||||
 | 
			
		||||
#define br0             R13
 | 
			
		||||
#define br1             R14
 | 
			
		||||
#define br2             R15
 | 
			
		||||
#define br3             BP
 | 
			
		||||
 | 
			
		||||
	MOVQ BP, 0(SP)
 | 
			
		||||
 | 
			
		||||
	XORQ exhausted, exhausted // exhausted = false
 | 
			
		||||
	XORQ off, off             // off = 0
 | 
			
		||||
 | 
			
		||||
	MOVBQZX peekBits+32(FP), peek_bits
 | 
			
		||||
	MOVQ    buf+40(FP), buffer
 | 
			
		||||
	MOVQ    tbl+48(FP), table
 | 
			
		||||
 | 
			
		||||
	MOVQ pbr0+0(FP), br0
 | 
			
		||||
	MOVQ pbr1+8(FP), br1
 | 
			
		||||
	MOVQ pbr2+16(FP), br2
 | 
			
		||||
	MOVQ pbr3+24(FP), br3
 | 
			
		||||
 | 
			
		||||
main_loop:
 | 
			
		||||
 | 
			
		||||
	// const stream = 0
 | 
			
		||||
	// br0.fillFast()
 | 
			
		||||
	MOVBQZX bitReaderShifted_bitsRead(br0), br_bits_read
 | 
			
		||||
	MOVQ    bitReaderShifted_value(br0), br_value
 | 
			
		||||
	MOVQ    bitReaderShifted_off(br0), br_offset
 | 
			
		||||
 | 
			
		||||
	// if b.bitsRead >= 32 {
 | 
			
		||||
	CMPQ br_bits_read, $32
 | 
			
		||||
	JB   skip_fill0
 | 
			
		||||
 | 
			
		||||
	SUBQ $32, br_bits_read // b.bitsRead -= 32
 | 
			
		||||
	SUBQ $4, br_offset     // b.off -= 4
 | 
			
		||||
 | 
			
		||||
	// v := b.in[b.off-4 : b.off]
 | 
			
		||||
	// v = v[:4]
 | 
			
		||||
	// low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24)
 | 
			
		||||
	MOVQ bitReaderShifted_in(br0), AX
 | 
			
		||||
	MOVL 0(br_offset)(AX*1), AX       // AX = uint32(b.in[b.off:b.off+4])
 | 
			
		||||
 | 
			
		||||
	// b.value |= uint64(low) << (b.bitsRead & 63)
 | 
			
		||||
	MOVQ br_bits_read, CX
 | 
			
		||||
	SHLQ CL, AX
 | 
			
		||||
	ORQ  AX, br_value
 | 
			
		||||
 | 
			
		||||
	// exhausted = exhausted || (br0.off < 4)
 | 
			
		||||
	CMPQ  br_offset, $4
 | 
			
		||||
	SETLT DL
 | 
			
		||||
	ORB   DL, DH
 | 
			
		||||
 | 
			
		||||
	// }
 | 
			
		||||
skip_fill0:
 | 
			
		||||
 | 
			
		||||
	// val0 := br0.peekTopBits(peekBits)
 | 
			
		||||
	MOVQ br_value, AX
 | 
			
		||||
	MOVQ peek_bits, CX
 | 
			
		||||
	SHRQ CL, AX        // AX = (value >> peek_bits) & mask
 | 
			
		||||
 | 
			
		||||
	// v0 := table[val0&mask]
 | 
			
		||||
	MOVW 0(table)(AX*2), AX // AX - v0
 | 
			
		||||
 | 
			
		||||
	// br0.advance(uint8(v0.entry))
 | 
			
		||||
	MOVB    AH, BL           // BL = uint8(v0.entry >> 8)
 | 
			
		||||
	MOVBQZX AL, CX
 | 
			
		||||
	SHLQ    CL, br_value     // value <<= n
 | 
			
		||||
	ADDQ    CX, br_bits_read // bits_read += n
 | 
			
		||||
 | 
			
		||||
	// val1 := br0.peekTopBits(peekBits)
 | 
			
		||||
	MOVQ peek_bits, CX
 | 
			
		||||
	MOVQ br_value, AX
 | 
			
		||||
	SHRQ CL, AX        // AX = (value >> peek_bits) & mask
 | 
			
		||||
 | 
			
		||||
	// v1 := table[val1&mask]
 | 
			
		||||
	MOVW 0(table)(AX*2), AX // AX - v1
 | 
			
		||||
 | 
			
		||||
	// br0.advance(uint8(v1.entry))
 | 
			
		||||
	MOVB    AH, BH           // BH = uint8(v1.entry >> 8)
 | 
			
		||||
	MOVBQZX AL, CX
 | 
			
		||||
	SHLQ    CX, br_value     // value <<= n
 | 
			
		||||
	ADDQ    CX, br_bits_read // bits_read += n
 | 
			
		||||
 | 
			
		||||
	// these two writes get coalesced
 | 
			
		||||
	// buf[stream][off] = uint8(v0.entry >> 8)
 | 
			
		||||
	// buf[stream][off+1] = uint8(v1.entry >> 8)
 | 
			
		||||
	MOVW BX, 0(buffer)(off*1)
 | 
			
		||||
 | 
			
		||||
	// SECOND PART:
 | 
			
		||||
	// val2 := br0.peekTopBits(peekBits)
 | 
			
		||||
	MOVQ br_value, AX
 | 
			
		||||
	MOVQ peek_bits, CX
 | 
			
		||||
	SHRQ CL, AX        // AX = (value >> peek_bits) & mask
 | 
			
		||||
 | 
			
		||||
	// v2 := table[val0&mask]
 | 
			
		||||
	MOVW 0(table)(AX*2), AX // AX - v0
 | 
			
		||||
 | 
			
		||||
	// br0.advance(uint8(v0.entry))
 | 
			
		||||
	MOVB    AH, BL           // BL = uint8(v0.entry >> 8)
 | 
			
		||||
	MOVBQZX AL, CX
 | 
			
		||||
	SHLQ    CL, br_value     // value <<= n
 | 
			
		||||
	ADDQ    CX, br_bits_read // bits_read += n
 | 
			
		||||
 | 
			
		||||
	// val3 := br0.peekTopBits(peekBits)
 | 
			
		||||
	MOVQ peek_bits, CX
 | 
			
		||||
	MOVQ br_value, AX
 | 
			
		||||
	SHRQ CL, AX        // AX = (value >> peek_bits) & mask
 | 
			
		||||
 | 
			
		||||
	// v3 := table[val1&mask]
 | 
			
		||||
	MOVW 0(table)(AX*2), AX // AX - v1
 | 
			
		||||
 | 
			
		||||
	// br0.advance(uint8(v1.entry))
 | 
			
		||||
	MOVB    AH, BH           // BH = uint8(v1.entry >> 8)
 | 
			
		||||
	MOVBQZX AL, CX
 | 
			
		||||
	SHLQ    CX, br_value     // value <<= n
 | 
			
		||||
	ADDQ    CX, br_bits_read // bits_read += n
 | 
			
		||||
 | 
			
		||||
	// these two writes get coalesced
 | 
			
		||||
	// buf[stream][off+2] = uint8(v2.entry >> 8)
 | 
			
		||||
	// buf[stream][off+3] = uint8(v3.entry >> 8)
 | 
			
		||||
	MOVW BX, 0+2(buffer)(off*1)
 | 
			
		||||
 | 
			
		||||
	// update the bitrader reader structure
 | 
			
		||||
	MOVB br_bits_read, bitReaderShifted_bitsRead(br0)
 | 
			
		||||
	MOVQ br_value, bitReaderShifted_value(br0)
 | 
			
		||||
	MOVQ br_offset, bitReaderShifted_off(br0)
 | 
			
		||||
 | 
			
		||||
	// const stream = 1
 | 
			
		||||
	// br1.fillFast()
 | 
			
		||||
	MOVBQZX bitReaderShifted_bitsRead(br1), br_bits_read
 | 
			
		||||
	MOVQ    bitReaderShifted_value(br1), br_value
 | 
			
		||||
	MOVQ    bitReaderShifted_off(br1), br_offset
 | 
			
		||||
 | 
			
		||||
	// if b.bitsRead >= 32 {
 | 
			
		||||
	CMPQ br_bits_read, $32
 | 
			
		||||
	JB   skip_fill1
 | 
			
		||||
 | 
			
		||||
	SUBQ $32, br_bits_read // b.bitsRead -= 32
 | 
			
		||||
	SUBQ $4, br_offset     // b.off -= 4
 | 
			
		||||
 | 
			
		||||
	// v := b.in[b.off-4 : b.off]
 | 
			
		||||
	// v = v[:4]
 | 
			
		||||
	// low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24)
 | 
			
		||||
	MOVQ bitReaderShifted_in(br1), AX
 | 
			
		||||
	MOVL 0(br_offset)(AX*1), AX       // AX = uint32(b.in[b.off:b.off+4])
 | 
			
		||||
 | 
			
		||||
	// b.value |= uint64(low) << (b.bitsRead & 63)
 | 
			
		||||
	MOVQ br_bits_read, CX
 | 
			
		||||
	SHLQ CL, AX
 | 
			
		||||
	ORQ  AX, br_value
 | 
			
		||||
 | 
			
		||||
	// exhausted = exhausted || (br1.off < 4)
 | 
			
		||||
	CMPQ  br_offset, $4
 | 
			
		||||
	SETLT DL
 | 
			
		||||
	ORB   DL, DH
 | 
			
		||||
 | 
			
		||||
	// }
 | 
			
		||||
skip_fill1:
 | 
			
		||||
 | 
			
		||||
	// val0 := br1.peekTopBits(peekBits)
 | 
			
		||||
	MOVQ br_value, AX
 | 
			
		||||
	MOVQ peek_bits, CX
 | 
			
		||||
	SHRQ CL, AX        // AX = (value >> peek_bits) & mask
 | 
			
		||||
 | 
			
		||||
	// v0 := table[val0&mask]
 | 
			
		||||
	MOVW 0(table)(AX*2), AX // AX - v0
 | 
			
		||||
 | 
			
		||||
	// br1.advance(uint8(v0.entry))
 | 
			
		||||
	MOVB    AH, BL           // BL = uint8(v0.entry >> 8)
 | 
			
		||||
	MOVBQZX AL, CX
 | 
			
		||||
	SHLQ    CL, br_value     // value <<= n
 | 
			
		||||
	ADDQ    CX, br_bits_read // bits_read += n
 | 
			
		||||
 | 
			
		||||
	// val1 := br1.peekTopBits(peekBits)
 | 
			
		||||
	MOVQ peek_bits, CX
 | 
			
		||||
	MOVQ br_value, AX
 | 
			
		||||
	SHRQ CL, AX        // AX = (value >> peek_bits) & mask
 | 
			
		||||
 | 
			
		||||
	// v1 := table[val1&mask]
 | 
			
		||||
	MOVW 0(table)(AX*2), AX // AX - v1
 | 
			
		||||
 | 
			
		||||
	// br1.advance(uint8(v1.entry))
 | 
			
		||||
	MOVB    AH, BH           // BH = uint8(v1.entry >> 8)
 | 
			
		||||
	MOVBQZX AL, CX
 | 
			
		||||
	SHLQ    CX, br_value     // value <<= n
 | 
			
		||||
	ADDQ    CX, br_bits_read // bits_read += n
 | 
			
		||||
 | 
			
		||||
	// these two writes get coalesced
 | 
			
		||||
	// buf[stream][off] = uint8(v0.entry >> 8)
 | 
			
		||||
	// buf[stream][off+1] = uint8(v1.entry >> 8)
 | 
			
		||||
	MOVW BX, 256(buffer)(off*1)
 | 
			
		||||
 | 
			
		||||
	// SECOND PART:
 | 
			
		||||
	// val2 := br1.peekTopBits(peekBits)
 | 
			
		||||
	MOVQ br_value, AX
 | 
			
		||||
	MOVQ peek_bits, CX
 | 
			
		||||
	SHRQ CL, AX        // AX = (value >> peek_bits) & mask
 | 
			
		||||
 | 
			
		||||
	// v2 := table[val0&mask]
 | 
			
		||||
	MOVW 0(table)(AX*2), AX // AX - v0
 | 
			
		||||
 | 
			
		||||
	// br1.advance(uint8(v0.entry))
 | 
			
		||||
	MOVB    AH, BL           // BL = uint8(v0.entry >> 8)
 | 
			
		||||
	MOVBQZX AL, CX
 | 
			
		||||
	SHLQ    CL, br_value     // value <<= n
 | 
			
		||||
	ADDQ    CX, br_bits_read // bits_read += n
 | 
			
		||||
 | 
			
		||||
	// val3 := br1.peekTopBits(peekBits)
 | 
			
		||||
	MOVQ peek_bits, CX
 | 
			
		||||
	MOVQ br_value, AX
 | 
			
		||||
	SHRQ CL, AX        // AX = (value >> peek_bits) & mask
 | 
			
		||||
 | 
			
		||||
	// v3 := table[val1&mask]
 | 
			
		||||
	MOVW 0(table)(AX*2), AX // AX - v1
 | 
			
		||||
 | 
			
		||||
	// br1.advance(uint8(v1.entry))
 | 
			
		||||
	MOVB    AH, BH           // BH = uint8(v1.entry >> 8)
 | 
			
		||||
	MOVBQZX AL, CX
 | 
			
		||||
	SHLQ    CX, br_value     // value <<= n
 | 
			
		||||
	ADDQ    CX, br_bits_read // bits_read += n
 | 
			
		||||
 | 
			
		||||
	// these two writes get coalesced
 | 
			
		||||
	// buf[stream][off+2] = uint8(v2.entry >> 8)
 | 
			
		||||
	// buf[stream][off+3] = uint8(v3.entry >> 8)
 | 
			
		||||
	MOVW BX, 256+2(buffer)(off*1)
 | 
			
		||||
 | 
			
		||||
	// update the bitrader reader structure
 | 
			
		||||
	MOVB br_bits_read, bitReaderShifted_bitsRead(br1)
 | 
			
		||||
	MOVQ br_value, bitReaderShifted_value(br1)
 | 
			
		||||
	MOVQ br_offset, bitReaderShifted_off(br1)
 | 
			
		||||
 | 
			
		||||
	// const stream = 2
 | 
			
		||||
	// br2.fillFast()
 | 
			
		||||
	MOVBQZX bitReaderShifted_bitsRead(br2), br_bits_read
 | 
			
		||||
	MOVQ    bitReaderShifted_value(br2), br_value
 | 
			
		||||
	MOVQ    bitReaderShifted_off(br2), br_offset
 | 
			
		||||
 | 
			
		||||
	// if b.bitsRead >= 32 {
 | 
			
		||||
	CMPQ br_bits_read, $32
 | 
			
		||||
	JB   skip_fill2
 | 
			
		||||
 | 
			
		||||
	SUBQ $32, br_bits_read // b.bitsRead -= 32
 | 
			
		||||
	SUBQ $4, br_offset     // b.off -= 4
 | 
			
		||||
 | 
			
		||||
	// v := b.in[b.off-4 : b.off]
 | 
			
		||||
	// v = v[:4]
 | 
			
		||||
	// low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24)
 | 
			
		||||
	MOVQ bitReaderShifted_in(br2), AX
 | 
			
		||||
	MOVL 0(br_offset)(AX*1), AX       // AX = uint32(b.in[b.off:b.off+4])
 | 
			
		||||
 | 
			
		||||
	// b.value |= uint64(low) << (b.bitsRead & 63)
 | 
			
		||||
	MOVQ br_bits_read, CX
 | 
			
		||||
	SHLQ CL, AX
 | 
			
		||||
	ORQ  AX, br_value
 | 
			
		||||
 | 
			
		||||
	// exhausted = exhausted || (br2.off < 4)
 | 
			
		||||
	CMPQ  br_offset, $4
 | 
			
		||||
	SETLT DL
 | 
			
		||||
	ORB   DL, DH
 | 
			
		||||
 | 
			
		||||
	// }
 | 
			
		||||
skip_fill2:
 | 
			
		||||
 | 
			
		||||
	// val0 := br2.peekTopBits(peekBits)
 | 
			
		||||
	MOVQ br_value, AX
 | 
			
		||||
	MOVQ peek_bits, CX
 | 
			
		||||
	SHRQ CL, AX        // AX = (value >> peek_bits) & mask
 | 
			
		||||
 | 
			
		||||
	// v0 := table[val0&mask]
 | 
			
		||||
	MOVW 0(table)(AX*2), AX // AX - v0
 | 
			
		||||
 | 
			
		||||
	// br2.advance(uint8(v0.entry))
 | 
			
		||||
	MOVB    AH, BL           // BL = uint8(v0.entry >> 8)
 | 
			
		||||
	MOVBQZX AL, CX
 | 
			
		||||
	SHLQ    CL, br_value     // value <<= n
 | 
			
		||||
	ADDQ    CX, br_bits_read // bits_read += n
 | 
			
		||||
 | 
			
		||||
	// val1 := br2.peekTopBits(peekBits)
 | 
			
		||||
	MOVQ peek_bits, CX
 | 
			
		||||
	MOVQ br_value, AX
 | 
			
		||||
	SHRQ CL, AX        // AX = (value >> peek_bits) & mask
 | 
			
		||||
 | 
			
		||||
	// v1 := table[val1&mask]
 | 
			
		||||
	MOVW 0(table)(AX*2), AX // AX - v1
 | 
			
		||||
 | 
			
		||||
	// br2.advance(uint8(v1.entry))
 | 
			
		||||
	MOVB    AH, BH           // BH = uint8(v1.entry >> 8)
 | 
			
		||||
	MOVBQZX AL, CX
 | 
			
		||||
	SHLQ    CX, br_value     // value <<= n
 | 
			
		||||
	ADDQ    CX, br_bits_read // bits_read += n
 | 
			
		||||
 | 
			
		||||
	// these two writes get coalesced
 | 
			
		||||
	// buf[stream][off] = uint8(v0.entry >> 8)
 | 
			
		||||
	// buf[stream][off+1] = uint8(v1.entry >> 8)
 | 
			
		||||
	MOVW BX, 512(buffer)(off*1)
 | 
			
		||||
 | 
			
		||||
	// SECOND PART:
 | 
			
		||||
	// val2 := br2.peekTopBits(peekBits)
 | 
			
		||||
	MOVQ br_value, AX
 | 
			
		||||
	MOVQ peek_bits, CX
 | 
			
		||||
	SHRQ CL, AX        // AX = (value >> peek_bits) & mask
 | 
			
		||||
 | 
			
		||||
	// v2 := table[val0&mask]
 | 
			
		||||
	MOVW 0(table)(AX*2), AX // AX - v0
 | 
			
		||||
 | 
			
		||||
	// br2.advance(uint8(v0.entry))
 | 
			
		||||
	MOVB    AH, BL           // BL = uint8(v0.entry >> 8)
 | 
			
		||||
	MOVBQZX AL, CX
 | 
			
		||||
	SHLQ    CL, br_value     // value <<= n
 | 
			
		||||
	ADDQ    CX, br_bits_read // bits_read += n
 | 
			
		||||
 | 
			
		||||
	// val3 := br2.peekTopBits(peekBits)
 | 
			
		||||
	MOVQ peek_bits, CX
 | 
			
		||||
	MOVQ br_value, AX
 | 
			
		||||
	SHRQ CL, AX        // AX = (value >> peek_bits) & mask
 | 
			
		||||
 | 
			
		||||
	// v3 := table[val1&mask]
 | 
			
		||||
	MOVW 0(table)(AX*2), AX // AX - v1
 | 
			
		||||
 | 
			
		||||
	// br2.advance(uint8(v1.entry))
 | 
			
		||||
	MOVB    AH, BH           // BH = uint8(v1.entry >> 8)
 | 
			
		||||
	MOVBQZX AL, CX
 | 
			
		||||
	SHLQ    CX, br_value     // value <<= n
 | 
			
		||||
	ADDQ    CX, br_bits_read // bits_read += n
 | 
			
		||||
 | 
			
		||||
	// these two writes get coalesced
 | 
			
		||||
	// buf[stream][off+2] = uint8(v2.entry >> 8)
 | 
			
		||||
	// buf[stream][off+3] = uint8(v3.entry >> 8)
 | 
			
		||||
	MOVW BX, 512+2(buffer)(off*1)
 | 
			
		||||
 | 
			
		||||
	// update the bitrader reader structure
 | 
			
		||||
	MOVB br_bits_read, bitReaderShifted_bitsRead(br2)
 | 
			
		||||
	MOVQ br_value, bitReaderShifted_value(br2)
 | 
			
		||||
	MOVQ br_offset, bitReaderShifted_off(br2)
 | 
			
		||||
 | 
			
		||||
	// const stream = 3
 | 
			
		||||
	// br3.fillFast()
 | 
			
		||||
	MOVBQZX bitReaderShifted_bitsRead(br3), br_bits_read
 | 
			
		||||
	MOVQ    bitReaderShifted_value(br3), br_value
 | 
			
		||||
	MOVQ    bitReaderShifted_off(br3), br_offset
 | 
			
		||||
 | 
			
		||||
	// if b.bitsRead >= 32 {
 | 
			
		||||
	CMPQ br_bits_read, $32
 | 
			
		||||
	JB   skip_fill3
 | 
			
		||||
 | 
			
		||||
	SUBQ $32, br_bits_read // b.bitsRead -= 32
 | 
			
		||||
	SUBQ $4, br_offset     // b.off -= 4
 | 
			
		||||
 | 
			
		||||
	// v := b.in[b.off-4 : b.off]
 | 
			
		||||
	// v = v[:4]
 | 
			
		||||
	// low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24)
 | 
			
		||||
	MOVQ bitReaderShifted_in(br3), AX
 | 
			
		||||
	MOVL 0(br_offset)(AX*1), AX       // AX = uint32(b.in[b.off:b.off+4])
 | 
			
		||||
 | 
			
		||||
	// b.value |= uint64(low) << (b.bitsRead & 63)
 | 
			
		||||
	MOVQ br_bits_read, CX
 | 
			
		||||
	SHLQ CL, AX
 | 
			
		||||
	ORQ  AX, br_value
 | 
			
		||||
 | 
			
		||||
	// exhausted = exhausted || (br3.off < 4)
 | 
			
		||||
	CMPQ  br_offset, $4
 | 
			
		||||
	SETLT DL
 | 
			
		||||
	ORB   DL, DH
 | 
			
		||||
 | 
			
		||||
	// }
 | 
			
		||||
skip_fill3:
 | 
			
		||||
 | 
			
		||||
	// val0 := br3.peekTopBits(peekBits)
 | 
			
		||||
	MOVQ br_value, AX
 | 
			
		||||
	MOVQ peek_bits, CX
 | 
			
		||||
	SHRQ CL, AX        // AX = (value >> peek_bits) & mask
 | 
			
		||||
 | 
			
		||||
	// v0 := table[val0&mask]
 | 
			
		||||
	MOVW 0(table)(AX*2), AX // AX - v0
 | 
			
		||||
 | 
			
		||||
	// br3.advance(uint8(v0.entry))
 | 
			
		||||
	MOVB    AH, BL           // BL = uint8(v0.entry >> 8)
 | 
			
		||||
	MOVBQZX AL, CX
 | 
			
		||||
	SHLQ    CL, br_value     // value <<= n
 | 
			
		||||
	ADDQ    CX, br_bits_read // bits_read += n
 | 
			
		||||
 | 
			
		||||
	// val1 := br3.peekTopBits(peekBits)
 | 
			
		||||
	MOVQ peek_bits, CX
 | 
			
		||||
	MOVQ br_value, AX
 | 
			
		||||
	SHRQ CL, AX        // AX = (value >> peek_bits) & mask
 | 
			
		||||
 | 
			
		||||
	// v1 := table[val1&mask]
 | 
			
		||||
	MOVW 0(table)(AX*2), AX // AX - v1
 | 
			
		||||
 | 
			
		||||
	// br3.advance(uint8(v1.entry))
 | 
			
		||||
	MOVB    AH, BH           // BH = uint8(v1.entry >> 8)
 | 
			
		||||
	MOVBQZX AL, CX
 | 
			
		||||
	SHLQ    CX, br_value     // value <<= n
 | 
			
		||||
	ADDQ    CX, br_bits_read // bits_read += n
 | 
			
		||||
 | 
			
		||||
	// these two writes get coalesced
 | 
			
		||||
	// buf[stream][off] = uint8(v0.entry >> 8)
 | 
			
		||||
	// buf[stream][off+1] = uint8(v1.entry >> 8)
 | 
			
		||||
	MOVW BX, 768(buffer)(off*1)
 | 
			
		||||
 | 
			
		||||
	// SECOND PART:
 | 
			
		||||
	// val2 := br3.peekTopBits(peekBits)
 | 
			
		||||
	MOVQ br_value, AX
 | 
			
		||||
	MOVQ peek_bits, CX
 | 
			
		||||
	SHRQ CL, AX        // AX = (value >> peek_bits) & mask
 | 
			
		||||
 | 
			
		||||
	// v2 := table[val0&mask]
 | 
			
		||||
	MOVW 0(table)(AX*2), AX // AX - v0
 | 
			
		||||
 | 
			
		||||
	// br3.advance(uint8(v0.entry))
 | 
			
		||||
	MOVB    AH, BL           // BL = uint8(v0.entry >> 8)
 | 
			
		||||
	MOVBQZX AL, CX
 | 
			
		||||
	SHLQ    CL, br_value     // value <<= n
 | 
			
		||||
	ADDQ    CX, br_bits_read // bits_read += n
 | 
			
		||||
 | 
			
		||||
	// val3 := br3.peekTopBits(peekBits)
 | 
			
		||||
	MOVQ peek_bits, CX
 | 
			
		||||
	MOVQ br_value, AX
 | 
			
		||||
	SHRQ CL, AX        // AX = (value >> peek_bits) & mask
 | 
			
		||||
 | 
			
		||||
	// v3 := table[val1&mask]
 | 
			
		||||
	MOVW 0(table)(AX*2), AX // AX - v1
 | 
			
		||||
 | 
			
		||||
	// br3.advance(uint8(v1.entry))
 | 
			
		||||
	MOVB    AH, BH           // BH = uint8(v1.entry >> 8)
 | 
			
		||||
	MOVBQZX AL, CX
 | 
			
		||||
	SHLQ    CX, br_value     // value <<= n
 | 
			
		||||
	ADDQ    CX, br_bits_read // bits_read += n
 | 
			
		||||
 | 
			
		||||
	// these two writes get coalesced
 | 
			
		||||
	// buf[stream][off+2] = uint8(v2.entry >> 8)
 | 
			
		||||
	// buf[stream][off+3] = uint8(v3.entry >> 8)
 | 
			
		||||
	MOVW BX, 768+2(buffer)(off*1)
 | 
			
		||||
 | 
			
		||||
	// update the bitrader reader structure
 | 
			
		||||
	MOVB br_bits_read, bitReaderShifted_bitsRead(br3)
 | 
			
		||||
	MOVQ br_value, bitReaderShifted_value(br3)
 | 
			
		||||
	MOVQ br_offset, bitReaderShifted_off(br3)
 | 
			
		||||
 | 
			
		||||
	ADDQ $4, off // off += 2
 | 
			
		||||
 | 
			
		||||
	TESTB DH, DH // any br[i].ofs < 4?
 | 
			
		||||
	JNZ   end
 | 
			
		||||
 | 
			
		||||
	CMPQ off, $bufoff
 | 
			
		||||
	JL   main_loop
 | 
			
		||||
 | 
			
		||||
end:
 | 
			
		||||
	MOVQ 0(SP), BP
 | 
			
		||||
 | 
			
		||||
	MOVB off, ret+56(FP)
 | 
			
		||||
	RET
 | 
			
		||||
 | 
			
		||||
#undef off
 | 
			
		||||
#undef buffer
 | 
			
		||||
#undef table
 | 
			
		||||
 | 
			
		||||
#undef br_bits_read
 | 
			
		||||
#undef br_value
 | 
			
		||||
#undef br_offset
 | 
			
		||||
#undef peek_bits
 | 
			
		||||
#undef exhausted
 | 
			
		||||
 | 
			
		||||
#undef br0
 | 
			
		||||
#undef br1
 | 
			
		||||
#undef br2
 | 
			
		||||
#undef br3
 | 
			
		||||
							
								
								
									
										197
									
								
								vendor/github.com/klauspost/compress/huff0/decompress_8b_amd64.s.in
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										197
									
								
								vendor/github.com/klauspost/compress/huff0/decompress_8b_amd64.s.in
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,197 +0,0 @@
 | 
			
		||||
// +build !appengine
 | 
			
		||||
// +build gc
 | 
			
		||||
// +build !noasm
 | 
			
		||||
 | 
			
		||||
#include "textflag.h"
 | 
			
		||||
#include "funcdata.h"
 | 
			
		||||
#include "go_asm.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define bufoff      256     // see decompress.go, we're using [4][256]byte table
 | 
			
		||||
 | 
			
		||||
//func decompress4x_main_loop_x86(pbr0, pbr1, pbr2, pbr3 *bitReaderShifted,
 | 
			
		||||
//	peekBits uint8, buf *byte, tbl *dEntrySingle) (int, bool)
 | 
			
		||||
TEXT ·decompress4x_8b_loop_x86(SB), NOSPLIT, $8
 | 
			
		||||
#define off             R8
 | 
			
		||||
#define buffer          DI
 | 
			
		||||
#define table           SI
 | 
			
		||||
 | 
			
		||||
#define br_bits_read    R9
 | 
			
		||||
#define br_value        R10
 | 
			
		||||
#define br_offset       R11
 | 
			
		||||
#define peek_bits       R12
 | 
			
		||||
#define exhausted       DX
 | 
			
		||||
 | 
			
		||||
#define br0             R13
 | 
			
		||||
#define br1             R14
 | 
			
		||||
#define br2             R15
 | 
			
		||||
#define br3             BP
 | 
			
		||||
 | 
			
		||||
    MOVQ    BP, 0(SP)
 | 
			
		||||
 | 
			
		||||
    XORQ    exhausted, exhausted    // exhausted = false
 | 
			
		||||
    XORQ    off, off                // off = 0
 | 
			
		||||
 | 
			
		||||
    MOVBQZX peekBits+32(FP), peek_bits
 | 
			
		||||
    MOVQ    buf+40(FP), buffer
 | 
			
		||||
    MOVQ    tbl+48(FP), table
 | 
			
		||||
 | 
			
		||||
    MOVQ    pbr0+0(FP), br0
 | 
			
		||||
    MOVQ    pbr1+8(FP), br1
 | 
			
		||||
    MOVQ    pbr2+16(FP), br2
 | 
			
		||||
    MOVQ    pbr3+24(FP), br3
 | 
			
		||||
 | 
			
		||||
main_loop:
 | 
			
		||||
{{ define "decode_2_values_x86" }}
 | 
			
		||||
    // const stream = {{ var "id" }}
 | 
			
		||||
    // br{{ var "id"}}.fillFast()
 | 
			
		||||
    MOVBQZX bitReaderShifted_bitsRead(br{{ var "id" }}), br_bits_read
 | 
			
		||||
    MOVQ    bitReaderShifted_value(br{{ var "id" }}), br_value
 | 
			
		||||
    MOVQ    bitReaderShifted_off(br{{ var "id" }}), br_offset
 | 
			
		||||
 | 
			
		||||
	// if b.bitsRead >= 32 {
 | 
			
		||||
    CMPQ    br_bits_read, $32
 | 
			
		||||
    JB      skip_fill{{ var "id" }}
 | 
			
		||||
 | 
			
		||||
    SUBQ    $32, br_bits_read       // b.bitsRead -= 32
 | 
			
		||||
    SUBQ    $4, br_offset           // b.off -= 4
 | 
			
		||||
 | 
			
		||||
	// v := b.in[b.off-4 : b.off]
 | 
			
		||||
	// v = v[:4]
 | 
			
		||||
	// low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24)
 | 
			
		||||
    MOVQ    bitReaderShifted_in(br{{ var "id" }}), AX
 | 
			
		||||
    MOVL    0(br_offset)(AX*1), AX  // AX = uint32(b.in[b.off:b.off+4])
 | 
			
		||||
 | 
			
		||||
	// b.value |= uint64(low) << (b.bitsRead & 63)
 | 
			
		||||
    MOVQ    br_bits_read, CX
 | 
			
		||||
    SHLQ    CL, AX
 | 
			
		||||
    ORQ     AX, br_value
 | 
			
		||||
 | 
			
		||||
    // exhausted = exhausted || (br{{ var "id"}}.off < 4)
 | 
			
		||||
    CMPQ    br_offset, $4
 | 
			
		||||
    SETLT   DL
 | 
			
		||||
    ORB     DL, DH
 | 
			
		||||
    // }
 | 
			
		||||
skip_fill{{ var "id" }}:
 | 
			
		||||
 | 
			
		||||
    // val0 := br{{ var "id"}}.peekTopBits(peekBits)
 | 
			
		||||
    MOVQ    br_value, AX
 | 
			
		||||
    MOVQ    peek_bits, CX
 | 
			
		||||
    SHRQ    CL, AX                  // AX = (value >> peek_bits) & mask
 | 
			
		||||
 | 
			
		||||
    // v0 := table[val0&mask]
 | 
			
		||||
    MOVW    0(table)(AX*2), AX      // AX - v0
 | 
			
		||||
 | 
			
		||||
    // br{{ var "id"}}.advance(uint8(v0.entry))
 | 
			
		||||
    MOVB    AH, BL                  // BL = uint8(v0.entry >> 8)
 | 
			
		||||
    MOVBQZX AL, CX
 | 
			
		||||
    SHLQ    CL, br_value            // value <<= n
 | 
			
		||||
    ADDQ    CX, br_bits_read        // bits_read += n
 | 
			
		||||
 | 
			
		||||
    // val1 := br{{ var "id"}}.peekTopBits(peekBits)
 | 
			
		||||
    MOVQ    peek_bits, CX
 | 
			
		||||
    MOVQ    br_value, AX
 | 
			
		||||
    SHRQ    CL, AX                  // AX = (value >> peek_bits) & mask
 | 
			
		||||
 | 
			
		||||
    // v1 := table[val1&mask]
 | 
			
		||||
    MOVW    0(table)(AX*2), AX      // AX - v1
 | 
			
		||||
 | 
			
		||||
    // br{{ var "id"}}.advance(uint8(v1.entry))
 | 
			
		||||
    MOVB    AH, BH                  // BH = uint8(v1.entry >> 8)
 | 
			
		||||
    MOVBQZX AL, CX
 | 
			
		||||
    SHLQ    CX, br_value            // value <<= n
 | 
			
		||||
    ADDQ    CX, br_bits_read        // bits_read += n
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // these two writes get coalesced
 | 
			
		||||
    // buf[stream][off] = uint8(v0.entry >> 8)
 | 
			
		||||
    // buf[stream][off+1] = uint8(v1.entry >> 8)
 | 
			
		||||
    MOVW    BX, {{ var "bufofs" }}(buffer)(off*1)
 | 
			
		||||
 | 
			
		||||
    // SECOND PART:
 | 
			
		||||
    // val2 := br{{ var "id"}}.peekTopBits(peekBits)
 | 
			
		||||
    MOVQ    br_value, AX
 | 
			
		||||
    MOVQ    peek_bits, CX
 | 
			
		||||
    SHRQ    CL, AX                  // AX = (value >> peek_bits) & mask
 | 
			
		||||
 | 
			
		||||
    // v2 := table[val0&mask]
 | 
			
		||||
    MOVW    0(table)(AX*2), AX      // AX - v0
 | 
			
		||||
 | 
			
		||||
    // br{{ var "id"}}.advance(uint8(v0.entry))
 | 
			
		||||
    MOVB    AH, BL                  // BL = uint8(v0.entry >> 8)
 | 
			
		||||
    MOVBQZX AL, CX
 | 
			
		||||
    SHLQ    CL, br_value            // value <<= n
 | 
			
		||||
    ADDQ    CX, br_bits_read        // bits_read += n
 | 
			
		||||
 | 
			
		||||
    // val3 := br{{ var "id"}}.peekTopBits(peekBits)
 | 
			
		||||
    MOVQ    peek_bits, CX
 | 
			
		||||
    MOVQ    br_value, AX
 | 
			
		||||
    SHRQ    CL, AX                  // AX = (value >> peek_bits) & mask
 | 
			
		||||
 | 
			
		||||
    // v3 := table[val1&mask]
 | 
			
		||||
    MOVW    0(table)(AX*2), AX      // AX - v1
 | 
			
		||||
 | 
			
		||||
    // br{{ var "id"}}.advance(uint8(v1.entry))
 | 
			
		||||
    MOVB    AH, BH                  // BH = uint8(v1.entry >> 8)
 | 
			
		||||
    MOVBQZX AL, CX
 | 
			
		||||
    SHLQ    CX, br_value            // value <<= n
 | 
			
		||||
    ADDQ    CX, br_bits_read        // bits_read += n
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // these two writes get coalesced
 | 
			
		||||
    // buf[stream][off+2] = uint8(v2.entry >> 8)
 | 
			
		||||
    // buf[stream][off+3] = uint8(v3.entry >> 8)
 | 
			
		||||
    MOVW    BX, {{ var "bufofs" }}+2(buffer)(off*1)
 | 
			
		||||
 | 
			
		||||
    // update the bitrader reader structure
 | 
			
		||||
    MOVB    br_bits_read, bitReaderShifted_bitsRead(br{{ var "id" }})
 | 
			
		||||
    MOVQ    br_value, bitReaderShifted_value(br{{ var "id" }})
 | 
			
		||||
    MOVQ    br_offset, bitReaderShifted_off(br{{ var "id" }})
 | 
			
		||||
{{ end }}
 | 
			
		||||
 | 
			
		||||
    {{ set "id" "0" }}
 | 
			
		||||
    {{ set "ofs" "0" }}
 | 
			
		||||
    {{ set "bufofs" "0" }} {{/* id * bufoff */}}
 | 
			
		||||
    {{ template "decode_2_values_x86" . }}
 | 
			
		||||
 | 
			
		||||
    {{ set "id" "1" }}
 | 
			
		||||
    {{ set "ofs" "8" }}
 | 
			
		||||
    {{ set "bufofs" "256" }}
 | 
			
		||||
    {{ template "decode_2_values_x86" . }}
 | 
			
		||||
 | 
			
		||||
    {{ set "id" "2" }}
 | 
			
		||||
    {{ set "ofs" "16" }}
 | 
			
		||||
    {{ set "bufofs" "512" }}
 | 
			
		||||
    {{ template "decode_2_values_x86" . }}
 | 
			
		||||
 | 
			
		||||
    {{ set "id" "3" }}
 | 
			
		||||
    {{ set "ofs" "24" }}
 | 
			
		||||
    {{ set "bufofs" "768" }}
 | 
			
		||||
    {{ template "decode_2_values_x86" . }}
 | 
			
		||||
 | 
			
		||||
    ADDQ    $4, off     // off += 2
 | 
			
		||||
 | 
			
		||||
    TESTB   DH, DH      // any br[i].ofs < 4?
 | 
			
		||||
    JNZ     end
 | 
			
		||||
 | 
			
		||||
    CMPQ    off, $bufoff
 | 
			
		||||
    JL      main_loop
 | 
			
		||||
end:
 | 
			
		||||
    MOVQ    0(SP), BP
 | 
			
		||||
 | 
			
		||||
    MOVB    off, ret+56(FP)
 | 
			
		||||
    RET
 | 
			
		||||
#undef  off
 | 
			
		||||
#undef  buffer
 | 
			
		||||
#undef  table
 | 
			
		||||
 | 
			
		||||
#undef  br_bits_read
 | 
			
		||||
#undef  br_value
 | 
			
		||||
#undef  br_offset
 | 
			
		||||
#undef  peek_bits
 | 
			
		||||
#undef  exhausted
 | 
			
		||||
 | 
			
		||||
#undef  br0
 | 
			
		||||
#undef  br1
 | 
			
		||||
#undef  br2
 | 
			
		||||
#undef  br3
 | 
			
		||||
							
								
								
									
										181
									
								
								vendor/github.com/klauspost/compress/huff0/decompress_amd64.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										181
									
								
								vendor/github.com/klauspost/compress/huff0/decompress_amd64.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -2,30 +2,43 @@
 | 
			
		||||
// +build amd64,!appengine,!noasm,gc
 | 
			
		||||
 | 
			
		||||
// This file contains the specialisation of Decoder.Decompress4X
 | 
			
		||||
// that uses an asm implementation of its main loop.
 | 
			
		||||
// and Decoder.Decompress1X that use an asm implementation of thir main loops.
 | 
			
		||||
package huff0
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/klauspost/compress/internal/cpuinfo"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// decompress4x_main_loop_x86 is an x86 assembler implementation
 | 
			
		||||
// of Decompress4X when tablelog > 8.
 | 
			
		||||
// go:noescape
 | 
			
		||||
func decompress4x_main_loop_x86(pbr0, pbr1, pbr2, pbr3 *bitReaderShifted,
 | 
			
		||||
	peekBits uint8, buf *byte, tbl *dEntrySingle) uint8
 | 
			
		||||
//go:noescape
 | 
			
		||||
func decompress4x_main_loop_amd64(ctx *decompress4xContext)
 | 
			
		||||
 | 
			
		||||
// decompress4x_8b_loop_x86 is an x86 assembler implementation
 | 
			
		||||
// of Decompress4X when tablelog <= 8 which decodes 4 entries
 | 
			
		||||
// per loop.
 | 
			
		||||
// go:noescape
 | 
			
		||||
func decompress4x_8b_loop_x86(pbr0, pbr1, pbr2, pbr3 *bitReaderShifted,
 | 
			
		||||
	peekBits uint8, buf *byte, tbl *dEntrySingle) uint8
 | 
			
		||||
//go:noescape
 | 
			
		||||
func decompress4x_8b_main_loop_amd64(ctx *decompress4xContext)
 | 
			
		||||
 | 
			
		||||
// fallback8BitSize is the size where using Go version is faster.
 | 
			
		||||
const fallback8BitSize = 800
 | 
			
		||||
 | 
			
		||||
type decompress4xContext struct {
 | 
			
		||||
	pbr0     *bitReaderShifted
 | 
			
		||||
	pbr1     *bitReaderShifted
 | 
			
		||||
	pbr2     *bitReaderShifted
 | 
			
		||||
	pbr3     *bitReaderShifted
 | 
			
		||||
	peekBits uint8
 | 
			
		||||
	out      *byte
 | 
			
		||||
	dstEvery int
 | 
			
		||||
	tbl      *dEntrySingle
 | 
			
		||||
	decoded  int
 | 
			
		||||
	limit    *byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decompress4X will decompress a 4X encoded stream.
 | 
			
		||||
// The length of the supplied input must match the end of a block exactly.
 | 
			
		||||
// The *capacity* of the dst slice must match the destination size of
 | 
			
		||||
@@ -42,6 +55,7 @@ func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) {
 | 
			
		||||
	if cap(dst) < fallback8BitSize && use8BitTables {
 | 
			
		||||
		return d.decompress4X8bit(dst, src)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var br [4]bitReaderShifted
 | 
			
		||||
	// Decode "jump table"
 | 
			
		||||
	start := 6
 | 
			
		||||
@@ -71,70 +85,28 @@ func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) {
 | 
			
		||||
	const tlMask = tlSize - 1
 | 
			
		||||
	single := d.dt.single[:tlSize]
 | 
			
		||||
 | 
			
		||||
	// Use temp table to avoid bound checks/append penalty.
 | 
			
		||||
	buf := d.buffer()
 | 
			
		||||
	var off uint8
 | 
			
		||||
	var decoded int
 | 
			
		||||
 | 
			
		||||
	const debug = false
 | 
			
		||||
 | 
			
		||||
	// see: bitReaderShifted.peekBitsFast()
 | 
			
		||||
	peekBits := uint8((64 - d.actualTableLog) & 63)
 | 
			
		||||
 | 
			
		||||
	// Decode 2 values from each decoder/loop.
 | 
			
		||||
	const bufoff = 256
 | 
			
		||||
	for {
 | 
			
		||||
		if br[0].off < 4 || br[1].off < 4 || br[2].off < 4 || br[3].off < 4 {
 | 
			
		||||
			break
 | 
			
		||||
	if len(out) > 4*4 && !(br[0].off < 4 || br[1].off < 4 || br[2].off < 4 || br[3].off < 4) {
 | 
			
		||||
		ctx := decompress4xContext{
 | 
			
		||||
			pbr0:     &br[0],
 | 
			
		||||
			pbr1:     &br[1],
 | 
			
		||||
			pbr2:     &br[2],
 | 
			
		||||
			pbr3:     &br[3],
 | 
			
		||||
			peekBits: uint8((64 - d.actualTableLog) & 63), // see: bitReaderShifted.peekBitsFast()
 | 
			
		||||
			out:      &out[0],
 | 
			
		||||
			dstEvery: dstEvery,
 | 
			
		||||
			tbl:      &single[0],
 | 
			
		||||
			limit:    &out[dstEvery-4], // Always stop decoding when first buffer gets here to avoid writing OOB on last.
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if use8BitTables {
 | 
			
		||||
			off = decompress4x_8b_loop_x86(&br[0], &br[1], &br[2], &br[3], peekBits, &buf[0][0], &single[0])
 | 
			
		||||
			decompress4x_8b_main_loop_amd64(&ctx)
 | 
			
		||||
		} else {
 | 
			
		||||
			off = decompress4x_main_loop_x86(&br[0], &br[1], &br[2], &br[3], peekBits, &buf[0][0], &single[0])
 | 
			
		||||
		}
 | 
			
		||||
		if debug {
 | 
			
		||||
			fmt.Print("DEBUG: ")
 | 
			
		||||
			fmt.Printf("off=%d,", off)
 | 
			
		||||
			for i := 0; i < 4; i++ {
 | 
			
		||||
				fmt.Printf(" br[%d]={bitsRead=%d, value=%x, off=%d}",
 | 
			
		||||
					i, br[i].bitsRead, br[i].value, br[i].off)
 | 
			
		||||
			}
 | 
			
		||||
			fmt.Println("")
 | 
			
		||||
			decompress4x_main_loop_amd64(&ctx)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if off != 0 {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if bufoff > dstEvery {
 | 
			
		||||
			d.bufs.Put(buf)
 | 
			
		||||
			return nil, errors.New("corruption detected: stream overrun 1")
 | 
			
		||||
		}
 | 
			
		||||
		copy(out, buf[0][:])
 | 
			
		||||
		copy(out[dstEvery:], buf[1][:])
 | 
			
		||||
		copy(out[dstEvery*2:], buf[2][:])
 | 
			
		||||
		copy(out[dstEvery*3:], buf[3][:])
 | 
			
		||||
		out = out[bufoff:]
 | 
			
		||||
		decoded += bufoff * 4
 | 
			
		||||
		// There must at least be 3 buffers left.
 | 
			
		||||
		if len(out) < dstEvery*3 {
 | 
			
		||||
			d.bufs.Put(buf)
 | 
			
		||||
			return nil, errors.New("corruption detected: stream overrun 2")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if off > 0 {
 | 
			
		||||
		ioff := int(off)
 | 
			
		||||
		if len(out) < dstEvery*3+ioff {
 | 
			
		||||
			d.bufs.Put(buf)
 | 
			
		||||
			return nil, errors.New("corruption detected: stream overrun 3")
 | 
			
		||||
		}
 | 
			
		||||
		copy(out, buf[0][:off])
 | 
			
		||||
		copy(out[dstEvery:], buf[1][:off])
 | 
			
		||||
		copy(out[dstEvery*2:], buf[2][:off])
 | 
			
		||||
		copy(out[dstEvery*3:], buf[3][:off])
 | 
			
		||||
		decoded += int(off) * 4
 | 
			
		||||
		out = out[off:]
 | 
			
		||||
		decoded = ctx.decoded
 | 
			
		||||
		out = out[decoded/4:]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Decode remaining.
 | 
			
		||||
@@ -150,7 +122,6 @@ func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) {
 | 
			
		||||
		for bitsLeft > 0 {
 | 
			
		||||
			br.fill()
 | 
			
		||||
			if offset >= endsAt {
 | 
			
		||||
				d.bufs.Put(buf)
 | 
			
		||||
				return nil, errors.New("corruption detected: stream overrun 4")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
@@ -164,7 +135,6 @@ func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) {
 | 
			
		||||
			offset++
 | 
			
		||||
		}
 | 
			
		||||
		if offset != endsAt {
 | 
			
		||||
			d.bufs.Put(buf)
 | 
			
		||||
			return nil, fmt.Errorf("corruption detected: short output block %d, end %d != %d", i, offset, endsAt)
 | 
			
		||||
		}
 | 
			
		||||
		decoded += offset - dstEvery*i
 | 
			
		||||
@@ -173,9 +143,86 @@ func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	d.bufs.Put(buf)
 | 
			
		||||
	if dstSize != decoded {
 | 
			
		||||
		return nil, errors.New("corruption detected: short output block")
 | 
			
		||||
	}
 | 
			
		||||
	return dst, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// decompress4x_main_loop_x86 is an x86 assembler implementation
 | 
			
		||||
// of Decompress1X when tablelog > 8.
 | 
			
		||||
//go:noescape
 | 
			
		||||
func decompress1x_main_loop_amd64(ctx *decompress1xContext)
 | 
			
		||||
 | 
			
		||||
// decompress4x_main_loop_x86 is an x86 with BMI2 assembler implementation
 | 
			
		||||
// of Decompress1X when tablelog > 8.
 | 
			
		||||
//go:noescape
 | 
			
		||||
func decompress1x_main_loop_bmi2(ctx *decompress1xContext)
 | 
			
		||||
 | 
			
		||||
type decompress1xContext struct {
 | 
			
		||||
	pbr      *bitReaderShifted
 | 
			
		||||
	peekBits uint8
 | 
			
		||||
	out      *byte
 | 
			
		||||
	outCap   int
 | 
			
		||||
	tbl      *dEntrySingle
 | 
			
		||||
	decoded  int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Error reported by asm implementations
 | 
			
		||||
const error_max_decoded_size_exeeded = -1
 | 
			
		||||
 | 
			
		||||
// Decompress1X will decompress a 1X encoded stream.
 | 
			
		||||
// The cap of the output buffer will be the maximum decompressed size.
 | 
			
		||||
// The length of the supplied input must match the end of a block exactly.
 | 
			
		||||
func (d *Decoder) Decompress1X(dst, src []byte) ([]byte, error) {
 | 
			
		||||
	if len(d.dt.single) == 0 {
 | 
			
		||||
		return nil, errors.New("no table loaded")
 | 
			
		||||
	}
 | 
			
		||||
	var br bitReaderShifted
 | 
			
		||||
	err := br.init(src)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return dst, err
 | 
			
		||||
	}
 | 
			
		||||
	maxDecodedSize := cap(dst)
 | 
			
		||||
	dst = dst[:maxDecodedSize]
 | 
			
		||||
 | 
			
		||||
	const tlSize = 1 << tableLogMax
 | 
			
		||||
	const tlMask = tlSize - 1
 | 
			
		||||
 | 
			
		||||
	if maxDecodedSize >= 4 {
 | 
			
		||||
		ctx := decompress1xContext{
 | 
			
		||||
			pbr:      &br,
 | 
			
		||||
			out:      &dst[0],
 | 
			
		||||
			outCap:   maxDecodedSize,
 | 
			
		||||
			peekBits: uint8((64 - d.actualTableLog) & 63), // see: bitReaderShifted.peekBitsFast()
 | 
			
		||||
			tbl:      &d.dt.single[0],
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if cpuinfo.HasBMI2() {
 | 
			
		||||
			decompress1x_main_loop_bmi2(&ctx)
 | 
			
		||||
		} else {
 | 
			
		||||
			decompress1x_main_loop_amd64(&ctx)
 | 
			
		||||
		}
 | 
			
		||||
		if ctx.decoded == error_max_decoded_size_exeeded {
 | 
			
		||||
			return nil, ErrMaxDecodedSizeExceeded
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		dst = dst[:ctx.decoded]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// br < 8, so uint8 is fine
 | 
			
		||||
	bitsLeft := uint8(br.off)*8 + 64 - br.bitsRead
 | 
			
		||||
	for bitsLeft > 0 {
 | 
			
		||||
		br.fill()
 | 
			
		||||
		if len(dst) >= maxDecodedSize {
 | 
			
		||||
			br.close()
 | 
			
		||||
			return nil, ErrMaxDecodedSizeExceeded
 | 
			
		||||
		}
 | 
			
		||||
		v := d.dt.single[br.peekBitsFast(d.actualTableLog)&tlMask]
 | 
			
		||||
		nBits := uint8(v.entry)
 | 
			
		||||
		br.advance(nBits)
 | 
			
		||||
		bitsLeft -= nBits
 | 
			
		||||
		dst = append(dst, uint8(v.entry>>8))
 | 
			
		||||
	}
 | 
			
		||||
	return dst, br.close()
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1185
									
								
								vendor/github.com/klauspost/compress/huff0/decompress_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1185
									
								
								vendor/github.com/klauspost/compress/huff0/decompress_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										195
									
								
								vendor/github.com/klauspost/compress/huff0/decompress_amd64.s.in
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										195
									
								
								vendor/github.com/klauspost/compress/huff0/decompress_amd64.s.in
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,195 +0,0 @@
 | 
			
		||||
// +build !appengine
 | 
			
		||||
// +build gc
 | 
			
		||||
// +build !noasm
 | 
			
		||||
 | 
			
		||||
#include "textflag.h"
 | 
			
		||||
#include "funcdata.h"
 | 
			
		||||
#include "go_asm.h"
 | 
			
		||||
 | 
			
		||||
#ifdef GOAMD64_v4
 | 
			
		||||
#ifndef GOAMD64_v3
 | 
			
		||||
#define GOAMD64_v3
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define bufoff      256     // see decompress.go, we're using [4][256]byte table
 | 
			
		||||
 | 
			
		||||
//func decompress4x_main_loop_x86(pbr0, pbr1, pbr2, pbr3 *bitReaderShifted,
 | 
			
		||||
//	peekBits uint8, buf *byte, tbl *dEntrySingle) (int, bool)
 | 
			
		||||
TEXT ·decompress4x_main_loop_x86(SB), NOSPLIT, $8
 | 
			
		||||
#define off             R8
 | 
			
		||||
#define buffer          DI
 | 
			
		||||
#define table           SI
 | 
			
		||||
 | 
			
		||||
#define br_bits_read    R9
 | 
			
		||||
#define br_value        R10
 | 
			
		||||
#define br_offset       R11
 | 
			
		||||
#define peek_bits       R12
 | 
			
		||||
#define exhausted       DX
 | 
			
		||||
 | 
			
		||||
#define br0             R13
 | 
			
		||||
#define br1             R14
 | 
			
		||||
#define br2             R15
 | 
			
		||||
#define br3             BP
 | 
			
		||||
 | 
			
		||||
    MOVQ    BP, 0(SP)
 | 
			
		||||
 | 
			
		||||
    XORQ    exhausted, exhausted    // exhausted = false
 | 
			
		||||
    XORQ    off, off                // off = 0
 | 
			
		||||
 | 
			
		||||
    MOVBQZX peekBits+32(FP), peek_bits
 | 
			
		||||
    MOVQ    buf+40(FP), buffer
 | 
			
		||||
    MOVQ    tbl+48(FP), table
 | 
			
		||||
 | 
			
		||||
    MOVQ    pbr0+0(FP), br0
 | 
			
		||||
    MOVQ    pbr1+8(FP), br1
 | 
			
		||||
    MOVQ    pbr2+16(FP), br2
 | 
			
		||||
    MOVQ    pbr3+24(FP), br3
 | 
			
		||||
 | 
			
		||||
main_loop:
 | 
			
		||||
{{ define "decode_2_values_x86" }}
 | 
			
		||||
    // const stream = {{ var "id" }}
 | 
			
		||||
    // br{{ var "id"}}.fillFast()
 | 
			
		||||
    MOVBQZX bitReaderShifted_bitsRead(br{{ var "id" }}), br_bits_read
 | 
			
		||||
    MOVQ    bitReaderShifted_value(br{{ var "id" }}), br_value
 | 
			
		||||
    MOVQ    bitReaderShifted_off(br{{ var "id" }}), br_offset
 | 
			
		||||
 | 
			
		||||
    // We must have at least 2 * max tablelog left
 | 
			
		||||
    CMPQ    br_bits_read, $64-22
 | 
			
		||||
    JBE     skip_fill{{ var "id" }}
 | 
			
		||||
 | 
			
		||||
    SUBQ    $32, br_bits_read       // b.bitsRead -= 32
 | 
			
		||||
    SUBQ    $4, br_offset           // b.off -= 4
 | 
			
		||||
 | 
			
		||||
	// v := b.in[b.off-4 : b.off]
 | 
			
		||||
	// v = v[:4]
 | 
			
		||||
	// low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24)
 | 
			
		||||
    MOVQ    bitReaderShifted_in(br{{ var "id" }}), AX
 | 
			
		||||
 | 
			
		||||
	// b.value |= uint64(low) << (b.bitsRead & 63)
 | 
			
		||||
#ifdef GOAMD64_v3
 | 
			
		||||
    SHLXQ   br_bits_read, 0(br_offset)(AX*1), AX // AX = uint32(b.in[b.off:b.off+4]) << (b.bitsRead & 63)
 | 
			
		||||
#else
 | 
			
		||||
    MOVL    0(br_offset)(AX*1), AX  // AX = uint32(b.in[b.off:b.off+4])
 | 
			
		||||
    MOVQ    br_bits_read, CX
 | 
			
		||||
    SHLQ    CL, AX
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    ORQ     AX, br_value
 | 
			
		||||
 | 
			
		||||
    // exhausted = exhausted || (br{{ var "id"}}.off < 4)
 | 
			
		||||
    CMPQ    br_offset, $4
 | 
			
		||||
    SETLT   DL
 | 
			
		||||
    ORB     DL, DH
 | 
			
		||||
    // }
 | 
			
		||||
skip_fill{{ var "id" }}:
 | 
			
		||||
 | 
			
		||||
    // val0 := br{{ var "id"}}.peekTopBits(peekBits)
 | 
			
		||||
#ifdef GOAMD64_v3
 | 
			
		||||
    SHRXQ   peek_bits, br_value, AX // AX = (value >> peek_bits) & mask
 | 
			
		||||
#else
 | 
			
		||||
    MOVQ    br_value, AX
 | 
			
		||||
    MOVQ    peek_bits, CX
 | 
			
		||||
    SHRQ    CL, AX                  // AX = (value >> peek_bits) & mask
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // v0 := table[val0&mask]
 | 
			
		||||
    MOVW    0(table)(AX*2), AX      // AX - v0
 | 
			
		||||
 | 
			
		||||
    // br{{ var "id"}}.advance(uint8(v0.entry))
 | 
			
		||||
    MOVB    AH, BL                  // BL = uint8(v0.entry >> 8)
 | 
			
		||||
 | 
			
		||||
#ifdef GOAMD64_v3
 | 
			
		||||
    MOVBQZX AL, CX
 | 
			
		||||
    SHLXQ   AX, br_value, br_value // value <<= n
 | 
			
		||||
#else
 | 
			
		||||
    MOVBQZX AL, CX
 | 
			
		||||
    SHLQ    CL, br_value            // value <<= n
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    ADDQ    CX, br_bits_read        // bits_read += n
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef GOAMD64_v3
 | 
			
		||||
    SHRXQ    peek_bits, br_value, AX  // AX = (value >> peek_bits) & mask
 | 
			
		||||
#else
 | 
			
		||||
    // val1 := br{{ var "id"}}.peekTopBits(peekBits)
 | 
			
		||||
    MOVQ    peek_bits, CX
 | 
			
		||||
    MOVQ    br_value, AX
 | 
			
		||||
    SHRQ    CL, AX                  // AX = (value >> peek_bits) & mask
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // v1 := table[val1&mask]
 | 
			
		||||
    MOVW    0(table)(AX*2), AX      // AX - v1
 | 
			
		||||
 | 
			
		||||
    // br{{ var "id"}}.advance(uint8(v1.entry))
 | 
			
		||||
    MOVB    AH, BH                  // BH = uint8(v1.entry >> 8)
 | 
			
		||||
 | 
			
		||||
#ifdef GOAMD64_v3
 | 
			
		||||
    MOVBQZX AL, CX
 | 
			
		||||
    SHLXQ   AX, br_value, br_value // value <<= n
 | 
			
		||||
#else
 | 
			
		||||
    MOVBQZX AL, CX
 | 
			
		||||
    SHLQ    CL, br_value            // value <<= n
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    ADDQ    CX, br_bits_read        // bits_read += n
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // these two writes get coalesced
 | 
			
		||||
    // buf[stream][off] = uint8(v0.entry >> 8)
 | 
			
		||||
    // buf[stream][off+1] = uint8(v1.entry >> 8)
 | 
			
		||||
    MOVW    BX, {{ var "bufofs" }}(buffer)(off*1)
 | 
			
		||||
 | 
			
		||||
    // update the bitrader reader structure
 | 
			
		||||
    MOVB    br_bits_read, bitReaderShifted_bitsRead(br{{ var "id" }})
 | 
			
		||||
    MOVQ    br_value, bitReaderShifted_value(br{{ var "id" }})
 | 
			
		||||
    MOVQ    br_offset, bitReaderShifted_off(br{{ var "id" }})
 | 
			
		||||
{{ end }}
 | 
			
		||||
 | 
			
		||||
    {{ set "id" "0" }}
 | 
			
		||||
    {{ set "ofs" "0" }}
 | 
			
		||||
    {{ set "bufofs" "0" }} {{/* id * bufoff */}}
 | 
			
		||||
    {{ template "decode_2_values_x86" . }}
 | 
			
		||||
 | 
			
		||||
    {{ set "id" "1" }}
 | 
			
		||||
    {{ set "ofs" "8" }}
 | 
			
		||||
    {{ set "bufofs" "256" }}
 | 
			
		||||
    {{ template "decode_2_values_x86" . }}
 | 
			
		||||
 | 
			
		||||
    {{ set "id" "2" }}
 | 
			
		||||
    {{ set "ofs" "16" }}
 | 
			
		||||
    {{ set "bufofs" "512" }}
 | 
			
		||||
    {{ template "decode_2_values_x86" . }}
 | 
			
		||||
 | 
			
		||||
    {{ set "id" "3" }}
 | 
			
		||||
    {{ set "ofs" "24" }}
 | 
			
		||||
    {{ set "bufofs" "768" }}
 | 
			
		||||
    {{ template "decode_2_values_x86" . }}
 | 
			
		||||
 | 
			
		||||
    ADDQ    $2, off     // off += 2
 | 
			
		||||
 | 
			
		||||
    TESTB   DH, DH      // any br[i].ofs < 4?
 | 
			
		||||
    JNZ     end
 | 
			
		||||
 | 
			
		||||
    CMPQ    off, $bufoff
 | 
			
		||||
    JL      main_loop
 | 
			
		||||
end:
 | 
			
		||||
    MOVQ    0(SP), BP
 | 
			
		||||
 | 
			
		||||
    MOVB    off, ret+56(FP)
 | 
			
		||||
    RET
 | 
			
		||||
#undef  off
 | 
			
		||||
#undef  buffer
 | 
			
		||||
#undef  table
 | 
			
		||||
 | 
			
		||||
#undef  br_bits_read
 | 
			
		||||
#undef  br_value
 | 
			
		||||
#undef  br_offset
 | 
			
		||||
#undef  peek_bits
 | 
			
		||||
#undef  exhausted
 | 
			
		||||
 | 
			
		||||
#undef  br0
 | 
			
		||||
#undef  br1
 | 
			
		||||
#undef  br2
 | 
			
		||||
#undef  br3
 | 
			
		||||
							
								
								
									
										102
									
								
								vendor/github.com/klauspost/compress/huff0/decompress_generic.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										102
									
								
								vendor/github.com/klauspost/compress/huff0/decompress_generic.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -191,3 +191,105 @@ func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) {
 | 
			
		||||
	}
 | 
			
		||||
	return dst, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decompress1X will decompress a 1X encoded stream.
 | 
			
		||||
// The cap of the output buffer will be the maximum decompressed size.
 | 
			
		||||
// The length of the supplied input must match the end of a block exactly.
 | 
			
		||||
func (d *Decoder) Decompress1X(dst, src []byte) ([]byte, error) {
 | 
			
		||||
	if len(d.dt.single) == 0 {
 | 
			
		||||
		return nil, errors.New("no table loaded")
 | 
			
		||||
	}
 | 
			
		||||
	if use8BitTables && d.actualTableLog <= 8 {
 | 
			
		||||
		return d.decompress1X8Bit(dst, src)
 | 
			
		||||
	}
 | 
			
		||||
	var br bitReaderShifted
 | 
			
		||||
	err := br.init(src)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return dst, err
 | 
			
		||||
	}
 | 
			
		||||
	maxDecodedSize := cap(dst)
 | 
			
		||||
	dst = dst[:0]
 | 
			
		||||
 | 
			
		||||
	// Avoid bounds check by always having full sized table.
 | 
			
		||||
	const tlSize = 1 << tableLogMax
 | 
			
		||||
	const tlMask = tlSize - 1
 | 
			
		||||
	dt := d.dt.single[:tlSize]
 | 
			
		||||
 | 
			
		||||
	// Use temp table to avoid bound checks/append penalty.
 | 
			
		||||
	bufs := d.buffer()
 | 
			
		||||
	buf := &bufs[0]
 | 
			
		||||
	var off uint8
 | 
			
		||||
 | 
			
		||||
	for br.off >= 8 {
 | 
			
		||||
		br.fillFast()
 | 
			
		||||
		v := dt[br.peekBitsFast(d.actualTableLog)&tlMask]
 | 
			
		||||
		br.advance(uint8(v.entry))
 | 
			
		||||
		buf[off+0] = uint8(v.entry >> 8)
 | 
			
		||||
 | 
			
		||||
		v = dt[br.peekBitsFast(d.actualTableLog)&tlMask]
 | 
			
		||||
		br.advance(uint8(v.entry))
 | 
			
		||||
		buf[off+1] = uint8(v.entry >> 8)
 | 
			
		||||
 | 
			
		||||
		// Refill
 | 
			
		||||
		br.fillFast()
 | 
			
		||||
 | 
			
		||||
		v = dt[br.peekBitsFast(d.actualTableLog)&tlMask]
 | 
			
		||||
		br.advance(uint8(v.entry))
 | 
			
		||||
		buf[off+2] = uint8(v.entry >> 8)
 | 
			
		||||
 | 
			
		||||
		v = dt[br.peekBitsFast(d.actualTableLog)&tlMask]
 | 
			
		||||
		br.advance(uint8(v.entry))
 | 
			
		||||
		buf[off+3] = uint8(v.entry >> 8)
 | 
			
		||||
 | 
			
		||||
		off += 4
 | 
			
		||||
		if off == 0 {
 | 
			
		||||
			if len(dst)+256 > maxDecodedSize {
 | 
			
		||||
				br.close()
 | 
			
		||||
				d.bufs.Put(bufs)
 | 
			
		||||
				return nil, ErrMaxDecodedSizeExceeded
 | 
			
		||||
			}
 | 
			
		||||
			dst = append(dst, buf[:]...)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(dst)+int(off) > maxDecodedSize {
 | 
			
		||||
		d.bufs.Put(bufs)
 | 
			
		||||
		br.close()
 | 
			
		||||
		return nil, ErrMaxDecodedSizeExceeded
 | 
			
		||||
	}
 | 
			
		||||
	dst = append(dst, buf[:off]...)
 | 
			
		||||
 | 
			
		||||
	// br < 8, so uint8 is fine
 | 
			
		||||
	bitsLeft := uint8(br.off)*8 + 64 - br.bitsRead
 | 
			
		||||
	for bitsLeft > 0 {
 | 
			
		||||
		br.fill()
 | 
			
		||||
		if false && br.bitsRead >= 32 {
 | 
			
		||||
			if br.off >= 4 {
 | 
			
		||||
				v := br.in[br.off-4:]
 | 
			
		||||
				v = v[:4]
 | 
			
		||||
				low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24)
 | 
			
		||||
				br.value = (br.value << 32) | uint64(low)
 | 
			
		||||
				br.bitsRead -= 32
 | 
			
		||||
				br.off -= 4
 | 
			
		||||
			} else {
 | 
			
		||||
				for br.off > 0 {
 | 
			
		||||
					br.value = (br.value << 8) | uint64(br.in[br.off-1])
 | 
			
		||||
					br.bitsRead -= 8
 | 
			
		||||
					br.off--
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if len(dst) >= maxDecodedSize {
 | 
			
		||||
			d.bufs.Put(bufs)
 | 
			
		||||
			br.close()
 | 
			
		||||
			return nil, ErrMaxDecodedSizeExceeded
 | 
			
		||||
		}
 | 
			
		||||
		v := d.dt.single[br.peekBitsFast(d.actualTableLog)&tlMask]
 | 
			
		||||
		nBits := uint8(v.entry)
 | 
			
		||||
		br.advance(nBits)
 | 
			
		||||
		bitsLeft -= nBits
 | 
			
		||||
		dst = append(dst, uint8(v.entry>>8))
 | 
			
		||||
	}
 | 
			
		||||
	d.bufs.Put(bufs)
 | 
			
		||||
	return dst, br.close()
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										34
									
								
								vendor/github.com/klauspost/compress/internal/cpuinfo/cpuinfo.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								vendor/github.com/klauspost/compress/internal/cpuinfo/cpuinfo.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
// Package cpuinfo gives runtime info about the current CPU.
 | 
			
		||||
//
 | 
			
		||||
// This is a very limited module meant for use internally
 | 
			
		||||
// in this project. For more versatile solution check
 | 
			
		||||
// https://github.com/klauspost/cpuid.
 | 
			
		||||
package cpuinfo
 | 
			
		||||
 | 
			
		||||
// HasBMI1 checks whether an x86 CPU supports the BMI1 extension.
 | 
			
		||||
func HasBMI1() bool {
 | 
			
		||||
	return hasBMI1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HasBMI2 checks whether an x86 CPU supports the BMI2 extension.
 | 
			
		||||
func HasBMI2() bool {
 | 
			
		||||
	return hasBMI2
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DisableBMI2 will disable BMI2, for testing purposes.
 | 
			
		||||
// Call returned function to restore previous state.
 | 
			
		||||
func DisableBMI2() func() {
 | 
			
		||||
	old := hasBMI2
 | 
			
		||||
	hasBMI2 = false
 | 
			
		||||
	return func() {
 | 
			
		||||
		hasBMI2 = old
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HasBMI checks whether an x86 CPU supports both BMI1 and BMI2 extensions.
 | 
			
		||||
func HasBMI() bool {
 | 
			
		||||
	return HasBMI1() && HasBMI2()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var hasBMI1 bool
 | 
			
		||||
var hasBMI2 bool
 | 
			
		||||
							
								
								
									
										11
									
								
								vendor/github.com/klauspost/compress/internal/cpuinfo/cpuinfo_amd64.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/klauspost/compress/internal/cpuinfo/cpuinfo_amd64.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
//go:build amd64 && !appengine && !noasm && gc
 | 
			
		||||
// +build amd64,!appengine,!noasm,gc
 | 
			
		||||
 | 
			
		||||
package cpuinfo
 | 
			
		||||
 | 
			
		||||
// go:noescape
 | 
			
		||||
func x86extensions() (bmi1, bmi2 bool)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	hasBMI1, hasBMI2 = x86extensions()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								vendor/github.com/klauspost/compress/internal/cpuinfo/cpuinfo_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								vendor/github.com/klauspost/compress/internal/cpuinfo/cpuinfo_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
// +build !appengine
 | 
			
		||||
// +build gc
 | 
			
		||||
// +build !noasm
 | 
			
		||||
 | 
			
		||||
#include "textflag.h"
 | 
			
		||||
#include "funcdata.h"
 | 
			
		||||
#include "go_asm.h"
 | 
			
		||||
 | 
			
		||||
TEXT ·x86extensions(SB), NOSPLIT, $0
 | 
			
		||||
	// 1. determine max EAX value
 | 
			
		||||
	XORQ AX, AX
 | 
			
		||||
	CPUID
 | 
			
		||||
 | 
			
		||||
	CMPQ AX, $7
 | 
			
		||||
	JB   unsupported
 | 
			
		||||
 | 
			
		||||
	// 2. EAX = 7, ECX = 0 --- see Table 3-8 "Information Returned by CPUID Instruction"
 | 
			
		||||
	MOVQ $7, AX
 | 
			
		||||
	MOVQ $0, CX
 | 
			
		||||
	CPUID
 | 
			
		||||
 | 
			
		||||
	BTQ   $3, BX // bit 3 = BMI1
 | 
			
		||||
	SETCS AL
 | 
			
		||||
 | 
			
		||||
	BTQ   $8, BX // bit 8 = BMI2
 | 
			
		||||
	SETCS AH
 | 
			
		||||
 | 
			
		||||
	MOVB AL, bmi1+0(FP)
 | 
			
		||||
	MOVB AH, bmi2+1(FP)
 | 
			
		||||
	RET
 | 
			
		||||
 | 
			
		||||
unsupported:
 | 
			
		||||
	XORQ AX, AX
 | 
			
		||||
	MOVB AL, bmi1+0(FP)
 | 
			
		||||
	MOVB AL, bmi2+1(FP)
 | 
			
		||||
	RET
 | 
			
		||||
							
								
								
									
										30
									
								
								vendor/github.com/klauspost/compress/s2/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								vendor/github.com/klauspost/compress/s2/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -19,6 +19,7 @@ This is important, so you don't have to worry about spending CPU cycles on alrea
 | 
			
		||||
* Adjustable compression (3 levels) 
 | 
			
		||||
* Concurrent stream compression
 | 
			
		||||
* Faster decompression, even for Snappy compatible content
 | 
			
		||||
* Concurrent Snappy/S2 stream decompression
 | 
			
		||||
* Ability to quickly skip forward in compressed stream
 | 
			
		||||
* Random seeking with indexes
 | 
			
		||||
* Compatible with reading Snappy compressed content
 | 
			
		||||
@@ -415,6 +416,25 @@ Without assembly decompression is also very fast; single goroutine decompression
 | 
			
		||||
 | 
			
		||||
Even though S2 typically compresses better than Snappy, decompression speed is always better. 
 | 
			
		||||
 | 
			
		||||
### Concurrent Stream Decompression
 | 
			
		||||
 | 
			
		||||
For full stream decompression S2 offers a [DecodeConcurrent](https://pkg.go.dev/github.com/klauspost/compress/s2#Reader.DecodeConcurrent) 
 | 
			
		||||
that will decode a full stream using multiple goroutines.
 | 
			
		||||
 | 
			
		||||
Example scaling, AMD Ryzen 3950X, 16 cores, decompression using `s2d -bench=3 <input>`, best of 3: 
 | 
			
		||||
 | 
			
		||||
| Input                                     | `-cpu=1`   | `-cpu=2`   | `-cpu=4`   | `-cpu=8`   | `-cpu=16`   |
 | 
			
		||||
|-------------------------------------------|------------|------------|------------|------------|-------------|
 | 
			
		||||
| enwik10.snappy                            | 1098.6MB/s | 1819.8MB/s | 3625.6MB/s | 6910.6MB/s | 10818.2MB/s |
 | 
			
		||||
| enwik10.s2                                | 1303.5MB/s | 2606.1MB/s | 4847.9MB/s | 8878.4MB/s | 9592.1MB/s  |
 | 
			
		||||
| sofia-air-quality-dataset.tar.snappy      | 1302.0MB/s | 2165.0MB/s | 4244.5MB/s | 8241.0MB/s | 12920.5MB/s |
 | 
			
		||||
| sofia-air-quality-dataset.tar.s2          | 1399.2MB/s | 2463.2MB/s | 5196.5MB/s | 9639.8MB/s | 11439.5MB/s |
 | 
			
		||||
| sofia-air-quality-dataset.tar.s2 (no asm) | 837.5MB/s  | 1652.6MB/s | 3183.6MB/s | 5945.0MB/s | 9620.7MB/s  |
 | 
			
		||||
 | 
			
		||||
Scaling can be expected to be pretty linear until memory bandwidth is saturated. 
 | 
			
		||||
 | 
			
		||||
For now the DecodeConcurrent can only be used for full streams without seeking or combining with regular reads.
 | 
			
		||||
 | 
			
		||||
## Block compression
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -873,7 +893,7 @@ for each entry {
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Uncompressed uses previous offset and adds EstBlockSize
 | 
			
		||||
    entry[entryNum].UncompressedOffset = entry[entryNum-1].UncompressedOffset + EstBlockSize
 | 
			
		||||
    entry[entryNum].UncompressedOffset = entry[entryNum-1].UncompressedOffset + EstBlockSize + uOff
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -901,6 +921,14 @@ for each entry {
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
To decode from any given uncompressed offset `(wantOffset)`:
 | 
			
		||||
 | 
			
		||||
* Iterate entries until `entry[n].UncompressedOffset > wantOffset`.
 | 
			
		||||
* Start decoding from `entry[n-1].CompressedOffset`.
 | 
			
		||||
* Discard `entry[n-1].UncompressedOffset - wantOffset` bytes from the decoded stream.
 | 
			
		||||
 | 
			
		||||
See [using indexes](https://github.com/klauspost/compress/tree/master/s2#using-indexes) for functions that perform the operations with a simpler interface.
 | 
			
		||||
 | 
			
		||||
# Format Extensions
 | 
			
		||||
 | 
			
		||||
* Frame [Stream identifier](https://github.com/google/snappy/blob/master/framing_format.txt#L68) changed from `sNaPpY` to `S2sTwO`.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										289
									
								
								vendor/github.com/klauspost/compress/s2/decode.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										289
									
								
								vendor/github.com/klauspost/compress/s2/decode.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -11,6 +11,8 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
@@ -169,6 +171,14 @@ func ReaderSkippableCB(id uint8, fn func(r io.Reader) error) ReaderOption {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReaderIgnoreCRC will make the reader skip CRC calculation and checks.
 | 
			
		||||
func ReaderIgnoreCRC() ReaderOption {
 | 
			
		||||
	return func(r *Reader) error {
 | 
			
		||||
		r.ignoreCRC = true
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Reader is an io.Reader that can read Snappy-compressed bytes.
 | 
			
		||||
type Reader struct {
 | 
			
		||||
	r           io.Reader
 | 
			
		||||
@@ -191,18 +201,19 @@ type Reader struct {
 | 
			
		||||
	paramsOK       bool
 | 
			
		||||
	snappyFrame    bool
 | 
			
		||||
	ignoreStreamID bool
 | 
			
		||||
	ignoreCRC      bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ensureBufferSize will ensure that the buffer can take at least n bytes.
 | 
			
		||||
// If false is returned the buffer exceeds maximum allowed size.
 | 
			
		||||
func (r *Reader) ensureBufferSize(n int) bool {
 | 
			
		||||
	if len(r.buf) >= n {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	if n > r.maxBufSize {
 | 
			
		||||
		r.err = ErrCorrupt
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	if cap(r.buf) >= n {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	// Realloc buffer.
 | 
			
		||||
	r.buf = make([]byte, n)
 | 
			
		||||
	return true
 | 
			
		||||
@@ -220,6 +231,7 @@ func (r *Reader) Reset(reader io.Reader) {
 | 
			
		||||
	r.err = nil
 | 
			
		||||
	r.i = 0
 | 
			
		||||
	r.j = 0
 | 
			
		||||
	r.blockStart = 0
 | 
			
		||||
	r.readHeader = r.ignoreStreamID
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -344,7 +356,7 @@ func (r *Reader) Read(p []byte) (int, error) {
 | 
			
		||||
				r.err = err
 | 
			
		||||
				return 0, r.err
 | 
			
		||||
			}
 | 
			
		||||
			if crc(r.decoded[:n]) != checksum {
 | 
			
		||||
			if !r.ignoreCRC && crc(r.decoded[:n]) != checksum {
 | 
			
		||||
				r.err = ErrCRC
 | 
			
		||||
				return 0, r.err
 | 
			
		||||
			}
 | 
			
		||||
@@ -385,7 +397,7 @@ func (r *Reader) Read(p []byte) (int, error) {
 | 
			
		||||
			if !r.readFull(r.decoded[:n], false) {
 | 
			
		||||
				return 0, r.err
 | 
			
		||||
			}
 | 
			
		||||
			if crc(r.decoded[:n]) != checksum {
 | 
			
		||||
			if !r.ignoreCRC && crc(r.decoded[:n]) != checksum {
 | 
			
		||||
				r.err = ErrCRC
 | 
			
		||||
				return 0, r.err
 | 
			
		||||
			}
 | 
			
		||||
@@ -435,6 +447,259 @@ func (r *Reader) Read(p []byte) (int, error) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecodeConcurrent will decode the full stream to w.
 | 
			
		||||
// This function should not be combined with reading, seeking or other operations.
 | 
			
		||||
// Up to 'concurrent' goroutines will be used.
 | 
			
		||||
// If <= 0, runtime.NumCPU will be used.
 | 
			
		||||
// On success the number of bytes decompressed nil and is returned.
 | 
			
		||||
// This is mainly intended for bigger streams.
 | 
			
		||||
func (r *Reader) DecodeConcurrent(w io.Writer, concurrent int) (written int64, err error) {
 | 
			
		||||
	if r.i > 0 || r.j > 0 || r.blockStart > 0 {
 | 
			
		||||
		return 0, errors.New("DecodeConcurrent called after ")
 | 
			
		||||
	}
 | 
			
		||||
	if concurrent <= 0 {
 | 
			
		||||
		concurrent = runtime.NumCPU()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Write to output
 | 
			
		||||
	var errMu sync.Mutex
 | 
			
		||||
	var aErr error
 | 
			
		||||
	setErr := func(e error) (ok bool) {
 | 
			
		||||
		errMu.Lock()
 | 
			
		||||
		defer errMu.Unlock()
 | 
			
		||||
		if e == nil {
 | 
			
		||||
			return aErr == nil
 | 
			
		||||
		}
 | 
			
		||||
		if aErr == nil {
 | 
			
		||||
			aErr = e
 | 
			
		||||
		}
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	hasErr := func() (ok bool) {
 | 
			
		||||
		errMu.Lock()
 | 
			
		||||
		v := aErr != nil
 | 
			
		||||
		errMu.Unlock()
 | 
			
		||||
		return v
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var aWritten int64
 | 
			
		||||
	toRead := make(chan []byte, concurrent)
 | 
			
		||||
	writtenBlocks := make(chan []byte, concurrent)
 | 
			
		||||
	queue := make(chan chan []byte, concurrent)
 | 
			
		||||
	reUse := make(chan chan []byte, concurrent)
 | 
			
		||||
	for i := 0; i < concurrent; i++ {
 | 
			
		||||
		toRead <- make([]byte, 0, r.maxBufSize)
 | 
			
		||||
		writtenBlocks <- make([]byte, 0, r.maxBufSize)
 | 
			
		||||
		reUse <- make(chan []byte, 1)
 | 
			
		||||
	}
 | 
			
		||||
	// Writer
 | 
			
		||||
	var wg sync.WaitGroup
 | 
			
		||||
	wg.Add(1)
 | 
			
		||||
	go func() {
 | 
			
		||||
		defer wg.Done()
 | 
			
		||||
		for toWrite := range queue {
 | 
			
		||||
			entry := <-toWrite
 | 
			
		||||
			reUse <- toWrite
 | 
			
		||||
			if hasErr() {
 | 
			
		||||
				writtenBlocks <- entry
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			n, err := w.Write(entry)
 | 
			
		||||
			want := len(entry)
 | 
			
		||||
			writtenBlocks <- entry
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				setErr(err)
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if n != want {
 | 
			
		||||
				setErr(io.ErrShortWrite)
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			aWritten += int64(n)
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	// Reader
 | 
			
		||||
	defer func() {
 | 
			
		||||
		close(queue)
 | 
			
		||||
		if r.err != nil {
 | 
			
		||||
			err = r.err
 | 
			
		||||
			setErr(r.err)
 | 
			
		||||
		}
 | 
			
		||||
		wg.Wait()
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			err = aErr
 | 
			
		||||
		}
 | 
			
		||||
		written = aWritten
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	for !hasErr() {
 | 
			
		||||
		if !r.readFull(r.buf[:4], true) {
 | 
			
		||||
			if r.err == io.EOF {
 | 
			
		||||
				r.err = nil
 | 
			
		||||
			}
 | 
			
		||||
			return 0, r.err
 | 
			
		||||
		}
 | 
			
		||||
		chunkType := r.buf[0]
 | 
			
		||||
		if !r.readHeader {
 | 
			
		||||
			if chunkType != chunkTypeStreamIdentifier {
 | 
			
		||||
				r.err = ErrCorrupt
 | 
			
		||||
				return 0, r.err
 | 
			
		||||
			}
 | 
			
		||||
			r.readHeader = true
 | 
			
		||||
		}
 | 
			
		||||
		chunkLen := int(r.buf[1]) | int(r.buf[2])<<8 | int(r.buf[3])<<16
 | 
			
		||||
 | 
			
		||||
		// The chunk types are specified at
 | 
			
		||||
		// https://github.com/google/snappy/blob/master/framing_format.txt
 | 
			
		||||
		switch chunkType {
 | 
			
		||||
		case chunkTypeCompressedData:
 | 
			
		||||
			r.blockStart += int64(r.j)
 | 
			
		||||
			// Section 4.2. Compressed data (chunk type 0x00).
 | 
			
		||||
			if chunkLen < checksumSize {
 | 
			
		||||
				r.err = ErrCorrupt
 | 
			
		||||
				return 0, r.err
 | 
			
		||||
			}
 | 
			
		||||
			if chunkLen > r.maxBufSize {
 | 
			
		||||
				r.err = ErrCorrupt
 | 
			
		||||
				return 0, r.err
 | 
			
		||||
			}
 | 
			
		||||
			orgBuf := <-toRead
 | 
			
		||||
			buf := orgBuf[:chunkLen]
 | 
			
		||||
 | 
			
		||||
			if !r.readFull(buf, false) {
 | 
			
		||||
				return 0, r.err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24
 | 
			
		||||
			buf = buf[checksumSize:]
 | 
			
		||||
 | 
			
		||||
			n, err := DecodedLen(buf)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				r.err = err
 | 
			
		||||
				return 0, r.err
 | 
			
		||||
			}
 | 
			
		||||
			if r.snappyFrame && n > maxSnappyBlockSize {
 | 
			
		||||
				r.err = ErrCorrupt
 | 
			
		||||
				return 0, r.err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if n > r.maxBlock {
 | 
			
		||||
				r.err = ErrCorrupt
 | 
			
		||||
				return 0, r.err
 | 
			
		||||
			}
 | 
			
		||||
			wg.Add(1)
 | 
			
		||||
 | 
			
		||||
			decoded := <-writtenBlocks
 | 
			
		||||
			entry := <-reUse
 | 
			
		||||
			queue <- entry
 | 
			
		||||
			go func() {
 | 
			
		||||
				defer wg.Done()
 | 
			
		||||
				decoded = decoded[:n]
 | 
			
		||||
				_, err := Decode(decoded, buf)
 | 
			
		||||
				toRead <- orgBuf
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					writtenBlocks <- decoded
 | 
			
		||||
					setErr(err)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
				if !r.ignoreCRC && crc(decoded) != checksum {
 | 
			
		||||
					writtenBlocks <- decoded
 | 
			
		||||
					setErr(ErrCRC)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
				entry <- decoded
 | 
			
		||||
			}()
 | 
			
		||||
			continue
 | 
			
		||||
 | 
			
		||||
		case chunkTypeUncompressedData:
 | 
			
		||||
 | 
			
		||||
			// Section 4.3. Uncompressed data (chunk type 0x01).
 | 
			
		||||
			if chunkLen < checksumSize {
 | 
			
		||||
				r.err = ErrCorrupt
 | 
			
		||||
				return 0, r.err
 | 
			
		||||
			}
 | 
			
		||||
			if chunkLen > r.maxBufSize {
 | 
			
		||||
				r.err = ErrCorrupt
 | 
			
		||||
				return 0, r.err
 | 
			
		||||
			}
 | 
			
		||||
			// Grab write buffer
 | 
			
		||||
			orgBuf := <-writtenBlocks
 | 
			
		||||
			buf := orgBuf[:checksumSize]
 | 
			
		||||
			if !r.readFull(buf, false) {
 | 
			
		||||
				return 0, r.err
 | 
			
		||||
			}
 | 
			
		||||
			checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24
 | 
			
		||||
			// Read content.
 | 
			
		||||
			n := chunkLen - checksumSize
 | 
			
		||||
 | 
			
		||||
			if r.snappyFrame && n > maxSnappyBlockSize {
 | 
			
		||||
				r.err = ErrCorrupt
 | 
			
		||||
				return 0, r.err
 | 
			
		||||
			}
 | 
			
		||||
			if n > r.maxBlock {
 | 
			
		||||
				r.err = ErrCorrupt
 | 
			
		||||
				return 0, r.err
 | 
			
		||||
			}
 | 
			
		||||
			// Read uncompressed
 | 
			
		||||
			buf = orgBuf[:n]
 | 
			
		||||
			if !r.readFull(buf, false) {
 | 
			
		||||
				return 0, r.err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if !r.ignoreCRC && crc(buf) != checksum {
 | 
			
		||||
				r.err = ErrCRC
 | 
			
		||||
				return 0, r.err
 | 
			
		||||
			}
 | 
			
		||||
			entry := <-reUse
 | 
			
		||||
			queue <- entry
 | 
			
		||||
			entry <- buf
 | 
			
		||||
			continue
 | 
			
		||||
 | 
			
		||||
		case chunkTypeStreamIdentifier:
 | 
			
		||||
			// Section 4.1. Stream identifier (chunk type 0xff).
 | 
			
		||||
			if chunkLen != len(magicBody) {
 | 
			
		||||
				r.err = ErrCorrupt
 | 
			
		||||
				return 0, r.err
 | 
			
		||||
			}
 | 
			
		||||
			if !r.readFull(r.buf[:len(magicBody)], false) {
 | 
			
		||||
				return 0, r.err
 | 
			
		||||
			}
 | 
			
		||||
			if string(r.buf[:len(magicBody)]) != magicBody {
 | 
			
		||||
				if string(r.buf[:len(magicBody)]) != magicBodySnappy {
 | 
			
		||||
					r.err = ErrCorrupt
 | 
			
		||||
					return 0, r.err
 | 
			
		||||
				} else {
 | 
			
		||||
					r.snappyFrame = true
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				r.snappyFrame = false
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if chunkType <= 0x7f {
 | 
			
		||||
			// Section 4.5. Reserved unskippable chunks (chunk types 0x02-0x7f).
 | 
			
		||||
			// fmt.Printf("ERR chunktype: 0x%x\n", chunkType)
 | 
			
		||||
			r.err = ErrUnsupported
 | 
			
		||||
			return 0, r.err
 | 
			
		||||
		}
 | 
			
		||||
		// Section 4.4 Padding (chunk type 0xfe).
 | 
			
		||||
		// Section 4.6. Reserved skippable chunks (chunk types 0x80-0xfd).
 | 
			
		||||
		if chunkLen > maxChunkSize {
 | 
			
		||||
			// fmt.Printf("ERR chunkLen: 0x%x\n", chunkLen)
 | 
			
		||||
			r.err = ErrUnsupported
 | 
			
		||||
			return 0, r.err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// fmt.Printf("skippable: ID: 0x%x, len: 0x%x\n", chunkType, chunkLen)
 | 
			
		||||
		if !r.skippable(r.buf, chunkLen, false, chunkType) {
 | 
			
		||||
			return 0, r.err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0, r.err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Skip will skip n bytes forward in the decompressed output.
 | 
			
		||||
// For larger skips this consumes less CPU and is faster than reading output and discarding it.
 | 
			
		||||
// CRC is not checked on skipped blocks.
 | 
			
		||||
@@ -699,8 +964,16 @@ func (r *ReadSeeker) Seek(offset int64, whence int) (int64, error) {
 | 
			
		||||
	case io.SeekCurrent:
 | 
			
		||||
		offset += r.blockStart + int64(r.i)
 | 
			
		||||
	case io.SeekEnd:
 | 
			
		||||
		offset = -offset
 | 
			
		||||
		if offset > 0 {
 | 
			
		||||
			return 0, errors.New("seek after end of file")
 | 
			
		||||
		}
 | 
			
		||||
		offset = r.index.TotalUncompressed + offset
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if offset < 0 {
 | 
			
		||||
		return 0, errors.New("seek before start of file")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c, u, err := r.index.Find(offset)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return r.blockStart + int64(r.i), err
 | 
			
		||||
@@ -712,10 +985,6 @@ func (r *ReadSeeker) Seek(offset int64, whence int) (int64, error) {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if offset < 0 {
 | 
			
		||||
		offset = r.index.TotalUncompressed + offset
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r.i = r.j // Remove rest of current block.
 | 
			
		||||
	if u < offset {
 | 
			
		||||
		// Forward inside block
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								vendor/github.com/klauspost/compress/s2/encode.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/klauspost/compress/s2/encode.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1119,12 +1119,6 @@ func (w *Writer) closeIndex(idx bool) ([]byte, error) {
 | 
			
		||||
			if w.appendIndex {
 | 
			
		||||
				w.written += int64(len(index))
 | 
			
		||||
			}
 | 
			
		||||
			if true {
 | 
			
		||||
				_, err := w.index.Load(index)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					panic(err)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if w.pad > 1 {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										28
									
								
								vendor/github.com/klauspost/compress/s2/encode_best.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								vendor/github.com/klauspost/compress/s2/encode_best.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -370,7 +370,7 @@ func encodeBlockBestSnappy(dst, src []byte) (d int) {
 | 
			
		||||
				}
 | 
			
		||||
				offset := m.s - m.offset
 | 
			
		||||
 | 
			
		||||
				return score - emitCopySize(offset, m.length)
 | 
			
		||||
				return score - emitCopyNoRepeatSize(offset, m.length)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			matchAt := func(offset, s int, first uint32) match {
 | 
			
		||||
@@ -567,6 +567,10 @@ func emitCopySize(offset, length int) int {
 | 
			
		||||
 | 
			
		||||
	// Offset no more than 2 bytes.
 | 
			
		||||
	if length > 64 {
 | 
			
		||||
		if offset < 2048 {
 | 
			
		||||
			// Emit 8 bytes, then rest as repeats...
 | 
			
		||||
			return 2 + emitRepeatSize(offset, length-8)
 | 
			
		||||
		}
 | 
			
		||||
		// Emit remaining as repeats, at least 4 bytes remain.
 | 
			
		||||
		return 3 + emitRepeatSize(offset, length-60)
 | 
			
		||||
	}
 | 
			
		||||
@@ -577,6 +581,28 @@ func emitCopySize(offset, length int) int {
 | 
			
		||||
	return 2
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// emitCopyNoRepeatSize returns the size to encode the offset+length
 | 
			
		||||
//
 | 
			
		||||
// It assumes that:
 | 
			
		||||
//	1 <= offset && offset <= math.MaxUint32
 | 
			
		||||
//	4 <= length && length <= 1 << 24
 | 
			
		||||
func emitCopyNoRepeatSize(offset, length int) int {
 | 
			
		||||
	if offset >= 65536 {
 | 
			
		||||
		return 5 + 5*(length/64)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Offset no more than 2 bytes.
 | 
			
		||||
	if length > 64 {
 | 
			
		||||
		// Emit remaining as repeats, at least 4 bytes remain.
 | 
			
		||||
		return 3 + 3*(length/60)
 | 
			
		||||
	}
 | 
			
		||||
	if length >= 12 || offset >= 2048 {
 | 
			
		||||
		return 3
 | 
			
		||||
	}
 | 
			
		||||
	// Emit the remaining copy, encoded as 2 bytes.
 | 
			
		||||
	return 2
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// emitRepeatSize returns the number of bytes required to encode a repeat.
 | 
			
		||||
// Length must be at least 4 and < 1<<24
 | 
			
		||||
func emitRepeatSize(offset, length int) int {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										23
									
								
								vendor/github.com/klauspost/compress/s2/encode_go.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/klauspost/compress/s2/encode_go.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -180,14 +180,23 @@ func emitCopy(dst []byte, offset, length int) int {
 | 
			
		||||
 | 
			
		||||
	// Offset no more than 2 bytes.
 | 
			
		||||
	if length > 64 {
 | 
			
		||||
		// Emit a length 60 copy, encoded as 3 bytes.
 | 
			
		||||
		// Emit remaining as repeat value (minimum 4 bytes).
 | 
			
		||||
		dst[2] = uint8(offset >> 8)
 | 
			
		||||
		dst[1] = uint8(offset)
 | 
			
		||||
		dst[0] = 59<<2 | tagCopy2
 | 
			
		||||
		length -= 60
 | 
			
		||||
		off := 3
 | 
			
		||||
		if offset < 2048 {
 | 
			
		||||
			// emit 8 bytes as tagCopy1, rest as repeats.
 | 
			
		||||
			dst[1] = uint8(offset)
 | 
			
		||||
			dst[0] = uint8(offset>>8)<<5 | uint8(8-4)<<2 | tagCopy1
 | 
			
		||||
			length -= 8
 | 
			
		||||
			off = 2
 | 
			
		||||
		} else {
 | 
			
		||||
			// Emit a length 60 copy, encoded as 3 bytes.
 | 
			
		||||
			// Emit remaining as repeat value (minimum 4 bytes).
 | 
			
		||||
			dst[2] = uint8(offset >> 8)
 | 
			
		||||
			dst[1] = uint8(offset)
 | 
			
		||||
			dst[0] = 59<<2 | tagCopy2
 | 
			
		||||
			length -= 60
 | 
			
		||||
		}
 | 
			
		||||
		// Emit remaining as repeats, at least 4 bytes remain.
 | 
			
		||||
		return 3 + emitRepeat(dst[3:], offset, length)
 | 
			
		||||
		return off + emitRepeat(dst[off:], offset, length)
 | 
			
		||||
	}
 | 
			
		||||
	if length >= 12 || offset >= 2048 {
 | 
			
		||||
		// Emit the remaining copy, encoded as 3 bytes.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/klauspost/compress/s2/encodeblock_amd64.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/klauspost/compress/s2/encodeblock_amd64.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -5,6 +5,8 @@
 | 
			
		||||
 | 
			
		||||
package s2
 | 
			
		||||
 | 
			
		||||
func _dummy_()
 | 
			
		||||
 | 
			
		||||
// encodeBlockAsm encodes a non-empty src to a guaranteed-large-enough dst.
 | 
			
		||||
// Maximum input 4294967295 bytes.
 | 
			
		||||
// It assumes that the varint-encoded length of the decompressed bytes has already been written.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1930
									
								
								vendor/github.com/klauspost/compress/s2/encodeblock_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1930
									
								
								vendor/github.com/klauspost/compress/s2/encodeblock_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										10
									
								
								vendor/github.com/klauspost/compress/s2/index.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								vendor/github.com/klauspost/compress/s2/index.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -10,6 +10,7 @@ import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"sort"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
@@ -100,6 +101,15 @@ func (i *Index) Find(offset int64) (compressedOff, uncompressedOff int64, err er
 | 
			
		||||
	if offset > i.TotalUncompressed {
 | 
			
		||||
		return 0, 0, io.ErrUnexpectedEOF
 | 
			
		||||
	}
 | 
			
		||||
	if len(i.info) > 200 {
 | 
			
		||||
		n := sort.Search(len(i.info), func(n int) bool {
 | 
			
		||||
			return i.info[n].uncompressedOffset > offset
 | 
			
		||||
		})
 | 
			
		||||
		if n == 0 {
 | 
			
		||||
			n = 1
 | 
			
		||||
		}
 | 
			
		||||
		return i.info[n-1].compressedOffset, i.info[n-1].uncompressedOffset, nil
 | 
			
		||||
	}
 | 
			
		||||
	for _, info := range i.info {
 | 
			
		||||
		if info.uncompressedOffset > offset {
 | 
			
		||||
			break
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										54
									
								
								vendor/github.com/klauspost/compress/zstd/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										54
									
								
								vendor/github.com/klauspost/compress/zstd/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -386,47 +386,31 @@ In practice this means that concurrency is often limited to utilizing about 3 co
 | 
			
		||||
  
 | 
			
		||||
### Benchmarks
 | 
			
		||||
 | 
			
		||||
These are some examples of performance compared to [datadog cgo library](https://github.com/DataDog/zstd).
 | 
			
		||||
 | 
			
		||||
The first two are streaming decodes and the last are smaller inputs. 
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
Running on AMD Ryzen 9 3950X 16-Core Processor. AMD64 assembly used.
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
BenchmarkDecoderSilesia-8                          3     385000067 ns/op     550.51 MB/s        5498 B/op          8 allocs/op
 | 
			
		||||
BenchmarkDecoderSilesiaCgo-8                       6     197666567 ns/op    1072.25 MB/s      270672 B/op          8 allocs/op
 | 
			
		||||
BenchmarkDecoderSilesia-32    	                   5	 206878840 ns/op	1024.50 MB/s	   49808 B/op	      43 allocs/op
 | 
			
		||||
BenchmarkDecoderEnwik9-32                          1	1271809000 ns/op	 786.28 MB/s	   72048 B/op	      52 allocs/op
 | 
			
		||||
 | 
			
		||||
BenchmarkDecoderEnwik9-8                           1    2027001600 ns/op     493.34 MB/s       10496 B/op         18 allocs/op
 | 
			
		||||
BenchmarkDecoderEnwik9Cgo-8                        2     979499200 ns/op    1020.93 MB/s      270672 B/op          8 allocs/op
 | 
			
		||||
Concurrent blocks, performance:
 | 
			
		||||
 | 
			
		||||
Concurrent performance:
 | 
			
		||||
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/kppkn.gtb.zst-16                28915         42469 ns/op    4340.07 MB/s         114 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/geo.protodata.zst-16           116505          9965 ns/op    11900.16 MB/s         16 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/plrabn12.txt.zst-16              8952        134272 ns/op    3588.70 MB/s         915 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/lcet10.txt.zst-16               11820        102538 ns/op    4161.90 MB/s         594 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/asyoulik.txt.zst-16             34782         34184 ns/op    3661.88 MB/s          60 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/alice29.txt.zst-16              27712         43447 ns/op    3500.58 MB/s          99 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/html_x_4.zst-16                 62826         18750 ns/op    21845.10 MB/s        104 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/paper-100k.pdf.zst-16          631545          1794 ns/op    57078.74 MB/s          2 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/fireworks.jpeg.zst-16         1690140           712 ns/op    172938.13 MB/s         1 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/urls.10K.zst-16                 10432        113593 ns/op    6180.73 MB/s        1143 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/html.zst-16                    113206         10671 ns/op    9596.27 MB/s          15 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/comp-data.bin.zst-16          1530615           779 ns/op    5229.49 MB/s           0 B/op          0 allocs/op
 | 
			
		||||
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallelCgo/kppkn.gtb.zst-16             65217         16192 ns/op    11383.34 MB/s         46 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallelCgo/geo.protodata.zst-16        292671          4039 ns/op    29363.19 MB/s          6 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallelCgo/plrabn12.txt.zst-16          26314         46021 ns/op    10470.43 MB/s        293 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallelCgo/lcet10.txt.zst-16            33897         34900 ns/op    12227.96 MB/s        205 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallelCgo/asyoulik.txt.zst-16         104348         11433 ns/op    10949.01 MB/s         20 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallelCgo/alice29.txt.zst-16           75949         15510 ns/op    9805.60 MB/s          32 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallelCgo/html_x_4.zst-16             173910          6756 ns/op    60624.29 MB/s         37 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallelCgo/paper-100k.pdf.zst-16       923076          1339 ns/op    76474.87 MB/s          1 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallelCgo/fireworks.jpeg.zst-16       922920          1351 ns/op    91102.57 MB/s          2 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallelCgo/urls.10K.zst-16              27649         43618 ns/op    16096.19 MB/s        407 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallelCgo/html.zst-16                 279073          4160 ns/op    24614.18 MB/s          6 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallelCgo/comp-data.bin.zst-16        749938          1579 ns/op    2581.71 MB/s           0 B/op          0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/kppkn.gtb.zst-32         	   67356	     17857 ns/op	10321.96 MB/s	        22.48 pct	     102 B/op	       0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/geo.protodata.zst-32     	  266656	      4421 ns/op	26823.21 MB/s	        11.89 pct	      19 B/op	       0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/plrabn12.txt.zst-32      	   20992	     56842 ns/op	8477.17 MB/s	        39.90 pct	     754 B/op	       0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/lcet10.txt.zst-32        	   27456	     43932 ns/op	9714.01 MB/s	        33.27 pct	     524 B/op	       0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/asyoulik.txt.zst-32      	   78432	     15047 ns/op	8319.15 MB/s	        40.34 pct	      66 B/op	       0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/alice29.txt.zst-32       	   65800	     18436 ns/op	8249.63 MB/s	        37.75 pct	      88 B/op	       0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/html_x_4.zst-32          	  102993	     11523 ns/op	35546.09 MB/s	         3.637 pct	     143 B/op	       0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/paper-100k.pdf.zst-32    	 1000000	      1070 ns/op	95720.98 MB/s	        80.53 pct	       3 B/op	       0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/fireworks.jpeg.zst-32    	  749802	      1752 ns/op	70272.35 MB/s	       100.0 pct	       5 B/op	       0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/urls.10K.zst-32          	   22640	     52934 ns/op	13263.37 MB/s	        26.25 pct	    1014 B/op	       0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/html.zst-32              	  226412	      5232 ns/op	19572.27 MB/s	        14.49 pct	      20 B/op	       0 allocs/op
 | 
			
		||||
BenchmarkDecoder_DecodeAllParallel/comp-data.bin.zst-32     	  923041	      1276 ns/op	3194.71 MB/s	        31.26 pct	       0 B/op	       0 allocs/op
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This reflects the performance around May 2020, but this may be out of date.
 | 
			
		||||
This reflects the performance around May 2022, but this may be out of date.
 | 
			
		||||
 | 
			
		||||
## Zstd inside ZIP files
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								vendor/github.com/klauspost/compress/zstd/bitreader.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/klauspost/compress/zstd/bitreader.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -63,13 +63,6 @@ func (b *bitReader) get32BitsFast(n uint8) uint32 {
 | 
			
		||||
	return v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *bitReader) get16BitsFast(n uint8) uint16 {
 | 
			
		||||
	const regMask = 64 - 1
 | 
			
		||||
	v := uint16((b.value << (b.bitsRead & regMask)) >> ((regMask + 1 - n) & regMask))
 | 
			
		||||
	b.bitsRead += n
 | 
			
		||||
	return v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// fillFast() will make sure at least 32 bits are available.
 | 
			
		||||
// There must be at least 4 bytes available.
 | 
			
		||||
func (b *bitReader) fillFast() {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										76
									
								
								vendor/github.com/klauspost/compress/zstd/bitwriter.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										76
									
								
								vendor/github.com/klauspost/compress/zstd/bitwriter.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -5,8 +5,6 @@
 | 
			
		||||
 | 
			
		||||
package zstd
 | 
			
		||||
 | 
			
		||||
import "fmt"
 | 
			
		||||
 | 
			
		||||
// bitWriter will write bits.
 | 
			
		||||
// First bit will be LSB of the first byte of output.
 | 
			
		||||
type bitWriter struct {
 | 
			
		||||
@@ -73,80 +71,6 @@ func (b *bitWriter) addBits16Clean(value uint16, bits uint8) {
 | 
			
		||||
	b.nBits += bits
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// flush will flush all pending full bytes.
 | 
			
		||||
// There will be at least 56 bits available for writing when this has been called.
 | 
			
		||||
// Using flush32 is faster, but leaves less space for writing.
 | 
			
		||||
func (b *bitWriter) flush() {
 | 
			
		||||
	v := b.nBits >> 3
 | 
			
		||||
	switch v {
 | 
			
		||||
	case 0:
 | 
			
		||||
	case 1:
 | 
			
		||||
		b.out = append(b.out,
 | 
			
		||||
			byte(b.bitContainer),
 | 
			
		||||
		)
 | 
			
		||||
	case 2:
 | 
			
		||||
		b.out = append(b.out,
 | 
			
		||||
			byte(b.bitContainer),
 | 
			
		||||
			byte(b.bitContainer>>8),
 | 
			
		||||
		)
 | 
			
		||||
	case 3:
 | 
			
		||||
		b.out = append(b.out,
 | 
			
		||||
			byte(b.bitContainer),
 | 
			
		||||
			byte(b.bitContainer>>8),
 | 
			
		||||
			byte(b.bitContainer>>16),
 | 
			
		||||
		)
 | 
			
		||||
	case 4:
 | 
			
		||||
		b.out = append(b.out,
 | 
			
		||||
			byte(b.bitContainer),
 | 
			
		||||
			byte(b.bitContainer>>8),
 | 
			
		||||
			byte(b.bitContainer>>16),
 | 
			
		||||
			byte(b.bitContainer>>24),
 | 
			
		||||
		)
 | 
			
		||||
	case 5:
 | 
			
		||||
		b.out = append(b.out,
 | 
			
		||||
			byte(b.bitContainer),
 | 
			
		||||
			byte(b.bitContainer>>8),
 | 
			
		||||
			byte(b.bitContainer>>16),
 | 
			
		||||
			byte(b.bitContainer>>24),
 | 
			
		||||
			byte(b.bitContainer>>32),
 | 
			
		||||
		)
 | 
			
		||||
	case 6:
 | 
			
		||||
		b.out = append(b.out,
 | 
			
		||||
			byte(b.bitContainer),
 | 
			
		||||
			byte(b.bitContainer>>8),
 | 
			
		||||
			byte(b.bitContainer>>16),
 | 
			
		||||
			byte(b.bitContainer>>24),
 | 
			
		||||
			byte(b.bitContainer>>32),
 | 
			
		||||
			byte(b.bitContainer>>40),
 | 
			
		||||
		)
 | 
			
		||||
	case 7:
 | 
			
		||||
		b.out = append(b.out,
 | 
			
		||||
			byte(b.bitContainer),
 | 
			
		||||
			byte(b.bitContainer>>8),
 | 
			
		||||
			byte(b.bitContainer>>16),
 | 
			
		||||
			byte(b.bitContainer>>24),
 | 
			
		||||
			byte(b.bitContainer>>32),
 | 
			
		||||
			byte(b.bitContainer>>40),
 | 
			
		||||
			byte(b.bitContainer>>48),
 | 
			
		||||
		)
 | 
			
		||||
	case 8:
 | 
			
		||||
		b.out = append(b.out,
 | 
			
		||||
			byte(b.bitContainer),
 | 
			
		||||
			byte(b.bitContainer>>8),
 | 
			
		||||
			byte(b.bitContainer>>16),
 | 
			
		||||
			byte(b.bitContainer>>24),
 | 
			
		||||
			byte(b.bitContainer>>32),
 | 
			
		||||
			byte(b.bitContainer>>40),
 | 
			
		||||
			byte(b.bitContainer>>48),
 | 
			
		||||
			byte(b.bitContainer>>56),
 | 
			
		||||
		)
 | 
			
		||||
	default:
 | 
			
		||||
		panic(fmt.Errorf("bits (%d) > 64", b.nBits))
 | 
			
		||||
	}
 | 
			
		||||
	b.bitContainer >>= v << 3
 | 
			
		||||
	b.nBits &= 7
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// flush32 will flush out, so there are at least 32 bits available for writing.
 | 
			
		||||
func (b *bitWriter) flush32() {
 | 
			
		||||
	if b.nBits < 32 {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										73
									
								
								vendor/github.com/klauspost/compress/zstd/blockdec.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										73
									
								
								vendor/github.com/klauspost/compress/zstd/blockdec.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -5,9 +5,14 @@
 | 
			
		||||
package zstd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"github.com/klauspost/compress/huff0"
 | 
			
		||||
@@ -38,14 +43,14 @@ const (
 | 
			
		||||
	// maxCompressedBlockSize is the biggest allowed compressed block size (128KB)
 | 
			
		||||
	maxCompressedBlockSize = 128 << 10
 | 
			
		||||
 | 
			
		||||
	compressedBlockOverAlloc    = 16
 | 
			
		||||
	maxCompressedBlockSizeAlloc = 128<<10 + compressedBlockOverAlloc
 | 
			
		||||
 | 
			
		||||
	// Maximum possible block size (all Raw+Uncompressed).
 | 
			
		||||
	maxBlockSize = (1 << 21) - 1
 | 
			
		||||
 | 
			
		||||
	// https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#literals_section_header
 | 
			
		||||
	maxCompressedLiteralSize = 1 << 18
 | 
			
		||||
	maxRLELiteralSize        = 1 << 20
 | 
			
		||||
	maxMatchLen              = 131074
 | 
			
		||||
	maxSequences             = 0x7f00 + 0xffff
 | 
			
		||||
	maxMatchLen  = 131074
 | 
			
		||||
	maxSequences = 0x7f00 + 0xffff
 | 
			
		||||
 | 
			
		||||
	// We support slightly less than the reference decoder to be able to
 | 
			
		||||
	// use ints on 32 bit archs.
 | 
			
		||||
@@ -97,7 +102,6 @@ type blockDec struct {
 | 
			
		||||
 | 
			
		||||
	// Block is RLE, this is the size.
 | 
			
		||||
	RLESize uint32
 | 
			
		||||
	tmp     [4]byte
 | 
			
		||||
 | 
			
		||||
	Type blockType
 | 
			
		||||
 | 
			
		||||
@@ -136,7 +140,7 @@ func (b *blockDec) reset(br byteBuffer, windowSize uint64) error {
 | 
			
		||||
	b.Type = blockType((bh >> 1) & 3)
 | 
			
		||||
	// find size.
 | 
			
		||||
	cSize := int(bh >> 3)
 | 
			
		||||
	maxSize := maxBlockSize
 | 
			
		||||
	maxSize := maxCompressedBlockSizeAlloc
 | 
			
		||||
	switch b.Type {
 | 
			
		||||
	case blockTypeReserved:
 | 
			
		||||
		return ErrReservedBlockType
 | 
			
		||||
@@ -157,9 +161,9 @@ func (b *blockDec) reset(br byteBuffer, windowSize uint64) error {
 | 
			
		||||
			println("Data size on stream:", cSize)
 | 
			
		||||
		}
 | 
			
		||||
		b.RLESize = 0
 | 
			
		||||
		maxSize = maxCompressedBlockSize
 | 
			
		||||
		maxSize = maxCompressedBlockSizeAlloc
 | 
			
		||||
		if windowSize < maxCompressedBlockSize && b.lowMem {
 | 
			
		||||
			maxSize = int(windowSize)
 | 
			
		||||
			maxSize = int(windowSize) + compressedBlockOverAlloc
 | 
			
		||||
		}
 | 
			
		||||
		if cSize > maxCompressedBlockSize || uint64(cSize) > b.WindowSize {
 | 
			
		||||
			if debugDecoder {
 | 
			
		||||
@@ -190,9 +194,9 @@ func (b *blockDec) reset(br byteBuffer, windowSize uint64) error {
 | 
			
		||||
	// Read block data.
 | 
			
		||||
	if cap(b.dataStorage) < cSize {
 | 
			
		||||
		if b.lowMem || cSize > maxCompressedBlockSize {
 | 
			
		||||
			b.dataStorage = make([]byte, 0, cSize)
 | 
			
		||||
			b.dataStorage = make([]byte, 0, cSize+compressedBlockOverAlloc)
 | 
			
		||||
		} else {
 | 
			
		||||
			b.dataStorage = make([]byte, 0, maxCompressedBlockSize)
 | 
			
		||||
			b.dataStorage = make([]byte, 0, maxCompressedBlockSizeAlloc)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if cap(b.dst) <= maxSize {
 | 
			
		||||
@@ -360,14 +364,9 @@ func (b *blockDec) decodeLiterals(in []byte, hist *history) (remain []byte, err
 | 
			
		||||
		}
 | 
			
		||||
		if cap(b.literalBuf) < litRegenSize {
 | 
			
		||||
			if b.lowMem {
 | 
			
		||||
				b.literalBuf = make([]byte, litRegenSize)
 | 
			
		||||
				b.literalBuf = make([]byte, litRegenSize, litRegenSize+compressedBlockOverAlloc)
 | 
			
		||||
			} else {
 | 
			
		||||
				if litRegenSize > maxCompressedLiteralSize {
 | 
			
		||||
					// Exceptional
 | 
			
		||||
					b.literalBuf = make([]byte, litRegenSize)
 | 
			
		||||
				} else {
 | 
			
		||||
					b.literalBuf = make([]byte, litRegenSize, maxCompressedLiteralSize)
 | 
			
		||||
				}
 | 
			
		||||
				b.literalBuf = make([]byte, litRegenSize, maxCompressedBlockSize+compressedBlockOverAlloc)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		literals = b.literalBuf[:litRegenSize]
 | 
			
		||||
@@ -397,14 +396,14 @@ func (b *blockDec) decodeLiterals(in []byte, hist *history) (remain []byte, err
 | 
			
		||||
		// Ensure we have space to store it.
 | 
			
		||||
		if cap(b.literalBuf) < litRegenSize {
 | 
			
		||||
			if b.lowMem {
 | 
			
		||||
				b.literalBuf = make([]byte, 0, litRegenSize)
 | 
			
		||||
				b.literalBuf = make([]byte, 0, litRegenSize+compressedBlockOverAlloc)
 | 
			
		||||
			} else {
 | 
			
		||||
				b.literalBuf = make([]byte, 0, maxCompressedLiteralSize)
 | 
			
		||||
				b.literalBuf = make([]byte, 0, maxCompressedBlockSize+compressedBlockOverAlloc)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		var err error
 | 
			
		||||
		// Use our out buffer.
 | 
			
		||||
		huff.MaxDecodedSize = maxCompressedBlockSize
 | 
			
		||||
		huff.MaxDecodedSize = litRegenSize
 | 
			
		||||
		if fourStreams {
 | 
			
		||||
			literals, err = huff.Decoder().Decompress4X(b.literalBuf[:0:litRegenSize], literals)
 | 
			
		||||
		} else {
 | 
			
		||||
@@ -429,9 +428,9 @@ func (b *blockDec) decodeLiterals(in []byte, hist *history) (remain []byte, err
 | 
			
		||||
		// Ensure we have space to store it.
 | 
			
		||||
		if cap(b.literalBuf) < litRegenSize {
 | 
			
		||||
			if b.lowMem {
 | 
			
		||||
				b.literalBuf = make([]byte, 0, litRegenSize)
 | 
			
		||||
				b.literalBuf = make([]byte, 0, litRegenSize+compressedBlockOverAlloc)
 | 
			
		||||
			} else {
 | 
			
		||||
				b.literalBuf = make([]byte, 0, maxCompressedBlockSize)
 | 
			
		||||
				b.literalBuf = make([]byte, 0, maxCompressedBlockSize+compressedBlockOverAlloc)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		huff := hist.huffTree
 | 
			
		||||
@@ -448,7 +447,7 @@ func (b *blockDec) decodeLiterals(in []byte, hist *history) (remain []byte, err
 | 
			
		||||
			return in, err
 | 
			
		||||
		}
 | 
			
		||||
		hist.huffTree = huff
 | 
			
		||||
		huff.MaxDecodedSize = maxCompressedBlockSize
 | 
			
		||||
		huff.MaxDecodedSize = litRegenSize
 | 
			
		||||
		// Use our out buffer.
 | 
			
		||||
		if fourStreams {
 | 
			
		||||
			literals, err = huff.Decoder().Decompress4X(b.literalBuf[:0:litRegenSize], literals)
 | 
			
		||||
@@ -463,6 +462,8 @@ func (b *blockDec) decodeLiterals(in []byte, hist *history) (remain []byte, err
 | 
			
		||||
		if len(literals) != litRegenSize {
 | 
			
		||||
			return in, fmt.Errorf("literal output size mismatch want %d, got %d", litRegenSize, len(literals))
 | 
			
		||||
		}
 | 
			
		||||
		// Re-cap to get extra size.
 | 
			
		||||
		literals = b.literalBuf[:len(literals)]
 | 
			
		||||
		if debugDecoder {
 | 
			
		||||
			printf("Decompressed %d literals into %d bytes\n", litCompSize, litRegenSize)
 | 
			
		||||
		}
 | 
			
		||||
@@ -486,10 +487,15 @@ func (b *blockDec) decodeCompressed(hist *history) error {
 | 
			
		||||
		b.dst = append(b.dst, hist.decoders.literals...)
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	err = hist.decoders.decodeSync(hist)
 | 
			
		||||
	before := len(hist.decoders.out)
 | 
			
		||||
	err = hist.decoders.decodeSync(hist.b[hist.ignoreBuffer:])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if hist.decoders.maxSyncLen > 0 {
 | 
			
		||||
		hist.decoders.maxSyncLen += uint64(before)
 | 
			
		||||
		hist.decoders.maxSyncLen -= uint64(len(hist.decoders.out))
 | 
			
		||||
	}
 | 
			
		||||
	b.dst = hist.decoders.out
 | 
			
		||||
	hist.recentOffsets = hist.decoders.prevOffset
 | 
			
		||||
	return nil
 | 
			
		||||
@@ -632,6 +638,22 @@ func (b *blockDec) prepareSequences(in []byte, hist *history) (err error) {
 | 
			
		||||
		println("initializing sequences:", err)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	// Extract blocks...
 | 
			
		||||
	if false && hist.dict == nil {
 | 
			
		||||
		fatalErr := func(err error) {
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				panic(err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		fn := fmt.Sprintf("n-%d-lits-%d-prev-%d-%d-%d-win-%d.blk", hist.decoders.nSeqs, len(hist.decoders.literals), hist.recentOffsets[0], hist.recentOffsets[1], hist.recentOffsets[2], hist.windowSize)
 | 
			
		||||
		var buf bytes.Buffer
 | 
			
		||||
		fatalErr(binary.Write(&buf, binary.LittleEndian, hist.decoders.litLengths.fse))
 | 
			
		||||
		fatalErr(binary.Write(&buf, binary.LittleEndian, hist.decoders.matchLengths.fse))
 | 
			
		||||
		fatalErr(binary.Write(&buf, binary.LittleEndian, hist.decoders.offsets.fse))
 | 
			
		||||
		buf.Write(in)
 | 
			
		||||
		ioutil.WriteFile(filepath.Join("testdata", "seqs", fn), buf.Bytes(), os.ModePerm)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -650,6 +672,7 @@ func (b *blockDec) decodeSequences(hist *history) error {
 | 
			
		||||
	}
 | 
			
		||||
	hist.decoders.windowSize = hist.windowSize
 | 
			
		||||
	hist.decoders.prevOffset = hist.recentOffsets
 | 
			
		||||
 | 
			
		||||
	err := hist.decoders.decode(b.sequence)
 | 
			
		||||
	hist.recentOffsets = hist.decoders.prevOffset
 | 
			
		||||
	return err
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/github.com/klauspost/compress/zstd/bytebuf.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/klauspost/compress/zstd/bytebuf.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -52,10 +52,6 @@ func (b *byteBuf) readBig(n int, dst []byte) ([]byte, error) {
 | 
			
		||||
	return r, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *byteBuf) remain() []byte {
 | 
			
		||||
	return *b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *byteBuf) readByte() (byte, error) {
 | 
			
		||||
	bb := *b
 | 
			
		||||
	if len(bb) < 1 {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								vendor/github.com/klauspost/compress/zstd/bytereader.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/klauspost/compress/zstd/bytereader.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -13,12 +13,6 @@ type byteReader struct {
 | 
			
		||||
	off int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// init will initialize the reader and set the input.
 | 
			
		||||
func (b *byteReader) init(in []byte) {
 | 
			
		||||
	b.b = in
 | 
			
		||||
	b.off = 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// advance the stream b n bytes.
 | 
			
		||||
func (b *byteReader) advance(n uint) {
 | 
			
		||||
	b.off += int(n)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										121
									
								
								vendor/github.com/klauspost/compress/zstd/decoder.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										121
									
								
								vendor/github.com/klauspost/compress/zstd/decoder.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -347,18 +347,20 @@ func (d *Decoder) DecodeAll(input, dst []byte) ([]byte, error) {
 | 
			
		||||
			}
 | 
			
		||||
			frame.history.setDict(&dict)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if frame.FrameContentSize != fcsUnknown && frame.FrameContentSize > d.o.maxDecodedSize-uint64(len(dst)) {
 | 
			
		||||
			return dst, ErrDecoderSizeExceeded
 | 
			
		||||
		if frame.WindowSize > d.o.maxWindowSize {
 | 
			
		||||
			return dst, ErrWindowSizeExceeded
 | 
			
		||||
		}
 | 
			
		||||
		if frame.FrameContentSize < 1<<30 {
 | 
			
		||||
			// Never preallocate more than 1 GB up front.
 | 
			
		||||
		if frame.FrameContentSize != fcsUnknown {
 | 
			
		||||
			if frame.FrameContentSize > d.o.maxDecodedSize-uint64(len(dst)) {
 | 
			
		||||
				return dst, ErrDecoderSizeExceeded
 | 
			
		||||
			}
 | 
			
		||||
			if cap(dst)-len(dst) < int(frame.FrameContentSize) {
 | 
			
		||||
				dst2 := make([]byte, len(dst), len(dst)+int(frame.FrameContentSize))
 | 
			
		||||
				dst2 := make([]byte, len(dst), len(dst)+int(frame.FrameContentSize)+compressedBlockOverAlloc)
 | 
			
		||||
				copy(dst2, dst)
 | 
			
		||||
				dst = dst2
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if cap(dst) == 0 {
 | 
			
		||||
			// Allocate len(input) * 2 by default if nothing is provided
 | 
			
		||||
			// and we didn't get frame content size.
 | 
			
		||||
@@ -437,7 +439,7 @@ func (d *Decoder) nextBlock(blocking bool) (ok bool) {
 | 
			
		||||
		println("got", len(d.current.b), "bytes, error:", d.current.err, "data crc:", tmp)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(next.b) > 0 {
 | 
			
		||||
	if !d.o.ignoreChecksum && len(next.b) > 0 {
 | 
			
		||||
		n, err := d.current.crc.Write(next.b)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			if n != len(next.b) {
 | 
			
		||||
@@ -449,7 +451,7 @@ func (d *Decoder) nextBlock(blocking bool) (ok bool) {
 | 
			
		||||
		got := d.current.crc.Sum64()
 | 
			
		||||
		var tmp [4]byte
 | 
			
		||||
		binary.LittleEndian.PutUint32(tmp[:], uint32(got))
 | 
			
		||||
		if !bytes.Equal(tmp[:], next.d.checkCRC) && !ignoreCRC {
 | 
			
		||||
		if !d.o.ignoreChecksum && !bytes.Equal(tmp[:], next.d.checkCRC) {
 | 
			
		||||
			if debugDecoder {
 | 
			
		||||
				println("CRC Check Failed:", tmp[:], " (got) !=", next.d.checkCRC, "(on stream)")
 | 
			
		||||
			}
 | 
			
		||||
@@ -533,9 +535,15 @@ func (d *Decoder) nextBlockSync() (ok bool) {
 | 
			
		||||
 | 
			
		||||
		// Update/Check CRC
 | 
			
		||||
		if d.frame.HasCheckSum {
 | 
			
		||||
			d.frame.crc.Write(d.current.b)
 | 
			
		||||
			if !d.o.ignoreChecksum {
 | 
			
		||||
				d.frame.crc.Write(d.current.b)
 | 
			
		||||
			}
 | 
			
		||||
			if d.current.d.Last {
 | 
			
		||||
				d.current.err = d.frame.checkCRC()
 | 
			
		||||
				if !d.o.ignoreChecksum {
 | 
			
		||||
					d.current.err = d.frame.checkCRC()
 | 
			
		||||
				} else {
 | 
			
		||||
					d.current.err = d.frame.consumeCRC()
 | 
			
		||||
				}
 | 
			
		||||
				if d.current.err != nil {
 | 
			
		||||
					println("CRC error:", d.current.err)
 | 
			
		||||
					return false
 | 
			
		||||
@@ -629,60 +637,18 @@ func (d *Decoder) startSyncDecoder(r io.Reader) error {
 | 
			
		||||
 | 
			
		||||
// Create Decoder:
 | 
			
		||||
// ASYNC:
 | 
			
		||||
// Spawn 4 go routines.
 | 
			
		||||
// 0: Read frames and decode blocks.
 | 
			
		||||
// 1: Decode block and literals. Receives hufftree and seqdecs, returns seqdecs and huff tree.
 | 
			
		||||
// 2: Wait for recentOffsets if needed. Decode sequences, send recentOffsets.
 | 
			
		||||
// 3: Wait for stream history, execute sequences, send stream history.
 | 
			
		||||
// Spawn 3 go routines.
 | 
			
		||||
// 0: Read frames and decode block literals.
 | 
			
		||||
// 1: Decode sequences.
 | 
			
		||||
// 2: Execute sequences, send to output.
 | 
			
		||||
func (d *Decoder) startStreamDecoder(ctx context.Context, r io.Reader, output chan decodeOutput) {
 | 
			
		||||
	defer d.streamWg.Done()
 | 
			
		||||
	br := readerWrapper{r: r}
 | 
			
		||||
 | 
			
		||||
	var seqPrepare = make(chan *blockDec, d.o.concurrent)
 | 
			
		||||
	var seqDecode = make(chan *blockDec, d.o.concurrent)
 | 
			
		||||
	var seqExecute = make(chan *blockDec, d.o.concurrent)
 | 
			
		||||
 | 
			
		||||
	// Async 1: Prepare blocks...
 | 
			
		||||
	go func() {
 | 
			
		||||
		var hist history
 | 
			
		||||
		var hasErr bool
 | 
			
		||||
		for block := range seqPrepare {
 | 
			
		||||
			if hasErr {
 | 
			
		||||
				if block != nil {
 | 
			
		||||
					seqDecode <- block
 | 
			
		||||
				}
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if block.async.newHist != nil {
 | 
			
		||||
				if debugDecoder {
 | 
			
		||||
					println("Async 1: new history")
 | 
			
		||||
				}
 | 
			
		||||
				hist.reset()
 | 
			
		||||
				if block.async.newHist.dict != nil {
 | 
			
		||||
					hist.setDict(block.async.newHist.dict)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if block.err != nil || block.Type != blockTypeCompressed {
 | 
			
		||||
				hasErr = block.err != nil
 | 
			
		||||
				seqDecode <- block
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			remain, err := block.decodeLiterals(block.data, &hist)
 | 
			
		||||
			block.err = err
 | 
			
		||||
			hasErr = block.err != nil
 | 
			
		||||
			if err == nil {
 | 
			
		||||
				block.async.literals = hist.decoders.literals
 | 
			
		||||
				block.async.seqData = remain
 | 
			
		||||
			} else if debugDecoder {
 | 
			
		||||
				println("decodeLiterals error:", err)
 | 
			
		||||
			}
 | 
			
		||||
			seqDecode <- block
 | 
			
		||||
		}
 | 
			
		||||
		close(seqDecode)
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	// Async 2: Decode sequences...
 | 
			
		||||
	// Async 1: Decode sequences...
 | 
			
		||||
	go func() {
 | 
			
		||||
		var hist history
 | 
			
		||||
		var hasErr bool
 | 
			
		||||
@@ -696,7 +662,7 @@ func (d *Decoder) startStreamDecoder(ctx context.Context, r io.Reader, output ch
 | 
			
		||||
			}
 | 
			
		||||
			if block.async.newHist != nil {
 | 
			
		||||
				if debugDecoder {
 | 
			
		||||
					println("Async 2: new history, recent:", block.async.newHist.recentOffsets)
 | 
			
		||||
					println("Async 1: new history, recent:", block.async.newHist.recentOffsets)
 | 
			
		||||
				}
 | 
			
		||||
				hist.decoders = block.async.newHist.decoders
 | 
			
		||||
				hist.recentOffsets = block.async.newHist.recentOffsets
 | 
			
		||||
@@ -750,7 +716,7 @@ func (d *Decoder) startStreamDecoder(ctx context.Context, r io.Reader, output ch
 | 
			
		||||
			}
 | 
			
		||||
			if block.async.newHist != nil {
 | 
			
		||||
				if debugDecoder {
 | 
			
		||||
					println("Async 3: new history")
 | 
			
		||||
					println("Async 2: new history")
 | 
			
		||||
				}
 | 
			
		||||
				hist.windowSize = block.async.newHist.windowSize
 | 
			
		||||
				hist.allocFrameBuffer = block.async.newHist.allocFrameBuffer
 | 
			
		||||
@@ -837,6 +803,33 @@ func (d *Decoder) startStreamDecoder(ctx context.Context, r io.Reader, output ch
 | 
			
		||||
 | 
			
		||||
decodeStream:
 | 
			
		||||
	for {
 | 
			
		||||
		var hist history
 | 
			
		||||
		var hasErr bool
 | 
			
		||||
 | 
			
		||||
		decodeBlock := func(block *blockDec) {
 | 
			
		||||
			if hasErr {
 | 
			
		||||
				if block != nil {
 | 
			
		||||
					seqDecode <- block
 | 
			
		||||
				}
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			if block.err != nil || block.Type != blockTypeCompressed {
 | 
			
		||||
				hasErr = block.err != nil
 | 
			
		||||
				seqDecode <- block
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			remain, err := block.decodeLiterals(block.data, &hist)
 | 
			
		||||
			block.err = err
 | 
			
		||||
			hasErr = block.err != nil
 | 
			
		||||
			if err == nil {
 | 
			
		||||
				block.async.literals = hist.decoders.literals
 | 
			
		||||
				block.async.seqData = remain
 | 
			
		||||
			} else if debugDecoder {
 | 
			
		||||
				println("decodeLiterals error:", err)
 | 
			
		||||
			}
 | 
			
		||||
			seqDecode <- block
 | 
			
		||||
		}
 | 
			
		||||
		frame := d.frame
 | 
			
		||||
		if debugDecoder {
 | 
			
		||||
			println("New frame...")
 | 
			
		||||
@@ -863,7 +856,7 @@ decodeStream:
 | 
			
		||||
			case <-ctx.Done():
 | 
			
		||||
			case dec := <-d.decoders:
 | 
			
		||||
				dec.sendErr(err)
 | 
			
		||||
				seqPrepare <- dec
 | 
			
		||||
				decodeBlock(dec)
 | 
			
		||||
			}
 | 
			
		||||
			break decodeStream
 | 
			
		||||
		}
 | 
			
		||||
@@ -883,6 +876,10 @@ decodeStream:
 | 
			
		||||
				if debugDecoder {
 | 
			
		||||
					println("Alloc History:", h.allocFrameBuffer)
 | 
			
		||||
				}
 | 
			
		||||
				hist.reset()
 | 
			
		||||
				if h.dict != nil {
 | 
			
		||||
					hist.setDict(h.dict)
 | 
			
		||||
				}
 | 
			
		||||
				dec.async.newHist = &h
 | 
			
		||||
				dec.async.fcs = frame.FrameContentSize
 | 
			
		||||
				historySent = true
 | 
			
		||||
@@ -909,7 +906,7 @@ decodeStream:
 | 
			
		||||
			}
 | 
			
		||||
			err = dec.err
 | 
			
		||||
			last := dec.Last
 | 
			
		||||
			seqPrepare <- dec
 | 
			
		||||
			decodeBlock(dec)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				break decodeStream
 | 
			
		||||
			}
 | 
			
		||||
@@ -918,7 +915,7 @@ decodeStream:
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	close(seqPrepare)
 | 
			
		||||
	close(seqDecode)
 | 
			
		||||
	wg.Wait()
 | 
			
		||||
	d.frame.history.b = frameHistCache
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								vendor/github.com/klauspost/compress/zstd/decoder_options.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/klauspost/compress/zstd/decoder_options.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -19,6 +19,7 @@ type decoderOptions struct {
 | 
			
		||||
	maxDecodedSize uint64
 | 
			
		||||
	maxWindowSize  uint64
 | 
			
		||||
	dicts          []dict
 | 
			
		||||
	ignoreChecksum bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *decoderOptions) setDefault() {
 | 
			
		||||
@@ -31,7 +32,7 @@ func (o *decoderOptions) setDefault() {
 | 
			
		||||
	if o.concurrent > 4 {
 | 
			
		||||
		o.concurrent = 4
 | 
			
		||||
	}
 | 
			
		||||
	o.maxDecodedSize = 1 << 63
 | 
			
		||||
	o.maxDecodedSize = 64 << 30
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WithDecoderLowmem will set whether to use a lower amount of memory,
 | 
			
		||||
@@ -66,7 +67,7 @@ func WithDecoderConcurrency(n int) DOption {
 | 
			
		||||
// WithDecoderMaxMemory allows to set a maximum decoded size for in-memory
 | 
			
		||||
// non-streaming operations or maximum window size for streaming operations.
 | 
			
		||||
// This can be used to control memory usage of potentially hostile content.
 | 
			
		||||
// Maximum and default is 1 << 63 bytes.
 | 
			
		||||
// Maximum is 1 << 63 bytes. Default is 64GiB.
 | 
			
		||||
func WithDecoderMaxMemory(n uint64) DOption {
 | 
			
		||||
	return func(o *decoderOptions) error {
 | 
			
		||||
		if n == 0 {
 | 
			
		||||
@@ -112,3 +113,11 @@ func WithDecoderMaxWindow(size uint64) DOption {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IgnoreChecksum allows to forcibly ignore checksum checking.
 | 
			
		||||
func IgnoreChecksum(b bool) DOption {
 | 
			
		||||
	return func(o *decoderOptions) error {
 | 
			
		||||
		o.ignoreChecksum = b
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								vendor/github.com/klauspost/compress/zstd/enc_better.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/klauspost/compress/zstd/enc_better.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -156,8 +156,8 @@ encodeLoop:
 | 
			
		||||
				panic("offset0 was 0")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			nextHashS := hashLen(cv, betterShortTableBits, betterShortLen)
 | 
			
		||||
			nextHashL := hashLen(cv, betterLongTableBits, betterLongLen)
 | 
			
		||||
			nextHashS := hashLen(cv, betterShortTableBits, betterShortLen)
 | 
			
		||||
			candidateL := e.longTable[nextHashL]
 | 
			
		||||
			candidateS := e.table[nextHashS]
 | 
			
		||||
 | 
			
		||||
@@ -518,8 +518,8 @@ encodeLoop:
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Store this, since we have it.
 | 
			
		||||
			nextHashS := hashLen(cv, betterShortTableBits, betterShortLen)
 | 
			
		||||
			nextHashL := hashLen(cv, betterLongTableBits, betterLongLen)
 | 
			
		||||
			nextHashS := hashLen(cv, betterShortTableBits, betterShortLen)
 | 
			
		||||
 | 
			
		||||
			// We have at least 4 byte match.
 | 
			
		||||
			// No need to check backwards. We come straight from a match
 | 
			
		||||
@@ -674,8 +674,8 @@ encodeLoop:
 | 
			
		||||
				panic("offset0 was 0")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			nextHashS := hashLen(cv, betterShortTableBits, betterShortLen)
 | 
			
		||||
			nextHashL := hashLen(cv, betterLongTableBits, betterLongLen)
 | 
			
		||||
			nextHashS := hashLen(cv, betterShortTableBits, betterShortLen)
 | 
			
		||||
			candidateL := e.longTable[nextHashL]
 | 
			
		||||
			candidateS := e.table[nextHashS]
 | 
			
		||||
 | 
			
		||||
@@ -1047,8 +1047,8 @@ encodeLoop:
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Store this, since we have it.
 | 
			
		||||
			nextHashS := hashLen(cv, betterShortTableBits, betterShortLen)
 | 
			
		||||
			nextHashL := hashLen(cv, betterLongTableBits, betterLongLen)
 | 
			
		||||
			nextHashS := hashLen(cv, betterShortTableBits, betterShortLen)
 | 
			
		||||
 | 
			
		||||
			// We have at least 4 byte match.
 | 
			
		||||
			// No need to check backwards. We come straight from a match
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								vendor/github.com/klauspost/compress/zstd/enc_dfast.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								vendor/github.com/klauspost/compress/zstd/enc_dfast.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -127,8 +127,8 @@ encodeLoop:
 | 
			
		||||
				panic("offset0 was 0")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			nextHashS := hashLen(cv, dFastShortTableBits, dFastShortLen)
 | 
			
		||||
			nextHashL := hashLen(cv, dFastLongTableBits, dFastLongLen)
 | 
			
		||||
			nextHashS := hashLen(cv, dFastShortTableBits, dFastShortLen)
 | 
			
		||||
			candidateL := e.longTable[nextHashL]
 | 
			
		||||
			candidateS := e.table[nextHashS]
 | 
			
		||||
 | 
			
		||||
@@ -439,8 +439,8 @@ encodeLoop:
 | 
			
		||||
		var t int32
 | 
			
		||||
		for {
 | 
			
		||||
 | 
			
		||||
			nextHashS := hashLen(cv, dFastShortTableBits, dFastShortLen)
 | 
			
		||||
			nextHashL := hashLen(cv, dFastLongTableBits, dFastLongLen)
 | 
			
		||||
			nextHashS := hashLen(cv, dFastShortTableBits, dFastShortLen)
 | 
			
		||||
			candidateL := e.longTable[nextHashL]
 | 
			
		||||
			candidateS := e.table[nextHashS]
 | 
			
		||||
 | 
			
		||||
@@ -785,8 +785,8 @@ encodeLoop:
 | 
			
		||||
				panic("offset0 was 0")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			nextHashS := hashLen(cv, dFastShortTableBits, dFastShortLen)
 | 
			
		||||
			nextHashL := hashLen(cv, dFastLongTableBits, dFastLongLen)
 | 
			
		||||
			nextHashS := hashLen(cv, dFastShortTableBits, dFastShortLen)
 | 
			
		||||
			candidateL := e.longTable[nextHashL]
 | 
			
		||||
			candidateS := e.table[nextHashS]
 | 
			
		||||
 | 
			
		||||
@@ -969,7 +969,7 @@ encodeLoop:
 | 
			
		||||
		te0 := tableEntry{offset: index0 + e.cur, val: uint32(cv0)}
 | 
			
		||||
		te1 := tableEntry{offset: index1 + e.cur, val: uint32(cv1)}
 | 
			
		||||
		longHash1 := hashLen(cv0, dFastLongTableBits, dFastLongLen)
 | 
			
		||||
		longHash2 := hashLen(cv0, dFastLongTableBits, dFastLongLen)
 | 
			
		||||
		longHash2 := hashLen(cv1, dFastLongTableBits, dFastLongLen)
 | 
			
		||||
		e.longTable[longHash1] = te0
 | 
			
		||||
		e.longTable[longHash2] = te1
 | 
			
		||||
		e.markLongShardDirty(longHash1)
 | 
			
		||||
@@ -1002,8 +1002,8 @@ encodeLoop:
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Store this, since we have it.
 | 
			
		||||
			nextHashS := hashLen(cv, dFastShortTableBits, dFastShortLen)
 | 
			
		||||
			nextHashL := hashLen(cv, dFastLongTableBits, dFastLongLen)
 | 
			
		||||
			nextHashS := hashLen(cv, dFastShortTableBits, dFastShortLen)
 | 
			
		||||
 | 
			
		||||
			// We have at least 4 byte match.
 | 
			
		||||
			// No need to check backwards. We come straight from a match
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/klauspost/compress/zstd/encoder.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/klauspost/compress/zstd/encoder.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -551,7 +551,7 @@ func (e *Encoder) EncodeAll(src, dst []byte) []byte {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If we can do everything in one block, prefer that.
 | 
			
		||||
	if len(src) <= maxCompressedBlockSize {
 | 
			
		||||
	if len(src) <= e.o.blockSize {
 | 
			
		||||
		enc.Reset(e.o.dict, true)
 | 
			
		||||
		// Slightly faster with no history and everything in one block.
 | 
			
		||||
		if e.o.crc {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										70
									
								
								vendor/github.com/klauspost/compress/zstd/framedec.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										70
									
								
								vendor/github.com/klauspost/compress/zstd/framedec.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -253,10 +253,11 @@ func (d *frameDec) reset(br byteBuffer) error {
 | 
			
		||||
		return ErrWindowSizeTooSmall
 | 
			
		||||
	}
 | 
			
		||||
	d.history.windowSize = int(d.WindowSize)
 | 
			
		||||
	if d.o.lowMem && d.history.windowSize < maxBlockSize {
 | 
			
		||||
	if !d.o.lowMem || d.history.windowSize < maxBlockSize {
 | 
			
		||||
		// Alloc 2x window size if not low-mem, or very small window size.
 | 
			
		||||
		d.history.allocFrameBuffer = d.history.windowSize * 2
 | 
			
		||||
		// TODO: Maybe use FrameContent size
 | 
			
		||||
	} else {
 | 
			
		||||
		// Alloc with one additional block
 | 
			
		||||
		d.history.allocFrameBuffer = d.history.windowSize + maxBlockSize
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -290,13 +291,6 @@ func (d *frameDec) checkCRC() error {
 | 
			
		||||
	if !d.HasCheckSum {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	var tmp [4]byte
 | 
			
		||||
	got := d.crc.Sum64()
 | 
			
		||||
	// Flip to match file order.
 | 
			
		||||
	tmp[0] = byte(got >> 0)
 | 
			
		||||
	tmp[1] = byte(got >> 8)
 | 
			
		||||
	tmp[2] = byte(got >> 16)
 | 
			
		||||
	tmp[3] = byte(got >> 24)
 | 
			
		||||
 | 
			
		||||
	// We can overwrite upper tmp now
 | 
			
		||||
	want, err := d.rawInput.readSmall(4)
 | 
			
		||||
@@ -305,7 +299,19 @@ func (d *frameDec) checkCRC() error {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !bytes.Equal(tmp[:], want) && !ignoreCRC {
 | 
			
		||||
	if d.o.ignoreChecksum {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var tmp [4]byte
 | 
			
		||||
	got := d.crc.Sum64()
 | 
			
		||||
	// Flip to match file order.
 | 
			
		||||
	tmp[0] = byte(got >> 0)
 | 
			
		||||
	tmp[1] = byte(got >> 8)
 | 
			
		||||
	tmp[2] = byte(got >> 16)
 | 
			
		||||
	tmp[3] = byte(got >> 24)
 | 
			
		||||
 | 
			
		||||
	if !bytes.Equal(tmp[:], want) {
 | 
			
		||||
		if debugDecoder {
 | 
			
		||||
			println("CRC Check Failed:", tmp[:], "!=", want)
 | 
			
		||||
		}
 | 
			
		||||
@@ -317,6 +323,19 @@ func (d *frameDec) checkCRC() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// consumeCRC reads the checksum data if the frame has one.
 | 
			
		||||
func (d *frameDec) consumeCRC() error {
 | 
			
		||||
	if d.HasCheckSum {
 | 
			
		||||
		_, err := d.rawInput.readSmall(4)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			println("CRC missing?", err)
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// runDecoder will create a sync decoder that will decode a block of data.
 | 
			
		||||
func (d *frameDec) runDecoder(dst []byte, dec *blockDec) ([]byte, error) {
 | 
			
		||||
	saved := d.history.b
 | 
			
		||||
@@ -326,6 +345,19 @@ func (d *frameDec) runDecoder(dst []byte, dec *blockDec) ([]byte, error) {
 | 
			
		||||
	d.history.ignoreBuffer = len(dst)
 | 
			
		||||
	// Store input length, so we only check new data.
 | 
			
		||||
	crcStart := len(dst)
 | 
			
		||||
	d.history.decoders.maxSyncLen = 0
 | 
			
		||||
	if d.FrameContentSize != fcsUnknown {
 | 
			
		||||
		d.history.decoders.maxSyncLen = d.FrameContentSize + uint64(len(dst))
 | 
			
		||||
		if d.history.decoders.maxSyncLen > d.o.maxDecodedSize {
 | 
			
		||||
			return dst, ErrDecoderSizeExceeded
 | 
			
		||||
		}
 | 
			
		||||
		if uint64(cap(dst)) < d.history.decoders.maxSyncLen {
 | 
			
		||||
			// Alloc for output
 | 
			
		||||
			dst2 := make([]byte, len(dst), d.history.decoders.maxSyncLen+compressedBlockOverAlloc)
 | 
			
		||||
			copy(dst2, dst)
 | 
			
		||||
			dst = dst2
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	var err error
 | 
			
		||||
	for {
 | 
			
		||||
		err = dec.reset(d.rawInput, d.WindowSize)
 | 
			
		||||
@@ -360,13 +392,17 @@ func (d *frameDec) runDecoder(dst []byte, dec *blockDec) ([]byte, error) {
 | 
			
		||||
		if d.FrameContentSize != fcsUnknown && uint64(len(d.history.b)-crcStart) != d.FrameContentSize {
 | 
			
		||||
			err = ErrFrameSizeMismatch
 | 
			
		||||
		} else if d.HasCheckSum {
 | 
			
		||||
			var n int
 | 
			
		||||
			n, err = d.crc.Write(dst[crcStart:])
 | 
			
		||||
			if err == nil {
 | 
			
		||||
				if n != len(dst)-crcStart {
 | 
			
		||||
					err = io.ErrShortWrite
 | 
			
		||||
				} else {
 | 
			
		||||
					err = d.checkCRC()
 | 
			
		||||
			if d.o.ignoreChecksum {
 | 
			
		||||
				err = d.consumeCRC()
 | 
			
		||||
			} else {
 | 
			
		||||
				var n int
 | 
			
		||||
				n, err = d.crc.Write(dst[crcStart:])
 | 
			
		||||
				if err == nil {
 | 
			
		||||
					if n != len(dst)-crcStart {
 | 
			
		||||
						err = io.ErrShortWrite
 | 
			
		||||
					} else {
 | 
			
		||||
						err = d.checkCRC()
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										65
									
								
								vendor/github.com/klauspost/compress/zstd/fse_decoder.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										65
									
								
								vendor/github.com/klauspost/compress/zstd/fse_decoder.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -5,8 +5,10 @@
 | 
			
		||||
package zstd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
@@ -182,6 +184,29 @@ func (s *fseDecoder) readNCount(b *byteReader, maxSymbol uint16) error {
 | 
			
		||||
	return s.buildDtable()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *fseDecoder) mustReadFrom(r io.Reader) {
 | 
			
		||||
	fatalErr := func(err error) {
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// 	dt             [maxTablesize]decSymbol // Decompression table.
 | 
			
		||||
	//	symbolLen      uint16                  // Length of active part of the symbol table.
 | 
			
		||||
	//	actualTableLog uint8                   // Selected tablelog.
 | 
			
		||||
	//	maxBits        uint8                   // Maximum number of additional bits
 | 
			
		||||
	//	// used for table creation to avoid allocations.
 | 
			
		||||
	//	stateTable [256]uint16
 | 
			
		||||
	//	norm       [maxSymbolValue + 1]int16
 | 
			
		||||
	//	preDefined bool
 | 
			
		||||
	fatalErr(binary.Read(r, binary.LittleEndian, &s.dt))
 | 
			
		||||
	fatalErr(binary.Read(r, binary.LittleEndian, &s.symbolLen))
 | 
			
		||||
	fatalErr(binary.Read(r, binary.LittleEndian, &s.actualTableLog))
 | 
			
		||||
	fatalErr(binary.Read(r, binary.LittleEndian, &s.maxBits))
 | 
			
		||||
	fatalErr(binary.Read(r, binary.LittleEndian, &s.stateTable))
 | 
			
		||||
	fatalErr(binary.Read(r, binary.LittleEndian, &s.norm))
 | 
			
		||||
	fatalErr(binary.Read(r, binary.LittleEndian, &s.preDefined))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// decSymbol contains information about a state entry,
 | 
			
		||||
// Including the state offset base, the output symbol and
 | 
			
		||||
// the number of bits to read for the low part of the destination state.
 | 
			
		||||
@@ -204,18 +229,10 @@ func (d decSymbol) newState() uint16 {
 | 
			
		||||
	return uint16(d >> 16)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d decSymbol) baseline() uint32 {
 | 
			
		||||
	return uint32(d >> 32)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d decSymbol) baselineInt() int {
 | 
			
		||||
	return int(d >> 32)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *decSymbol) set(nbits, addBits uint8, newState uint16, baseline uint32) {
 | 
			
		||||
	*d = decSymbol(nbits) | (decSymbol(addBits) << 8) | (decSymbol(newState) << 16) | (decSymbol(baseline) << 32)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *decSymbol) setNBits(nBits uint8) {
 | 
			
		||||
	const mask = 0xffffffffffffff00
 | 
			
		||||
	*d = (*d & mask) | decSymbol(nBits)
 | 
			
		||||
@@ -231,11 +248,6 @@ func (d *decSymbol) setNewState(state uint16) {
 | 
			
		||||
	*d = (*d & mask) | decSymbol(state)<<16
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *decSymbol) setBaseline(baseline uint32) {
 | 
			
		||||
	const mask = 0xffffffff
 | 
			
		||||
	*d = (*d & mask) | decSymbol(baseline)<<32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *decSymbol) setExt(addBits uint8, baseline uint32) {
 | 
			
		||||
	const mask = 0xffff00ff
 | 
			
		||||
	*d = (*d & mask) | (decSymbol(addBits) << 8) | (decSymbol(baseline) << 32)
 | 
			
		||||
@@ -352,34 +364,7 @@ func (s *fseState) init(br *bitReader, tableLog uint8, dt []decSymbol) {
 | 
			
		||||
	s.state = dt[br.getBits(tableLog)]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// next returns the current symbol and sets the next state.
 | 
			
		||||
// At least tablelog bits must be available in the bit reader.
 | 
			
		||||
func (s *fseState) next(br *bitReader) {
 | 
			
		||||
	lowBits := uint16(br.getBits(s.state.nbBits()))
 | 
			
		||||
	s.state = s.dt[s.state.newState()+lowBits]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// finished returns true if all bits have been read from the bitstream
 | 
			
		||||
// and the next state would require reading bits from the input.
 | 
			
		||||
func (s *fseState) finished(br *bitReader) bool {
 | 
			
		||||
	return br.finished() && s.state.nbBits() > 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// final returns the current state symbol without decoding the next.
 | 
			
		||||
func (s *fseState) final() (int, uint8) {
 | 
			
		||||
	return s.state.baselineInt(), s.state.addBits()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// final returns the current state symbol without decoding the next.
 | 
			
		||||
func (s decSymbol) final() (int, uint8) {
 | 
			
		||||
	return s.baselineInt(), s.addBits()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// nextFast returns the next symbol and sets the next state.
 | 
			
		||||
// This can only be used if no symbols are 0 bits.
 | 
			
		||||
// At least tablelog bits must be available in the bit reader.
 | 
			
		||||
func (s *fseState) nextFast(br *bitReader) (uint32, uint8) {
 | 
			
		||||
	lowBits := br.get16BitsFast(s.state.nbBits())
 | 
			
		||||
	s.state = s.dt[s.state.newState()+lowBits]
 | 
			
		||||
	return s.state.baseline(), s.state.addBits()
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										23
									
								
								vendor/github.com/klauspost/compress/zstd/fse_encoder.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/klauspost/compress/zstd/fse_encoder.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -76,21 +76,6 @@ func (s *fseEncoder) HistogramFinished(maxSymbol uint8, maxCount int) {
 | 
			
		||||
	s.clearCount = maxCount != 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// prepare will prepare and allocate scratch tables used for both compression and decompression.
 | 
			
		||||
func (s *fseEncoder) prepare() (*fseEncoder, error) {
 | 
			
		||||
	if s == nil {
 | 
			
		||||
		s = &fseEncoder{}
 | 
			
		||||
	}
 | 
			
		||||
	s.useRLE = false
 | 
			
		||||
	if s.clearCount && s.maxCount == 0 {
 | 
			
		||||
		for i := range s.count {
 | 
			
		||||
			s.count[i] = 0
 | 
			
		||||
		}
 | 
			
		||||
		s.clearCount = false
 | 
			
		||||
	}
 | 
			
		||||
	return s, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// allocCtable will allocate tables needed for compression.
 | 
			
		||||
// If existing tables a re big enough, they are simply re-used.
 | 
			
		||||
func (s *fseEncoder) allocCtable() {
 | 
			
		||||
@@ -709,14 +694,6 @@ func (c *cState) init(bw *bitWriter, ct *cTable, first symbolTransform) {
 | 
			
		||||
	c.state = c.stateTable[lu]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// encode the output symbol provided and write it to the bitstream.
 | 
			
		||||
func (c *cState) encode(symbolTT symbolTransform) {
 | 
			
		||||
	nbBitsOut := (uint32(c.state) + symbolTT.deltaNbBits) >> 16
 | 
			
		||||
	dstState := int32(c.state>>(nbBitsOut&15)) + int32(symbolTT.deltaFindState)
 | 
			
		||||
	c.bw.addBits16NC(c.state, uint8(nbBitsOut))
 | 
			
		||||
	c.state = c.stateTable[dstState]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// flush will write the tablelog to the output and flush the remaining full bytes.
 | 
			
		||||
func (c *cState) flush(tableLog uint8) {
 | 
			
		||||
	c.bw.flush32()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								vendor/github.com/klauspost/compress/zstd/fuzz.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/klauspost/compress/zstd/fuzz.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,11 +0,0 @@
 | 
			
		||||
//go:build ignorecrc
 | 
			
		||||
// +build ignorecrc
 | 
			
		||||
 | 
			
		||||
// Copyright 2019+ Klaus Post. All rights reserved.
 | 
			
		||||
// License information can be found in the LICENSE file.
 | 
			
		||||
// Based on work by Yann Collet, released under BSD License.
 | 
			
		||||
 | 
			
		||||
package zstd
 | 
			
		||||
 | 
			
		||||
// ignoreCRC can be used for fuzz testing to ignore CRC values...
 | 
			
		||||
const ignoreCRC = true
 | 
			
		||||
							
								
								
									
										11
									
								
								vendor/github.com/klauspost/compress/zstd/fuzz_none.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/klauspost/compress/zstd/fuzz_none.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,11 +0,0 @@
 | 
			
		||||
//go:build !ignorecrc
 | 
			
		||||
// +build !ignorecrc
 | 
			
		||||
 | 
			
		||||
// Copyright 2019+ Klaus Post. All rights reserved.
 | 
			
		||||
// License information can be found in the LICENSE file.
 | 
			
		||||
// Based on work by Yann Collet, released under BSD License.
 | 
			
		||||
 | 
			
		||||
package zstd
 | 
			
		||||
 | 
			
		||||
// ignoreCRC can be used for fuzz testing to ignore CRC values...
 | 
			
		||||
const ignoreCRC = false
 | 
			
		||||
							
								
								
									
										6
									
								
								vendor/github.com/klauspost/compress/zstd/hash.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/klauspost/compress/zstd/hash.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -33,9 +33,3 @@ func hashLen(u uint64, length, mls uint8) uint32 {
 | 
			
		||||
		return (uint32(u) * prime4bytes) >> (32 - length)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// hash3 returns the hash of the lower 3 bytes of u to fit in a hash table with h bits.
 | 
			
		||||
// Preferably h should be a constant and should always be <32.
 | 
			
		||||
func hash3(u uint32, h uint8) uint32 {
 | 
			
		||||
	return ((u << (32 - 24)) * prime3bytes) >> ((32 - h) & 31)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										260
									
								
								vendor/github.com/klauspost/compress/zstd/seqdec.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										260
									
								
								vendor/github.com/klauspost/compress/zstd/seqdec.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -73,6 +73,7 @@ type sequenceDecs struct {
 | 
			
		||||
	seqSize      int
 | 
			
		||||
	windowSize   int
 | 
			
		||||
	maxBits      uint8
 | 
			
		||||
	maxSyncLen   uint64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// initialize all 3 decoders from the stream input.
 | 
			
		||||
@@ -98,153 +99,13 @@ func (s *sequenceDecs) initialize(br *bitReader, hist *history, out []byte) erro
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// decode sequences from the stream with the provided history.
 | 
			
		||||
func (s *sequenceDecs) decode(seqs []seqVals) error {
 | 
			
		||||
	br := s.br
 | 
			
		||||
 | 
			
		||||
	// Grab full sizes tables, to avoid bounds checks.
 | 
			
		||||
	llTable, mlTable, ofTable := s.litLengths.fse.dt[:maxTablesize], s.matchLengths.fse.dt[:maxTablesize], s.offsets.fse.dt[:maxTablesize]
 | 
			
		||||
	llState, mlState, ofState := s.litLengths.state.state, s.matchLengths.state.state, s.offsets.state.state
 | 
			
		||||
	s.seqSize = 0
 | 
			
		||||
	litRemain := len(s.literals)
 | 
			
		||||
	maxBlockSize := maxCompressedBlockSize
 | 
			
		||||
	if s.windowSize < maxBlockSize {
 | 
			
		||||
		maxBlockSize = s.windowSize
 | 
			
		||||
	}
 | 
			
		||||
	for i := range seqs {
 | 
			
		||||
		var ll, mo, ml int
 | 
			
		||||
		if br.off > 4+((maxOffsetBits+16+16)>>3) {
 | 
			
		||||
			// inlined function:
 | 
			
		||||
			// ll, mo, ml = s.nextFast(br, llState, mlState, ofState)
 | 
			
		||||
 | 
			
		||||
			// Final will not read from stream.
 | 
			
		||||
			var llB, mlB, moB uint8
 | 
			
		||||
			ll, llB = llState.final()
 | 
			
		||||
			ml, mlB = mlState.final()
 | 
			
		||||
			mo, moB = ofState.final()
 | 
			
		||||
 | 
			
		||||
			// extra bits are stored in reverse order.
 | 
			
		||||
			br.fillFast()
 | 
			
		||||
			mo += br.getBits(moB)
 | 
			
		||||
			if s.maxBits > 32 {
 | 
			
		||||
				br.fillFast()
 | 
			
		||||
			}
 | 
			
		||||
			ml += br.getBits(mlB)
 | 
			
		||||
			ll += br.getBits(llB)
 | 
			
		||||
 | 
			
		||||
			if moB > 1 {
 | 
			
		||||
				s.prevOffset[2] = s.prevOffset[1]
 | 
			
		||||
				s.prevOffset[1] = s.prevOffset[0]
 | 
			
		||||
				s.prevOffset[0] = mo
 | 
			
		||||
			} else {
 | 
			
		||||
				// mo = s.adjustOffset(mo, ll, moB)
 | 
			
		||||
				// Inlined for rather big speedup
 | 
			
		||||
				if ll == 0 {
 | 
			
		||||
					// There is an exception though, when current sequence's literals_length = 0.
 | 
			
		||||
					// In this case, repeated offsets are shifted by one, so an offset_value of 1 means Repeated_Offset2,
 | 
			
		||||
					// an offset_value of 2 means Repeated_Offset3, and an offset_value of 3 means Repeated_Offset1 - 1_byte.
 | 
			
		||||
					mo++
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if mo == 0 {
 | 
			
		||||
					mo = s.prevOffset[0]
 | 
			
		||||
				} else {
 | 
			
		||||
					var temp int
 | 
			
		||||
					if mo == 3 {
 | 
			
		||||
						temp = s.prevOffset[0] - 1
 | 
			
		||||
					} else {
 | 
			
		||||
						temp = s.prevOffset[mo]
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if temp == 0 {
 | 
			
		||||
						// 0 is not valid; input is corrupted; force offset to 1
 | 
			
		||||
						println("WARNING: temp was 0")
 | 
			
		||||
						temp = 1
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if mo != 1 {
 | 
			
		||||
						s.prevOffset[2] = s.prevOffset[1]
 | 
			
		||||
					}
 | 
			
		||||
					s.prevOffset[1] = s.prevOffset[0]
 | 
			
		||||
					s.prevOffset[0] = temp
 | 
			
		||||
					mo = temp
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			br.fillFast()
 | 
			
		||||
		} else {
 | 
			
		||||
			if br.overread() {
 | 
			
		||||
				if debugDecoder {
 | 
			
		||||
					printf("reading sequence %d, exceeded available data\n", i)
 | 
			
		||||
				}
 | 
			
		||||
				return io.ErrUnexpectedEOF
 | 
			
		||||
			}
 | 
			
		||||
			ll, mo, ml = s.next(br, llState, mlState, ofState)
 | 
			
		||||
			br.fill()
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if debugSequences {
 | 
			
		||||
			println("Seq", i, "Litlen:", ll, "mo:", mo, "(abs) ml:", ml)
 | 
			
		||||
		}
 | 
			
		||||
		// Evaluate.
 | 
			
		||||
		// We might be doing this async, so do it early.
 | 
			
		||||
		if mo == 0 && ml > 0 {
 | 
			
		||||
			return fmt.Errorf("zero matchoff and matchlen (%d) > 0", ml)
 | 
			
		||||
		}
 | 
			
		||||
		if ml > maxMatchLen {
 | 
			
		||||
			return fmt.Errorf("match len (%d) bigger than max allowed length", ml)
 | 
			
		||||
		}
 | 
			
		||||
		s.seqSize += ll + ml
 | 
			
		||||
		if s.seqSize > maxBlockSize {
 | 
			
		||||
			return fmt.Errorf("output (%d) bigger than max block size (%d)", s.seqSize, maxBlockSize)
 | 
			
		||||
		}
 | 
			
		||||
		litRemain -= ll
 | 
			
		||||
		if litRemain < 0 {
 | 
			
		||||
			return fmt.Errorf("unexpected literal count, want %d bytes, but only %d is available", ll, litRemain+ll)
 | 
			
		||||
		}
 | 
			
		||||
		seqs[i] = seqVals{
 | 
			
		||||
			ll: ll,
 | 
			
		||||
			ml: ml,
 | 
			
		||||
			mo: mo,
 | 
			
		||||
		}
 | 
			
		||||
		if i == len(seqs)-1 {
 | 
			
		||||
			// This is the last sequence, so we shouldn't update state.
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Manually inlined, ~ 5-20% faster
 | 
			
		||||
		// Update all 3 states at once. Approx 20% faster.
 | 
			
		||||
		nBits := llState.nbBits() + mlState.nbBits() + ofState.nbBits()
 | 
			
		||||
		if nBits == 0 {
 | 
			
		||||
			llState = llTable[llState.newState()&maxTableMask]
 | 
			
		||||
			mlState = mlTable[mlState.newState()&maxTableMask]
 | 
			
		||||
			ofState = ofTable[ofState.newState()&maxTableMask]
 | 
			
		||||
		} else {
 | 
			
		||||
			bits := br.get32BitsFast(nBits)
 | 
			
		||||
			lowBits := uint16(bits >> ((ofState.nbBits() + mlState.nbBits()) & 31))
 | 
			
		||||
			llState = llTable[(llState.newState()+lowBits)&maxTableMask]
 | 
			
		||||
 | 
			
		||||
			lowBits = uint16(bits >> (ofState.nbBits() & 31))
 | 
			
		||||
			lowBits &= bitMask[mlState.nbBits()&15]
 | 
			
		||||
			mlState = mlTable[(mlState.newState()+lowBits)&maxTableMask]
 | 
			
		||||
 | 
			
		||||
			lowBits = uint16(bits) & bitMask[ofState.nbBits()&15]
 | 
			
		||||
			ofState = ofTable[(ofState.newState()+lowBits)&maxTableMask]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	s.seqSize += litRemain
 | 
			
		||||
	if s.seqSize > maxBlockSize {
 | 
			
		||||
		return fmt.Errorf("output (%d) bigger than max block size (%d)", s.seqSize, maxBlockSize)
 | 
			
		||||
	}
 | 
			
		||||
	err := br.close()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		printf("Closing sequences: %v, %+v\n", err, *br)
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// execute will execute the decoded sequence with the provided history.
 | 
			
		||||
// The sequence must be evaluated before being sent.
 | 
			
		||||
func (s *sequenceDecs) execute(seqs []seqVals, hist []byte) error {
 | 
			
		||||
	if len(s.dict) == 0 {
 | 
			
		||||
		return s.executeSimple(seqs, hist)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Ensure we have enough output size...
 | 
			
		||||
	if len(s.out)+s.seqSize > cap(s.out) {
 | 
			
		||||
		addBytes := s.seqSize + len(s.out)
 | 
			
		||||
@@ -327,6 +188,7 @@ func (s *sequenceDecs) execute(seqs []seqVals, hist []byte) error {
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Add final literals
 | 
			
		||||
	copy(out[t:], s.literals)
 | 
			
		||||
	if debugDecoder {
 | 
			
		||||
@@ -341,14 +203,18 @@ func (s *sequenceDecs) execute(seqs []seqVals, hist []byte) error {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// decode sequences from the stream with the provided history.
 | 
			
		||||
func (s *sequenceDecs) decodeSync(history *history) error {
 | 
			
		||||
func (s *sequenceDecs) decodeSync(hist []byte) error {
 | 
			
		||||
	supported, err := s.decodeSyncSimple(hist)
 | 
			
		||||
	if supported {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	br := s.br
 | 
			
		||||
	seqs := s.nSeqs
 | 
			
		||||
	startSize := len(s.out)
 | 
			
		||||
	// Grab full sizes tables, to avoid bounds checks.
 | 
			
		||||
	llTable, mlTable, ofTable := s.litLengths.fse.dt[:maxTablesize], s.matchLengths.fse.dt[:maxTablesize], s.offsets.fse.dt[:maxTablesize]
 | 
			
		||||
	llState, mlState, ofState := s.litLengths.state.state, s.matchLengths.state.state, s.offsets.state.state
 | 
			
		||||
	hist := history.b[history.ignoreBuffer:]
 | 
			
		||||
	out := s.out
 | 
			
		||||
	maxBlockSize := maxCompressedBlockSize
 | 
			
		||||
	if s.windowSize < maxBlockSize {
 | 
			
		||||
@@ -433,7 +299,7 @@ func (s *sequenceDecs) decodeSync(history *history) error {
 | 
			
		||||
		}
 | 
			
		||||
		size := ll + ml + len(out)
 | 
			
		||||
		if size-startSize > maxBlockSize {
 | 
			
		||||
			return fmt.Errorf("output (%d) bigger than max block size (%d)", size, maxBlockSize)
 | 
			
		||||
			return fmt.Errorf("output (%d) bigger than max block size (%d)", size-startSize, maxBlockSize)
 | 
			
		||||
		}
 | 
			
		||||
		if size > cap(out) {
 | 
			
		||||
			// Not enough size, which can happen under high volume block streaming conditions
 | 
			
		||||
@@ -463,13 +329,13 @@ func (s *sequenceDecs) decodeSync(history *history) error {
 | 
			
		||||
 | 
			
		||||
		if mo > len(out)+len(hist) || mo > s.windowSize {
 | 
			
		||||
			if len(s.dict) == 0 {
 | 
			
		||||
				return fmt.Errorf("match offset (%d) bigger than current history (%d)", mo, len(out)+len(hist))
 | 
			
		||||
				return fmt.Errorf("match offset (%d) bigger than current history (%d)", mo, len(out)+len(hist)-startSize)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// we may be in dictionary.
 | 
			
		||||
			dictO := len(s.dict) - (mo - (len(out) + len(hist)))
 | 
			
		||||
			if dictO < 0 || dictO >= len(s.dict) {
 | 
			
		||||
				return fmt.Errorf("match offset (%d) bigger than current history (%d)", mo, len(out)+len(hist))
 | 
			
		||||
				return fmt.Errorf("match offset (%d) bigger than current history (%d)", mo, len(out)+len(hist)-startSize)
 | 
			
		||||
			}
 | 
			
		||||
			end := dictO + ml
 | 
			
		||||
			if end > len(s.dict) {
 | 
			
		||||
@@ -530,6 +396,7 @@ func (s *sequenceDecs) decodeSync(history *history) error {
 | 
			
		||||
			ofState = ofTable[ofState.newState()&maxTableMask]
 | 
			
		||||
		} else {
 | 
			
		||||
			bits := br.get32BitsFast(nBits)
 | 
			
		||||
 | 
			
		||||
			lowBits := uint16(bits >> ((ofState.nbBits() + mlState.nbBits()) & 31))
 | 
			
		||||
			llState = llTable[(llState.newState()+lowBits)&maxTableMask]
 | 
			
		||||
 | 
			
		||||
@@ -543,8 +410,8 @@ func (s *sequenceDecs) decodeSync(history *history) error {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Check if space for literals
 | 
			
		||||
	if len(s.literals)+len(s.out)-startSize > maxBlockSize {
 | 
			
		||||
		return fmt.Errorf("output (%d) bigger than max block size (%d)", len(s.out), maxBlockSize)
 | 
			
		||||
	if size := len(s.literals) + len(s.out) - startSize; size > maxBlockSize {
 | 
			
		||||
		return fmt.Errorf("output (%d) bigger than max block size (%d)", size, maxBlockSize)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Add final literals
 | 
			
		||||
@@ -552,16 +419,6 @@ func (s *sequenceDecs) decodeSync(history *history) error {
 | 
			
		||||
	return br.close()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// update states, at least 27 bits must be available.
 | 
			
		||||
func (s *sequenceDecs) update(br *bitReader) {
 | 
			
		||||
	// Max 8 bits
 | 
			
		||||
	s.litLengths.state.next(br)
 | 
			
		||||
	// Max 9 bits
 | 
			
		||||
	s.matchLengths.state.next(br)
 | 
			
		||||
	// Max 8 bits
 | 
			
		||||
	s.offsets.state.next(br)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var bitMask [16]uint16
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
@@ -570,87 +427,6 @@ func init() {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// update states, at least 27 bits must be available.
 | 
			
		||||
func (s *sequenceDecs) updateAlt(br *bitReader) {
 | 
			
		||||
	// Update all 3 states at once. Approx 20% faster.
 | 
			
		||||
	a, b, c := s.litLengths.state.state, s.matchLengths.state.state, s.offsets.state.state
 | 
			
		||||
 | 
			
		||||
	nBits := a.nbBits() + b.nbBits() + c.nbBits()
 | 
			
		||||
	if nBits == 0 {
 | 
			
		||||
		s.litLengths.state.state = s.litLengths.state.dt[a.newState()]
 | 
			
		||||
		s.matchLengths.state.state = s.matchLengths.state.dt[b.newState()]
 | 
			
		||||
		s.offsets.state.state = s.offsets.state.dt[c.newState()]
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	bits := br.get32BitsFast(nBits)
 | 
			
		||||
	lowBits := uint16(bits >> ((c.nbBits() + b.nbBits()) & 31))
 | 
			
		||||
	s.litLengths.state.state = s.litLengths.state.dt[a.newState()+lowBits]
 | 
			
		||||
 | 
			
		||||
	lowBits = uint16(bits >> (c.nbBits() & 31))
 | 
			
		||||
	lowBits &= bitMask[b.nbBits()&15]
 | 
			
		||||
	s.matchLengths.state.state = s.matchLengths.state.dt[b.newState()+lowBits]
 | 
			
		||||
 | 
			
		||||
	lowBits = uint16(bits) & bitMask[c.nbBits()&15]
 | 
			
		||||
	s.offsets.state.state = s.offsets.state.dt[c.newState()+lowBits]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// nextFast will return new states when there are at least 4 unused bytes left on the stream when done.
 | 
			
		||||
func (s *sequenceDecs) nextFast(br *bitReader, llState, mlState, ofState decSymbol) (ll, mo, ml int) {
 | 
			
		||||
	// Final will not read from stream.
 | 
			
		||||
	ll, llB := llState.final()
 | 
			
		||||
	ml, mlB := mlState.final()
 | 
			
		||||
	mo, moB := ofState.final()
 | 
			
		||||
 | 
			
		||||
	// extra bits are stored in reverse order.
 | 
			
		||||
	br.fillFast()
 | 
			
		||||
	mo += br.getBits(moB)
 | 
			
		||||
	if s.maxBits > 32 {
 | 
			
		||||
		br.fillFast()
 | 
			
		||||
	}
 | 
			
		||||
	ml += br.getBits(mlB)
 | 
			
		||||
	ll += br.getBits(llB)
 | 
			
		||||
 | 
			
		||||
	if moB > 1 {
 | 
			
		||||
		s.prevOffset[2] = s.prevOffset[1]
 | 
			
		||||
		s.prevOffset[1] = s.prevOffset[0]
 | 
			
		||||
		s.prevOffset[0] = mo
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	// mo = s.adjustOffset(mo, ll, moB)
 | 
			
		||||
	// Inlined for rather big speedup
 | 
			
		||||
	if ll == 0 {
 | 
			
		||||
		// There is an exception though, when current sequence's literals_length = 0.
 | 
			
		||||
		// In this case, repeated offsets are shifted by one, so an offset_value of 1 means Repeated_Offset2,
 | 
			
		||||
		// an offset_value of 2 means Repeated_Offset3, and an offset_value of 3 means Repeated_Offset1 - 1_byte.
 | 
			
		||||
		mo++
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if mo == 0 {
 | 
			
		||||
		mo = s.prevOffset[0]
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	var temp int
 | 
			
		||||
	if mo == 3 {
 | 
			
		||||
		temp = s.prevOffset[0] - 1
 | 
			
		||||
	} else {
 | 
			
		||||
		temp = s.prevOffset[mo]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if temp == 0 {
 | 
			
		||||
		// 0 is not valid; input is corrupted; force offset to 1
 | 
			
		||||
		println("temp was 0")
 | 
			
		||||
		temp = 1
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if mo != 1 {
 | 
			
		||||
		s.prevOffset[2] = s.prevOffset[1]
 | 
			
		||||
	}
 | 
			
		||||
	s.prevOffset[1] = s.prevOffset[0]
 | 
			
		||||
	s.prevOffset[0] = temp
 | 
			
		||||
	mo = temp
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *sequenceDecs) next(br *bitReader, llState, mlState, ofState decSymbol) (ll, mo, ml int) {
 | 
			
		||||
	// Final will not read from stream.
 | 
			
		||||
	ll, llB := llState.final()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										362
									
								
								vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										362
									
								
								vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,362 @@
 | 
			
		||||
//go:build amd64 && !appengine && !noasm && gc
 | 
			
		||||
// +build amd64,!appengine,!noasm,gc
 | 
			
		||||
 | 
			
		||||
package zstd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/klauspost/compress/internal/cpuinfo"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type decodeSyncAsmContext struct {
 | 
			
		||||
	llTable     []decSymbol
 | 
			
		||||
	mlTable     []decSymbol
 | 
			
		||||
	ofTable     []decSymbol
 | 
			
		||||
	llState     uint64
 | 
			
		||||
	mlState     uint64
 | 
			
		||||
	ofState     uint64
 | 
			
		||||
	iteration   int
 | 
			
		||||
	litRemain   int
 | 
			
		||||
	out         []byte
 | 
			
		||||
	outPosition int
 | 
			
		||||
	literals    []byte
 | 
			
		||||
	litPosition int
 | 
			
		||||
	history     []byte
 | 
			
		||||
	windowSize  int
 | 
			
		||||
	ll          int // set on error (not for all errors, please refer to _generate/gen.go)
 | 
			
		||||
	ml          int // set on error (not for all errors, please refer to _generate/gen.go)
 | 
			
		||||
	mo          int // set on error (not for all errors, please refer to _generate/gen.go)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// sequenceDecs_decodeSync_amd64 implements the main loop of sequenceDecs.decodeSync in x86 asm.
 | 
			
		||||
//
 | 
			
		||||
// Please refer to seqdec_generic.go for the reference implementation.
 | 
			
		||||
//go:noescape
 | 
			
		||||
func sequenceDecs_decodeSync_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int
 | 
			
		||||
 | 
			
		||||
// sequenceDecs_decodeSync_bmi2 implements the main loop of sequenceDecs.decodeSync in x86 asm with BMI2 extensions.
 | 
			
		||||
//go:noescape
 | 
			
		||||
func sequenceDecs_decodeSync_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int
 | 
			
		||||
 | 
			
		||||
// sequenceDecs_decodeSync_safe_amd64 does the same as above, but does not write more than output buffer.
 | 
			
		||||
//go:noescape
 | 
			
		||||
func sequenceDecs_decodeSync_safe_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int
 | 
			
		||||
 | 
			
		||||
// sequenceDecs_decodeSync_safe_bmi2 does the same as above, but does not write more than output buffer.
 | 
			
		||||
//go:noescape
 | 
			
		||||
func sequenceDecs_decodeSync_safe_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int
 | 
			
		||||
 | 
			
		||||
// decode sequences from the stream with the provided history but without a dictionary.
 | 
			
		||||
func (s *sequenceDecs) decodeSyncSimple(hist []byte) (bool, error) {
 | 
			
		||||
	if len(s.dict) > 0 {
 | 
			
		||||
		return false, nil
 | 
			
		||||
	}
 | 
			
		||||
	if s.maxSyncLen == 0 && cap(s.out)-len(s.out) < maxCompressedBlockSize {
 | 
			
		||||
		return false, nil
 | 
			
		||||
	}
 | 
			
		||||
	useSafe := false
 | 
			
		||||
	if s.maxSyncLen == 0 && cap(s.out)-len(s.out) < maxCompressedBlockSizeAlloc {
 | 
			
		||||
		useSafe = true
 | 
			
		||||
	}
 | 
			
		||||
	if s.maxSyncLen > 0 && cap(s.out)-len(s.out)-compressedBlockOverAlloc < int(s.maxSyncLen) {
 | 
			
		||||
		useSafe = true
 | 
			
		||||
	}
 | 
			
		||||
	if cap(s.literals) < len(s.literals)+compressedBlockOverAlloc {
 | 
			
		||||
		useSafe = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	br := s.br
 | 
			
		||||
 | 
			
		||||
	maxBlockSize := maxCompressedBlockSize
 | 
			
		||||
	if s.windowSize < maxBlockSize {
 | 
			
		||||
		maxBlockSize = s.windowSize
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx := decodeSyncAsmContext{
 | 
			
		||||
		llTable:     s.litLengths.fse.dt[:maxTablesize],
 | 
			
		||||
		mlTable:     s.matchLengths.fse.dt[:maxTablesize],
 | 
			
		||||
		ofTable:     s.offsets.fse.dt[:maxTablesize],
 | 
			
		||||
		llState:     uint64(s.litLengths.state.state),
 | 
			
		||||
		mlState:     uint64(s.matchLengths.state.state),
 | 
			
		||||
		ofState:     uint64(s.offsets.state.state),
 | 
			
		||||
		iteration:   s.nSeqs - 1,
 | 
			
		||||
		litRemain:   len(s.literals),
 | 
			
		||||
		out:         s.out,
 | 
			
		||||
		outPosition: len(s.out),
 | 
			
		||||
		literals:    s.literals,
 | 
			
		||||
		windowSize:  s.windowSize,
 | 
			
		||||
		history:     hist,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.seqSize = 0
 | 
			
		||||
	startSize := len(s.out)
 | 
			
		||||
 | 
			
		||||
	var errCode int
 | 
			
		||||
	if cpuinfo.HasBMI2() {
 | 
			
		||||
		if useSafe {
 | 
			
		||||
			errCode = sequenceDecs_decodeSync_safe_bmi2(s, br, &ctx)
 | 
			
		||||
		} else {
 | 
			
		||||
			errCode = sequenceDecs_decodeSync_bmi2(s, br, &ctx)
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		if useSafe {
 | 
			
		||||
			errCode = sequenceDecs_decodeSync_safe_amd64(s, br, &ctx)
 | 
			
		||||
		} else {
 | 
			
		||||
			errCode = sequenceDecs_decodeSync_amd64(s, br, &ctx)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	switch errCode {
 | 
			
		||||
	case noError:
 | 
			
		||||
		break
 | 
			
		||||
 | 
			
		||||
	case errorMatchLenOfsMismatch:
 | 
			
		||||
		return true, fmt.Errorf("zero matchoff and matchlen (%d) > 0", ctx.ml)
 | 
			
		||||
 | 
			
		||||
	case errorMatchLenTooBig:
 | 
			
		||||
		return true, fmt.Errorf("match len (%d) bigger than max allowed length", ctx.ml)
 | 
			
		||||
 | 
			
		||||
	case errorMatchOffTooBig:
 | 
			
		||||
		return true, fmt.Errorf("match offset (%d) bigger than current history (%d)",
 | 
			
		||||
			ctx.mo, ctx.outPosition+len(hist)-startSize)
 | 
			
		||||
 | 
			
		||||
	case errorNotEnoughLiterals:
 | 
			
		||||
		return true, fmt.Errorf("unexpected literal count, want %d bytes, but only %d is available",
 | 
			
		||||
			ctx.ll, ctx.litRemain+ctx.ll)
 | 
			
		||||
 | 
			
		||||
	case errorNotEnoughSpace:
 | 
			
		||||
		size := ctx.outPosition + ctx.ll + ctx.ml
 | 
			
		||||
		if debugDecoder {
 | 
			
		||||
			println("msl:", s.maxSyncLen, "cap", cap(s.out), "bef:", startSize, "sz:", size-startSize, "mbs:", maxBlockSize, "outsz:", cap(s.out)-startSize)
 | 
			
		||||
		}
 | 
			
		||||
		return true, fmt.Errorf("output (%d) bigger than max block size (%d)", size-startSize, maxBlockSize)
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		return true, fmt.Errorf("sequenceDecs_decode returned erronous code %d", errCode)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.seqSize += ctx.litRemain
 | 
			
		||||
	if s.seqSize > maxBlockSize {
 | 
			
		||||
		return true, fmt.Errorf("output (%d) bigger than max block size (%d)", s.seqSize, maxBlockSize)
 | 
			
		||||
	}
 | 
			
		||||
	err := br.close()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		printf("Closing sequences: %v, %+v\n", err, *br)
 | 
			
		||||
		return true, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.literals = s.literals[ctx.litPosition:]
 | 
			
		||||
	t := ctx.outPosition
 | 
			
		||||
	s.out = s.out[:t]
 | 
			
		||||
 | 
			
		||||
	// Add final literals
 | 
			
		||||
	s.out = append(s.out, s.literals...)
 | 
			
		||||
	if debugDecoder {
 | 
			
		||||
		t += len(s.literals)
 | 
			
		||||
		if t != len(s.out) {
 | 
			
		||||
			panic(fmt.Errorf("length mismatch, want %d, got %d", len(s.out), t))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
type decodeAsmContext struct {
 | 
			
		||||
	llTable   []decSymbol
 | 
			
		||||
	mlTable   []decSymbol
 | 
			
		||||
	ofTable   []decSymbol
 | 
			
		||||
	llState   uint64
 | 
			
		||||
	mlState   uint64
 | 
			
		||||
	ofState   uint64
 | 
			
		||||
	iteration int
 | 
			
		||||
	seqs      []seqVals
 | 
			
		||||
	litRemain int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const noError = 0
 | 
			
		||||
 | 
			
		||||
// error reported when mo == 0 && ml > 0
 | 
			
		||||
const errorMatchLenOfsMismatch = 1
 | 
			
		||||
 | 
			
		||||
// error reported when ml > maxMatchLen
 | 
			
		||||
const errorMatchLenTooBig = 2
 | 
			
		||||
 | 
			
		||||
// error reported when mo > available history or mo > s.windowSize
 | 
			
		||||
const errorMatchOffTooBig = 3
 | 
			
		||||
 | 
			
		||||
// error reported when the sum of literal lengths exeeceds the literal buffer size
 | 
			
		||||
const errorNotEnoughLiterals = 4
 | 
			
		||||
 | 
			
		||||
// error reported when capacity of `out` is too small
 | 
			
		||||
const errorNotEnoughSpace = 5
 | 
			
		||||
 | 
			
		||||
// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm.
 | 
			
		||||
//
 | 
			
		||||
// Please refer to seqdec_generic.go for the reference implementation.
 | 
			
		||||
//go:noescape
 | 
			
		||||
func sequenceDecs_decode_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
 | 
			
		||||
 | 
			
		||||
// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm.
 | 
			
		||||
//
 | 
			
		||||
// Please refer to seqdec_generic.go for the reference implementation.
 | 
			
		||||
//go:noescape
 | 
			
		||||
func sequenceDecs_decode_56_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
 | 
			
		||||
 | 
			
		||||
// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm with BMI2 extensions.
 | 
			
		||||
//go:noescape
 | 
			
		||||
func sequenceDecs_decode_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
 | 
			
		||||
 | 
			
		||||
// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm with BMI2 extensions.
 | 
			
		||||
//go:noescape
 | 
			
		||||
func sequenceDecs_decode_56_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
 | 
			
		||||
 | 
			
		||||
// decode sequences from the stream without the provided history.
 | 
			
		||||
func (s *sequenceDecs) decode(seqs []seqVals) error {
 | 
			
		||||
	br := s.br
 | 
			
		||||
 | 
			
		||||
	maxBlockSize := maxCompressedBlockSize
 | 
			
		||||
	if s.windowSize < maxBlockSize {
 | 
			
		||||
		maxBlockSize = s.windowSize
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx := decodeAsmContext{
 | 
			
		||||
		llTable:   s.litLengths.fse.dt[:maxTablesize],
 | 
			
		||||
		mlTable:   s.matchLengths.fse.dt[:maxTablesize],
 | 
			
		||||
		ofTable:   s.offsets.fse.dt[:maxTablesize],
 | 
			
		||||
		llState:   uint64(s.litLengths.state.state),
 | 
			
		||||
		mlState:   uint64(s.matchLengths.state.state),
 | 
			
		||||
		ofState:   uint64(s.offsets.state.state),
 | 
			
		||||
		seqs:      seqs,
 | 
			
		||||
		iteration: len(seqs) - 1,
 | 
			
		||||
		litRemain: len(s.literals),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.seqSize = 0
 | 
			
		||||
	lte56bits := s.maxBits+s.offsets.fse.actualTableLog+s.matchLengths.fse.actualTableLog+s.litLengths.fse.actualTableLog <= 56
 | 
			
		||||
	var errCode int
 | 
			
		||||
	if cpuinfo.HasBMI2() {
 | 
			
		||||
		if lte56bits {
 | 
			
		||||
			errCode = sequenceDecs_decode_56_bmi2(s, br, &ctx)
 | 
			
		||||
		} else {
 | 
			
		||||
			errCode = sequenceDecs_decode_bmi2(s, br, &ctx)
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		if lte56bits {
 | 
			
		||||
			errCode = sequenceDecs_decode_56_amd64(s, br, &ctx)
 | 
			
		||||
		} else {
 | 
			
		||||
			errCode = sequenceDecs_decode_amd64(s, br, &ctx)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if errCode != 0 {
 | 
			
		||||
		i := len(seqs) - ctx.iteration - 1
 | 
			
		||||
		switch errCode {
 | 
			
		||||
		case errorMatchLenOfsMismatch:
 | 
			
		||||
			ml := ctx.seqs[i].ml
 | 
			
		||||
			return fmt.Errorf("zero matchoff and matchlen (%d) > 0", ml)
 | 
			
		||||
 | 
			
		||||
		case errorMatchLenTooBig:
 | 
			
		||||
			ml := ctx.seqs[i].ml
 | 
			
		||||
			return fmt.Errorf("match len (%d) bigger than max allowed length", ml)
 | 
			
		||||
 | 
			
		||||
		case errorNotEnoughLiterals:
 | 
			
		||||
			ll := ctx.seqs[i].ll
 | 
			
		||||
			return fmt.Errorf("unexpected literal count, want %d bytes, but only %d is available", ll, ctx.litRemain+ll)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return fmt.Errorf("sequenceDecs_decode_amd64 returned erronous code %d", errCode)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ctx.litRemain < 0 {
 | 
			
		||||
		return fmt.Errorf("literal count is too big: total available %d, total requested %d",
 | 
			
		||||
			len(s.literals), len(s.literals)-ctx.litRemain)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.seqSize += ctx.litRemain
 | 
			
		||||
	if s.seqSize > maxBlockSize {
 | 
			
		||||
		return fmt.Errorf("output (%d) bigger than max block size (%d)", s.seqSize, maxBlockSize)
 | 
			
		||||
	}
 | 
			
		||||
	err := br.close()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		printf("Closing sequences: %v, %+v\n", err, *br)
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
type executeAsmContext struct {
 | 
			
		||||
	seqs        []seqVals
 | 
			
		||||
	seqIndex    int
 | 
			
		||||
	out         []byte
 | 
			
		||||
	history     []byte
 | 
			
		||||
	literals    []byte
 | 
			
		||||
	outPosition int
 | 
			
		||||
	litPosition int
 | 
			
		||||
	windowSize  int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// sequenceDecs_executeSimple_amd64 implements the main loop of sequenceDecs.executeSimple in x86 asm.
 | 
			
		||||
//
 | 
			
		||||
// Returns false if a match offset is too big.
 | 
			
		||||
//
 | 
			
		||||
// Please refer to seqdec_generic.go for the reference implementation.
 | 
			
		||||
//go:noescape
 | 
			
		||||
func sequenceDecs_executeSimple_amd64(ctx *executeAsmContext) bool
 | 
			
		||||
 | 
			
		||||
// Same as above, but with safe memcopies
 | 
			
		||||
//go:noescape
 | 
			
		||||
func sequenceDecs_executeSimple_safe_amd64(ctx *executeAsmContext) bool
 | 
			
		||||
 | 
			
		||||
// executeSimple handles cases when dictionary is not used.
 | 
			
		||||
func (s *sequenceDecs) executeSimple(seqs []seqVals, hist []byte) error {
 | 
			
		||||
	// Ensure we have enough output size...
 | 
			
		||||
	if len(s.out)+s.seqSize+compressedBlockOverAlloc > cap(s.out) {
 | 
			
		||||
		addBytes := s.seqSize + len(s.out) + compressedBlockOverAlloc
 | 
			
		||||
		s.out = append(s.out, make([]byte, addBytes)...)
 | 
			
		||||
		s.out = s.out[:len(s.out)-addBytes]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if debugDecoder {
 | 
			
		||||
		printf("Execute %d seqs with literals: %d into %d bytes\n", len(seqs), len(s.literals), s.seqSize)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var t = len(s.out)
 | 
			
		||||
	out := s.out[:t+s.seqSize]
 | 
			
		||||
 | 
			
		||||
	ctx := executeAsmContext{
 | 
			
		||||
		seqs:        seqs,
 | 
			
		||||
		seqIndex:    0,
 | 
			
		||||
		out:         out,
 | 
			
		||||
		history:     hist,
 | 
			
		||||
		outPosition: t,
 | 
			
		||||
		litPosition: 0,
 | 
			
		||||
		literals:    s.literals,
 | 
			
		||||
		windowSize:  s.windowSize,
 | 
			
		||||
	}
 | 
			
		||||
	var ok bool
 | 
			
		||||
	if cap(s.literals) < len(s.literals)+compressedBlockOverAlloc {
 | 
			
		||||
		ok = sequenceDecs_executeSimple_safe_amd64(&ctx)
 | 
			
		||||
	} else {
 | 
			
		||||
		ok = sequenceDecs_executeSimple_amd64(&ctx)
 | 
			
		||||
	}
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return fmt.Errorf("match offset (%d) bigger than current history (%d)",
 | 
			
		||||
			seqs[ctx.seqIndex].mo, ctx.outPosition+len(hist))
 | 
			
		||||
	}
 | 
			
		||||
	s.literals = s.literals[ctx.litPosition:]
 | 
			
		||||
	t = ctx.outPosition
 | 
			
		||||
 | 
			
		||||
	// Add final literals
 | 
			
		||||
	copy(out[t:], s.literals)
 | 
			
		||||
	if debugDecoder {
 | 
			
		||||
		t += len(s.literals)
 | 
			
		||||
		if t != len(out) {
 | 
			
		||||
			panic(fmt.Errorf("length mismatch, want %d, got %d, ss: %d", len(out), t, s.seqSize))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	s.out = out
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3689
									
								
								vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3689
									
								
								vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										237
									
								
								vendor/github.com/klauspost/compress/zstd/seqdec_generic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										237
									
								
								vendor/github.com/klauspost/compress/zstd/seqdec_generic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,237 @@
 | 
			
		||||
//go:build !amd64 || appengine || !gc || noasm
 | 
			
		||||
// +build !amd64 appengine !gc noasm
 | 
			
		||||
 | 
			
		||||
package zstd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// decode sequences from the stream with the provided history but without dictionary.
 | 
			
		||||
func (s *sequenceDecs) decodeSyncSimple(hist []byte) (bool, error) {
 | 
			
		||||
	return false, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// decode sequences from the stream without the provided history.
 | 
			
		||||
func (s *sequenceDecs) decode(seqs []seqVals) error {
 | 
			
		||||
	br := s.br
 | 
			
		||||
 | 
			
		||||
	// Grab full sizes tables, to avoid bounds checks.
 | 
			
		||||
	llTable, mlTable, ofTable := s.litLengths.fse.dt[:maxTablesize], s.matchLengths.fse.dt[:maxTablesize], s.offsets.fse.dt[:maxTablesize]
 | 
			
		||||
	llState, mlState, ofState := s.litLengths.state.state, s.matchLengths.state.state, s.offsets.state.state
 | 
			
		||||
	s.seqSize = 0
 | 
			
		||||
	litRemain := len(s.literals)
 | 
			
		||||
 | 
			
		||||
	maxBlockSize := maxCompressedBlockSize
 | 
			
		||||
	if s.windowSize < maxBlockSize {
 | 
			
		||||
		maxBlockSize = s.windowSize
 | 
			
		||||
	}
 | 
			
		||||
	for i := range seqs {
 | 
			
		||||
		var ll, mo, ml int
 | 
			
		||||
		if br.off > 4+((maxOffsetBits+16+16)>>3) {
 | 
			
		||||
			// inlined function:
 | 
			
		||||
			// ll, mo, ml = s.nextFast(br, llState, mlState, ofState)
 | 
			
		||||
 | 
			
		||||
			// Final will not read from stream.
 | 
			
		||||
			var llB, mlB, moB uint8
 | 
			
		||||
			ll, llB = llState.final()
 | 
			
		||||
			ml, mlB = mlState.final()
 | 
			
		||||
			mo, moB = ofState.final()
 | 
			
		||||
 | 
			
		||||
			// extra bits are stored in reverse order.
 | 
			
		||||
			br.fillFast()
 | 
			
		||||
			mo += br.getBits(moB)
 | 
			
		||||
			if s.maxBits > 32 {
 | 
			
		||||
				br.fillFast()
 | 
			
		||||
			}
 | 
			
		||||
			ml += br.getBits(mlB)
 | 
			
		||||
			ll += br.getBits(llB)
 | 
			
		||||
 | 
			
		||||
			if moB > 1 {
 | 
			
		||||
				s.prevOffset[2] = s.prevOffset[1]
 | 
			
		||||
				s.prevOffset[1] = s.prevOffset[0]
 | 
			
		||||
				s.prevOffset[0] = mo
 | 
			
		||||
			} else {
 | 
			
		||||
				// mo = s.adjustOffset(mo, ll, moB)
 | 
			
		||||
				// Inlined for rather big speedup
 | 
			
		||||
				if ll == 0 {
 | 
			
		||||
					// There is an exception though, when current sequence's literals_length = 0.
 | 
			
		||||
					// In this case, repeated offsets are shifted by one, so an offset_value of 1 means Repeated_Offset2,
 | 
			
		||||
					// an offset_value of 2 means Repeated_Offset3, and an offset_value of 3 means Repeated_Offset1 - 1_byte.
 | 
			
		||||
					mo++
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if mo == 0 {
 | 
			
		||||
					mo = s.prevOffset[0]
 | 
			
		||||
				} else {
 | 
			
		||||
					var temp int
 | 
			
		||||
					if mo == 3 {
 | 
			
		||||
						temp = s.prevOffset[0] - 1
 | 
			
		||||
					} else {
 | 
			
		||||
						temp = s.prevOffset[mo]
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if temp == 0 {
 | 
			
		||||
						// 0 is not valid; input is corrupted; force offset to 1
 | 
			
		||||
						println("WARNING: temp was 0")
 | 
			
		||||
						temp = 1
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if mo != 1 {
 | 
			
		||||
						s.prevOffset[2] = s.prevOffset[1]
 | 
			
		||||
					}
 | 
			
		||||
					s.prevOffset[1] = s.prevOffset[0]
 | 
			
		||||
					s.prevOffset[0] = temp
 | 
			
		||||
					mo = temp
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			br.fillFast()
 | 
			
		||||
		} else {
 | 
			
		||||
			if br.overread() {
 | 
			
		||||
				if debugDecoder {
 | 
			
		||||
					printf("reading sequence %d, exceeded available data\n", i)
 | 
			
		||||
				}
 | 
			
		||||
				return io.ErrUnexpectedEOF
 | 
			
		||||
			}
 | 
			
		||||
			ll, mo, ml = s.next(br, llState, mlState, ofState)
 | 
			
		||||
			br.fill()
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if debugSequences {
 | 
			
		||||
			println("Seq", i, "Litlen:", ll, "mo:", mo, "(abs) ml:", ml)
 | 
			
		||||
		}
 | 
			
		||||
		// Evaluate.
 | 
			
		||||
		// We might be doing this async, so do it early.
 | 
			
		||||
		if mo == 0 && ml > 0 {
 | 
			
		||||
			return fmt.Errorf("zero matchoff and matchlen (%d) > 0", ml)
 | 
			
		||||
		}
 | 
			
		||||
		if ml > maxMatchLen {
 | 
			
		||||
			return fmt.Errorf("match len (%d) bigger than max allowed length", ml)
 | 
			
		||||
		}
 | 
			
		||||
		s.seqSize += ll + ml
 | 
			
		||||
		if s.seqSize > maxBlockSize {
 | 
			
		||||
			return fmt.Errorf("output (%d) bigger than max block size (%d)", s.seqSize, maxBlockSize)
 | 
			
		||||
		}
 | 
			
		||||
		litRemain -= ll
 | 
			
		||||
		if litRemain < 0 {
 | 
			
		||||
			return fmt.Errorf("unexpected literal count, want %d bytes, but only %d is available", ll, litRemain+ll)
 | 
			
		||||
		}
 | 
			
		||||
		seqs[i] = seqVals{
 | 
			
		||||
			ll: ll,
 | 
			
		||||
			ml: ml,
 | 
			
		||||
			mo: mo,
 | 
			
		||||
		}
 | 
			
		||||
		if i == len(seqs)-1 {
 | 
			
		||||
			// This is the last sequence, so we shouldn't update state.
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Manually inlined, ~ 5-20% faster
 | 
			
		||||
		// Update all 3 states at once. Approx 20% faster.
 | 
			
		||||
		nBits := llState.nbBits() + mlState.nbBits() + ofState.nbBits()
 | 
			
		||||
		if nBits == 0 {
 | 
			
		||||
			llState = llTable[llState.newState()&maxTableMask]
 | 
			
		||||
			mlState = mlTable[mlState.newState()&maxTableMask]
 | 
			
		||||
			ofState = ofTable[ofState.newState()&maxTableMask]
 | 
			
		||||
		} else {
 | 
			
		||||
			bits := br.get32BitsFast(nBits)
 | 
			
		||||
			lowBits := uint16(bits >> ((ofState.nbBits() + mlState.nbBits()) & 31))
 | 
			
		||||
			llState = llTable[(llState.newState()+lowBits)&maxTableMask]
 | 
			
		||||
 | 
			
		||||
			lowBits = uint16(bits >> (ofState.nbBits() & 31))
 | 
			
		||||
			lowBits &= bitMask[mlState.nbBits()&15]
 | 
			
		||||
			mlState = mlTable[(mlState.newState()+lowBits)&maxTableMask]
 | 
			
		||||
 | 
			
		||||
			lowBits = uint16(bits) & bitMask[ofState.nbBits()&15]
 | 
			
		||||
			ofState = ofTable[(ofState.newState()+lowBits)&maxTableMask]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	s.seqSize += litRemain
 | 
			
		||||
	if s.seqSize > maxBlockSize {
 | 
			
		||||
		return fmt.Errorf("output (%d) bigger than max block size (%d)", s.seqSize, maxBlockSize)
 | 
			
		||||
	}
 | 
			
		||||
	err := br.close()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		printf("Closing sequences: %v, %+v\n", err, *br)
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// executeSimple handles cases when a dictionary is not used.
 | 
			
		||||
func (s *sequenceDecs) executeSimple(seqs []seqVals, hist []byte) error {
 | 
			
		||||
	// Ensure we have enough output size...
 | 
			
		||||
	if len(s.out)+s.seqSize > cap(s.out) {
 | 
			
		||||
		addBytes := s.seqSize + len(s.out)
 | 
			
		||||
		s.out = append(s.out, make([]byte, addBytes)...)
 | 
			
		||||
		s.out = s.out[:len(s.out)-addBytes]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if debugDecoder {
 | 
			
		||||
		printf("Execute %d seqs with literals: %d into %d bytes\n", len(seqs), len(s.literals), s.seqSize)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var t = len(s.out)
 | 
			
		||||
	out := s.out[:t+s.seqSize]
 | 
			
		||||
 | 
			
		||||
	for _, seq := range seqs {
 | 
			
		||||
		// Add literals
 | 
			
		||||
		copy(out[t:], s.literals[:seq.ll])
 | 
			
		||||
		t += seq.ll
 | 
			
		||||
		s.literals = s.literals[seq.ll:]
 | 
			
		||||
 | 
			
		||||
		// Malformed input
 | 
			
		||||
		if seq.mo > t+len(hist) || seq.mo > s.windowSize {
 | 
			
		||||
			return fmt.Errorf("match offset (%d) bigger than current history (%d)", seq.mo, t+len(hist))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Copy from history.
 | 
			
		||||
		if v := seq.mo - t; v > 0 {
 | 
			
		||||
			// v is the start position in history from end.
 | 
			
		||||
			start := len(hist) - v
 | 
			
		||||
			if seq.ml > v {
 | 
			
		||||
				// Some goes into the current block.
 | 
			
		||||
				// Copy remainder of history
 | 
			
		||||
				copy(out[t:], hist[start:])
 | 
			
		||||
				t += v
 | 
			
		||||
				seq.ml -= v
 | 
			
		||||
			} else {
 | 
			
		||||
				copy(out[t:], hist[start:start+seq.ml])
 | 
			
		||||
				t += seq.ml
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// We must be in the current buffer now
 | 
			
		||||
		if seq.ml > 0 {
 | 
			
		||||
			start := t - seq.mo
 | 
			
		||||
			if seq.ml <= t-start {
 | 
			
		||||
				// No overlap
 | 
			
		||||
				copy(out[t:], out[start:start+seq.ml])
 | 
			
		||||
				t += seq.ml
 | 
			
		||||
			} else {
 | 
			
		||||
				// Overlapping copy
 | 
			
		||||
				// Extend destination slice and copy one byte at the time.
 | 
			
		||||
				src := out[start : start+seq.ml]
 | 
			
		||||
				dst := out[t:]
 | 
			
		||||
				dst = dst[:len(src)]
 | 
			
		||||
				t += len(src)
 | 
			
		||||
				// Destination is the space we just added.
 | 
			
		||||
				for i := range src {
 | 
			
		||||
					dst[i] = src[i]
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// Add final literals
 | 
			
		||||
	copy(out[t:], s.literals)
 | 
			
		||||
	if debugDecoder {
 | 
			
		||||
		t += len(s.literals)
 | 
			
		||||
		if t != len(out) {
 | 
			
		||||
			panic(fmt.Errorf("length mismatch, want %d, got %d, ss: %d", len(out), t, s.seqSize))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	s.out = out
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										59
									
								
								vendor/github.com/klauspost/compress/zstd/zip.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										59
									
								
								vendor/github.com/klauspost/compress/zstd/zip.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -18,26 +18,44 @@ const ZipMethodWinZip = 93
 | 
			
		||||
// See https://pkware.cachefly.net/webdocs/APPNOTE/APPNOTE-6.3.9.TXT
 | 
			
		||||
const ZipMethodPKWare = 20
 | 
			
		||||
 | 
			
		||||
var zipReaderPool sync.Pool
 | 
			
		||||
// zipReaderPool is the default reader pool.
 | 
			
		||||
var zipReaderPool = sync.Pool{New: func() interface{} {
 | 
			
		||||
	z, err := NewReader(nil, WithDecoderLowmem(true), WithDecoderMaxWindow(128<<20), WithDecoderConcurrency(1))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return z
 | 
			
		||||
}}
 | 
			
		||||
 | 
			
		||||
// newZipReader creates a pooled zip decompressor.
 | 
			
		||||
func newZipReader(r io.Reader) io.ReadCloser {
 | 
			
		||||
	dec, ok := zipReaderPool.Get().(*Decoder)
 | 
			
		||||
	if ok {
 | 
			
		||||
		dec.Reset(r)
 | 
			
		||||
	} else {
 | 
			
		||||
		d, err := NewReader(r, WithDecoderConcurrency(1), WithDecoderLowmem(true))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
		dec = d
 | 
			
		||||
func newZipReader(opts ...DOption) func(r io.Reader) io.ReadCloser {
 | 
			
		||||
	pool := &zipReaderPool
 | 
			
		||||
	if len(opts) > 0 {
 | 
			
		||||
		opts = append([]DOption{WithDecoderLowmem(true), WithDecoderMaxWindow(128 << 20)}, opts...)
 | 
			
		||||
		// Force concurrency 1
 | 
			
		||||
		opts = append(opts, WithDecoderConcurrency(1))
 | 
			
		||||
		// Create our own pool
 | 
			
		||||
		pool = &sync.Pool{}
 | 
			
		||||
	}
 | 
			
		||||
	return func(r io.Reader) io.ReadCloser {
 | 
			
		||||
		dec, ok := pool.Get().(*Decoder)
 | 
			
		||||
		if ok {
 | 
			
		||||
			dec.Reset(r)
 | 
			
		||||
		} else {
 | 
			
		||||
			d, err := NewReader(r, opts...)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				panic(err)
 | 
			
		||||
			}
 | 
			
		||||
			dec = d
 | 
			
		||||
		}
 | 
			
		||||
		return &pooledZipReader{dec: dec, pool: pool}
 | 
			
		||||
	}
 | 
			
		||||
	return &pooledZipReader{dec: dec}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type pooledZipReader struct {
 | 
			
		||||
	mu  sync.Mutex // guards Close and Read
 | 
			
		||||
	dec *Decoder
 | 
			
		||||
	mu   sync.Mutex // guards Close and Read
 | 
			
		||||
	pool *sync.Pool
 | 
			
		||||
	dec  *Decoder
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *pooledZipReader) Read(p []byte) (n int, err error) {
 | 
			
		||||
@@ -48,8 +66,8 @@ func (r *pooledZipReader) Read(p []byte) (n int, err error) {
 | 
			
		||||
	}
 | 
			
		||||
	dec, err := r.dec.Read(p)
 | 
			
		||||
	if err == io.EOF {
 | 
			
		||||
		err = r.dec.Reset(nil)
 | 
			
		||||
		zipReaderPool.Put(r.dec)
 | 
			
		||||
		r.dec.Reset(nil)
 | 
			
		||||
		r.pool.Put(r.dec)
 | 
			
		||||
		r.dec = nil
 | 
			
		||||
	}
 | 
			
		||||
	return dec, err
 | 
			
		||||
@@ -61,7 +79,7 @@ func (r *pooledZipReader) Close() error {
 | 
			
		||||
	var err error
 | 
			
		||||
	if r.dec != nil {
 | 
			
		||||
		err = r.dec.Reset(nil)
 | 
			
		||||
		zipReaderPool.Put(r.dec)
 | 
			
		||||
		r.pool.Put(r.dec)
 | 
			
		||||
		r.dec = nil
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
@@ -115,6 +133,9 @@ func ZipCompressor(opts ...EOption) func(w io.Writer) (io.WriteCloser, error) {
 | 
			
		||||
 | 
			
		||||
// ZipDecompressor returns a decompressor that can be registered with zip libraries.
 | 
			
		||||
// See ZipCompressor for example.
 | 
			
		||||
func ZipDecompressor() func(r io.Reader) io.ReadCloser {
 | 
			
		||||
	return newZipReader
 | 
			
		||||
// Options can be specified. WithDecoderConcurrency(1) is forced,
 | 
			
		||||
// and by default a 128MB maximum decompression window is specified.
 | 
			
		||||
// The window size can be overridden if required.
 | 
			
		||||
func ZipDecompressor(opts ...DOption) func(r io.Reader) io.ReadCloser {
 | 
			
		||||
	return newZipReader(opts...)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								vendor/github.com/klauspost/compress/zstd/zstd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/klauspost/compress/zstd/zstd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -110,17 +110,6 @@ func printf(format string, a ...interface{}) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// matchLenFast does matching, but will not match the last up to 7 bytes.
 | 
			
		||||
func matchLenFast(a, b []byte) int {
 | 
			
		||||
	endI := len(a) & (math.MaxInt32 - 7)
 | 
			
		||||
	for i := 0; i < endI; i += 8 {
 | 
			
		||||
		if diff := load64(a, i) ^ load64(b, i); diff != 0 {
 | 
			
		||||
			return i + bits.TrailingZeros64(diff)>>3
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return endI
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// matchLen returns the maximum length.
 | 
			
		||||
// a must be the shortest of the two.
 | 
			
		||||
// The function also returns whether all bytes matched.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								vendor/github.com/slack-go/slack/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/slack-go/slack/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -39,7 +39,7 @@ func main() {
 | 
			
		||||
	// If you set debugging, it will log all requests to the console
 | 
			
		||||
	// Useful when encountering issues
 | 
			
		||||
	// slack.New("YOUR_TOKEN_HERE", slack.OptionDebug(true))
 | 
			
		||||
	groups, err := api.GetUserGroups(false)
 | 
			
		||||
	groups, err := api.GetUserGroups(slack.GetUserGroupsOptionIncludeUsers(false))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Printf("%s\n", err)
 | 
			
		||||
		return
 | 
			
		||||
@@ -86,7 +86,13 @@ See https://github.com/slack-go/slack/blob/master/examples/websocket/websocket.g
 | 
			
		||||
 | 
			
		||||
See https://github.com/slack-go/slack/blob/master/examples/eventsapi/events.go
 | 
			
		||||
 | 
			
		||||
## Socketmode Event Handler (Experimental)
 | 
			
		||||
 | 
			
		||||
When using socket mode, dealing with an event can be pretty lengthy as it requires you to route the event to the right place.
 | 
			
		||||
 | 
			
		||||
Instead, you can use `SocketmodeHandler` much like you use an HTTP handler to register which event you would like to listen to and what callback function will process that event when it occurs.
 | 
			
		||||
 | 
			
		||||
See [./examples/socketmode_handler/socketmode_handler.go](./examples/socketmode_handler/socketmode_handler.go)
 | 
			
		||||
## Contributing
 | 
			
		||||
 | 
			
		||||
You are more than welcome to contribute to this project.  Fork and
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								vendor/github.com/slack-go/slack/block_input.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/slack-go/slack/block_input.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -19,11 +19,12 @@ func (s InputBlock) BlockType() MessageBlockType {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewInputBlock returns a new instance of an input block
 | 
			
		||||
func NewInputBlock(blockID string, label *TextBlockObject, element BlockElement) *InputBlock {
 | 
			
		||||
func NewInputBlock(blockID string, label, hint *TextBlockObject, element BlockElement) *InputBlock {
 | 
			
		||||
	return &InputBlock{
 | 
			
		||||
		Type:    MBTInput,
 | 
			
		||||
		BlockID: blockID,
 | 
			
		||||
		Label:   label,
 | 
			
		||||
		Element: element,
 | 
			
		||||
		Hint:    hint,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										159
									
								
								vendor/github.com/slack-go/slack/bookmarks.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								vendor/github.com/slack-go/slack/bookmarks.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,159 @@
 | 
			
		||||
package slack
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"net/url"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Bookmark struct {
 | 
			
		||||
	ID        string   `json:"id"`
 | 
			
		||||
	ChannelID string   `json:"channel_id"`
 | 
			
		||||
	Title     string   `json:"title"`
 | 
			
		||||
	Link      string   `json:"link"`
 | 
			
		||||
	Emoji     string   `json:"emoji"`
 | 
			
		||||
	IconURL   string   `json:"icon_url"`
 | 
			
		||||
	Type      string   `json:"type"`
 | 
			
		||||
	Created   JSONTime `json:"date_created"`
 | 
			
		||||
	Updated   JSONTime `json:"date_updated"`
 | 
			
		||||
	Rank      string   `json:"rank"`
 | 
			
		||||
 | 
			
		||||
	LastUpdatedByUserID string `json:"last_updated_by_user_id"`
 | 
			
		||||
	LastUpdatedByTeamID string `json:"last_updated_by_team_id"`
 | 
			
		||||
 | 
			
		||||
	ShortcutID string `json:"shortcut_id"`
 | 
			
		||||
	EntityID   string `json:"entity_id"`
 | 
			
		||||
	AppID      string `json:"app_id"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type AddBookmarkParameters struct {
 | 
			
		||||
	Title    string // A required title for the bookmark
 | 
			
		||||
	Type     string // A required type for the bookmark
 | 
			
		||||
	Link     string // URL required for type:link
 | 
			
		||||
	Emoji    string // An optional emoji
 | 
			
		||||
	EntityID string
 | 
			
		||||
	ParentID string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type EditBookmarkParameters struct {
 | 
			
		||||
	Title *string // Change the title. Set to "" to clear
 | 
			
		||||
	Emoji *string // Change the emoji. Set to "" to clear
 | 
			
		||||
	Link  string  // Change the link
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type addBookmarkResponse struct {
 | 
			
		||||
	Bookmark Bookmark `json:"bookmark"`
 | 
			
		||||
	SlackResponse
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type editBookmarkResponse struct {
 | 
			
		||||
	Bookmark Bookmark `json:"bookmark"`
 | 
			
		||||
	SlackResponse
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type listBookmarksResponse struct {
 | 
			
		||||
	Bookmarks []Bookmark `json:"bookmarks"`
 | 
			
		||||
	SlackResponse
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddBookmark adds a bookmark in a channel
 | 
			
		||||
func (api *Client) AddBookmark(channelID string, params AddBookmarkParameters) (Bookmark, error) {
 | 
			
		||||
	return api.AddBookmarkContext(context.Background(), channelID, params)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddBookmarkContext adds a bookmark in a channel with a custom context
 | 
			
		||||
func (api *Client) AddBookmarkContext(ctx context.Context, channelID string, params AddBookmarkParameters) (Bookmark, error) {
 | 
			
		||||
	values := url.Values{
 | 
			
		||||
		"channel_id": {channelID},
 | 
			
		||||
		"token":      {api.token},
 | 
			
		||||
		"title":      {params.Title},
 | 
			
		||||
		"type":       {params.Type},
 | 
			
		||||
	}
 | 
			
		||||
	if params.Link != "" {
 | 
			
		||||
		values.Set("link", params.Link)
 | 
			
		||||
	}
 | 
			
		||||
	if params.Emoji != "" {
 | 
			
		||||
		values.Set("emoji", params.Emoji)
 | 
			
		||||
	}
 | 
			
		||||
	if params.EntityID != "" {
 | 
			
		||||
		values.Set("entity_id", params.EntityID)
 | 
			
		||||
	}
 | 
			
		||||
	if params.ParentID != "" {
 | 
			
		||||
		values.Set("parent_id", params.ParentID)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	response := &addBookmarkResponse{}
 | 
			
		||||
	if err := api.postMethod(ctx, "bookmarks.add", values, response); err != nil {
 | 
			
		||||
		return Bookmark{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return response.Bookmark, response.Err()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RemoveBookmark removes a bookmark from a channel
 | 
			
		||||
func (api *Client) RemoveBookmark(channelID, bookmarkID string) error {
 | 
			
		||||
	return api.RemoveBookmarkContext(context.Background(), channelID, bookmarkID)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RemoveBookmarkContext removes a bookmark from a channel with a custom context
 | 
			
		||||
func (api *Client) RemoveBookmarkContext(ctx context.Context, channelID, bookmarkID string) error {
 | 
			
		||||
	values := url.Values{
 | 
			
		||||
		"channel_id":  {channelID},
 | 
			
		||||
		"token":       {api.token},
 | 
			
		||||
		"bookmark_id": {bookmarkID},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	response := &SlackResponse{}
 | 
			
		||||
	if err := api.postMethod(ctx, "bookmarks.remove", values, response); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return response.Err()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListBookmarks returns all bookmarks for a channel.
 | 
			
		||||
func (api *Client) ListBookmarks(channelID string) ([]Bookmark, error) {
 | 
			
		||||
	return api.ListBookmarksContext(context.Background(), channelID)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListBookmarksContext returns all bookmarks for a channel with a custom context.
 | 
			
		||||
func (api *Client) ListBookmarksContext(ctx context.Context, channelID string) ([]Bookmark, error) {
 | 
			
		||||
	values := url.Values{
 | 
			
		||||
		"channel_id": {channelID},
 | 
			
		||||
		"token":      {api.token},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	response := &listBookmarksResponse{}
 | 
			
		||||
	err := api.postMethod(ctx, "bookmarks.list", values, response)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return response.Bookmarks, response.Err()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (api *Client) EditBookmark(channelID, bookmarkID string, params EditBookmarkParameters) (Bookmark, error) {
 | 
			
		||||
	return api.EditBookmarkContext(context.Background(), channelID, bookmarkID, params)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (api *Client) EditBookmarkContext(ctx context.Context, channelID, bookmarkID string, params EditBookmarkParameters) (Bookmark, error) {
 | 
			
		||||
	values := url.Values{
 | 
			
		||||
		"channel_id":  {channelID},
 | 
			
		||||
		"token":       {api.token},
 | 
			
		||||
		"bookmark_id": {bookmarkID},
 | 
			
		||||
	}
 | 
			
		||||
	if params.Link != "" {
 | 
			
		||||
		values.Set("link", params.Link)
 | 
			
		||||
	}
 | 
			
		||||
	if params.Emoji != nil {
 | 
			
		||||
		values.Set("emoji", *params.Emoji)
 | 
			
		||||
	}
 | 
			
		||||
	if params.Title != nil {
 | 
			
		||||
		values.Set("title", *params.Title)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	response := &editBookmarkResponse{}
 | 
			
		||||
	if err := api.postMethod(ctx, "bookmarks.edit", values, response); err != nil {
 | 
			
		||||
		return Bookmark{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return response.Bookmark, response.Err()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/github.com/slack-go/slack/misc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/slack-go/slack/misc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -18,8 +18,6 @@ import (
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/slack-go/slack/internal/misc"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SlackResponse handles parsing out errors from the web api.
 | 
			
		||||
@@ -299,7 +297,7 @@ func checkStatusCode(resp *http.Response, d Debug) error {
 | 
			
		||||
	// Slack seems to send an HTML body along with 5xx error codes. Don't parse it.
 | 
			
		||||
	if resp.StatusCode != http.StatusOK {
 | 
			
		||||
		logResponse(resp, d)
 | 
			
		||||
		return misc.StatusCodeError{Code: resp.StatusCode, Status: resp.Status}
 | 
			
		||||
		return StatusCodeError{Code: resp.StatusCode, Status: resp.Status}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										316
									
								
								vendor/github.com/slack-go/slack/remotefiles.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										316
									
								
								vendor/github.com/slack-go/slack/remotefiles.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,316 @@
 | 
			
		||||
package slack
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	DEFAULT_REMOTE_FILES_CHANNEL = ""
 | 
			
		||||
	DEFAULT_REMOTE_FILES_TS_FROM = 0
 | 
			
		||||
	DEFAULT_REMOTE_FILES_TS_TO   = -1
 | 
			
		||||
	DEFAULT_REMOTE_FILES_COUNT   = 100
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// RemoteFile contains all the information for a remote file
 | 
			
		||||
// For more details:
 | 
			
		||||
// https://api.slack.com/messaging/files/remote
 | 
			
		||||
type RemoteFile struct {
 | 
			
		||||
	ID              string   `json:"id"`
 | 
			
		||||
	Created         JSONTime `json:"created"`
 | 
			
		||||
	Timestamp       JSONTime `json:"timestamp"`
 | 
			
		||||
	Name            string   `json:"name"`
 | 
			
		||||
	Title           string   `json:"title"`
 | 
			
		||||
	Mimetype        string   `json:"mimetype"`
 | 
			
		||||
	Filetype        string   `json:"filetype"`
 | 
			
		||||
	PrettyType      string   `json:"pretty_type"`
 | 
			
		||||
	User            string   `json:"user"`
 | 
			
		||||
	Editable        bool     `json:"editable"`
 | 
			
		||||
	Size            int      `json:"size"`
 | 
			
		||||
	Mode            string   `json:"mode"`
 | 
			
		||||
	IsExternal      bool     `json:"is_external"`
 | 
			
		||||
	ExternalType    string   `json:"external_type"`
 | 
			
		||||
	IsPublic        bool     `json:"is_public"`
 | 
			
		||||
	PublicURLShared bool     `json:"public_url_shared"`
 | 
			
		||||
	DisplayAsBot    bool     `json:"display_as_bot"`
 | 
			
		||||
	Username        string   `json:"username"`
 | 
			
		||||
	URLPrivate      string   `json:"url_private"`
 | 
			
		||||
	Permalink       string   `json:"permalink"`
 | 
			
		||||
	CommentsCount   int      `json:"comments_count"`
 | 
			
		||||
	IsStarred       bool     `json:"is_starred"`
 | 
			
		||||
	Shares          Share    `json:"shares"`
 | 
			
		||||
	Channels        []string `json:"channels"`
 | 
			
		||||
	Groups          []string `json:"groups"`
 | 
			
		||||
	IMs             []string `json:"ims"`
 | 
			
		||||
	ExternalID      string   `json:"external_id"`
 | 
			
		||||
	ExternalURL     string   `json:"external_url"`
 | 
			
		||||
	HasRichPreview  bool     `json:"has_rich_preview"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RemoteFileParameters contains required and optional parameters for a remote file.
 | 
			
		||||
//
 | 
			
		||||
// ExternalID is a user defined GUID, ExternalURL is where the remote file can be accessed,
 | 
			
		||||
// and Title is the name of the file.
 | 
			
		||||
//
 | 
			
		||||
// For more details:
 | 
			
		||||
// https://api.slack.com/methods/files.remote.add
 | 
			
		||||
type RemoteFileParameters struct {
 | 
			
		||||
	ExternalID            string // required
 | 
			
		||||
	ExternalURL           string // required
 | 
			
		||||
	Title                 string // required
 | 
			
		||||
	Filetype              string
 | 
			
		||||
	IndexableFileContents string
 | 
			
		||||
	PreviewImage          string
 | 
			
		||||
	PreviewImageReader    io.Reader
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListRemoteFilesParameters contains arguments for the ListRemoteFiles method.
 | 
			
		||||
// For more details:
 | 
			
		||||
// https://api.slack.com/methods/files.remote.list
 | 
			
		||||
type ListRemoteFilesParameters struct {
 | 
			
		||||
	Channel       string
 | 
			
		||||
	Cursor        string
 | 
			
		||||
	Limit         int
 | 
			
		||||
	TimestampFrom JSONTime
 | 
			
		||||
	TimestampTo   JSONTime
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type remoteFileResponseFull struct {
 | 
			
		||||
	RemoteFile `json:"file"`
 | 
			
		||||
	Paging     `json:"paging"`
 | 
			
		||||
	Files      []RemoteFile `json:"files"`
 | 
			
		||||
	SlackResponse
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (api *Client) remoteFileRequest(ctx context.Context, path string, values url.Values) (*remoteFileResponseFull, error) {
 | 
			
		||||
	response := &remoteFileResponseFull{}
 | 
			
		||||
	err := api.postMethod(ctx, path, values, response)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return response, response.Err()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddRemoteFile adds a remote file. Unlike regular files, remote files must be explicitly shared.
 | 
			
		||||
// For more details:
 | 
			
		||||
// https://api.slack.com/methods/files.remote.add
 | 
			
		||||
func (api *Client) AddRemoteFile(params RemoteFileParameters) (*RemoteFile, error) {
 | 
			
		||||
	return api.AddRemoteFileContext(context.Background(), params)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddRemoteFileContext adds a remote file and setting a custom context
 | 
			
		||||
// For more details see the AddRemoteFile documentation.
 | 
			
		||||
func (api *Client) AddRemoteFileContext(ctx context.Context, params RemoteFileParameters) (remotefile *RemoteFile, err error) {
 | 
			
		||||
	if params.ExternalID == "" || params.ExternalURL == "" || params.Title == "" {
 | 
			
		||||
		return nil, ErrParametersMissing
 | 
			
		||||
	}
 | 
			
		||||
	response := &remoteFileResponseFull{}
 | 
			
		||||
	values := url.Values{
 | 
			
		||||
		"token":        {api.token},
 | 
			
		||||
		"external_id":  {params.ExternalID},
 | 
			
		||||
		"external_url": {params.ExternalURL},
 | 
			
		||||
		"title":        {params.Title},
 | 
			
		||||
	}
 | 
			
		||||
	if params.Filetype != "" {
 | 
			
		||||
		values.Add("filetype", params.Filetype)
 | 
			
		||||
	}
 | 
			
		||||
	if params.IndexableFileContents != "" {
 | 
			
		||||
		values.Add("indexable_file_contents", params.IndexableFileContents)
 | 
			
		||||
	}
 | 
			
		||||
	if params.PreviewImage != "" {
 | 
			
		||||
		err = postLocalWithMultipartResponse(ctx, api.httpclient, api.endpoint+"files.remote.add", params.PreviewImage, "preview_image", api.token, values, response, api)
 | 
			
		||||
	} else if params.PreviewImageReader != nil {
 | 
			
		||||
		err = postWithMultipartResponse(ctx, api.httpclient, api.endpoint+"files.remote.add", "preview.png", "preview_image", api.token, values, params.PreviewImageReader, response, api)
 | 
			
		||||
	} else {
 | 
			
		||||
		response, err = api.remoteFileRequest(ctx, "files.remote.add", values)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &response.RemoteFile, response.Err()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListRemoteFiles retrieves all remote files according to the parameters given. Uses cursor based pagination.
 | 
			
		||||
// For more details:
 | 
			
		||||
// https://api.slack.com/methods/files.remote.list
 | 
			
		||||
func (api *Client) ListRemoteFiles(params ListRemoteFilesParameters) ([]RemoteFile, error) {
 | 
			
		||||
	return api.ListRemoteFilesContext(context.Background(), params)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListRemoteFilesContext retrieves all remote files according to the parameters given with a custom context. Uses cursor based pagination.
 | 
			
		||||
// For more details see the ListRemoteFiles documentation.
 | 
			
		||||
func (api *Client) ListRemoteFilesContext(ctx context.Context, params ListRemoteFilesParameters) ([]RemoteFile, error) {
 | 
			
		||||
	values := url.Values{
 | 
			
		||||
		"token": {api.token},
 | 
			
		||||
	}
 | 
			
		||||
	if params.Channel != DEFAULT_REMOTE_FILES_CHANNEL {
 | 
			
		||||
		values.Add("channel", params.Channel)
 | 
			
		||||
	}
 | 
			
		||||
	if params.TimestampFrom != DEFAULT_REMOTE_FILES_TS_FROM {
 | 
			
		||||
		values.Add("ts_from", strconv.FormatInt(int64(params.TimestampFrom), 10))
 | 
			
		||||
	}
 | 
			
		||||
	if params.TimestampTo != DEFAULT_REMOTE_FILES_TS_TO {
 | 
			
		||||
		values.Add("ts_to", strconv.FormatInt(int64(params.TimestampTo), 10))
 | 
			
		||||
	}
 | 
			
		||||
	if params.Limit != DEFAULT_REMOTE_FILES_COUNT {
 | 
			
		||||
		values.Add("limit", strconv.Itoa(params.Limit))
 | 
			
		||||
	}
 | 
			
		||||
	if params.Cursor != "" {
 | 
			
		||||
		values.Add("cursor", params.Cursor)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	response, err := api.remoteFileRequest(ctx, "files.remote.list", values)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	params.Cursor = response.SlackResponse.ResponseMetadata.Cursor
 | 
			
		||||
 | 
			
		||||
	return response.Files, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetRemoteFileInfo retrieves the complete remote file information.
 | 
			
		||||
// For more details:
 | 
			
		||||
// https://api.slack.com/methods/files.remote.info
 | 
			
		||||
func (api *Client) GetRemoteFileInfo(externalID, fileID string) (remotefile *RemoteFile, err error) {
 | 
			
		||||
	return api.GetRemoteFileInfoContext(context.Background(), externalID, fileID)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetRemoteFileInfoContext retrieves the complete remote file information given with a custom context.
 | 
			
		||||
// For more details see the GetRemoteFileInfo documentation.
 | 
			
		||||
func (api *Client) GetRemoteFileInfoContext(ctx context.Context, externalID, fileID string) (remotefile *RemoteFile, err error) {
 | 
			
		||||
	if fileID == "" && externalID == "" {
 | 
			
		||||
		return nil, fmt.Errorf("either externalID or fileID is required")
 | 
			
		||||
	}
 | 
			
		||||
	if fileID != "" && externalID != "" {
 | 
			
		||||
		return nil, fmt.Errorf("don't provide both externalID and fileID")
 | 
			
		||||
	}
 | 
			
		||||
	values := url.Values{
 | 
			
		||||
		"token": {api.token},
 | 
			
		||||
	}
 | 
			
		||||
	if fileID != "" {
 | 
			
		||||
		values.Add("file", fileID)
 | 
			
		||||
	}
 | 
			
		||||
	if externalID != "" {
 | 
			
		||||
		values.Add("external_id", externalID)
 | 
			
		||||
	}
 | 
			
		||||
	response, err := api.remoteFileRequest(ctx, "files.remote.info", values)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &response.RemoteFile, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ShareRemoteFile shares a remote file to channels
 | 
			
		||||
// For more details:
 | 
			
		||||
// https://api.slack.com/methods/files.remote.share
 | 
			
		||||
func (api *Client) ShareRemoteFile(channels []string, externalID, fileID string) (file *RemoteFile, err error) {
 | 
			
		||||
	return api.ShareRemoteFileContext(context.Background(), channels, externalID, fileID)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ShareRemoteFileContext shares a remote file to channels with a custom context.
 | 
			
		||||
// For more details see the ShareRemoteFile documentation.
 | 
			
		||||
func (api *Client) ShareRemoteFileContext(ctx context.Context, channels []string, externalID, fileID string) (file *RemoteFile, err error) {
 | 
			
		||||
	if channels == nil || len(channels) == 0 {
 | 
			
		||||
		return nil, ErrParametersMissing
 | 
			
		||||
	}
 | 
			
		||||
	if fileID == "" && externalID == "" {
 | 
			
		||||
		return nil, fmt.Errorf("either externalID or fileID is required")
 | 
			
		||||
	}
 | 
			
		||||
	values := url.Values{
 | 
			
		||||
		"token":    {api.token},
 | 
			
		||||
		"channels": {strings.Join(channels, ",")},
 | 
			
		||||
	}
 | 
			
		||||
	if fileID != "" {
 | 
			
		||||
		values.Add("file", fileID)
 | 
			
		||||
	}
 | 
			
		||||
	if externalID != "" {
 | 
			
		||||
		values.Add("external_id", externalID)
 | 
			
		||||
	}
 | 
			
		||||
	response, err := api.remoteFileRequest(ctx, "files.remote.share", values)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &response.RemoteFile, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateRemoteFile updates a remote file
 | 
			
		||||
// For more details:
 | 
			
		||||
// https://api.slack.com/methods/files.remote.update
 | 
			
		||||
func (api *Client) UpdateRemoteFile(fileID string, params RemoteFileParameters) (remotefile *RemoteFile, err error) {
 | 
			
		||||
	return api.UpdateRemoteFileContext(context.Background(), fileID, params)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateRemoteFileContext updates a remote file with a custom context
 | 
			
		||||
// For more details see the UpdateRemoteFile documentation.
 | 
			
		||||
func (api *Client) UpdateRemoteFileContext(ctx context.Context, fileID string, params RemoteFileParameters) (remotefile *RemoteFile, err error) {
 | 
			
		||||
	response := &remoteFileResponseFull{}
 | 
			
		||||
	values := url.Values{
 | 
			
		||||
		"token": {api.token},
 | 
			
		||||
	}
 | 
			
		||||
	if fileID != "" {
 | 
			
		||||
		values.Add("file", fileID)
 | 
			
		||||
	}
 | 
			
		||||
	if params.ExternalID != "" {
 | 
			
		||||
		values.Add("external_id", params.ExternalID)
 | 
			
		||||
	}
 | 
			
		||||
	if params.ExternalURL != "" {
 | 
			
		||||
		values.Add("external_url", params.ExternalURL)
 | 
			
		||||
	}
 | 
			
		||||
	if params.Title != "" {
 | 
			
		||||
		values.Add("title", params.Title)
 | 
			
		||||
	}
 | 
			
		||||
	if params.Filetype != "" {
 | 
			
		||||
		values.Add("filetype", params.Filetype)
 | 
			
		||||
	}
 | 
			
		||||
	if params.IndexableFileContents != "" {
 | 
			
		||||
		values.Add("indexable_file_contents", params.IndexableFileContents)
 | 
			
		||||
	}
 | 
			
		||||
	if params.PreviewImageReader != nil {
 | 
			
		||||
		err = postWithMultipartResponse(ctx, api.httpclient, api.endpoint+"files.remote.update", "preview.png", "preview_image", api.token, values, params.PreviewImageReader, response, api)
 | 
			
		||||
	} else {
 | 
			
		||||
		response, err = api.remoteFileRequest(ctx, "files.remote.update", values)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &response.RemoteFile, response.Err()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RemoveRemoteFile removes a remote file.
 | 
			
		||||
// For more details:
 | 
			
		||||
// https://api.slack.com/methods/files.remote.remove
 | 
			
		||||
func (api *Client) RemoveRemoteFile(externalID, fileID string) (err error) {
 | 
			
		||||
	return api.RemoveRemoteFileContext(context.Background(), externalID, fileID)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RemoveRemoteFileContext removes a remote file with a custom context
 | 
			
		||||
// For more information see the RemoveRemoteFiles documentation.
 | 
			
		||||
func (api *Client) RemoveRemoteFileContext(ctx context.Context, externalID, fileID string) (err error) {
 | 
			
		||||
	if fileID == "" && externalID == "" {
 | 
			
		||||
		return fmt.Errorf("either externalID or fileID is required")
 | 
			
		||||
	}
 | 
			
		||||
	if fileID != "" && externalID != "" {
 | 
			
		||||
		return fmt.Errorf("don't provide both externalID and fileID")
 | 
			
		||||
	}
 | 
			
		||||
	values := url.Values{
 | 
			
		||||
		"token": {api.token},
 | 
			
		||||
	}
 | 
			
		||||
	if fileID != "" {
 | 
			
		||||
		values.Add("file", fileID)
 | 
			
		||||
	}
 | 
			
		||||
	if externalID != "" {
 | 
			
		||||
		values.Add("external_id", externalID)
 | 
			
		||||
	}
 | 
			
		||||
	_, err = api.remoteFileRequest(ctx, "files.remote.remove", values)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
package misc
 | 
			
		||||
package slack
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
							
								
								
									
										37
									
								
								vendor/github.com/slack-go/slack/views.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/slack-go/slack/views.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -18,24 +18,25 @@ type ViewState struct {
 | 
			
		||||
 | 
			
		||||
type View struct {
 | 
			
		||||
	SlackResponse
 | 
			
		||||
	ID              string           `json:"id"`
 | 
			
		||||
	TeamID          string           `json:"team_id"`
 | 
			
		||||
	Type            ViewType         `json:"type"`
 | 
			
		||||
	Title           *TextBlockObject `json:"title"`
 | 
			
		||||
	Close           *TextBlockObject `json:"close"`
 | 
			
		||||
	Submit          *TextBlockObject `json:"submit"`
 | 
			
		||||
	Blocks          Blocks           `json:"blocks"`
 | 
			
		||||
	PrivateMetadata string           `json:"private_metadata"`
 | 
			
		||||
	CallbackID      string           `json:"callback_id"`
 | 
			
		||||
	State           *ViewState       `json:"state"`
 | 
			
		||||
	Hash            string           `json:"hash"`
 | 
			
		||||
	ClearOnClose    bool             `json:"clear_on_close"`
 | 
			
		||||
	NotifyOnClose   bool             `json:"notify_on_close"`
 | 
			
		||||
	RootViewID      string           `json:"root_view_id"`
 | 
			
		||||
	PreviousViewID  string           `json:"previous_view_id"`
 | 
			
		||||
	AppID           string           `json:"app_id"`
 | 
			
		||||
	ExternalID      string           `json:"external_id"`
 | 
			
		||||
	BotID           string           `json:"bot_id"`
 | 
			
		||||
	ID                 string           `json:"id"`
 | 
			
		||||
	TeamID             string           `json:"team_id"`
 | 
			
		||||
	Type               ViewType         `json:"type"`
 | 
			
		||||
	Title              *TextBlockObject `json:"title"`
 | 
			
		||||
	Close              *TextBlockObject `json:"close"`
 | 
			
		||||
	Submit             *TextBlockObject `json:"submit"`
 | 
			
		||||
	Blocks             Blocks           `json:"blocks"`
 | 
			
		||||
	PrivateMetadata    string           `json:"private_metadata"`
 | 
			
		||||
	CallbackID         string           `json:"callback_id"`
 | 
			
		||||
	State              *ViewState       `json:"state"`
 | 
			
		||||
	Hash               string           `json:"hash"`
 | 
			
		||||
	ClearOnClose       bool             `json:"clear_on_close"`
 | 
			
		||||
	NotifyOnClose      bool             `json:"notify_on_close"`
 | 
			
		||||
	RootViewID         string           `json:"root_view_id"`
 | 
			
		||||
	PreviousViewID     string           `json:"previous_view_id"`
 | 
			
		||||
	AppID              string           `json:"app_id"`
 | 
			
		||||
	ExternalID         string           `json:"external_id"`
 | 
			
		||||
	BotID              string           `json:"bot_id"`
 | 
			
		||||
	AppInstalledTeamID string           `json:"app_installed_team_id"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ViewSubmissionCallbackResponseURL struct {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								vendor/github.com/slack-go/slack/webhooks.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/slack-go/slack/webhooks.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -5,6 +5,8 @@ import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"net/http"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -21,6 +23,7 @@ type WebhookMessage struct {
 | 
			
		||||
	ResponseType    string       `json:"response_type,omitempty"`
 | 
			
		||||
	ReplaceOriginal bool         `json:"replace_original,omitempty"`
 | 
			
		||||
	DeleteOriginal  bool         `json:"delete_original,omitempty"`
 | 
			
		||||
	ReplyBroadcast  bool         `json:"reply_broadcast,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func PostWebhook(url string, msg *WebhookMessage) error {
 | 
			
		||||
@@ -51,7 +54,10 @@ func PostWebhookCustomHTTPContext(ctx context.Context, url string, httpClient *h
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("failed to post webhook: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer resp.Body.Close()
 | 
			
		||||
	defer func() {
 | 
			
		||||
		io.Copy(ioutil.Discard, resp.Body)
 | 
			
		||||
		resp.Body.Close()
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	return checkStatusCode(resp, discard{})
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								vendor/github.com/slack-go/slack/websocket_managed_conn.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/slack-go/slack/websocket_managed_conn.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -13,7 +13,6 @@ import (
 | 
			
		||||
 | 
			
		||||
	"github.com/slack-go/slack/internal/backoff"
 | 
			
		||||
	"github.com/slack-go/slack/internal/errorsx"
 | 
			
		||||
	"github.com/slack-go/slack/internal/misc"
 | 
			
		||||
	"github.com/slack-go/slack/internal/timex"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -127,7 +126,7 @@ func (rtm *RTM) connect(connectionCount int, useRTMStart bool) (*Info, *websocke
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch actual := err.(type) {
 | 
			
		||||
		case misc.StatusCodeError:
 | 
			
		||||
		case StatusCodeError:
 | 
			
		||||
			if actual.Code == http.StatusNotFound {
 | 
			
		||||
				rtm.Debugf("invalid auth when connecting with RTM: %s", err)
 | 
			
		||||
				rtm.IncomingEvents <- RTMEvent{"invalid_auth", &InvalidAuthEvent{}}
 | 
			
		||||
@@ -475,7 +474,7 @@ func (rtm *RTM) handleEvent(typeStr string, event json.RawMessage) {
 | 
			
		||||
	v, exists := EventMapping[typeStr]
 | 
			
		||||
	if !exists {
 | 
			
		||||
		rtm.Debugf("RTM Error - received unmapped event %q: %s\n", typeStr, string(event))
 | 
			
		||||
		err := fmt.Errorf("RTM Error: Received unmapped event %q: %s", typeStr, string(event))
 | 
			
		||||
		err := fmt.Errorf("RTM Error: Received unmapped event %q", typeStr)
 | 
			
		||||
		rtm.IncomingEvents <- RTMEvent{"unmarshalling_error", &UnmarshallingErrorEvent{err}}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
@@ -484,7 +483,7 @@ func (rtm *RTM) handleEvent(typeStr string, event json.RawMessage) {
 | 
			
		||||
	err := json.Unmarshal(event, recvEvent)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		rtm.Debugf("RTM Error, could not unmarshall event %q: %s\n", typeStr, string(event))
 | 
			
		||||
		err := fmt.Errorf("RTM Error: Could not unmarshall event %q: %s", typeStr, string(event))
 | 
			
		||||
		err := fmt.Errorf("RTM Error: Could not unmarshall event %q", typeStr)
 | 
			
		||||
		rtm.IncomingEvents <- RTMEvent{"unmarshalling_error", &UnmarshallingErrorEvent{err}}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/github.com/slack-go/slack/websocket_subteam.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/slack-go/slack/websocket_subteam.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -14,9 +14,9 @@ type SubteamMembersChangedEvent struct {
 | 
			
		||||
	DatePreviousUpdate JSONTime `json:"date_previous_update"`
 | 
			
		||||
	DateUpdate         JSONTime `json:"date_update"`
 | 
			
		||||
	AddedUsers         []string `json:"added_users"`
 | 
			
		||||
	AddedUsersCount    string   `json:"added_users_count"`
 | 
			
		||||
	AddedUsersCount    int      `json:"added_users_count"`
 | 
			
		||||
	RemovedUsers       []string `json:"removed_users"`
 | 
			
		||||
	RemovedUsersCount  string   `json:"removed_users_count"`
 | 
			
		||||
	RemovedUsersCount  int      `json:"removed_users_count"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SubteamSelfAddedEvent represents an event of you have been added to a User Group
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -9,7 +9,7 @@ package assert
 | 
			
		||||
 | 
			
		||||
import "reflect"
 | 
			
		||||
 | 
			
		||||
// Wrapper around reflect.Value.CanConvert, for compatability
 | 
			
		||||
// Wrapper around reflect.Value.CanConvert, for compatibility
 | 
			
		||||
// reasons.
 | 
			
		||||
func canConvert(value reflect.Value, to reflect.Type) bool {
 | 
			
		||||
	return value.CanConvert(to)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								vendor/github.com/stretchr/testify/suite/suite.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								vendor/github.com/stretchr/testify/suite/suite.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -7,6 +7,7 @@ import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"runtime/debug"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
@@ -21,17 +22,22 @@ var matchMethod = flag.String("testify.m", "", "regular expression to select tes
 | 
			
		||||
// retrieving the current *testing.T context.
 | 
			
		||||
type Suite struct {
 | 
			
		||||
	*assert.Assertions
 | 
			
		||||
	mu      sync.RWMutex
 | 
			
		||||
	require *require.Assertions
 | 
			
		||||
	t       *testing.T
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// T retrieves the current *testing.T context.
 | 
			
		||||
func (suite *Suite) T() *testing.T {
 | 
			
		||||
	suite.mu.RLock()
 | 
			
		||||
	defer suite.mu.RUnlock()
 | 
			
		||||
	return suite.t
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetT sets the current *testing.T context.
 | 
			
		||||
func (suite *Suite) SetT(t *testing.T) {
 | 
			
		||||
	suite.mu.Lock()
 | 
			
		||||
	defer suite.mu.Unlock()
 | 
			
		||||
	suite.t = t
 | 
			
		||||
	suite.Assertions = assert.New(t)
 | 
			
		||||
	suite.require = require.New(t)
 | 
			
		||||
@@ -39,6 +45,8 @@ func (suite *Suite) SetT(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
// Require returns a require context for suite.
 | 
			
		||||
func (suite *Suite) Require() *require.Assertions {
 | 
			
		||||
	suite.mu.Lock()
 | 
			
		||||
	defer suite.mu.Unlock()
 | 
			
		||||
	if suite.require == nil {
 | 
			
		||||
		suite.require = require.New(suite.T())
 | 
			
		||||
	}
 | 
			
		||||
@@ -51,6 +59,8 @@ func (suite *Suite) Require() *require.Assertions {
 | 
			
		||||
// assert.Assertions with require.Assertions), this method is provided so you
 | 
			
		||||
// can call `suite.Assert().NoError()`.
 | 
			
		||||
func (suite *Suite) Assert() *assert.Assertions {
 | 
			
		||||
	suite.mu.Lock()
 | 
			
		||||
	defer suite.mu.Unlock()
 | 
			
		||||
	if suite.Assertions == nil {
 | 
			
		||||
		suite.Assertions = assert.New(suite.T())
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3598
									
								
								vendor/go.mau.fi/whatsmeow/binary/proto/def.pb.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3598
									
								
								vendor/go.mau.fi/whatsmeow/binary/proto/def.pb.go
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								vendor/go.mau.fi/whatsmeow/binary/proto/def.pb.raw
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								vendor/go.mau.fi/whatsmeow/binary/proto/def.pb.raw
									
									
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										158
									
								
								vendor/go.mau.fi/whatsmeow/binary/proto/def.proto
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										158
									
								
								vendor/go.mau.fi/whatsmeow/binary/proto/def.proto
									
									
									
									
										vendored
									
									
								
							@@ -31,10 +31,10 @@ message ADVDeviceIdentity {
 | 
			
		||||
    optional uint32 keyIndex = 3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message CompanionProps {
 | 
			
		||||
message DeviceProps {
 | 
			
		||||
    optional string os = 1;
 | 
			
		||||
    optional AppVersion version = 2;
 | 
			
		||||
    enum CompanionPropsPlatformType {
 | 
			
		||||
    enum DevicePropsPlatformType {
 | 
			
		||||
        UNKNOWN = 0;
 | 
			
		||||
        CHROME = 1;
 | 
			
		||||
        FIREFOX = 2;
 | 
			
		||||
@@ -50,7 +50,7 @@ message CompanionProps {
 | 
			
		||||
        CATALINA = 12;
 | 
			
		||||
        TCL_TV = 13;
 | 
			
		||||
    }
 | 
			
		||||
    optional CompanionPropsPlatformType platformType = 3;
 | 
			
		||||
    optional DevicePropsPlatformType platformType = 3;
 | 
			
		||||
    optional bool requireFullSync = 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -62,39 +62,6 @@ message AppVersion {
 | 
			
		||||
    optional uint32 quinary = 5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message ProtocolMessage {
 | 
			
		||||
    optional MessageKey key = 1;
 | 
			
		||||
    enum ProtocolMessageType {
 | 
			
		||||
        REVOKE = 0;
 | 
			
		||||
        EPHEMERAL_SETTING = 3;
 | 
			
		||||
        EPHEMERAL_SYNC_RESPONSE = 4;
 | 
			
		||||
        HISTORY_SYNC_NOTIFICATION = 5;
 | 
			
		||||
        APP_STATE_SYNC_KEY_SHARE = 6;
 | 
			
		||||
        APP_STATE_SYNC_KEY_REQUEST = 7;
 | 
			
		||||
        MSG_FANOUT_BACKFILL_REQUEST = 8;
 | 
			
		||||
        INITIAL_SECURITY_NOTIFICATION_SETTING_SYNC = 9;
 | 
			
		||||
        APP_STATE_FATAL_EXCEPTION_NOTIFICATION = 10;
 | 
			
		||||
    }
 | 
			
		||||
    optional ProtocolMessageType type = 2;
 | 
			
		||||
    optional uint32 ephemeralExpiration = 4;
 | 
			
		||||
    optional int64 ephemeralSettingTimestamp = 5;
 | 
			
		||||
    optional HistorySyncNotification historySyncNotification = 6;
 | 
			
		||||
    optional AppStateSyncKeyShare appStateSyncKeyShare = 7;
 | 
			
		||||
    optional AppStateSyncKeyRequest appStateSyncKeyRequest = 8;
 | 
			
		||||
    optional InitialSecurityNotificationSettingSync initialSecurityNotificationSettingSync = 9;
 | 
			
		||||
    optional AppStateFatalExceptionNotification appStateFatalExceptionNotification = 10;
 | 
			
		||||
    optional DisappearingMode disappearingMode = 11;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message ProductMessage {
 | 
			
		||||
    optional ProductSnapshot product = 1;
 | 
			
		||||
    optional string businessOwnerJid = 2;
 | 
			
		||||
    optional CatalogSnapshot catalog = 4;
 | 
			
		||||
    optional string body = 5;
 | 
			
		||||
    optional string footer = 6;
 | 
			
		||||
    optional ContextInfo contextInfo = 17;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message ProductSnapshot {
 | 
			
		||||
    optional ImageMessage productImage = 1;
 | 
			
		||||
    optional string productId = 2;
 | 
			
		||||
@@ -123,6 +90,10 @@ message PollVoteMessage {
 | 
			
		||||
message PollUpdateMessage {
 | 
			
		||||
    optional MessageKey pollCreationMessageKey = 1;
 | 
			
		||||
    optional PollEncValue vote = 2;
 | 
			
		||||
    optional PollUpdateMessageMetadata metadata = 3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message PollUpdateMessageMetadata {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message PollEncValue {
 | 
			
		||||
@@ -265,6 +236,12 @@ message ProductListHeaderImage {
 | 
			
		||||
    optional bytes jpegThumbnail = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message KeepInChatMessage {
 | 
			
		||||
    optional MessageKey key = 1;
 | 
			
		||||
    optional KeepType keepType = 2;
 | 
			
		||||
    optional int64 timestampMs = 3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message InvoiceMessage {
 | 
			
		||||
    optional string note = 1;
 | 
			
		||||
    optional string token = 2;
 | 
			
		||||
@@ -708,6 +685,11 @@ message Location {
 | 
			
		||||
    optional string name = 3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum KeepType {
 | 
			
		||||
    UNKNOWN = 0;
 | 
			
		||||
    KEEP_FOR_ALL = 1;
 | 
			
		||||
    UNDO_KEEP_FOR_ALL = 2;
 | 
			
		||||
}
 | 
			
		||||
message InteractiveAnnotation {
 | 
			
		||||
    repeated Point polygonVertices = 1;
 | 
			
		||||
    oneof action {
 | 
			
		||||
@@ -926,12 +908,14 @@ message Message {
 | 
			
		||||
    optional InteractiveResponseMessage interactiveResponseMessage = 48;
 | 
			
		||||
    optional PollCreationMessage pollCreationMessage = 49;
 | 
			
		||||
    optional PollUpdateMessage pollUpdateMessage = 50;
 | 
			
		||||
    optional KeepInChatMessage keepInChatMessage = 51;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message MessageContextInfo {
 | 
			
		||||
    optional DeviceListMetadata deviceListMetadata = 1;
 | 
			
		||||
    optional int32 deviceListMetadataVersion = 2;
 | 
			
		||||
    optional bytes messageSecret = 3;
 | 
			
		||||
    optional bytes paddingBytes = 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message VideoMessage {
 | 
			
		||||
@@ -1060,6 +1044,39 @@ message ReactionMessage {
 | 
			
		||||
    optional int64 senderTimestampMs = 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message ProtocolMessage {
 | 
			
		||||
    optional MessageKey key = 1;
 | 
			
		||||
    enum ProtocolMessageType {
 | 
			
		||||
        REVOKE = 0;
 | 
			
		||||
        EPHEMERAL_SETTING = 3;
 | 
			
		||||
        EPHEMERAL_SYNC_RESPONSE = 4;
 | 
			
		||||
        HISTORY_SYNC_NOTIFICATION = 5;
 | 
			
		||||
        APP_STATE_SYNC_KEY_SHARE = 6;
 | 
			
		||||
        APP_STATE_SYNC_KEY_REQUEST = 7;
 | 
			
		||||
        MSG_FANOUT_BACKFILL_REQUEST = 8;
 | 
			
		||||
        INITIAL_SECURITY_NOTIFICATION_SETTING_SYNC = 9;
 | 
			
		||||
        APP_STATE_FATAL_EXCEPTION_NOTIFICATION = 10;
 | 
			
		||||
    }
 | 
			
		||||
    optional ProtocolMessageType type = 2;
 | 
			
		||||
    optional uint32 ephemeralExpiration = 4;
 | 
			
		||||
    optional int64 ephemeralSettingTimestamp = 5;
 | 
			
		||||
    optional HistorySyncNotification historySyncNotification = 6;
 | 
			
		||||
    optional AppStateSyncKeyShare appStateSyncKeyShare = 7;
 | 
			
		||||
    optional AppStateSyncKeyRequest appStateSyncKeyRequest = 8;
 | 
			
		||||
    optional InitialSecurityNotificationSettingSync initialSecurityNotificationSettingSync = 9;
 | 
			
		||||
    optional AppStateFatalExceptionNotification appStateFatalExceptionNotification = 10;
 | 
			
		||||
    optional DisappearingMode disappearingMode = 11;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message ProductMessage {
 | 
			
		||||
    optional ProductSnapshot product = 1;
 | 
			
		||||
    optional string businessOwnerJid = 2;
 | 
			
		||||
    optional CatalogSnapshot catalog = 4;
 | 
			
		||||
    optional string body = 5;
 | 
			
		||||
    optional string footer = 6;
 | 
			
		||||
    optional ContextInfo contextInfo = 17;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message EphemeralSetting {
 | 
			
		||||
    optional sfixed32 duration = 1;
 | 
			
		||||
    optional sfixed64 timestamp = 2;
 | 
			
		||||
@@ -1161,6 +1178,17 @@ message Conversation {
 | 
			
		||||
    optional MediaVisibility mediaVisibility = 27;
 | 
			
		||||
    optional uint64 tcTokenSenderTimestamp = 28;
 | 
			
		||||
    optional bool suspended = 29;
 | 
			
		||||
    optional bool terminated = 30;
 | 
			
		||||
    optional uint64 createdAt = 31;
 | 
			
		||||
    optional string createdBy = 32;
 | 
			
		||||
    optional string description = 33;
 | 
			
		||||
    optional bool support = 34;
 | 
			
		||||
    optional bool isParentGroup = 35;
 | 
			
		||||
    optional bool isDefaultSubgroup = 36;
 | 
			
		||||
    optional string parentGroupId = 37;
 | 
			
		||||
    optional string displayName = 38;
 | 
			
		||||
    optional string pnJid = 39;
 | 
			
		||||
    optional bool selfMasked = 40;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message AutoDownloadSettings {
 | 
			
		||||
@@ -1192,8 +1220,8 @@ message MsgOpaqueData {
 | 
			
		||||
    optional string loc = 16;
 | 
			
		||||
    optional string pollName = 17;
 | 
			
		||||
    repeated PollOption pollOptions = 18;
 | 
			
		||||
    optional bytes pollEncKey = 19;
 | 
			
		||||
    optional uint32 pollSelectableOptionsCount = 20;
 | 
			
		||||
    optional bytes messageSecret = 21;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message PollOption {
 | 
			
		||||
@@ -1559,20 +1587,6 @@ message BizAccountLinkInfo {
 | 
			
		||||
    optional BizAccountLinkInfoAccountType accountType = 5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message NoiseCertificate {
 | 
			
		||||
    optional bytes details = 1;
 | 
			
		||||
    optional bytes signature = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Renamed from NoiseCertificate$Details
 | 
			
		||||
message NoiseCertificateDetails {
 | 
			
		||||
    optional uint32 serial = 1;
 | 
			
		||||
    optional string issuer = 2;
 | 
			
		||||
    optional uint64 expires = 3;
 | 
			
		||||
    optional string subject = 4;
 | 
			
		||||
    optional bytes key = 5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message HandshakeMessage {
 | 
			
		||||
    optional ClientHello clientHello = 2;
 | 
			
		||||
    optional ServerHello serverHello = 3;
 | 
			
		||||
@@ -1943,6 +1957,7 @@ message WebMessageInfo {
 | 
			
		||||
        GROUP_PARTICIPANT_ACCEPT = 140;
 | 
			
		||||
        GROUP_PARTICIPANT_LINKED_GROUP_JOIN = 141;
 | 
			
		||||
        COMMUNITY_CREATE = 142;
 | 
			
		||||
        EPHEMERAL_KEEP_IN_CHAT = 143;
 | 
			
		||||
    }
 | 
			
		||||
    optional WebMessageInfoStubType messageStubType = 24;
 | 
			
		||||
    optional bool clearMedia = 25;
 | 
			
		||||
@@ -1976,6 +1991,7 @@ message WebMessageInfo {
 | 
			
		||||
    optional string agentId = 47;
 | 
			
		||||
    optional bool statusAlreadyViewed = 48;
 | 
			
		||||
    optional bytes messageSecret = 49;
 | 
			
		||||
    optional KeepInChat keepInChat = 50;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message WebFeatures {
 | 
			
		||||
@@ -2148,3 +2164,43 @@ message MediaData {
 | 
			
		||||
    optional string localPath = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message KeepInChat {
 | 
			
		||||
    optional KeepType keepType = 1;
 | 
			
		||||
    optional int64 serverTimestamp = 2;
 | 
			
		||||
    optional string deviceJid = 3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message NoiseCertificate {
 | 
			
		||||
    optional bytes details = 1;
 | 
			
		||||
    optional bytes signature = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Renamed from NoiseCertificate$Details
 | 
			
		||||
message NoiseCertificateDetails {
 | 
			
		||||
    optional uint32 serial = 1;
 | 
			
		||||
    optional string issuer = 2;
 | 
			
		||||
    optional uint64 expires = 3;
 | 
			
		||||
    optional string subject = 4;
 | 
			
		||||
    optional bytes key = 5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message CertChain {
 | 
			
		||||
    optional CertChainNoiseCertificate leaf = 1;
 | 
			
		||||
    optional CertChainNoiseCertificate intermediate = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Renamed from CertChain$NoiseCertificate
 | 
			
		||||
message CertChainNoiseCertificate {
 | 
			
		||||
    optional bytes details = 1;
 | 
			
		||||
    optional bytes signature = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Renamed from CertChain$NoiseCertificate$Details
 | 
			
		||||
message CertChainNoiseCertificateDetails {
 | 
			
		||||
    optional uint32 serial = 1;
 | 
			
		||||
    optional uint32 issuerSerial = 2;
 | 
			
		||||
    optional bytes key = 3;
 | 
			
		||||
    optional uint64 notBefore = 4;
 | 
			
		||||
    optional uint64 notAfter = 5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								vendor/go.mau.fi/whatsmeow/message.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								vendor/go.mau.fi/whatsmeow/message.go
									
									
									
									
										vendored
									
									
								
							@@ -40,6 +40,9 @@ func (cli *Client) handleEncryptedMessage(node *waBinary.Node) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		cli.Log.Warnf("Failed to parse message: %v", err)
 | 
			
		||||
	} else {
 | 
			
		||||
		if info.VerifiedName != nil && len(info.VerifiedName.Details.GetVerifiedName()) > 0 {
 | 
			
		||||
			go cli.updateBusinessName(info.Sender, info, info.VerifiedName.Details.GetVerifiedName())
 | 
			
		||||
		}
 | 
			
		||||
		if len(info.PushName) > 0 && info.PushName != "-" {
 | 
			
		||||
			go cli.updatePushName(info.Sender, info, info.PushName)
 | 
			
		||||
		}
 | 
			
		||||
@@ -47,13 +50,17 @@ func (cli *Client) handleEncryptedMessage(node *waBinary.Node) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (cli *Client) parseMessageSource(node *waBinary.Node) (source types.MessageSource, err error) {
 | 
			
		||||
func (cli *Client) parseMessageSource(node *waBinary.Node, requireParticipant bool) (source types.MessageSource, err error) {
 | 
			
		||||
	ag := node.AttrGetter()
 | 
			
		||||
	from := ag.JID("from")
 | 
			
		||||
	if from.Server == types.GroupServer || from.Server == types.BroadcastServer {
 | 
			
		||||
		source.IsGroup = true
 | 
			
		||||
		source.Chat = from
 | 
			
		||||
		source.Sender = ag.JID("participant")
 | 
			
		||||
		if requireParticipant {
 | 
			
		||||
			source.Sender = ag.JID("participant")
 | 
			
		||||
		} else {
 | 
			
		||||
			source.Sender = ag.OptionalJIDOrEmpty("participant")
 | 
			
		||||
		}
 | 
			
		||||
		if source.Sender.User == cli.Store.ID.User {
 | 
			
		||||
			source.IsFromMe = true
 | 
			
		||||
		}
 | 
			
		||||
@@ -80,7 +87,7 @@ func (cli *Client) parseMessageSource(node *waBinary.Node) (source types.Message
 | 
			
		||||
func (cli *Client) parseMessageInfo(node *waBinary.Node) (*types.MessageInfo, error) {
 | 
			
		||||
	var info types.MessageInfo
 | 
			
		||||
	var err error
 | 
			
		||||
	info.MessageSource, err = cli.parseMessageSource(node)
 | 
			
		||||
	info.MessageSource, err = cli.parseMessageSource(node, true)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -96,6 +103,11 @@ func (cli *Client) parseMessageInfo(node *waBinary.Node) (*types.MessageInfo, er
 | 
			
		||||
	for _, child := range node.GetChildren() {
 | 
			
		||||
		if child.Tag == "multicast" {
 | 
			
		||||
			info.Multicast = true
 | 
			
		||||
		} else if child.Tag == "verified_name" {
 | 
			
		||||
			info.VerifiedName, err = parseVerifiedNameContent(child)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				cli.Log.Warnf("Failed to parse verified_name node in %s: %v", info.ID, err)
 | 
			
		||||
			}
 | 
			
		||||
		} else if mediaType, ok := child.AttrGetter().GetString("mediatype", false); ok {
 | 
			
		||||
			info.MediaType = mediaType
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/go.mau.fi/whatsmeow/presence.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/go.mau.fi/whatsmeow/presence.go
									
									
									
									
										vendored
									
									
								
							@@ -15,7 +15,7 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (cli *Client) handleChatState(node *waBinary.Node) {
 | 
			
		||||
	source, err := cli.parseMessageSource(node)
 | 
			
		||||
	source, err := cli.parseMessageSource(node, true)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		cli.Log.Warnf("Failed to parse chat state update: %v", err)
 | 
			
		||||
	} else if len(node.GetChildren()) != 1 {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										34
									
								
								vendor/go.mau.fi/whatsmeow/receipt.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										34
									
								
								vendor/go.mau.fi/whatsmeow/receipt.go
									
									
									
									
										vendored
									
									
								
							@@ -20,7 +20,7 @@ func (cli *Client) handleReceipt(node *waBinary.Node) {
 | 
			
		||||
	receipt, err := cli.parseReceipt(node)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		cli.Log.Warnf("Failed to parse receipt: %v", err)
 | 
			
		||||
	} else {
 | 
			
		||||
	} else if receipt != nil {
 | 
			
		||||
		if receipt.Type == events.ReceiptTypeRetry {
 | 
			
		||||
			go func() {
 | 
			
		||||
				err := cli.handleRetryReceipt(receipt, node)
 | 
			
		||||
@@ -34,9 +34,29 @@ func (cli *Client) handleReceipt(node *waBinary.Node) {
 | 
			
		||||
	go cli.sendAck(node)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (cli *Client) handleGroupedReceipt(partialReceipt events.Receipt, participants *waBinary.Node) {
 | 
			
		||||
	pag := participants.AttrGetter()
 | 
			
		||||
	partialReceipt.MessageIDs = []types.MessageID{pag.String("key")}
 | 
			
		||||
	for _, child := range participants.GetChildren() {
 | 
			
		||||
		if child.Tag != "user" {
 | 
			
		||||
			cli.Log.Warnf("Unexpected node in grouped receipt participants: %s", child.XMLString())
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		ag := child.AttrGetter()
 | 
			
		||||
		receipt := partialReceipt
 | 
			
		||||
		receipt.Timestamp = ag.UnixTime("t")
 | 
			
		||||
		receipt.MessageSource.Sender = ag.JID("jid")
 | 
			
		||||
		if !ag.OK() {
 | 
			
		||||
			cli.Log.Warnf("Failed to parse user node %s in grouped receipt: %v", child.XMLString(), ag.Error())
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		go cli.dispatchEvent(&receipt)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (cli *Client) parseReceipt(node *waBinary.Node) (*events.Receipt, error) {
 | 
			
		||||
	ag := node.AttrGetter()
 | 
			
		||||
	source, err := cli.parseMessageSource(node)
 | 
			
		||||
	source, err := cli.parseMessageSource(node, false)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -45,6 +65,16 @@ func (cli *Client) parseReceipt(node *waBinary.Node) (*events.Receipt, error) {
 | 
			
		||||
		Timestamp:     ag.UnixTime("t"),
 | 
			
		||||
		Type:          events.ReceiptType(ag.OptionalString("type")),
 | 
			
		||||
	}
 | 
			
		||||
	if source.IsGroup && source.Sender.IsEmpty() {
 | 
			
		||||
		participantTags := node.GetChildrenByTag("participants")
 | 
			
		||||
		if len(participantTags) == 0 {
 | 
			
		||||
			return nil, &ElementMissingError{Tag: "participants", In: "grouped receipt"}
 | 
			
		||||
		}
 | 
			
		||||
		for _, pcp := range participantTags {
 | 
			
		||||
			cli.handleGroupedReceipt(receipt, &pcp)
 | 
			
		||||
		}
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
	mainMessageID := ag.String("id")
 | 
			
		||||
	if !ag.OK() {
 | 
			
		||||
		return nil, fmt.Errorf("failed to parse read receipt attrs: %+v", ag.Errors)
 | 
			
		||||
 
 | 
			
		||||
@@ -74,7 +74,7 @@ func (vc WAVersionContainer) ProtoAppVersion() *waProto.AppVersion {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// waVersion is the WhatsApp web client version
 | 
			
		||||
var waVersion = WAVersionContainer{2, 2218, 8}
 | 
			
		||||
var waVersion = WAVersionContainer{2, 2222, 11}
 | 
			
		||||
 | 
			
		||||
// waVersionHash is the md5 hash of a dot-separated waVersion
 | 
			
		||||
var waVersionHash [16]byte
 | 
			
		||||
@@ -125,14 +125,14 @@ var BaseClientPayload = &waProto.ClientPayload{
 | 
			
		||||
// Deprecated: renamed to DeviceProps
 | 
			
		||||
var CompanionProps = DeviceProps
 | 
			
		||||
 | 
			
		||||
var DeviceProps = &waProto.CompanionProps{
 | 
			
		||||
var DeviceProps = &waProto.DeviceProps{
 | 
			
		||||
	Os: proto.String("whatsmeow"),
 | 
			
		||||
	Version: &waProto.AppVersion{
 | 
			
		||||
		Primary:   proto.Uint32(0),
 | 
			
		||||
		Secondary: proto.Uint32(1),
 | 
			
		||||
		Tertiary:  proto.Uint32(0),
 | 
			
		||||
	},
 | 
			
		||||
	PlatformType:    waProto.CompanionProps_UNKNOWN.Enum(),
 | 
			
		||||
	PlatformType:    waProto.DeviceProps_UNKNOWN.Enum(),
 | 
			
		||||
	RequireFullSync: proto.Bool(false),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -181,7 +181,8 @@ const (
 | 
			
		||||
									  adv_key, adv_details, adv_account_sig, adv_account_sig_key, adv_device_sig,
 | 
			
		||||
									  platform, business_name, push_name)
 | 
			
		||||
		VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)
 | 
			
		||||
		ON CONFLICT (jid) DO UPDATE SET platform=$12, business_name=$13, push_name=$14
 | 
			
		||||
		ON CONFLICT (jid) DO UPDATE
 | 
			
		||||
		    SET platform=excluded.platform, business_name=excluded.business_name, push_name=excluded.push_name
 | 
			
		||||
	`
 | 
			
		||||
	deleteDeviceQuery = `DELETE FROM whatsmeow_device WHERE jid=$1`
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -67,7 +67,7 @@ var _ store.ContactStore = (*SQLStore)(nil)
 | 
			
		||||
const (
 | 
			
		||||
	putIdentityQuery = `
 | 
			
		||||
		INSERT INTO whatsmeow_identity_keys (our_jid, their_id, identity) VALUES ($1, $2, $3)
 | 
			
		||||
		ON CONFLICT (our_jid, their_id) DO UPDATE SET identity=$3
 | 
			
		||||
		ON CONFLICT (our_jid, their_id) DO UPDATE SET identity=excluded.identity
 | 
			
		||||
	`
 | 
			
		||||
	deleteAllIdentitiesQuery = `DELETE FROM whatsmeow_identity_keys WHERE our_jid=$1 AND their_id LIKE $2`
 | 
			
		||||
	deleteIdentityQuery      = `DELETE FROM whatsmeow_identity_keys WHERE our_jid=$1 AND their_id=$2`
 | 
			
		||||
@@ -108,7 +108,7 @@ const (
 | 
			
		||||
	hasSessionQuery = `SELECT true FROM whatsmeow_sessions WHERE our_jid=$1 AND their_id=$2`
 | 
			
		||||
	putSessionQuery = `
 | 
			
		||||
		INSERT INTO whatsmeow_sessions (our_jid, their_id, session) VALUES ($1, $2, $3)
 | 
			
		||||
		ON CONFLICT (our_jid, their_id) DO UPDATE SET session=$3
 | 
			
		||||
		ON CONFLICT (our_jid, their_id) DO UPDATE SET session=excluded.session
 | 
			
		||||
	`
 | 
			
		||||
	deleteAllSessionsQuery = `DELETE FROM whatsmeow_sessions WHERE our_jid=$1 AND their_id LIKE $2`
 | 
			
		||||
	deleteSessionQuery     = `DELETE FROM whatsmeow_sessions WHERE our_jid=$1 AND their_id=$2`
 | 
			
		||||
@@ -259,7 +259,7 @@ const (
 | 
			
		||||
	getSenderKeyQuery = `SELECT sender_key FROM whatsmeow_sender_keys WHERE our_jid=$1 AND chat_id=$2 AND sender_id=$3`
 | 
			
		||||
	putSenderKeyQuery = `
 | 
			
		||||
		INSERT INTO whatsmeow_sender_keys (our_jid, chat_id, sender_id, sender_key) VALUES ($1, $2, $3, $4)
 | 
			
		||||
		ON CONFLICT (our_jid, chat_id, sender_id) DO UPDATE SET sender_key=$4
 | 
			
		||||
		ON CONFLICT (our_jid, chat_id, sender_id) DO UPDATE SET sender_key=excluded.sender_key
 | 
			
		||||
	`
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -279,7 +279,8 @@ func (s *SQLStore) GetSenderKey(group, user string) (key []byte, err error) {
 | 
			
		||||
const (
 | 
			
		||||
	putAppStateSyncKeyQuery = `
 | 
			
		||||
		INSERT INTO whatsmeow_app_state_sync_keys (jid, key_id, key_data, timestamp, fingerprint) VALUES ($1, $2, $3, $4, $5)
 | 
			
		||||
		ON CONFLICT (jid, key_id) DO UPDATE SET key_data=$3, timestamp=$4, fingerprint=$5
 | 
			
		||||
		ON CONFLICT (jid, key_id) DO UPDATE
 | 
			
		||||
			SET key_data=excluded.key_data, timestamp=excluded.timestamp, fingerprint=excluded.fingerprint
 | 
			
		||||
	`
 | 
			
		||||
	getAppStateSyncKeyQuery = `SELECT key_data, timestamp, fingerprint FROM whatsmeow_app_state_sync_keys WHERE jid=$1 AND key_id=$2`
 | 
			
		||||
)
 | 
			
		||||
@@ -301,7 +302,7 @@ func (s *SQLStore) GetAppStateSyncKey(id []byte) (*store.AppStateSyncKey, error)
 | 
			
		||||
const (
 | 
			
		||||
	putAppStateVersionQuery = `
 | 
			
		||||
		INSERT INTO whatsmeow_app_state_version (jid, name, version, hash) VALUES ($1, $2, $3, $4)
 | 
			
		||||
		ON CONFLICT (jid, name) DO UPDATE SET version=$3, hash=$4
 | 
			
		||||
		ON CONFLICT (jid, name) DO UPDATE SET version=excluded.version, hash=excluded.hash
 | 
			
		||||
	`
 | 
			
		||||
	getAppStateVersionQuery                 = `SELECT version, hash FROM whatsmeow_app_state_version WHERE jid=$1 AND name=$2`
 | 
			
		||||
	deleteAppStateVersionQuery              = `DELETE FROM whatsmeow_app_state_version WHERE jid=$1 AND name=$2`
 | 
			
		||||
@@ -435,11 +436,11 @@ const (
 | 
			
		||||
	`
 | 
			
		||||
	putPushNameQuery = `
 | 
			
		||||
		INSERT INTO whatsmeow_contacts (our_jid, their_jid, push_name) VALUES ($1, $2, $3)
 | 
			
		||||
		ON CONFLICT (our_jid, their_jid) DO UPDATE SET push_name=$3
 | 
			
		||||
		ON CONFLICT (our_jid, their_jid) DO UPDATE SET push_name=excluded.push_name
 | 
			
		||||
	`
 | 
			
		||||
	putBusinessNameQuery = `
 | 
			
		||||
		INSERT INTO whatsmeow_contacts (our_jid, their_jid, business_name) VALUES ($1, $2, $3)
 | 
			
		||||
		ON CONFLICT (our_jid, their_jid) DO UPDATE SET business_name=$3
 | 
			
		||||
		ON CONFLICT (our_jid, their_jid) DO UPDATE SET business_name=excluded.business_name
 | 
			
		||||
	`
 | 
			
		||||
	getContactQuery = `
 | 
			
		||||
		SELECT first_name, full_name, push_name, business_name FROM whatsmeow_contacts WHERE our_jid=$1 AND their_jid=$2
 | 
			
		||||
@@ -470,23 +471,25 @@ func (s *SQLStore) PutPushName(user types.JID, pushName string) (bool, string, e
 | 
			
		||||
	return false, "", nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *SQLStore) PutBusinessName(user types.JID, businessName string) error {
 | 
			
		||||
func (s *SQLStore) PutBusinessName(user types.JID, businessName string) (bool, string, error) {
 | 
			
		||||
	s.contactCacheLock.Lock()
 | 
			
		||||
	defer s.contactCacheLock.Unlock()
 | 
			
		||||
 | 
			
		||||
	cached, err := s.getContact(user)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
		return false, "", err
 | 
			
		||||
	}
 | 
			
		||||
	if cached.BusinessName != businessName {
 | 
			
		||||
		_, err = s.db.Exec(putBusinessNameQuery, s.JID, user, businessName)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
			return false, "", err
 | 
			
		||||
		}
 | 
			
		||||
		previousName := cached.BusinessName
 | 
			
		||||
		cached.BusinessName = businessName
 | 
			
		||||
		cached.Found = true
 | 
			
		||||
		return true, previousName, nil
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
	return false, "", nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *SQLStore) PutContactName(user types.JID, firstName, fullName string) error {
 | 
			
		||||
@@ -643,7 +646,7 @@ func (s *SQLStore) GetAllContacts() (map[types.JID]types.ContactInfo, error) {
 | 
			
		||||
const (
 | 
			
		||||
	putChatSettingQuery = `
 | 
			
		||||
		INSERT INTO whatsmeow_chat_settings (our_jid, chat_jid, %[1]s) VALUES ($1, $2, $3)
 | 
			
		||||
		ON CONFLICT (our_jid, chat_jid) DO UPDATE SET %[1]s=$3
 | 
			
		||||
		ON CONFLICT (our_jid, chat_jid) DO UPDATE SET %[1]s=excluded.%[1]s
 | 
			
		||||
	`
 | 
			
		||||
	getChatSettingsQuery = `
 | 
			
		||||
		SELECT muted_until, pinned, archived FROM whatsmeow_chat_settings WHERE our_jid=$1 AND chat_jid=$2
 | 
			
		||||
 
 | 
			
		||||
@@ -239,7 +239,7 @@ func upgradeV2(tx *sql.Tx, container *Container) error {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if container.dialect == "postgres" {
 | 
			
		||||
	if container.dialect == "postgres" || container.dialect == "pgx" {
 | 
			
		||||
		_, err = tx.Exec(fillSigKeyPostgres)
 | 
			
		||||
	} else {
 | 
			
		||||
		_, err = tx.Exec(fillSigKeySQLite)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/go.mau.fi/whatsmeow/store/store.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/go.mau.fi/whatsmeow/store/store.go
									
									
									
									
										vendored
									
									
								
							@@ -80,7 +80,7 @@ type ContactEntry struct {
 | 
			
		||||
 | 
			
		||||
type ContactStore interface {
 | 
			
		||||
	PutPushName(user types.JID, pushName string) (bool, string, error)
 | 
			
		||||
	PutBusinessName(user types.JID, businessName string) error
 | 
			
		||||
	PutBusinessName(user types.JID, businessName string) (bool, string, error)
 | 
			
		||||
	PutContactName(user types.JID, fullName, firstName string) error
 | 
			
		||||
	PutAllContactNames(contacts []ContactEntry) error
 | 
			
		||||
	GetContact(user types.JID) (types.ContactInfo, error)
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,14 @@ type PushName struct {
 | 
			
		||||
	NewPushName string             // The new push name that was included in the message.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BusinessName is emitted when a message is received with a different verified business name than the previous value cached for the same user.
 | 
			
		||||
type BusinessName struct {
 | 
			
		||||
	JID             types.JID
 | 
			
		||||
	Message         *types.MessageInfo // This is only present if the change was detected in a message.
 | 
			
		||||
	OldBusinessName string
 | 
			
		||||
	NewBusinessName string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Pin is emitted when a chat is pinned or unpinned from another device.
 | 
			
		||||
type Pin struct {
 | 
			
		||||
	JID       types.JID // The chat which was pinned or unpinned.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								vendor/go.mau.fi/whatsmeow/types/message.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/go.mau.fi/whatsmeow/types/message.go
									
									
									
									
										vendored
									
									
								
							@@ -47,6 +47,7 @@ type MessageInfo struct {
 | 
			
		||||
	Multicast bool
 | 
			
		||||
	MediaType string
 | 
			
		||||
 | 
			
		||||
	VerifiedName   *VerifiedName
 | 
			
		||||
	DeviceSentMeta *DeviceSentMeta // Metadata for direct messages sent from another one of the user's own devices.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								vendor/go.mau.fi/whatsmeow/user.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								vendor/go.mau.fi/whatsmeow/user.go
									
									
									
									
										vendored
									
									
								
							@@ -133,7 +133,7 @@ func (cli *Client) GetUserInfo(jids []types.JID) (map[types.JID]types.UserInfo,
 | 
			
		||||
		info.PictureID, _ = child.GetChildByTag("picture").Attrs["id"].(string)
 | 
			
		||||
		info.Devices = parseDeviceList(jid.User, child.GetChildByTag("devices"))
 | 
			
		||||
		if verifiedName != nil {
 | 
			
		||||
			cli.updateBusinessName(jid, verifiedName.Details.GetVerifiedName())
 | 
			
		||||
			cli.updateBusinessName(jid, nil, verifiedName.Details.GetVerifiedName())
 | 
			
		||||
		}
 | 
			
		||||
		respData[jid] = info
 | 
			
		||||
	}
 | 
			
		||||
@@ -262,13 +262,21 @@ func (cli *Client) updatePushName(user types.JID, messageInfo *types.MessageInfo
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (cli *Client) updateBusinessName(user types.JID, name string) {
 | 
			
		||||
func (cli *Client) updateBusinessName(user types.JID, messageInfo *types.MessageInfo, name string) {
 | 
			
		||||
	if cli.Store.Contacts == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	err := cli.Store.Contacts.PutBusinessName(user, name)
 | 
			
		||||
	changed, previousName, err := cli.Store.Contacts.PutBusinessName(user, name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		cli.Log.Errorf("Failed to save business name of %s in device store: %v", user, err)
 | 
			
		||||
	} else if changed {
 | 
			
		||||
		cli.Log.Debugf("Business name of %s changed from %s to %s, dispatching event", user, previousName, name)
 | 
			
		||||
		cli.dispatchEvent(&events.BusinessName{
 | 
			
		||||
			JID:             user,
 | 
			
		||||
			Message:         messageInfo,
 | 
			
		||||
			OldBusinessName: previousName,
 | 
			
		||||
			NewBusinessName: name,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -280,6 +288,10 @@ func parseVerifiedName(businessNode waBinary.Node) (*types.VerifiedName, error)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
	return parseVerifiedNameContent(verifiedNameNode)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseVerifiedNameContent(verifiedNameNode waBinary.Node) (*types.VerifiedName, error) {
 | 
			
		||||
	rawCert, ok := verifiedNameNode.Content.([]byte)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								vendor/gopkg.in/yaml.v3/parserc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								vendor/gopkg.in/yaml.v3/parserc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -687,6 +687,9 @@ func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, i
 | 
			
		||||
func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
 | 
			
		||||
	if first {
 | 
			
		||||
		token := peek_token(parser)
 | 
			
		||||
		if token == nil {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		parser.marks = append(parser.marks, token.start_mark)
 | 
			
		||||
		skip_token(parser)
 | 
			
		||||
	}
 | 
			
		||||
@@ -786,7 +789,7 @@ func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	token := peek_token(parser)
 | 
			
		||||
	if token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN {
 | 
			
		||||
	if token == nil || token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -813,6 +816,9 @@ func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
 | 
			
		||||
func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
 | 
			
		||||
	if first {
 | 
			
		||||
		token := peek_token(parser)
 | 
			
		||||
		if token == nil {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		parser.marks = append(parser.marks, token.start_mark)
 | 
			
		||||
		skip_token(parser)
 | 
			
		||||
	}
 | 
			
		||||
@@ -922,6 +928,9 @@ func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_ev
 | 
			
		||||
func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
 | 
			
		||||
	if first {
 | 
			
		||||
		token := peek_token(parser)
 | 
			
		||||
		if token == nil {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		parser.marks = append(parser.marks, token.start_mark)
 | 
			
		||||
		skip_token(parser)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							@@ -38,7 +38,7 @@ github.com/Rhymen/go-whatsapp/binary/token
 | 
			
		||||
github.com/Rhymen/go-whatsapp/crypto/cbc
 | 
			
		||||
github.com/Rhymen/go-whatsapp/crypto/curve25519
 | 
			
		||||
github.com/Rhymen/go-whatsapp/crypto/hkdf
 | 
			
		||||
# github.com/SevereCloud/vksdk/v2 v2.14.0
 | 
			
		||||
# github.com/SevereCloud/vksdk/v2 v2.14.1
 | 
			
		||||
## explicit; go 1.16
 | 
			
		||||
github.com/SevereCloud/vksdk/v2
 | 
			
		||||
github.com/SevereCloud/vksdk/v2/api
 | 
			
		||||
@@ -58,7 +58,7 @@ github.com/blang/semver
 | 
			
		||||
# github.com/bwmarrin/discordgo v0.25.0
 | 
			
		||||
## explicit; go 1.13
 | 
			
		||||
github.com/bwmarrin/discordgo
 | 
			
		||||
# github.com/d5/tengo/v2 v2.10.1
 | 
			
		||||
# github.com/d5/tengo/v2 v2.12.0
 | 
			
		||||
## explicit; go 1.13
 | 
			
		||||
github.com/d5/tengo/v2
 | 
			
		||||
github.com/d5/tengo/v2/parser
 | 
			
		||||
@@ -93,7 +93,7 @@ github.com/golang-jwt/jwt
 | 
			
		||||
## explicit; go 1.9
 | 
			
		||||
github.com/golang/protobuf/proto
 | 
			
		||||
github.com/golang/protobuf/protoc-gen-go/descriptor
 | 
			
		||||
# github.com/gomarkdown/markdown v0.0.0-20220603122033-8f3b341fef32
 | 
			
		||||
# github.com/gomarkdown/markdown v0.0.0-20220607163217-45f7c050e2d1
 | 
			
		||||
## explicit; go 1.12
 | 
			
		||||
github.com/gomarkdown/markdown
 | 
			
		||||
github.com/gomarkdown/markdown/ast
 | 
			
		||||
@@ -183,11 +183,12 @@ github.com/keybase/go-keybase-chat-bot/kbchat/types/chat1
 | 
			
		||||
github.com/keybase/go-keybase-chat-bot/kbchat/types/gregor1
 | 
			
		||||
github.com/keybase/go-keybase-chat-bot/kbchat/types/keybase1
 | 
			
		||||
github.com/keybase/go-keybase-chat-bot/kbchat/types/stellar1
 | 
			
		||||
# github.com/klauspost/compress v1.15.1
 | 
			
		||||
## explicit; go 1.15
 | 
			
		||||
# github.com/klauspost/compress v1.15.6
 | 
			
		||||
## explicit; go 1.16
 | 
			
		||||
github.com/klauspost/compress
 | 
			
		||||
github.com/klauspost/compress/fse
 | 
			
		||||
github.com/klauspost/compress/huff0
 | 
			
		||||
github.com/klauspost/compress/internal/cpuinfo
 | 
			
		||||
github.com/klauspost/compress/internal/snapref
 | 
			
		||||
github.com/klauspost/compress/s2
 | 
			
		||||
github.com/klauspost/compress/zstd
 | 
			
		||||
@@ -403,12 +404,11 @@ github.com/sizeofint/webpanimation
 | 
			
		||||
github.com/skip2/go-qrcode
 | 
			
		||||
github.com/skip2/go-qrcode/bitset
 | 
			
		||||
github.com/skip2/go-qrcode/reedsolomon
 | 
			
		||||
# github.com/slack-go/slack v0.10.3
 | 
			
		||||
# github.com/slack-go/slack v0.11.0
 | 
			
		||||
## explicit; go 1.16
 | 
			
		||||
github.com/slack-go/slack
 | 
			
		||||
github.com/slack-go/slack/internal/backoff
 | 
			
		||||
github.com/slack-go/slack/internal/errorsx
 | 
			
		||||
github.com/slack-go/slack/internal/misc
 | 
			
		||||
github.com/slack-go/slack/internal/timex
 | 
			
		||||
github.com/slack-go/slack/slackutilsx
 | 
			
		||||
# github.com/spf13/afero v1.8.2
 | 
			
		||||
@@ -435,7 +435,7 @@ github.com/spf13/viper/internal/encoding/javaproperties
 | 
			
		||||
github.com/spf13/viper/internal/encoding/json
 | 
			
		||||
github.com/spf13/viper/internal/encoding/toml
 | 
			
		||||
github.com/spf13/viper/internal/encoding/yaml
 | 
			
		||||
# github.com/stretchr/testify v1.7.1
 | 
			
		||||
# github.com/stretchr/testify v1.7.2
 | 
			
		||||
## explicit; go 1.13
 | 
			
		||||
github.com/stretchr/testify/assert
 | 
			
		||||
github.com/stretchr/testify/require
 | 
			
		||||
@@ -514,7 +514,7 @@ go.mau.fi/libsignal/util/errorhelper
 | 
			
		||||
go.mau.fi/libsignal/util/keyhelper
 | 
			
		||||
go.mau.fi/libsignal/util/medium
 | 
			
		||||
go.mau.fi/libsignal/util/optional
 | 
			
		||||
# go.mau.fi/whatsmeow v0.0.0-20220601182603-a8d86cf1812c
 | 
			
		||||
# go.mau.fi/whatsmeow v0.0.0-20220624184947-57a69a641154
 | 
			
		||||
## explicit; go 1.17
 | 
			
		||||
go.mau.fi/whatsmeow
 | 
			
		||||
go.mau.fi/whatsmeow/appstate
 | 
			
		||||
@@ -567,7 +567,7 @@ golang.org/x/crypto/scrypt
 | 
			
		||||
golang.org/x/crypto/ssh
 | 
			
		||||
golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
 | 
			
		||||
golang.org/x/crypto/ssh/terminal
 | 
			
		||||
# golang.org/x/image v0.0.0-20220601225756-64ec528b34cd
 | 
			
		||||
# golang.org/x/image v0.0.0-20220617043117-41969df76e82
 | 
			
		||||
## explicit; go 1.12
 | 
			
		||||
golang.org/x/image/riff
 | 
			
		||||
golang.org/x/image/vp8
 | 
			
		||||
@@ -589,8 +589,8 @@ golang.org/x/net/http2/hpack
 | 
			
		||||
golang.org/x/net/idna
 | 
			
		||||
golang.org/x/net/publicsuffix
 | 
			
		||||
golang.org/x/net/websocket
 | 
			
		||||
# golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401
 | 
			
		||||
## explicit; go 1.11
 | 
			
		||||
# golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2
 | 
			
		||||
## explicit; go 1.15
 | 
			
		||||
golang.org/x/oauth2
 | 
			
		||||
golang.org/x/oauth2/clientcredentials
 | 
			
		||||
golang.org/x/oauth2/internal
 | 
			
		||||
@@ -705,7 +705,7 @@ gopkg.in/olahol/melody.v1
 | 
			
		||||
# gopkg.in/yaml.v2 v2.4.0
 | 
			
		||||
## explicit; go 1.15
 | 
			
		||||
gopkg.in/yaml.v2
 | 
			
		||||
# gopkg.in/yaml.v3 v3.0.0
 | 
			
		||||
# gopkg.in/yaml.v3 v3.0.1
 | 
			
		||||
## explicit
 | 
			
		||||
gopkg.in/yaml.v3
 | 
			
		||||
# layeh.com/gumble v0.0.0-20200818122324-146f9205029b
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user