mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 18:43:34 +00:00
rebase: bump k8s.io/kubernetes from 1.26.2 to 1.27.2
Bumps [k8s.io/kubernetes](https://github.com/kubernetes/kubernetes) from 1.26.2 to 1.27.2. - [Release notes](https://github.com/kubernetes/kubernetes/releases) - [Commits](https://github.com/kubernetes/kubernetes/compare/v1.26.2...v1.27.2) --- updated-dependencies: - dependency-name: k8s.io/kubernetes dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
committed by
mergify[bot]
parent
0e79135419
commit
07b05616a0
824
vendor/golang.org/x/crypto/cryptobyte/asn1.go
generated
vendored
Normal file
824
vendor/golang.org/x/crypto/cryptobyte/asn1.go
generated
vendored
Normal file
@ -0,0 +1,824 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cryptobyte
|
||||
|
||||
import (
|
||||
encoding_asn1 "encoding/asn1"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/cryptobyte/asn1"
|
||||
)
|
||||
|
||||
// This file contains ASN.1-related methods for String and Builder.
|
||||
|
||||
// Builder
|
||||
|
||||
// AddASN1Int64 appends a DER-encoded ASN.1 INTEGER.
|
||||
func (b *Builder) AddASN1Int64(v int64) {
|
||||
b.addASN1Signed(asn1.INTEGER, v)
|
||||
}
|
||||
|
||||
// AddASN1Int64WithTag appends a DER-encoded ASN.1 INTEGER with the
|
||||
// given tag.
|
||||
func (b *Builder) AddASN1Int64WithTag(v int64, tag asn1.Tag) {
|
||||
b.addASN1Signed(tag, v)
|
||||
}
|
||||
|
||||
// AddASN1Enum appends a DER-encoded ASN.1 ENUMERATION.
|
||||
func (b *Builder) AddASN1Enum(v int64) {
|
||||
b.addASN1Signed(asn1.ENUM, v)
|
||||
}
|
||||
|
||||
func (b *Builder) addASN1Signed(tag asn1.Tag, v int64) {
|
||||
b.AddASN1(tag, func(c *Builder) {
|
||||
length := 1
|
||||
for i := v; i >= 0x80 || i < -0x80; i >>= 8 {
|
||||
length++
|
||||
}
|
||||
|
||||
for ; length > 0; length-- {
|
||||
i := v >> uint((length-1)*8) & 0xff
|
||||
c.AddUint8(uint8(i))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// AddASN1Uint64 appends a DER-encoded ASN.1 INTEGER.
|
||||
func (b *Builder) AddASN1Uint64(v uint64) {
|
||||
b.AddASN1(asn1.INTEGER, func(c *Builder) {
|
||||
length := 1
|
||||
for i := v; i >= 0x80; i >>= 8 {
|
||||
length++
|
||||
}
|
||||
|
||||
for ; length > 0; length-- {
|
||||
i := v >> uint((length-1)*8) & 0xff
|
||||
c.AddUint8(uint8(i))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// AddASN1BigInt appends a DER-encoded ASN.1 INTEGER.
|
||||
func (b *Builder) AddASN1BigInt(n *big.Int) {
|
||||
if b.err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
b.AddASN1(asn1.INTEGER, func(c *Builder) {
|
||||
if n.Sign() < 0 {
|
||||
// A negative number has to be converted to two's-complement form. So we
|
||||
// invert and subtract 1. If the most-significant-bit isn't set then
|
||||
// we'll need to pad the beginning with 0xff in order to keep the number
|
||||
// negative.
|
||||
nMinus1 := new(big.Int).Neg(n)
|
||||
nMinus1.Sub(nMinus1, bigOne)
|
||||
bytes := nMinus1.Bytes()
|
||||
for i := range bytes {
|
||||
bytes[i] ^= 0xff
|
||||
}
|
||||
if len(bytes) == 0 || bytes[0]&0x80 == 0 {
|
||||
c.add(0xff)
|
||||
}
|
||||
c.add(bytes...)
|
||||
} else if n.Sign() == 0 {
|
||||
c.add(0)
|
||||
} else {
|
||||
bytes := n.Bytes()
|
||||
if bytes[0]&0x80 != 0 {
|
||||
c.add(0)
|
||||
}
|
||||
c.add(bytes...)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// AddASN1OctetString appends a DER-encoded ASN.1 OCTET STRING.
|
||||
func (b *Builder) AddASN1OctetString(bytes []byte) {
|
||||
b.AddASN1(asn1.OCTET_STRING, func(c *Builder) {
|
||||
c.AddBytes(bytes)
|
||||
})
|
||||
}
|
||||
|
||||
const generalizedTimeFormatStr = "20060102150405Z0700"
|
||||
|
||||
// AddASN1GeneralizedTime appends a DER-encoded ASN.1 GENERALIZEDTIME.
|
||||
func (b *Builder) AddASN1GeneralizedTime(t time.Time) {
|
||||
if t.Year() < 0 || t.Year() > 9999 {
|
||||
b.err = fmt.Errorf("cryptobyte: cannot represent %v as a GeneralizedTime", t)
|
||||
return
|
||||
}
|
||||
b.AddASN1(asn1.GeneralizedTime, func(c *Builder) {
|
||||
c.AddBytes([]byte(t.Format(generalizedTimeFormatStr)))
|
||||
})
|
||||
}
|
||||
|
||||
// AddASN1UTCTime appends a DER-encoded ASN.1 UTCTime.
|
||||
func (b *Builder) AddASN1UTCTime(t time.Time) {
|
||||
b.AddASN1(asn1.UTCTime, func(c *Builder) {
|
||||
// As utilized by the X.509 profile, UTCTime can only
|
||||
// represent the years 1950 through 2049.
|
||||
if t.Year() < 1950 || t.Year() >= 2050 {
|
||||
b.err = fmt.Errorf("cryptobyte: cannot represent %v as a UTCTime", t)
|
||||
return
|
||||
}
|
||||
c.AddBytes([]byte(t.Format(defaultUTCTimeFormatStr)))
|
||||
})
|
||||
}
|
||||
|
||||
// AddASN1BitString appends a DER-encoded ASN.1 BIT STRING. This does not
|
||||
// support BIT STRINGs that are not a whole number of bytes.
|
||||
func (b *Builder) AddASN1BitString(data []byte) {
|
||||
b.AddASN1(asn1.BIT_STRING, func(b *Builder) {
|
||||
b.AddUint8(0)
|
||||
b.AddBytes(data)
|
||||
})
|
||||
}
|
||||
|
||||
func (b *Builder) addBase128Int(n int64) {
|
||||
var length int
|
||||
if n == 0 {
|
||||
length = 1
|
||||
} else {
|
||||
for i := n; i > 0; i >>= 7 {
|
||||
length++
|
||||
}
|
||||
}
|
||||
|
||||
for i := length - 1; i >= 0; i-- {
|
||||
o := byte(n >> uint(i*7))
|
||||
o &= 0x7f
|
||||
if i != 0 {
|
||||
o |= 0x80
|
||||
}
|
||||
|
||||
b.add(o)
|
||||
}
|
||||
}
|
||||
|
||||
func isValidOID(oid encoding_asn1.ObjectIdentifier) bool {
|
||||
if len(oid) < 2 {
|
||||
return false
|
||||
}
|
||||
|
||||
if oid[0] > 2 || (oid[0] <= 1 && oid[1] >= 40) {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, v := range oid {
|
||||
if v < 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (b *Builder) AddASN1ObjectIdentifier(oid encoding_asn1.ObjectIdentifier) {
|
||||
b.AddASN1(asn1.OBJECT_IDENTIFIER, func(b *Builder) {
|
||||
if !isValidOID(oid) {
|
||||
b.err = fmt.Errorf("cryptobyte: invalid OID: %v", oid)
|
||||
return
|
||||
}
|
||||
|
||||
b.addBase128Int(int64(oid[0])*40 + int64(oid[1]))
|
||||
for _, v := range oid[2:] {
|
||||
b.addBase128Int(int64(v))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (b *Builder) AddASN1Boolean(v bool) {
|
||||
b.AddASN1(asn1.BOOLEAN, func(b *Builder) {
|
||||
if v {
|
||||
b.AddUint8(0xff)
|
||||
} else {
|
||||
b.AddUint8(0)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (b *Builder) AddASN1NULL() {
|
||||
b.add(uint8(asn1.NULL), 0)
|
||||
}
|
||||
|
||||
// MarshalASN1 calls encoding_asn1.Marshal on its input and appends the result if
|
||||
// successful or records an error if one occurred.
|
||||
func (b *Builder) MarshalASN1(v interface{}) {
|
||||
// NOTE(martinkr): This is somewhat of a hack to allow propagation of
|
||||
// encoding_asn1.Marshal errors into Builder.err. N.B. if you call MarshalASN1 with a
|
||||
// value embedded into a struct, its tag information is lost.
|
||||
if b.err != nil {
|
||||
return
|
||||
}
|
||||
bytes, err := encoding_asn1.Marshal(v)
|
||||
if err != nil {
|
||||
b.err = err
|
||||
return
|
||||
}
|
||||
b.AddBytes(bytes)
|
||||
}
|
||||
|
||||
// AddASN1 appends an ASN.1 object. The object is prefixed with the given tag.
|
||||
// Tags greater than 30 are not supported and result in an error (i.e.
|
||||
// low-tag-number form only). The child builder passed to the
|
||||
// BuilderContinuation can be used to build the content of the ASN.1 object.
|
||||
func (b *Builder) AddASN1(tag asn1.Tag, f BuilderContinuation) {
|
||||
if b.err != nil {
|
||||
return
|
||||
}
|
||||
// Identifiers with the low five bits set indicate high-tag-number format
|
||||
// (two or more octets), which we don't support.
|
||||
if tag&0x1f == 0x1f {
|
||||
b.err = fmt.Errorf("cryptobyte: high-tag number identifier octects not supported: 0x%x", tag)
|
||||
return
|
||||
}
|
||||
b.AddUint8(uint8(tag))
|
||||
b.addLengthPrefixed(1, true, f)
|
||||
}
|
||||
|
||||
// String
|
||||
|
||||
// ReadASN1Boolean decodes an ASN.1 BOOLEAN and converts it to a boolean
|
||||
// representation into out and advances. It reports whether the read
|
||||
// was successful.
|
||||
func (s *String) ReadASN1Boolean(out *bool) bool {
|
||||
var bytes String
|
||||
if !s.ReadASN1(&bytes, asn1.BOOLEAN) || len(bytes) != 1 {
|
||||
return false
|
||||
}
|
||||
|
||||
switch bytes[0] {
|
||||
case 0:
|
||||
*out = false
|
||||
case 0xff:
|
||||
*out = true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// ReadASN1Integer decodes an ASN.1 INTEGER into out and advances. If out does
|
||||
// not point to an integer, to a big.Int, or to a []byte it panics. Only
|
||||
// positive and zero values can be decoded into []byte, and they are returned as
|
||||
// big-endian binary values that share memory with s. Positive values will have
|
||||
// no leading zeroes, and zero will be returned as a single zero byte.
|
||||
// ReadASN1Integer reports whether the read was successful.
|
||||
func (s *String) ReadASN1Integer(out interface{}) bool {
|
||||
switch out := out.(type) {
|
||||
case *int, *int8, *int16, *int32, *int64:
|
||||
var i int64
|
||||
if !s.readASN1Int64(&i) || reflect.ValueOf(out).Elem().OverflowInt(i) {
|
||||
return false
|
||||
}
|
||||
reflect.ValueOf(out).Elem().SetInt(i)
|
||||
return true
|
||||
case *uint, *uint8, *uint16, *uint32, *uint64:
|
||||
var u uint64
|
||||
if !s.readASN1Uint64(&u) || reflect.ValueOf(out).Elem().OverflowUint(u) {
|
||||
return false
|
||||
}
|
||||
reflect.ValueOf(out).Elem().SetUint(u)
|
||||
return true
|
||||
case *big.Int:
|
||||
return s.readASN1BigInt(out)
|
||||
case *[]byte:
|
||||
return s.readASN1Bytes(out)
|
||||
default:
|
||||
panic("out does not point to an integer type")
|
||||
}
|
||||
}
|
||||
|
||||
func checkASN1Integer(bytes []byte) bool {
|
||||
if len(bytes) == 0 {
|
||||
// An INTEGER is encoded with at least one octet.
|
||||
return false
|
||||
}
|
||||
if len(bytes) == 1 {
|
||||
return true
|
||||
}
|
||||
if bytes[0] == 0 && bytes[1]&0x80 == 0 || bytes[0] == 0xff && bytes[1]&0x80 == 0x80 {
|
||||
// Value is not minimally encoded.
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
var bigOne = big.NewInt(1)
|
||||
|
||||
func (s *String) readASN1BigInt(out *big.Int) bool {
|
||||
var bytes String
|
||||
if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) {
|
||||
return false
|
||||
}
|
||||
if bytes[0]&0x80 == 0x80 {
|
||||
// Negative number.
|
||||
neg := make([]byte, len(bytes))
|
||||
for i, b := range bytes {
|
||||
neg[i] = ^b
|
||||
}
|
||||
out.SetBytes(neg)
|
||||
out.Add(out, bigOne)
|
||||
out.Neg(out)
|
||||
} else {
|
||||
out.SetBytes(bytes)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *String) readASN1Bytes(out *[]byte) bool {
|
||||
var bytes String
|
||||
if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) {
|
||||
return false
|
||||
}
|
||||
if bytes[0]&0x80 == 0x80 {
|
||||
return false
|
||||
}
|
||||
for len(bytes) > 1 && bytes[0] == 0 {
|
||||
bytes = bytes[1:]
|
||||
}
|
||||
*out = bytes
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *String) readASN1Int64(out *int64) bool {
|
||||
var bytes String
|
||||
if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Signed(out, bytes) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func asn1Signed(out *int64, n []byte) bool {
|
||||
length := len(n)
|
||||
if length > 8 {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < length; i++ {
|
||||
*out <<= 8
|
||||
*out |= int64(n[i])
|
||||
}
|
||||
// Shift up and down in order to sign extend the result.
|
||||
*out <<= 64 - uint8(length)*8
|
||||
*out >>= 64 - uint8(length)*8
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *String) readASN1Uint64(out *uint64) bool {
|
||||
var bytes String
|
||||
if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Unsigned(out, bytes) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func asn1Unsigned(out *uint64, n []byte) bool {
|
||||
length := len(n)
|
||||
if length > 9 || length == 9 && n[0] != 0 {
|
||||
// Too large for uint64.
|
||||
return false
|
||||
}
|
||||
if n[0]&0x80 != 0 {
|
||||
// Negative number.
|
||||
return false
|
||||
}
|
||||
for i := 0; i < length; i++ {
|
||||
*out <<= 8
|
||||
*out |= uint64(n[i])
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ReadASN1Int64WithTag decodes an ASN.1 INTEGER with the given tag into out
|
||||
// and advances. It reports whether the read was successful and resulted in a
|
||||
// value that can be represented in an int64.
|
||||
func (s *String) ReadASN1Int64WithTag(out *int64, tag asn1.Tag) bool {
|
||||
var bytes String
|
||||
return s.ReadASN1(&bytes, tag) && checkASN1Integer(bytes) && asn1Signed(out, bytes)
|
||||
}
|
||||
|
||||
// ReadASN1Enum decodes an ASN.1 ENUMERATION into out and advances. It reports
|
||||
// whether the read was successful.
|
||||
func (s *String) ReadASN1Enum(out *int) bool {
|
||||
var bytes String
|
||||
var i int64
|
||||
if !s.ReadASN1(&bytes, asn1.ENUM) || !checkASN1Integer(bytes) || !asn1Signed(&i, bytes) {
|
||||
return false
|
||||
}
|
||||
if int64(int(i)) != i {
|
||||
return false
|
||||
}
|
||||
*out = int(i)
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *String) readBase128Int(out *int) bool {
|
||||
ret := 0
|
||||
for i := 0; len(*s) > 0; i++ {
|
||||
if i == 5 {
|
||||
return false
|
||||
}
|
||||
// Avoid overflowing int on a 32-bit platform.
|
||||
// We don't want different behavior based on the architecture.
|
||||
if ret >= 1<<(31-7) {
|
||||
return false
|
||||
}
|
||||
ret <<= 7
|
||||
b := s.read(1)[0]
|
||||
|
||||
// ITU-T X.690, section 8.19.2:
|
||||
// The subidentifier shall be encoded in the fewest possible octets,
|
||||
// that is, the leading octet of the subidentifier shall not have the value 0x80.
|
||||
if i == 0 && b == 0x80 {
|
||||
return false
|
||||
}
|
||||
|
||||
ret |= int(b & 0x7f)
|
||||
if b&0x80 == 0 {
|
||||
*out = ret
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false // truncated
|
||||
}
|
||||
|
||||
// ReadASN1ObjectIdentifier decodes an ASN.1 OBJECT IDENTIFIER into out and
|
||||
// advances. It reports whether the read was successful.
|
||||
func (s *String) ReadASN1ObjectIdentifier(out *encoding_asn1.ObjectIdentifier) bool {
|
||||
var bytes String
|
||||
if !s.ReadASN1(&bytes, asn1.OBJECT_IDENTIFIER) || len(bytes) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
// In the worst case, we get two elements from the first byte (which is
|
||||
// encoded differently) and then every varint is a single byte long.
|
||||
components := make([]int, len(bytes)+1)
|
||||
|
||||
// The first varint is 40*value1 + value2:
|
||||
// According to this packing, value1 can take the values 0, 1 and 2 only.
|
||||
// When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2,
|
||||
// then there are no restrictions on value2.
|
||||
var v int
|
||||
if !bytes.readBase128Int(&v) {
|
||||
return false
|
||||
}
|
||||
if v < 80 {
|
||||
components[0] = v / 40
|
||||
components[1] = v % 40
|
||||
} else {
|
||||
components[0] = 2
|
||||
components[1] = v - 80
|
||||
}
|
||||
|
||||
i := 2
|
||||
for ; len(bytes) > 0; i++ {
|
||||
if !bytes.readBase128Int(&v) {
|
||||
return false
|
||||
}
|
||||
components[i] = v
|
||||
}
|
||||
*out = components[:i]
|
||||
return true
|
||||
}
|
||||
|
||||
// ReadASN1GeneralizedTime decodes an ASN.1 GENERALIZEDTIME into out and
|
||||
// advances. It reports whether the read was successful.
|
||||
func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool {
|
||||
var bytes String
|
||||
if !s.ReadASN1(&bytes, asn1.GeneralizedTime) {
|
||||
return false
|
||||
}
|
||||
t := string(bytes)
|
||||
res, err := time.Parse(generalizedTimeFormatStr, t)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if serialized := res.Format(generalizedTimeFormatStr); serialized != t {
|
||||
return false
|
||||
}
|
||||
*out = res
|
||||
return true
|
||||
}
|
||||
|
||||
const defaultUTCTimeFormatStr = "060102150405Z0700"
|
||||
|
||||
// ReadASN1UTCTime decodes an ASN.1 UTCTime into out and advances.
|
||||
// It reports whether the read was successful.
|
||||
func (s *String) ReadASN1UTCTime(out *time.Time) bool {
|
||||
var bytes String
|
||||
if !s.ReadASN1(&bytes, asn1.UTCTime) {
|
||||
return false
|
||||
}
|
||||
t := string(bytes)
|
||||
|
||||
formatStr := defaultUTCTimeFormatStr
|
||||
var err error
|
||||
res, err := time.Parse(formatStr, t)
|
||||
if err != nil {
|
||||
// Fallback to minute precision if we can't parse second
|
||||
// precision. If we are following X.509 or X.690 we shouldn't
|
||||
// support this, but we do.
|
||||
formatStr = "0601021504Z0700"
|
||||
res, err = time.Parse(formatStr, t)
|
||||
}
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if serialized := res.Format(formatStr); serialized != t {
|
||||
return false
|
||||
}
|
||||
|
||||
if res.Year() >= 2050 {
|
||||
// UTCTime interprets the low order digits 50-99 as 1950-99.
|
||||
// This only applies to its use in the X.509 profile.
|
||||
// See https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1
|
||||
res = res.AddDate(-100, 0, 0)
|
||||
}
|
||||
*out = res
|
||||
return true
|
||||
}
|
||||
|
||||
// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances.
|
||||
// It reports whether the read was successful.
|
||||
func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool {
|
||||
var bytes String
|
||||
if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 ||
|
||||
len(bytes)*8/8 != len(bytes) {
|
||||
return false
|
||||
}
|
||||
|
||||
paddingBits := bytes[0]
|
||||
bytes = bytes[1:]
|
||||
if paddingBits > 7 ||
|
||||
len(bytes) == 0 && paddingBits != 0 ||
|
||||
len(bytes) > 0 && bytes[len(bytes)-1]&(1<<paddingBits-1) != 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
out.BitLength = len(bytes)*8 - int(paddingBits)
|
||||
out.Bytes = bytes
|
||||
return true
|
||||
}
|
||||
|
||||
// ReadASN1BitStringAsBytes decodes an ASN.1 BIT STRING into out and advances. It is
|
||||
// an error if the BIT STRING is not a whole number of bytes. It reports
|
||||
// whether the read was successful.
|
||||
func (s *String) ReadASN1BitStringAsBytes(out *[]byte) bool {
|
||||
var bytes String
|
||||
if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
paddingBits := bytes[0]
|
||||
if paddingBits != 0 {
|
||||
return false
|
||||
}
|
||||
*out = bytes[1:]
|
||||
return true
|
||||
}
|
||||
|
||||
// ReadASN1Bytes reads the contents of a DER-encoded ASN.1 element (not including
|
||||
// tag and length bytes) into out, and advances. The element must match the
|
||||
// given tag. It reports whether the read was successful.
|
||||
func (s *String) ReadASN1Bytes(out *[]byte, tag asn1.Tag) bool {
|
||||
return s.ReadASN1((*String)(out), tag)
|
||||
}
|
||||
|
||||
// ReadASN1 reads the contents of a DER-encoded ASN.1 element (not including
|
||||
// tag and length bytes) into out, and advances. The element must match the
|
||||
// given tag. It reports whether the read was successful.
|
||||
//
|
||||
// Tags greater than 30 are not supported (i.e. low-tag-number format only).
|
||||
func (s *String) ReadASN1(out *String, tag asn1.Tag) bool {
|
||||
var t asn1.Tag
|
||||
if !s.ReadAnyASN1(out, &t) || t != tag {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ReadASN1Element reads the contents of a DER-encoded ASN.1 element (including
|
||||
// tag and length bytes) into out, and advances. The element must match the
|
||||
// given tag. It reports whether the read was successful.
|
||||
//
|
||||
// Tags greater than 30 are not supported (i.e. low-tag-number format only).
|
||||
func (s *String) ReadASN1Element(out *String, tag asn1.Tag) bool {
|
||||
var t asn1.Tag
|
||||
if !s.ReadAnyASN1Element(out, &t) || t != tag {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ReadAnyASN1 reads the contents of a DER-encoded ASN.1 element (not including
|
||||
// tag and length bytes) into out, sets outTag to its tag, and advances.
|
||||
// It reports whether the read was successful.
|
||||
//
|
||||
// Tags greater than 30 are not supported (i.e. low-tag-number format only).
|
||||
func (s *String) ReadAnyASN1(out *String, outTag *asn1.Tag) bool {
|
||||
return s.readASN1(out, outTag, true /* skip header */)
|
||||
}
|
||||
|
||||
// ReadAnyASN1Element reads the contents of a DER-encoded ASN.1 element
|
||||
// (including tag and length bytes) into out, sets outTag to is tag, and
|
||||
// advances. It reports whether the read was successful.
|
||||
//
|
||||
// Tags greater than 30 are not supported (i.e. low-tag-number format only).
|
||||
func (s *String) ReadAnyASN1Element(out *String, outTag *asn1.Tag) bool {
|
||||
return s.readASN1(out, outTag, false /* include header */)
|
||||
}
|
||||
|
||||
// PeekASN1Tag reports whether the next ASN.1 value on the string starts with
|
||||
// the given tag.
|
||||
func (s String) PeekASN1Tag(tag asn1.Tag) bool {
|
||||
if len(s) == 0 {
|
||||
return false
|
||||
}
|
||||
return asn1.Tag(s[0]) == tag
|
||||
}
|
||||
|
||||
// SkipASN1 reads and discards an ASN.1 element with the given tag. It
|
||||
// reports whether the operation was successful.
|
||||
func (s *String) SkipASN1(tag asn1.Tag) bool {
|
||||
var unused String
|
||||
return s.ReadASN1(&unused, tag)
|
||||
}
|
||||
|
||||
// ReadOptionalASN1 attempts to read the contents of a DER-encoded ASN.1
|
||||
// element (not including tag and length bytes) tagged with the given tag into
|
||||
// out. It stores whether an element with the tag was found in outPresent,
|
||||
// unless outPresent is nil. It reports whether the read was successful.
|
||||
func (s *String) ReadOptionalASN1(out *String, outPresent *bool, tag asn1.Tag) bool {
|
||||
present := s.PeekASN1Tag(tag)
|
||||
if outPresent != nil {
|
||||
*outPresent = present
|
||||
}
|
||||
if present && !s.ReadASN1(out, tag) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// SkipOptionalASN1 advances s over an ASN.1 element with the given tag, or
|
||||
// else leaves s unchanged. It reports whether the operation was successful.
|
||||
func (s *String) SkipOptionalASN1(tag asn1.Tag) bool {
|
||||
if !s.PeekASN1Tag(tag) {
|
||||
return true
|
||||
}
|
||||
var unused String
|
||||
return s.ReadASN1(&unused, tag)
|
||||
}
|
||||
|
||||
// ReadOptionalASN1Integer attempts to read an optional ASN.1 INTEGER explicitly
|
||||
// tagged with tag into out and advances. If no element with a matching tag is
|
||||
// present, it writes defaultValue into out instead. Otherwise, it behaves like
|
||||
// ReadASN1Integer.
|
||||
func (s *String) ReadOptionalASN1Integer(out interface{}, tag asn1.Tag, defaultValue interface{}) bool {
|
||||
var present bool
|
||||
var i String
|
||||
if !s.ReadOptionalASN1(&i, &present, tag) {
|
||||
return false
|
||||
}
|
||||
if !present {
|
||||
switch out.(type) {
|
||||
case *int, *int8, *int16, *int32, *int64,
|
||||
*uint, *uint8, *uint16, *uint32, *uint64, *[]byte:
|
||||
reflect.ValueOf(out).Elem().Set(reflect.ValueOf(defaultValue))
|
||||
case *big.Int:
|
||||
if defaultValue, ok := defaultValue.(*big.Int); ok {
|
||||
out.(*big.Int).Set(defaultValue)
|
||||
} else {
|
||||
panic("out points to big.Int, but defaultValue does not")
|
||||
}
|
||||
default:
|
||||
panic("invalid integer type")
|
||||
}
|
||||
return true
|
||||
}
|
||||
if !i.ReadASN1Integer(out) || !i.Empty() {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ReadOptionalASN1OctetString attempts to read an optional ASN.1 OCTET STRING
|
||||
// explicitly tagged with tag into out and advances. If no element with a
|
||||
// matching tag is present, it sets "out" to nil instead. It reports
|
||||
// whether the read was successful.
|
||||
func (s *String) ReadOptionalASN1OctetString(out *[]byte, outPresent *bool, tag asn1.Tag) bool {
|
||||
var present bool
|
||||
var child String
|
||||
if !s.ReadOptionalASN1(&child, &present, tag) {
|
||||
return false
|
||||
}
|
||||
if outPresent != nil {
|
||||
*outPresent = present
|
||||
}
|
||||
if present {
|
||||
var oct String
|
||||
if !child.ReadASN1(&oct, asn1.OCTET_STRING) || !child.Empty() {
|
||||
return false
|
||||
}
|
||||
*out = oct
|
||||
} else {
|
||||
*out = nil
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ReadOptionalASN1Boolean sets *out to the value of the next ASN.1 BOOLEAN or,
|
||||
// if the next bytes are not an ASN.1 BOOLEAN, to the value of defaultValue.
|
||||
// It reports whether the operation was successful.
|
||||
func (s *String) ReadOptionalASN1Boolean(out *bool, defaultValue bool) bool {
|
||||
var present bool
|
||||
var child String
|
||||
if !s.ReadOptionalASN1(&child, &present, asn1.BOOLEAN) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !present {
|
||||
*out = defaultValue
|
||||
return true
|
||||
}
|
||||
|
||||
return s.ReadASN1Boolean(out)
|
||||
}
|
||||
|
||||
func (s *String) readASN1(out *String, outTag *asn1.Tag, skipHeader bool) bool {
|
||||
if len(*s) < 2 {
|
||||
return false
|
||||
}
|
||||
tag, lenByte := (*s)[0], (*s)[1]
|
||||
|
||||
if tag&0x1f == 0x1f {
|
||||
// ITU-T X.690 section 8.1.2
|
||||
//
|
||||
// An identifier octet with a tag part of 0x1f indicates a high-tag-number
|
||||
// form identifier with two or more octets. We only support tags less than
|
||||
// 31 (i.e. low-tag-number form, single octet identifier).
|
||||
return false
|
||||
}
|
||||
|
||||
if outTag != nil {
|
||||
*outTag = asn1.Tag(tag)
|
||||
}
|
||||
|
||||
// ITU-T X.690 section 8.1.3
|
||||
//
|
||||
// Bit 8 of the first length byte indicates whether the length is short- or
|
||||
// long-form.
|
||||
var length, headerLen uint32 // length includes headerLen
|
||||
if lenByte&0x80 == 0 {
|
||||
// Short-form length (section 8.1.3.4), encoded in bits 1-7.
|
||||
length = uint32(lenByte) + 2
|
||||
headerLen = 2
|
||||
} else {
|
||||
// Long-form length (section 8.1.3.5). Bits 1-7 encode the number of octets
|
||||
// used to encode the length.
|
||||
lenLen := lenByte & 0x7f
|
||||
var len32 uint32
|
||||
|
||||
if lenLen == 0 || lenLen > 4 || len(*s) < int(2+lenLen) {
|
||||
return false
|
||||
}
|
||||
|
||||
lenBytes := String((*s)[2 : 2+lenLen])
|
||||
if !lenBytes.readUnsigned(&len32, int(lenLen)) {
|
||||
return false
|
||||
}
|
||||
|
||||
// ITU-T X.690 section 10.1 (DER length forms) requires encoding the length
|
||||
// with the minimum number of octets.
|
||||
if len32 < 128 {
|
||||
// Length should have used short-form encoding.
|
||||
return false
|
||||
}
|
||||
if len32>>((lenLen-1)*8) == 0 {
|
||||
// Leading octet is 0. Length should have been at least one byte shorter.
|
||||
return false
|
||||
}
|
||||
|
||||
headerLen = 2 + uint32(lenLen)
|
||||
if headerLen+len32 < len32 {
|
||||
// Overflow.
|
||||
return false
|
||||
}
|
||||
length = headerLen + len32
|
||||
}
|
||||
|
||||
if int(length) < 0 || !s.ReadBytes((*[]byte)(out), int(length)) {
|
||||
return false
|
||||
}
|
||||
if skipHeader && !out.Skip(int(headerLen)) {
|
||||
panic("cryptobyte: internal error")
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
46
vendor/golang.org/x/crypto/cryptobyte/asn1/asn1.go
generated
vendored
Normal file
46
vendor/golang.org/x/crypto/cryptobyte/asn1/asn1.go
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package asn1 contains supporting types for parsing and building ASN.1
|
||||
// messages with the cryptobyte package.
|
||||
package asn1 // import "golang.org/x/crypto/cryptobyte/asn1"
|
||||
|
||||
// Tag represents an ASN.1 identifier octet, consisting of a tag number
|
||||
// (indicating a type) and class (such as context-specific or constructed).
|
||||
//
|
||||
// Methods in the cryptobyte package only support the low-tag-number form, i.e.
|
||||
// a single identifier octet with bits 7-8 encoding the class and bits 1-6
|
||||
// encoding the tag number.
|
||||
type Tag uint8
|
||||
|
||||
const (
|
||||
classConstructed = 0x20
|
||||
classContextSpecific = 0x80
|
||||
)
|
||||
|
||||
// Constructed returns t with the constructed class bit set.
|
||||
func (t Tag) Constructed() Tag { return t | classConstructed }
|
||||
|
||||
// ContextSpecific returns t with the context-specific class bit set.
|
||||
func (t Tag) ContextSpecific() Tag { return t | classContextSpecific }
|
||||
|
||||
// The following is a list of standard tag and class combinations.
|
||||
const (
|
||||
BOOLEAN = Tag(1)
|
||||
INTEGER = Tag(2)
|
||||
BIT_STRING = Tag(3)
|
||||
OCTET_STRING = Tag(4)
|
||||
NULL = Tag(5)
|
||||
OBJECT_IDENTIFIER = Tag(6)
|
||||
ENUM = Tag(10)
|
||||
UTF8String = Tag(12)
|
||||
SEQUENCE = Tag(16 | classConstructed)
|
||||
SET = Tag(17 | classConstructed)
|
||||
PrintableString = Tag(19)
|
||||
T61String = Tag(20)
|
||||
IA5String = Tag(22)
|
||||
UTCTime = Tag(23)
|
||||
GeneralizedTime = Tag(24)
|
||||
GeneralString = Tag(27)
|
||||
)
|
345
vendor/golang.org/x/crypto/cryptobyte/builder.go
generated
vendored
Normal file
345
vendor/golang.org/x/crypto/cryptobyte/builder.go
generated
vendored
Normal file
@ -0,0 +1,345 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cryptobyte
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// A Builder builds byte strings from fixed-length and length-prefixed values.
|
||||
// Builders either allocate space as needed, or are ‘fixed’, which means that
|
||||
// they write into a given buffer and produce an error if it's exhausted.
|
||||
//
|
||||
// The zero value is a usable Builder that allocates space as needed.
|
||||
//
|
||||
// Simple values are marshaled and appended to a Builder using methods on the
|
||||
// Builder. Length-prefixed values are marshaled by providing a
|
||||
// BuilderContinuation, which is a function that writes the inner contents of
|
||||
// the value to a given Builder. See the documentation for BuilderContinuation
|
||||
// for details.
|
||||
type Builder struct {
|
||||
err error
|
||||
result []byte
|
||||
fixedSize bool
|
||||
child *Builder
|
||||
offset int
|
||||
pendingLenLen int
|
||||
pendingIsASN1 bool
|
||||
inContinuation *bool
|
||||
}
|
||||
|
||||
// NewBuilder creates a Builder that appends its output to the given buffer.
|
||||
// Like append(), the slice will be reallocated if its capacity is exceeded.
|
||||
// Use Bytes to get the final buffer.
|
||||
func NewBuilder(buffer []byte) *Builder {
|
||||
return &Builder{
|
||||
result: buffer,
|
||||
}
|
||||
}
|
||||
|
||||
// NewFixedBuilder creates a Builder that appends its output into the given
|
||||
// buffer. This builder does not reallocate the output buffer. Writes that
|
||||
// would exceed the buffer's capacity are treated as an error.
|
||||
func NewFixedBuilder(buffer []byte) *Builder {
|
||||
return &Builder{
|
||||
result: buffer,
|
||||
fixedSize: true,
|
||||
}
|
||||
}
|
||||
|
||||
// SetError sets the value to be returned as the error from Bytes. Writes
|
||||
// performed after calling SetError are ignored.
|
||||
func (b *Builder) SetError(err error) {
|
||||
b.err = err
|
||||
}
|
||||
|
||||
// Bytes returns the bytes written by the builder or an error if one has
|
||||
// occurred during building.
|
||||
func (b *Builder) Bytes() ([]byte, error) {
|
||||
if b.err != nil {
|
||||
return nil, b.err
|
||||
}
|
||||
return b.result[b.offset:], nil
|
||||
}
|
||||
|
||||
// BytesOrPanic returns the bytes written by the builder or panics if an error
|
||||
// has occurred during building.
|
||||
func (b *Builder) BytesOrPanic() []byte {
|
||||
if b.err != nil {
|
||||
panic(b.err)
|
||||
}
|
||||
return b.result[b.offset:]
|
||||
}
|
||||
|
||||
// AddUint8 appends an 8-bit value to the byte string.
|
||||
func (b *Builder) AddUint8(v uint8) {
|
||||
b.add(byte(v))
|
||||
}
|
||||
|
||||
// AddUint16 appends a big-endian, 16-bit value to the byte string.
|
||||
func (b *Builder) AddUint16(v uint16) {
|
||||
b.add(byte(v>>8), byte(v))
|
||||
}
|
||||
|
||||
// AddUint24 appends a big-endian, 24-bit value to the byte string. The highest
|
||||
// byte of the 32-bit input value is silently truncated.
|
||||
func (b *Builder) AddUint24(v uint32) {
|
||||
b.add(byte(v>>16), byte(v>>8), byte(v))
|
||||
}
|
||||
|
||||
// AddUint32 appends a big-endian, 32-bit value to the byte string.
|
||||
func (b *Builder) AddUint32(v uint32) {
|
||||
b.add(byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
|
||||
}
|
||||
|
||||
// AddUint64 appends a big-endian, 64-bit value to the byte string.
|
||||
func (b *Builder) AddUint64(v uint64) {
|
||||
b.add(byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
|
||||
}
|
||||
|
||||
// AddBytes appends a sequence of bytes to the byte string.
|
||||
func (b *Builder) AddBytes(v []byte) {
|
||||
b.add(v...)
|
||||
}
|
||||
|
||||
// BuilderContinuation is a continuation-passing interface for building
|
||||
// length-prefixed byte sequences. Builder methods for length-prefixed
|
||||
// sequences (AddUint8LengthPrefixed etc) will invoke the BuilderContinuation
|
||||
// supplied to them. The child builder passed to the continuation can be used
|
||||
// to build the content of the length-prefixed sequence. For example:
|
||||
//
|
||||
// parent := cryptobyte.NewBuilder()
|
||||
// parent.AddUint8LengthPrefixed(func (child *Builder) {
|
||||
// child.AddUint8(42)
|
||||
// child.AddUint8LengthPrefixed(func (grandchild *Builder) {
|
||||
// grandchild.AddUint8(5)
|
||||
// })
|
||||
// })
|
||||
//
|
||||
// It is an error to write more bytes to the child than allowed by the reserved
|
||||
// length prefix. After the continuation returns, the child must be considered
|
||||
// invalid, i.e. users must not store any copies or references of the child
|
||||
// that outlive the continuation.
|
||||
//
|
||||
// If the continuation panics with a value of type BuildError then the inner
|
||||
// error will be returned as the error from Bytes. If the child panics
|
||||
// otherwise then Bytes will repanic with the same value.
|
||||
type BuilderContinuation func(child *Builder)
|
||||
|
||||
// BuildError wraps an error. If a BuilderContinuation panics with this value,
|
||||
// the panic will be recovered and the inner error will be returned from
|
||||
// Builder.Bytes.
|
||||
type BuildError struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
// AddUint8LengthPrefixed adds a 8-bit length-prefixed byte sequence.
|
||||
func (b *Builder) AddUint8LengthPrefixed(f BuilderContinuation) {
|
||||
b.addLengthPrefixed(1, false, f)
|
||||
}
|
||||
|
||||
// AddUint16LengthPrefixed adds a big-endian, 16-bit length-prefixed byte sequence.
|
||||
func (b *Builder) AddUint16LengthPrefixed(f BuilderContinuation) {
|
||||
b.addLengthPrefixed(2, false, f)
|
||||
}
|
||||
|
||||
// AddUint24LengthPrefixed adds a big-endian, 24-bit length-prefixed byte sequence.
|
||||
func (b *Builder) AddUint24LengthPrefixed(f BuilderContinuation) {
|
||||
b.addLengthPrefixed(3, false, f)
|
||||
}
|
||||
|
||||
// AddUint32LengthPrefixed adds a big-endian, 32-bit length-prefixed byte sequence.
|
||||
func (b *Builder) AddUint32LengthPrefixed(f BuilderContinuation) {
|
||||
b.addLengthPrefixed(4, false, f)
|
||||
}
|
||||
|
||||
func (b *Builder) callContinuation(f BuilderContinuation, arg *Builder) {
|
||||
if !*b.inContinuation {
|
||||
*b.inContinuation = true
|
||||
|
||||
defer func() {
|
||||
*b.inContinuation = false
|
||||
|
||||
r := recover()
|
||||
if r == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if buildError, ok := r.(BuildError); ok {
|
||||
b.err = buildError.Err
|
||||
} else {
|
||||
panic(r)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
f(arg)
|
||||
}
|
||||
|
||||
func (b *Builder) addLengthPrefixed(lenLen int, isASN1 bool, f BuilderContinuation) {
|
||||
// Subsequent writes can be ignored if the builder has encountered an error.
|
||||
if b.err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
offset := len(b.result)
|
||||
b.add(make([]byte, lenLen)...)
|
||||
|
||||
if b.inContinuation == nil {
|
||||
b.inContinuation = new(bool)
|
||||
}
|
||||
|
||||
b.child = &Builder{
|
||||
result: b.result,
|
||||
fixedSize: b.fixedSize,
|
||||
offset: offset,
|
||||
pendingLenLen: lenLen,
|
||||
pendingIsASN1: isASN1,
|
||||
inContinuation: b.inContinuation,
|
||||
}
|
||||
|
||||
b.callContinuation(f, b.child)
|
||||
b.flushChild()
|
||||
if b.child != nil {
|
||||
panic("cryptobyte: internal error")
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Builder) flushChild() {
|
||||
if b.child == nil {
|
||||
return
|
||||
}
|
||||
b.child.flushChild()
|
||||
child := b.child
|
||||
b.child = nil
|
||||
|
||||
if child.err != nil {
|
||||
b.err = child.err
|
||||
return
|
||||
}
|
||||
|
||||
length := len(child.result) - child.pendingLenLen - child.offset
|
||||
|
||||
if length < 0 {
|
||||
panic("cryptobyte: internal error") // result unexpectedly shrunk
|
||||
}
|
||||
|
||||
if child.pendingIsASN1 {
|
||||
// For ASN.1, we reserved a single byte for the length. If that turned out
|
||||
// to be incorrect, we have to move the contents along in order to make
|
||||
// space.
|
||||
if child.pendingLenLen != 1 {
|
||||
panic("cryptobyte: internal error")
|
||||
}
|
||||
var lenLen, lenByte uint8
|
||||
if int64(length) > 0xfffffffe {
|
||||
b.err = errors.New("pending ASN.1 child too long")
|
||||
return
|
||||
} else if length > 0xffffff {
|
||||
lenLen = 5
|
||||
lenByte = 0x80 | 4
|
||||
} else if length > 0xffff {
|
||||
lenLen = 4
|
||||
lenByte = 0x80 | 3
|
||||
} else if length > 0xff {
|
||||
lenLen = 3
|
||||
lenByte = 0x80 | 2
|
||||
} else if length > 0x7f {
|
||||
lenLen = 2
|
||||
lenByte = 0x80 | 1
|
||||
} else {
|
||||
lenLen = 1
|
||||
lenByte = uint8(length)
|
||||
length = 0
|
||||
}
|
||||
|
||||
// Insert the initial length byte, make space for successive length bytes,
|
||||
// and adjust the offset.
|
||||
child.result[child.offset] = lenByte
|
||||
extraBytes := int(lenLen - 1)
|
||||
if extraBytes != 0 {
|
||||
child.add(make([]byte, extraBytes)...)
|
||||
childStart := child.offset + child.pendingLenLen
|
||||
copy(child.result[childStart+extraBytes:], child.result[childStart:])
|
||||
}
|
||||
child.offset++
|
||||
child.pendingLenLen = extraBytes
|
||||
}
|
||||
|
||||
l := length
|
||||
for i := child.pendingLenLen - 1; i >= 0; i-- {
|
||||
child.result[child.offset+i] = uint8(l)
|
||||
l >>= 8
|
||||
}
|
||||
if l != 0 {
|
||||
b.err = fmt.Errorf("cryptobyte: pending child length %d exceeds %d-byte length prefix", length, child.pendingLenLen)
|
||||
return
|
||||
}
|
||||
|
||||
if b.fixedSize && &b.result[0] != &child.result[0] {
|
||||
panic("cryptobyte: BuilderContinuation reallocated a fixed-size buffer")
|
||||
}
|
||||
|
||||
b.result = child.result
|
||||
}
|
||||
|
||||
func (b *Builder) add(bytes ...byte) {
|
||||
if b.err != nil {
|
||||
return
|
||||
}
|
||||
if b.child != nil {
|
||||
panic("cryptobyte: attempted write while child is pending")
|
||||
}
|
||||
if len(b.result)+len(bytes) < len(bytes) {
|
||||
b.err = errors.New("cryptobyte: length overflow")
|
||||
}
|
||||
if b.fixedSize && len(b.result)+len(bytes) > cap(b.result) {
|
||||
b.err = errors.New("cryptobyte: Builder is exceeding its fixed-size buffer")
|
||||
return
|
||||
}
|
||||
b.result = append(b.result, bytes...)
|
||||
}
|
||||
|
||||
// Unwrite rolls back non-negative n bytes written directly to the Builder.
|
||||
// An attempt by a child builder passed to a continuation to unwrite bytes
|
||||
// from its parent will panic.
|
||||
func (b *Builder) Unwrite(n int) {
|
||||
if b.err != nil {
|
||||
return
|
||||
}
|
||||
if b.child != nil {
|
||||
panic("cryptobyte: attempted unwrite while child is pending")
|
||||
}
|
||||
length := len(b.result) - b.pendingLenLen - b.offset
|
||||
if length < 0 {
|
||||
panic("cryptobyte: internal error")
|
||||
}
|
||||
if n < 0 {
|
||||
panic("cryptobyte: attempted to unwrite negative number of bytes")
|
||||
}
|
||||
if n > length {
|
||||
panic("cryptobyte: attempted to unwrite more than was written")
|
||||
}
|
||||
b.result = b.result[:len(b.result)-n]
|
||||
}
|
||||
|
||||
// A MarshalingValue marshals itself into a Builder.
|
||||
type MarshalingValue interface {
|
||||
// Marshal is called by Builder.AddValue. It receives a pointer to a builder
|
||||
// to marshal itself into. It may return an error that occurred during
|
||||
// marshaling, such as unset or invalid values.
|
||||
Marshal(b *Builder) error
|
||||
}
|
||||
|
||||
// AddValue calls Marshal on v, passing a pointer to the builder to append to.
|
||||
// If Marshal returns an error, it is set on the Builder so that subsequent
|
||||
// appends don't have an effect.
|
||||
func (b *Builder) AddValue(v MarshalingValue) {
|
||||
err := v.Marshal(b)
|
||||
if err != nil {
|
||||
b.err = err
|
||||
}
|
||||
}
|
172
vendor/golang.org/x/crypto/cryptobyte/string.go
generated
vendored
Normal file
172
vendor/golang.org/x/crypto/cryptobyte/string.go
generated
vendored
Normal file
@ -0,0 +1,172 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package cryptobyte contains types that help with parsing and constructing
|
||||
// length-prefixed, binary messages, including ASN.1 DER. (The asn1 subpackage
|
||||
// contains useful ASN.1 constants.)
|
||||
//
|
||||
// The String type is for parsing. It wraps a []byte slice and provides helper
|
||||
// functions for consuming structures, value by value.
|
||||
//
|
||||
// The Builder type is for constructing messages. It providers helper functions
|
||||
// for appending values and also for appending length-prefixed submessages –
|
||||
// without having to worry about calculating the length prefix ahead of time.
|
||||
//
|
||||
// See the documentation and examples for the Builder and String types to get
|
||||
// started.
|
||||
package cryptobyte // import "golang.org/x/crypto/cryptobyte"
|
||||
|
||||
// String represents a string of bytes. It provides methods for parsing
|
||||
// fixed-length and length-prefixed values from it.
|
||||
type String []byte
|
||||
|
||||
// read advances a String by n bytes and returns them. If less than n bytes
|
||||
// remain, it returns nil.
|
||||
func (s *String) read(n int) []byte {
|
||||
if len(*s) < n || n < 0 {
|
||||
return nil
|
||||
}
|
||||
v := (*s)[:n]
|
||||
*s = (*s)[n:]
|
||||
return v
|
||||
}
|
||||
|
||||
// Skip advances the String by n byte and reports whether it was successful.
|
||||
func (s *String) Skip(n int) bool {
|
||||
return s.read(n) != nil
|
||||
}
|
||||
|
||||
// ReadUint8 decodes an 8-bit value into out and advances over it.
|
||||
// It reports whether the read was successful.
|
||||
func (s *String) ReadUint8(out *uint8) bool {
|
||||
v := s.read(1)
|
||||
if v == nil {
|
||||
return false
|
||||
}
|
||||
*out = uint8(v[0])
|
||||
return true
|
||||
}
|
||||
|
||||
// ReadUint16 decodes a big-endian, 16-bit value into out and advances over it.
|
||||
// It reports whether the read was successful.
|
||||
func (s *String) ReadUint16(out *uint16) bool {
|
||||
v := s.read(2)
|
||||
if v == nil {
|
||||
return false
|
||||
}
|
||||
*out = uint16(v[0])<<8 | uint16(v[1])
|
||||
return true
|
||||
}
|
||||
|
||||
// ReadUint24 decodes a big-endian, 24-bit value into out and advances over it.
|
||||
// It reports whether the read was successful.
|
||||
func (s *String) ReadUint24(out *uint32) bool {
|
||||
v := s.read(3)
|
||||
if v == nil {
|
||||
return false
|
||||
}
|
||||
*out = uint32(v[0])<<16 | uint32(v[1])<<8 | uint32(v[2])
|
||||
return true
|
||||
}
|
||||
|
||||
// ReadUint32 decodes a big-endian, 32-bit value into out and advances over it.
|
||||
// It reports whether the read was successful.
|
||||
func (s *String) ReadUint32(out *uint32) bool {
|
||||
v := s.read(4)
|
||||
if v == nil {
|
||||
return false
|
||||
}
|
||||
*out = uint32(v[0])<<24 | uint32(v[1])<<16 | uint32(v[2])<<8 | uint32(v[3])
|
||||
return true
|
||||
}
|
||||
|
||||
// ReadUint64 decodes a big-endian, 64-bit value into out and advances over it.
|
||||
// It reports whether the read was successful.
|
||||
func (s *String) ReadUint64(out *uint64) bool {
|
||||
v := s.read(8)
|
||||
if v == nil {
|
||||
return false
|
||||
}
|
||||
*out = uint64(v[0])<<56 | uint64(v[1])<<48 | uint64(v[2])<<40 | uint64(v[3])<<32 | uint64(v[4])<<24 | uint64(v[5])<<16 | uint64(v[6])<<8 | uint64(v[7])
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *String) readUnsigned(out *uint32, length int) bool {
|
||||
v := s.read(length)
|
||||
if v == nil {
|
||||
return false
|
||||
}
|
||||
var result uint32
|
||||
for i := 0; i < length; i++ {
|
||||
result <<= 8
|
||||
result |= uint32(v[i])
|
||||
}
|
||||
*out = result
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *String) readLengthPrefixed(lenLen int, outChild *String) bool {
|
||||
lenBytes := s.read(lenLen)
|
||||
if lenBytes == nil {
|
||||
return false
|
||||
}
|
||||
var length uint32
|
||||
for _, b := range lenBytes {
|
||||
length = length << 8
|
||||
length = length | uint32(b)
|
||||
}
|
||||
v := s.read(int(length))
|
||||
if v == nil {
|
||||
return false
|
||||
}
|
||||
*outChild = v
|
||||
return true
|
||||
}
|
||||
|
||||
// ReadUint8LengthPrefixed reads the content of an 8-bit length-prefixed value
|
||||
// into out and advances over it. It reports whether the read was successful.
|
||||
func (s *String) ReadUint8LengthPrefixed(out *String) bool {
|
||||
return s.readLengthPrefixed(1, out)
|
||||
}
|
||||
|
||||
// ReadUint16LengthPrefixed reads the content of a big-endian, 16-bit
|
||||
// length-prefixed value into out and advances over it. It reports whether the
|
||||
// read was successful.
|
||||
func (s *String) ReadUint16LengthPrefixed(out *String) bool {
|
||||
return s.readLengthPrefixed(2, out)
|
||||
}
|
||||
|
||||
// ReadUint24LengthPrefixed reads the content of a big-endian, 24-bit
|
||||
// length-prefixed value into out and advances over it. It reports whether
|
||||
// the read was successful.
|
||||
func (s *String) ReadUint24LengthPrefixed(out *String) bool {
|
||||
return s.readLengthPrefixed(3, out)
|
||||
}
|
||||
|
||||
// ReadBytes reads n bytes into out and advances over them. It reports
|
||||
// whether the read was successful.
|
||||
func (s *String) ReadBytes(out *[]byte, n int) bool {
|
||||
v := s.read(n)
|
||||
if v == nil {
|
||||
return false
|
||||
}
|
||||
*out = v
|
||||
return true
|
||||
}
|
||||
|
||||
// CopyBytes copies len(out) bytes into out and advances over them. It reports
|
||||
// whether the copy operation was successful
|
||||
func (s *String) CopyBytes(out []byte) bool {
|
||||
n := len(out)
|
||||
v := s.read(n)
|
||||
if v == nil {
|
||||
return false
|
||||
}
|
||||
return copy(out, v) == n
|
||||
}
|
||||
|
||||
// Empty reports whether the string does not contain any bytes.
|
||||
func (s String) Empty() bool {
|
||||
return len(s) == 0
|
||||
}
|
173
vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go
generated
vendored
Normal file
173
vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go
generated
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package secretbox encrypts and authenticates small messages.
|
||||
|
||||
Secretbox uses XSalsa20 and Poly1305 to encrypt and authenticate messages with
|
||||
secret-key cryptography. The length of messages is not hidden.
|
||||
|
||||
It is the caller's responsibility to ensure the uniqueness of nonces—for
|
||||
example, by using nonce 1 for the first message, nonce 2 for the second
|
||||
message, etc. Nonces are long enough that randomly generated nonces have
|
||||
negligible risk of collision.
|
||||
|
||||
Messages should be small because:
|
||||
|
||||
1. The whole message needs to be held in memory to be processed.
|
||||
|
||||
2. Using large messages pressures implementations on small machines to decrypt
|
||||
and process plaintext before authenticating it. This is very dangerous, and
|
||||
this API does not allow it, but a protocol that uses excessive message sizes
|
||||
might present some implementations with no other choice.
|
||||
|
||||
3. Fixed overheads will be sufficiently amortised by messages as small as 8KB.
|
||||
|
||||
4. Performance may be improved by working with messages that fit into data caches.
|
||||
|
||||
Thus large amounts of data should be chunked so that each message is small.
|
||||
(Each message still needs a unique nonce.) If in doubt, 16KB is a reasonable
|
||||
chunk size.
|
||||
|
||||
This package is interoperable with NaCl: https://nacl.cr.yp.to/secretbox.html.
|
||||
*/
|
||||
package secretbox // import "golang.org/x/crypto/nacl/secretbox"
|
||||
|
||||
import (
|
||||
"golang.org/x/crypto/internal/alias"
|
||||
"golang.org/x/crypto/internal/poly1305"
|
||||
"golang.org/x/crypto/salsa20/salsa"
|
||||
)
|
||||
|
||||
// Overhead is the number of bytes of overhead when boxing a message.
|
||||
const Overhead = poly1305.TagSize
|
||||
|
||||
// setup produces a sub-key and Salsa20 counter given a nonce and key.
|
||||
func setup(subKey *[32]byte, counter *[16]byte, nonce *[24]byte, key *[32]byte) {
|
||||
// We use XSalsa20 for encryption so first we need to generate a
|
||||
// key and nonce with HSalsa20.
|
||||
var hNonce [16]byte
|
||||
copy(hNonce[:], nonce[:])
|
||||
salsa.HSalsa20(subKey, &hNonce, key, &salsa.Sigma)
|
||||
|
||||
// The final 8 bytes of the original nonce form the new nonce.
|
||||
copy(counter[:], nonce[16:])
|
||||
}
|
||||
|
||||
// sliceForAppend takes a slice and a requested number of bytes. It returns a
|
||||
// slice with the contents of the given slice followed by that many bytes and a
|
||||
// second slice that aliases into it and contains only the extra bytes. If the
|
||||
// original slice has sufficient capacity then no allocation is performed.
|
||||
func sliceForAppend(in []byte, n int) (head, tail []byte) {
|
||||
if total := len(in) + n; cap(in) >= total {
|
||||
head = in[:total]
|
||||
} else {
|
||||
head = make([]byte, total)
|
||||
copy(head, in)
|
||||
}
|
||||
tail = head[len(in):]
|
||||
return
|
||||
}
|
||||
|
||||
// Seal appends an encrypted and authenticated copy of message to out, which
|
||||
// must not overlap message. The key and nonce pair must be unique for each
|
||||
// distinct message and the output will be Overhead bytes longer than message.
|
||||
func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte {
|
||||
var subKey [32]byte
|
||||
var counter [16]byte
|
||||
setup(&subKey, &counter, nonce, key)
|
||||
|
||||
// The Poly1305 key is generated by encrypting 32 bytes of zeros. Since
|
||||
// Salsa20 works with 64-byte blocks, we also generate 32 bytes of
|
||||
// keystream as a side effect.
|
||||
var firstBlock [64]byte
|
||||
salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey)
|
||||
|
||||
var poly1305Key [32]byte
|
||||
copy(poly1305Key[:], firstBlock[:])
|
||||
|
||||
ret, out := sliceForAppend(out, len(message)+poly1305.TagSize)
|
||||
if alias.AnyOverlap(out, message) {
|
||||
panic("nacl: invalid buffer overlap")
|
||||
}
|
||||
|
||||
// We XOR up to 32 bytes of message with the keystream generated from
|
||||
// the first block.
|
||||
firstMessageBlock := message
|
||||
if len(firstMessageBlock) > 32 {
|
||||
firstMessageBlock = firstMessageBlock[:32]
|
||||
}
|
||||
|
||||
tagOut := out
|
||||
out = out[poly1305.TagSize:]
|
||||
for i, x := range firstMessageBlock {
|
||||
out[i] = firstBlock[32+i] ^ x
|
||||
}
|
||||
message = message[len(firstMessageBlock):]
|
||||
ciphertext := out
|
||||
out = out[len(firstMessageBlock):]
|
||||
|
||||
// Now encrypt the rest.
|
||||
counter[8] = 1
|
||||
salsa.XORKeyStream(out, message, &counter, &subKey)
|
||||
|
||||
var tag [poly1305.TagSize]byte
|
||||
poly1305.Sum(&tag, ciphertext, &poly1305Key)
|
||||
copy(tagOut, tag[:])
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// Open authenticates and decrypts a box produced by Seal and appends the
|
||||
// message to out, which must not overlap box. The output will be Overhead
|
||||
// bytes smaller than box.
|
||||
func Open(out, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool) {
|
||||
if len(box) < Overhead {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
var subKey [32]byte
|
||||
var counter [16]byte
|
||||
setup(&subKey, &counter, nonce, key)
|
||||
|
||||
// The Poly1305 key is generated by encrypting 32 bytes of zeros. Since
|
||||
// Salsa20 works with 64-byte blocks, we also generate 32 bytes of
|
||||
// keystream as a side effect.
|
||||
var firstBlock [64]byte
|
||||
salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey)
|
||||
|
||||
var poly1305Key [32]byte
|
||||
copy(poly1305Key[:], firstBlock[:])
|
||||
var tag [poly1305.TagSize]byte
|
||||
copy(tag[:], box)
|
||||
|
||||
if !poly1305.Verify(&tag, box[poly1305.TagSize:], &poly1305Key) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
ret, out := sliceForAppend(out, len(box)-Overhead)
|
||||
if alias.AnyOverlap(out, box) {
|
||||
panic("nacl: invalid buffer overlap")
|
||||
}
|
||||
|
||||
// We XOR up to 32 bytes of box with the keystream generated from
|
||||
// the first block.
|
||||
box = box[Overhead:]
|
||||
firstMessageBlock := box
|
||||
if len(firstMessageBlock) > 32 {
|
||||
firstMessageBlock = firstMessageBlock[:32]
|
||||
}
|
||||
for i, x := range firstMessageBlock {
|
||||
out[i] = firstBlock[32+i] ^ x
|
||||
}
|
||||
|
||||
box = box[len(firstMessageBlock):]
|
||||
out = out[len(firstMessageBlock):]
|
||||
|
||||
// Now decrypt the rest.
|
||||
counter[8] = 1
|
||||
salsa.XORKeyStream(out, box, &counter, &subKey)
|
||||
|
||||
return ret, true
|
||||
}
|
146
vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go
generated
vendored
Normal file
146
vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go
generated
vendored
Normal file
@ -0,0 +1,146 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package salsa provides low-level access to functions in the Salsa family.
|
||||
package salsa // import "golang.org/x/crypto/salsa20/salsa"
|
||||
|
||||
import "math/bits"
|
||||
|
||||
// Sigma is the Salsa20 constant for 256-bit keys.
|
||||
var Sigma = [16]byte{'e', 'x', 'p', 'a', 'n', 'd', ' ', '3', '2', '-', 'b', 'y', 't', 'e', ' ', 'k'}
|
||||
|
||||
// HSalsa20 applies the HSalsa20 core function to a 16-byte input in, 32-byte
|
||||
// key k, and 16-byte constant c, and puts the result into the 32-byte array
|
||||
// out.
|
||||
func HSalsa20(out *[32]byte, in *[16]byte, k *[32]byte, c *[16]byte) {
|
||||
x0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24
|
||||
x1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24
|
||||
x2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24
|
||||
x3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24
|
||||
x4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24
|
||||
x5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24
|
||||
x6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24
|
||||
x7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24
|
||||
x8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24
|
||||
x9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24
|
||||
x10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24
|
||||
x11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24
|
||||
x12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24
|
||||
x13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24
|
||||
x14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24
|
||||
x15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24
|
||||
|
||||
for i := 0; i < 20; i += 2 {
|
||||
u := x0 + x12
|
||||
x4 ^= bits.RotateLeft32(u, 7)
|
||||
u = x4 + x0
|
||||
x8 ^= bits.RotateLeft32(u, 9)
|
||||
u = x8 + x4
|
||||
x12 ^= bits.RotateLeft32(u, 13)
|
||||
u = x12 + x8
|
||||
x0 ^= bits.RotateLeft32(u, 18)
|
||||
|
||||
u = x5 + x1
|
||||
x9 ^= bits.RotateLeft32(u, 7)
|
||||
u = x9 + x5
|
||||
x13 ^= bits.RotateLeft32(u, 9)
|
||||
u = x13 + x9
|
||||
x1 ^= bits.RotateLeft32(u, 13)
|
||||
u = x1 + x13
|
||||
x5 ^= bits.RotateLeft32(u, 18)
|
||||
|
||||
u = x10 + x6
|
||||
x14 ^= bits.RotateLeft32(u, 7)
|
||||
u = x14 + x10
|
||||
x2 ^= bits.RotateLeft32(u, 9)
|
||||
u = x2 + x14
|
||||
x6 ^= bits.RotateLeft32(u, 13)
|
||||
u = x6 + x2
|
||||
x10 ^= bits.RotateLeft32(u, 18)
|
||||
|
||||
u = x15 + x11
|
||||
x3 ^= bits.RotateLeft32(u, 7)
|
||||
u = x3 + x15
|
||||
x7 ^= bits.RotateLeft32(u, 9)
|
||||
u = x7 + x3
|
||||
x11 ^= bits.RotateLeft32(u, 13)
|
||||
u = x11 + x7
|
||||
x15 ^= bits.RotateLeft32(u, 18)
|
||||
|
||||
u = x0 + x3
|
||||
x1 ^= bits.RotateLeft32(u, 7)
|
||||
u = x1 + x0
|
||||
x2 ^= bits.RotateLeft32(u, 9)
|
||||
u = x2 + x1
|
||||
x3 ^= bits.RotateLeft32(u, 13)
|
||||
u = x3 + x2
|
||||
x0 ^= bits.RotateLeft32(u, 18)
|
||||
|
||||
u = x5 + x4
|
||||
x6 ^= bits.RotateLeft32(u, 7)
|
||||
u = x6 + x5
|
||||
x7 ^= bits.RotateLeft32(u, 9)
|
||||
u = x7 + x6
|
||||
x4 ^= bits.RotateLeft32(u, 13)
|
||||
u = x4 + x7
|
||||
x5 ^= bits.RotateLeft32(u, 18)
|
||||
|
||||
u = x10 + x9
|
||||
x11 ^= bits.RotateLeft32(u, 7)
|
||||
u = x11 + x10
|
||||
x8 ^= bits.RotateLeft32(u, 9)
|
||||
u = x8 + x11
|
||||
x9 ^= bits.RotateLeft32(u, 13)
|
||||
u = x9 + x8
|
||||
x10 ^= bits.RotateLeft32(u, 18)
|
||||
|
||||
u = x15 + x14
|
||||
x12 ^= bits.RotateLeft32(u, 7)
|
||||
u = x12 + x15
|
||||
x13 ^= bits.RotateLeft32(u, 9)
|
||||
u = x13 + x12
|
||||
x14 ^= bits.RotateLeft32(u, 13)
|
||||
u = x14 + x13
|
||||
x15 ^= bits.RotateLeft32(u, 18)
|
||||
}
|
||||
out[0] = byte(x0)
|
||||
out[1] = byte(x0 >> 8)
|
||||
out[2] = byte(x0 >> 16)
|
||||
out[3] = byte(x0 >> 24)
|
||||
|
||||
out[4] = byte(x5)
|
||||
out[5] = byte(x5 >> 8)
|
||||
out[6] = byte(x5 >> 16)
|
||||
out[7] = byte(x5 >> 24)
|
||||
|
||||
out[8] = byte(x10)
|
||||
out[9] = byte(x10 >> 8)
|
||||
out[10] = byte(x10 >> 16)
|
||||
out[11] = byte(x10 >> 24)
|
||||
|
||||
out[12] = byte(x15)
|
||||
out[13] = byte(x15 >> 8)
|
||||
out[14] = byte(x15 >> 16)
|
||||
out[15] = byte(x15 >> 24)
|
||||
|
||||
out[16] = byte(x6)
|
||||
out[17] = byte(x6 >> 8)
|
||||
out[18] = byte(x6 >> 16)
|
||||
out[19] = byte(x6 >> 24)
|
||||
|
||||
out[20] = byte(x7)
|
||||
out[21] = byte(x7 >> 8)
|
||||
out[22] = byte(x7 >> 16)
|
||||
out[23] = byte(x7 >> 24)
|
||||
|
||||
out[24] = byte(x8)
|
||||
out[25] = byte(x8 >> 8)
|
||||
out[26] = byte(x8 >> 16)
|
||||
out[27] = byte(x8 >> 24)
|
||||
|
||||
out[28] = byte(x9)
|
||||
out[29] = byte(x9 >> 8)
|
||||
out[30] = byte(x9 >> 16)
|
||||
out[31] = byte(x9 >> 24)
|
||||
}
|
201
vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go
generated
vendored
Normal file
201
vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go
generated
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package salsa
|
||||
|
||||
import "math/bits"
|
||||
|
||||
// Core208 applies the Salsa20/8 core function to the 64-byte array in and puts
|
||||
// the result into the 64-byte array out. The input and output may be the same array.
|
||||
func Core208(out *[64]byte, in *[64]byte) {
|
||||
j0 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24
|
||||
j1 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24
|
||||
j2 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24
|
||||
j3 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24
|
||||
j4 := uint32(in[16]) | uint32(in[17])<<8 | uint32(in[18])<<16 | uint32(in[19])<<24
|
||||
j5 := uint32(in[20]) | uint32(in[21])<<8 | uint32(in[22])<<16 | uint32(in[23])<<24
|
||||
j6 := uint32(in[24]) | uint32(in[25])<<8 | uint32(in[26])<<16 | uint32(in[27])<<24
|
||||
j7 := uint32(in[28]) | uint32(in[29])<<8 | uint32(in[30])<<16 | uint32(in[31])<<24
|
||||
j8 := uint32(in[32]) | uint32(in[33])<<8 | uint32(in[34])<<16 | uint32(in[35])<<24
|
||||
j9 := uint32(in[36]) | uint32(in[37])<<8 | uint32(in[38])<<16 | uint32(in[39])<<24
|
||||
j10 := uint32(in[40]) | uint32(in[41])<<8 | uint32(in[42])<<16 | uint32(in[43])<<24
|
||||
j11 := uint32(in[44]) | uint32(in[45])<<8 | uint32(in[46])<<16 | uint32(in[47])<<24
|
||||
j12 := uint32(in[48]) | uint32(in[49])<<8 | uint32(in[50])<<16 | uint32(in[51])<<24
|
||||
j13 := uint32(in[52]) | uint32(in[53])<<8 | uint32(in[54])<<16 | uint32(in[55])<<24
|
||||
j14 := uint32(in[56]) | uint32(in[57])<<8 | uint32(in[58])<<16 | uint32(in[59])<<24
|
||||
j15 := uint32(in[60]) | uint32(in[61])<<8 | uint32(in[62])<<16 | uint32(in[63])<<24
|
||||
|
||||
x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8
|
||||
x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15
|
||||
|
||||
for i := 0; i < 8; i += 2 {
|
||||
u := x0 + x12
|
||||
x4 ^= bits.RotateLeft32(u, 7)
|
||||
u = x4 + x0
|
||||
x8 ^= bits.RotateLeft32(u, 9)
|
||||
u = x8 + x4
|
||||
x12 ^= bits.RotateLeft32(u, 13)
|
||||
u = x12 + x8
|
||||
x0 ^= bits.RotateLeft32(u, 18)
|
||||
|
||||
u = x5 + x1
|
||||
x9 ^= bits.RotateLeft32(u, 7)
|
||||
u = x9 + x5
|
||||
x13 ^= bits.RotateLeft32(u, 9)
|
||||
u = x13 + x9
|
||||
x1 ^= bits.RotateLeft32(u, 13)
|
||||
u = x1 + x13
|
||||
x5 ^= bits.RotateLeft32(u, 18)
|
||||
|
||||
u = x10 + x6
|
||||
x14 ^= bits.RotateLeft32(u, 7)
|
||||
u = x14 + x10
|
||||
x2 ^= bits.RotateLeft32(u, 9)
|
||||
u = x2 + x14
|
||||
x6 ^= bits.RotateLeft32(u, 13)
|
||||
u = x6 + x2
|
||||
x10 ^= bits.RotateLeft32(u, 18)
|
||||
|
||||
u = x15 + x11
|
||||
x3 ^= bits.RotateLeft32(u, 7)
|
||||
u = x3 + x15
|
||||
x7 ^= bits.RotateLeft32(u, 9)
|
||||
u = x7 + x3
|
||||
x11 ^= bits.RotateLeft32(u, 13)
|
||||
u = x11 + x7
|
||||
x15 ^= bits.RotateLeft32(u, 18)
|
||||
|
||||
u = x0 + x3
|
||||
x1 ^= bits.RotateLeft32(u, 7)
|
||||
u = x1 + x0
|
||||
x2 ^= bits.RotateLeft32(u, 9)
|
||||
u = x2 + x1
|
||||
x3 ^= bits.RotateLeft32(u, 13)
|
||||
u = x3 + x2
|
||||
x0 ^= bits.RotateLeft32(u, 18)
|
||||
|
||||
u = x5 + x4
|
||||
x6 ^= bits.RotateLeft32(u, 7)
|
||||
u = x6 + x5
|
||||
x7 ^= bits.RotateLeft32(u, 9)
|
||||
u = x7 + x6
|
||||
x4 ^= bits.RotateLeft32(u, 13)
|
||||
u = x4 + x7
|
||||
x5 ^= bits.RotateLeft32(u, 18)
|
||||
|
||||
u = x10 + x9
|
||||
x11 ^= bits.RotateLeft32(u, 7)
|
||||
u = x11 + x10
|
||||
x8 ^= bits.RotateLeft32(u, 9)
|
||||
u = x8 + x11
|
||||
x9 ^= bits.RotateLeft32(u, 13)
|
||||
u = x9 + x8
|
||||
x10 ^= bits.RotateLeft32(u, 18)
|
||||
|
||||
u = x15 + x14
|
||||
x12 ^= bits.RotateLeft32(u, 7)
|
||||
u = x12 + x15
|
||||
x13 ^= bits.RotateLeft32(u, 9)
|
||||
u = x13 + x12
|
||||
x14 ^= bits.RotateLeft32(u, 13)
|
||||
u = x14 + x13
|
||||
x15 ^= bits.RotateLeft32(u, 18)
|
||||
}
|
||||
x0 += j0
|
||||
x1 += j1
|
||||
x2 += j2
|
||||
x3 += j3
|
||||
x4 += j4
|
||||
x5 += j5
|
||||
x6 += j6
|
||||
x7 += j7
|
||||
x8 += j8
|
||||
x9 += j9
|
||||
x10 += j10
|
||||
x11 += j11
|
||||
x12 += j12
|
||||
x13 += j13
|
||||
x14 += j14
|
||||
x15 += j15
|
||||
|
||||
out[0] = byte(x0)
|
||||
out[1] = byte(x0 >> 8)
|
||||
out[2] = byte(x0 >> 16)
|
||||
out[3] = byte(x0 >> 24)
|
||||
|
||||
out[4] = byte(x1)
|
||||
out[5] = byte(x1 >> 8)
|
||||
out[6] = byte(x1 >> 16)
|
||||
out[7] = byte(x1 >> 24)
|
||||
|
||||
out[8] = byte(x2)
|
||||
out[9] = byte(x2 >> 8)
|
||||
out[10] = byte(x2 >> 16)
|
||||
out[11] = byte(x2 >> 24)
|
||||
|
||||
out[12] = byte(x3)
|
||||
out[13] = byte(x3 >> 8)
|
||||
out[14] = byte(x3 >> 16)
|
||||
out[15] = byte(x3 >> 24)
|
||||
|
||||
out[16] = byte(x4)
|
||||
out[17] = byte(x4 >> 8)
|
||||
out[18] = byte(x4 >> 16)
|
||||
out[19] = byte(x4 >> 24)
|
||||
|
||||
out[20] = byte(x5)
|
||||
out[21] = byte(x5 >> 8)
|
||||
out[22] = byte(x5 >> 16)
|
||||
out[23] = byte(x5 >> 24)
|
||||
|
||||
out[24] = byte(x6)
|
||||
out[25] = byte(x6 >> 8)
|
||||
out[26] = byte(x6 >> 16)
|
||||
out[27] = byte(x6 >> 24)
|
||||
|
||||
out[28] = byte(x7)
|
||||
out[29] = byte(x7 >> 8)
|
||||
out[30] = byte(x7 >> 16)
|
||||
out[31] = byte(x7 >> 24)
|
||||
|
||||
out[32] = byte(x8)
|
||||
out[33] = byte(x8 >> 8)
|
||||
out[34] = byte(x8 >> 16)
|
||||
out[35] = byte(x8 >> 24)
|
||||
|
||||
out[36] = byte(x9)
|
||||
out[37] = byte(x9 >> 8)
|
||||
out[38] = byte(x9 >> 16)
|
||||
out[39] = byte(x9 >> 24)
|
||||
|
||||
out[40] = byte(x10)
|
||||
out[41] = byte(x10 >> 8)
|
||||
out[42] = byte(x10 >> 16)
|
||||
out[43] = byte(x10 >> 24)
|
||||
|
||||
out[44] = byte(x11)
|
||||
out[45] = byte(x11 >> 8)
|
||||
out[46] = byte(x11 >> 16)
|
||||
out[47] = byte(x11 >> 24)
|
||||
|
||||
out[48] = byte(x12)
|
||||
out[49] = byte(x12 >> 8)
|
||||
out[50] = byte(x12 >> 16)
|
||||
out[51] = byte(x12 >> 24)
|
||||
|
||||
out[52] = byte(x13)
|
||||
out[53] = byte(x13 >> 8)
|
||||
out[54] = byte(x13 >> 16)
|
||||
out[55] = byte(x13 >> 24)
|
||||
|
||||
out[56] = byte(x14)
|
||||
out[57] = byte(x14 >> 8)
|
||||
out[58] = byte(x14 >> 16)
|
||||
out[59] = byte(x14 >> 24)
|
||||
|
||||
out[60] = byte(x15)
|
||||
out[61] = byte(x15 >> 8)
|
||||
out[62] = byte(x15 >> 16)
|
||||
out[63] = byte(x15 >> 24)
|
||||
}
|
24
vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go
generated
vendored
Normal file
24
vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build amd64 && !purego && gc
|
||||
// +build amd64,!purego,gc
|
||||
|
||||
package salsa
|
||||
|
||||
//go:noescape
|
||||
|
||||
// salsa2020XORKeyStream is implemented in salsa20_amd64.s.
|
||||
func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte)
|
||||
|
||||
// XORKeyStream crypts bytes from in to out using the given key and counters.
|
||||
// In and out must overlap entirely or not at all. Counter
|
||||
// contains the raw salsa20 counter bytes (both nonce and block counter).
|
||||
func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
|
||||
if len(in) == 0 {
|
||||
return
|
||||
}
|
||||
_ = out[len(in)-1]
|
||||
salsa2020XORKeyStream(&out[0], &in[0], uint64(len(in)), &counter[0], &key[0])
|
||||
}
|
881
vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s
generated
vendored
Normal file
881
vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s
generated
vendored
Normal file
@ -0,0 +1,881 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build amd64 && !purego && gc
|
||||
// +build amd64,!purego,gc
|
||||
|
||||
// This code was translated into a form compatible with 6a from the public
|
||||
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
|
||||
|
||||
// func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte)
|
||||
// This needs up to 64 bytes at 360(R12); hence the non-obvious frame size.
|
||||
TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment
|
||||
MOVQ out+0(FP),DI
|
||||
MOVQ in+8(FP),SI
|
||||
MOVQ n+16(FP),DX
|
||||
MOVQ nonce+24(FP),CX
|
||||
MOVQ key+32(FP),R8
|
||||
|
||||
MOVQ SP,R12
|
||||
ADDQ $31, R12
|
||||
ANDQ $~31, R12
|
||||
|
||||
MOVQ DX,R9
|
||||
MOVQ CX,DX
|
||||
MOVQ R8,R10
|
||||
CMPQ R9,$0
|
||||
JBE DONE
|
||||
START:
|
||||
MOVL 20(R10),CX
|
||||
MOVL 0(R10),R8
|
||||
MOVL 0(DX),AX
|
||||
MOVL 16(R10),R11
|
||||
MOVL CX,0(R12)
|
||||
MOVL R8, 4 (R12)
|
||||
MOVL AX, 8 (R12)
|
||||
MOVL R11, 12 (R12)
|
||||
MOVL 8(DX),CX
|
||||
MOVL 24(R10),R8
|
||||
MOVL 4(R10),AX
|
||||
MOVL 4(DX),R11
|
||||
MOVL CX,16(R12)
|
||||
MOVL R8, 20 (R12)
|
||||
MOVL AX, 24 (R12)
|
||||
MOVL R11, 28 (R12)
|
||||
MOVL 12(DX),CX
|
||||
MOVL 12(R10),DX
|
||||
MOVL 28(R10),R8
|
||||
MOVL 8(R10),AX
|
||||
MOVL DX,32(R12)
|
||||
MOVL CX, 36 (R12)
|
||||
MOVL R8, 40 (R12)
|
||||
MOVL AX, 44 (R12)
|
||||
MOVQ $1634760805,DX
|
||||
MOVQ $857760878,CX
|
||||
MOVQ $2036477234,R8
|
||||
MOVQ $1797285236,AX
|
||||
MOVL DX,48(R12)
|
||||
MOVL CX, 52 (R12)
|
||||
MOVL R8, 56 (R12)
|
||||
MOVL AX, 60 (R12)
|
||||
CMPQ R9,$256
|
||||
JB BYTESBETWEEN1AND255
|
||||
MOVOA 48(R12),X0
|
||||
PSHUFL $0X55,X0,X1
|
||||
PSHUFL $0XAA,X0,X2
|
||||
PSHUFL $0XFF,X0,X3
|
||||
PSHUFL $0X00,X0,X0
|
||||
MOVOA X1,64(R12)
|
||||
MOVOA X2,80(R12)
|
||||
MOVOA X3,96(R12)
|
||||
MOVOA X0,112(R12)
|
||||
MOVOA 0(R12),X0
|
||||
PSHUFL $0XAA,X0,X1
|
||||
PSHUFL $0XFF,X0,X2
|
||||
PSHUFL $0X00,X0,X3
|
||||
PSHUFL $0X55,X0,X0
|
||||
MOVOA X1,128(R12)
|
||||
MOVOA X2,144(R12)
|
||||
MOVOA X3,160(R12)
|
||||
MOVOA X0,176(R12)
|
||||
MOVOA 16(R12),X0
|
||||
PSHUFL $0XFF,X0,X1
|
||||
PSHUFL $0X55,X0,X2
|
||||
PSHUFL $0XAA,X0,X0
|
||||
MOVOA X1,192(R12)
|
||||
MOVOA X2,208(R12)
|
||||
MOVOA X0,224(R12)
|
||||
MOVOA 32(R12),X0
|
||||
PSHUFL $0X00,X0,X1
|
||||
PSHUFL $0XAA,X0,X2
|
||||
PSHUFL $0XFF,X0,X0
|
||||
MOVOA X1,240(R12)
|
||||
MOVOA X2,256(R12)
|
||||
MOVOA X0,272(R12)
|
||||
BYTESATLEAST256:
|
||||
MOVL 16(R12),DX
|
||||
MOVL 36 (R12),CX
|
||||
MOVL DX,288(R12)
|
||||
MOVL CX,304(R12)
|
||||
SHLQ $32,CX
|
||||
ADDQ CX,DX
|
||||
ADDQ $1,DX
|
||||
MOVQ DX,CX
|
||||
SHRQ $32,CX
|
||||
MOVL DX, 292 (R12)
|
||||
MOVL CX, 308 (R12)
|
||||
ADDQ $1,DX
|
||||
MOVQ DX,CX
|
||||
SHRQ $32,CX
|
||||
MOVL DX, 296 (R12)
|
||||
MOVL CX, 312 (R12)
|
||||
ADDQ $1,DX
|
||||
MOVQ DX,CX
|
||||
SHRQ $32,CX
|
||||
MOVL DX, 300 (R12)
|
||||
MOVL CX, 316 (R12)
|
||||
ADDQ $1,DX
|
||||
MOVQ DX,CX
|
||||
SHRQ $32,CX
|
||||
MOVL DX,16(R12)
|
||||
MOVL CX, 36 (R12)
|
||||
MOVQ R9,352(R12)
|
||||
MOVQ $20,DX
|
||||
MOVOA 64(R12),X0
|
||||
MOVOA 80(R12),X1
|
||||
MOVOA 96(R12),X2
|
||||
MOVOA 256(R12),X3
|
||||
MOVOA 272(R12),X4
|
||||
MOVOA 128(R12),X5
|
||||
MOVOA 144(R12),X6
|
||||
MOVOA 176(R12),X7
|
||||
MOVOA 192(R12),X8
|
||||
MOVOA 208(R12),X9
|
||||
MOVOA 224(R12),X10
|
||||
MOVOA 304(R12),X11
|
||||
MOVOA 112(R12),X12
|
||||
MOVOA 160(R12),X13
|
||||
MOVOA 240(R12),X14
|
||||
MOVOA 288(R12),X15
|
||||
MAINLOOP1:
|
||||
MOVOA X1,320(R12)
|
||||
MOVOA X2,336(R12)
|
||||
MOVOA X13,X1
|
||||
PADDL X12,X1
|
||||
MOVOA X1,X2
|
||||
PSLLL $7,X1
|
||||
PXOR X1,X14
|
||||
PSRLL $25,X2
|
||||
PXOR X2,X14
|
||||
MOVOA X7,X1
|
||||
PADDL X0,X1
|
||||
MOVOA X1,X2
|
||||
PSLLL $7,X1
|
||||
PXOR X1,X11
|
||||
PSRLL $25,X2
|
||||
PXOR X2,X11
|
||||
MOVOA X12,X1
|
||||
PADDL X14,X1
|
||||
MOVOA X1,X2
|
||||
PSLLL $9,X1
|
||||
PXOR X1,X15
|
||||
PSRLL $23,X2
|
||||
PXOR X2,X15
|
||||
MOVOA X0,X1
|
||||
PADDL X11,X1
|
||||
MOVOA X1,X2
|
||||
PSLLL $9,X1
|
||||
PXOR X1,X9
|
||||
PSRLL $23,X2
|
||||
PXOR X2,X9
|
||||
MOVOA X14,X1
|
||||
PADDL X15,X1
|
||||
MOVOA X1,X2
|
||||
PSLLL $13,X1
|
||||
PXOR X1,X13
|
||||
PSRLL $19,X2
|
||||
PXOR X2,X13
|
||||
MOVOA X11,X1
|
||||
PADDL X9,X1
|
||||
MOVOA X1,X2
|
||||
PSLLL $13,X1
|
||||
PXOR X1,X7
|
||||
PSRLL $19,X2
|
||||
PXOR X2,X7
|
||||
MOVOA X15,X1
|
||||
PADDL X13,X1
|
||||
MOVOA X1,X2
|
||||
PSLLL $18,X1
|
||||
PXOR X1,X12
|
||||
PSRLL $14,X2
|
||||
PXOR X2,X12
|
||||
MOVOA 320(R12),X1
|
||||
MOVOA X12,320(R12)
|
||||
MOVOA X9,X2
|
||||
PADDL X7,X2
|
||||
MOVOA X2,X12
|
||||
PSLLL $18,X2
|
||||
PXOR X2,X0
|
||||
PSRLL $14,X12
|
||||
PXOR X12,X0
|
||||
MOVOA X5,X2
|
||||
PADDL X1,X2
|
||||
MOVOA X2,X12
|
||||
PSLLL $7,X2
|
||||
PXOR X2,X3
|
||||
PSRLL $25,X12
|
||||
PXOR X12,X3
|
||||
MOVOA 336(R12),X2
|
||||
MOVOA X0,336(R12)
|
||||
MOVOA X6,X0
|
||||
PADDL X2,X0
|
||||
MOVOA X0,X12
|
||||
PSLLL $7,X0
|
||||
PXOR X0,X4
|
||||
PSRLL $25,X12
|
||||
PXOR X12,X4
|
||||
MOVOA X1,X0
|
||||
PADDL X3,X0
|
||||
MOVOA X0,X12
|
||||
PSLLL $9,X0
|
||||
PXOR X0,X10
|
||||
PSRLL $23,X12
|
||||
PXOR X12,X10
|
||||
MOVOA X2,X0
|
||||
PADDL X4,X0
|
||||
MOVOA X0,X12
|
||||
PSLLL $9,X0
|
||||
PXOR X0,X8
|
||||
PSRLL $23,X12
|
||||
PXOR X12,X8
|
||||
MOVOA X3,X0
|
||||
PADDL X10,X0
|
||||
MOVOA X0,X12
|
||||
PSLLL $13,X0
|
||||
PXOR X0,X5
|
||||
PSRLL $19,X12
|
||||
PXOR X12,X5
|
||||
MOVOA X4,X0
|
||||
PADDL X8,X0
|
||||
MOVOA X0,X12
|
||||
PSLLL $13,X0
|
||||
PXOR X0,X6
|
||||
PSRLL $19,X12
|
||||
PXOR X12,X6
|
||||
MOVOA X10,X0
|
||||
PADDL X5,X0
|
||||
MOVOA X0,X12
|
||||
PSLLL $18,X0
|
||||
PXOR X0,X1
|
||||
PSRLL $14,X12
|
||||
PXOR X12,X1
|
||||
MOVOA 320(R12),X0
|
||||
MOVOA X1,320(R12)
|
||||
MOVOA X4,X1
|
||||
PADDL X0,X1
|
||||
MOVOA X1,X12
|
||||
PSLLL $7,X1
|
||||
PXOR X1,X7
|
||||
PSRLL $25,X12
|
||||
PXOR X12,X7
|
||||
MOVOA X8,X1
|
||||
PADDL X6,X1
|
||||
MOVOA X1,X12
|
||||
PSLLL $18,X1
|
||||
PXOR X1,X2
|
||||
PSRLL $14,X12
|
||||
PXOR X12,X2
|
||||
MOVOA 336(R12),X12
|
||||
MOVOA X2,336(R12)
|
||||
MOVOA X14,X1
|
||||
PADDL X12,X1
|
||||
MOVOA X1,X2
|
||||
PSLLL $7,X1
|
||||
PXOR X1,X5
|
||||
PSRLL $25,X2
|
||||
PXOR X2,X5
|
||||
MOVOA X0,X1
|
||||
PADDL X7,X1
|
||||
MOVOA X1,X2
|
||||
PSLLL $9,X1
|
||||
PXOR X1,X10
|
||||
PSRLL $23,X2
|
||||
PXOR X2,X10
|
||||
MOVOA X12,X1
|
||||
PADDL X5,X1
|
||||
MOVOA X1,X2
|
||||
PSLLL $9,X1
|
||||
PXOR X1,X8
|
||||
PSRLL $23,X2
|
||||
PXOR X2,X8
|
||||
MOVOA X7,X1
|
||||
PADDL X10,X1
|
||||
MOVOA X1,X2
|
||||
PSLLL $13,X1
|
||||
PXOR X1,X4
|
||||
PSRLL $19,X2
|
||||
PXOR X2,X4
|
||||
MOVOA X5,X1
|
||||
PADDL X8,X1
|
||||
MOVOA X1,X2
|
||||
PSLLL $13,X1
|
||||
PXOR X1,X14
|
||||
PSRLL $19,X2
|
||||
PXOR X2,X14
|
||||
MOVOA X10,X1
|
||||
PADDL X4,X1
|
||||
MOVOA X1,X2
|
||||
PSLLL $18,X1
|
||||
PXOR X1,X0
|
||||
PSRLL $14,X2
|
||||
PXOR X2,X0
|
||||
MOVOA 320(R12),X1
|
||||
MOVOA X0,320(R12)
|
||||
MOVOA X8,X0
|
||||
PADDL X14,X0
|
||||
MOVOA X0,X2
|
||||
PSLLL $18,X0
|
||||
PXOR X0,X12
|
||||
PSRLL $14,X2
|
||||
PXOR X2,X12
|
||||
MOVOA X11,X0
|
||||
PADDL X1,X0
|
||||
MOVOA X0,X2
|
||||
PSLLL $7,X0
|
||||
PXOR X0,X6
|
||||
PSRLL $25,X2
|
||||
PXOR X2,X6
|
||||
MOVOA 336(R12),X2
|
||||
MOVOA X12,336(R12)
|
||||
MOVOA X3,X0
|
||||
PADDL X2,X0
|
||||
MOVOA X0,X12
|
||||
PSLLL $7,X0
|
||||
PXOR X0,X13
|
||||
PSRLL $25,X12
|
||||
PXOR X12,X13
|
||||
MOVOA X1,X0
|
||||
PADDL X6,X0
|
||||
MOVOA X0,X12
|
||||
PSLLL $9,X0
|
||||
PXOR X0,X15
|
||||
PSRLL $23,X12
|
||||
PXOR X12,X15
|
||||
MOVOA X2,X0
|
||||
PADDL X13,X0
|
||||
MOVOA X0,X12
|
||||
PSLLL $9,X0
|
||||
PXOR X0,X9
|
||||
PSRLL $23,X12
|
||||
PXOR X12,X9
|
||||
MOVOA X6,X0
|
||||
PADDL X15,X0
|
||||
MOVOA X0,X12
|
||||
PSLLL $13,X0
|
||||
PXOR X0,X11
|
||||
PSRLL $19,X12
|
||||
PXOR X12,X11
|
||||
MOVOA X13,X0
|
||||
PADDL X9,X0
|
||||
MOVOA X0,X12
|
||||
PSLLL $13,X0
|
||||
PXOR X0,X3
|
||||
PSRLL $19,X12
|
||||
PXOR X12,X3
|
||||
MOVOA X15,X0
|
||||
PADDL X11,X0
|
||||
MOVOA X0,X12
|
||||
PSLLL $18,X0
|
||||
PXOR X0,X1
|
||||
PSRLL $14,X12
|
||||
PXOR X12,X1
|
||||
MOVOA X9,X0
|
||||
PADDL X3,X0
|
||||
MOVOA X0,X12
|
||||
PSLLL $18,X0
|
||||
PXOR X0,X2
|
||||
PSRLL $14,X12
|
||||
PXOR X12,X2
|
||||
MOVOA 320(R12),X12
|
||||
MOVOA 336(R12),X0
|
||||
SUBQ $2,DX
|
||||
JA MAINLOOP1
|
||||
PADDL 112(R12),X12
|
||||
PADDL 176(R12),X7
|
||||
PADDL 224(R12),X10
|
||||
PADDL 272(R12),X4
|
||||
MOVD X12,DX
|
||||
MOVD X7,CX
|
||||
MOVD X10,R8
|
||||
MOVD X4,R9
|
||||
PSHUFL $0X39,X12,X12
|
||||
PSHUFL $0X39,X7,X7
|
||||
PSHUFL $0X39,X10,X10
|
||||
PSHUFL $0X39,X4,X4
|
||||
XORL 0(SI),DX
|
||||
XORL 4(SI),CX
|
||||
XORL 8(SI),R8
|
||||
XORL 12(SI),R9
|
||||
MOVL DX,0(DI)
|
||||
MOVL CX,4(DI)
|
||||
MOVL R8,8(DI)
|
||||
MOVL R9,12(DI)
|
||||
MOVD X12,DX
|
||||
MOVD X7,CX
|
||||
MOVD X10,R8
|
||||
MOVD X4,R9
|
||||
PSHUFL $0X39,X12,X12
|
||||
PSHUFL $0X39,X7,X7
|
||||
PSHUFL $0X39,X10,X10
|
||||
PSHUFL $0X39,X4,X4
|
||||
XORL 64(SI),DX
|
||||
XORL 68(SI),CX
|
||||
XORL 72(SI),R8
|
||||
XORL 76(SI),R9
|
||||
MOVL DX,64(DI)
|
||||
MOVL CX,68(DI)
|
||||
MOVL R8,72(DI)
|
||||
MOVL R9,76(DI)
|
||||
MOVD X12,DX
|
||||
MOVD X7,CX
|
||||
MOVD X10,R8
|
||||
MOVD X4,R9
|
||||
PSHUFL $0X39,X12,X12
|
||||
PSHUFL $0X39,X7,X7
|
||||
PSHUFL $0X39,X10,X10
|
||||
PSHUFL $0X39,X4,X4
|
||||
XORL 128(SI),DX
|
||||
XORL 132(SI),CX
|
||||
XORL 136(SI),R8
|
||||
XORL 140(SI),R9
|
||||
MOVL DX,128(DI)
|
||||
MOVL CX,132(DI)
|
||||
MOVL R8,136(DI)
|
||||
MOVL R9,140(DI)
|
||||
MOVD X12,DX
|
||||
MOVD X7,CX
|
||||
MOVD X10,R8
|
||||
MOVD X4,R9
|
||||
XORL 192(SI),DX
|
||||
XORL 196(SI),CX
|
||||
XORL 200(SI),R8
|
||||
XORL 204(SI),R9
|
||||
MOVL DX,192(DI)
|
||||
MOVL CX,196(DI)
|
||||
MOVL R8,200(DI)
|
||||
MOVL R9,204(DI)
|
||||
PADDL 240(R12),X14
|
||||
PADDL 64(R12),X0
|
||||
PADDL 128(R12),X5
|
||||
PADDL 192(R12),X8
|
||||
MOVD X14,DX
|
||||
MOVD X0,CX
|
||||
MOVD X5,R8
|
||||
MOVD X8,R9
|
||||
PSHUFL $0X39,X14,X14
|
||||
PSHUFL $0X39,X0,X0
|
||||
PSHUFL $0X39,X5,X5
|
||||
PSHUFL $0X39,X8,X8
|
||||
XORL 16(SI),DX
|
||||
XORL 20(SI),CX
|
||||
XORL 24(SI),R8
|
||||
XORL 28(SI),R9
|
||||
MOVL DX,16(DI)
|
||||
MOVL CX,20(DI)
|
||||
MOVL R8,24(DI)
|
||||
MOVL R9,28(DI)
|
||||
MOVD X14,DX
|
||||
MOVD X0,CX
|
||||
MOVD X5,R8
|
||||
MOVD X8,R9
|
||||
PSHUFL $0X39,X14,X14
|
||||
PSHUFL $0X39,X0,X0
|
||||
PSHUFL $0X39,X5,X5
|
||||
PSHUFL $0X39,X8,X8
|
||||
XORL 80(SI),DX
|
||||
XORL 84(SI),CX
|
||||
XORL 88(SI),R8
|
||||
XORL 92(SI),R9
|
||||
MOVL DX,80(DI)
|
||||
MOVL CX,84(DI)
|
||||
MOVL R8,88(DI)
|
||||
MOVL R9,92(DI)
|
||||
MOVD X14,DX
|
||||
MOVD X0,CX
|
||||
MOVD X5,R8
|
||||
MOVD X8,R9
|
||||
PSHUFL $0X39,X14,X14
|
||||
PSHUFL $0X39,X0,X0
|
||||
PSHUFL $0X39,X5,X5
|
||||
PSHUFL $0X39,X8,X8
|
||||
XORL 144(SI),DX
|
||||
XORL 148(SI),CX
|
||||
XORL 152(SI),R8
|
||||
XORL 156(SI),R9
|
||||
MOVL DX,144(DI)
|
||||
MOVL CX,148(DI)
|
||||
MOVL R8,152(DI)
|
||||
MOVL R9,156(DI)
|
||||
MOVD X14,DX
|
||||
MOVD X0,CX
|
||||
MOVD X5,R8
|
||||
MOVD X8,R9
|
||||
XORL 208(SI),DX
|
||||
XORL 212(SI),CX
|
||||
XORL 216(SI),R8
|
||||
XORL 220(SI),R9
|
||||
MOVL DX,208(DI)
|
||||
MOVL CX,212(DI)
|
||||
MOVL R8,216(DI)
|
||||
MOVL R9,220(DI)
|
||||
PADDL 288(R12),X15
|
||||
PADDL 304(R12),X11
|
||||
PADDL 80(R12),X1
|
||||
PADDL 144(R12),X6
|
||||
MOVD X15,DX
|
||||
MOVD X11,CX
|
||||
MOVD X1,R8
|
||||
MOVD X6,R9
|
||||
PSHUFL $0X39,X15,X15
|
||||
PSHUFL $0X39,X11,X11
|
||||
PSHUFL $0X39,X1,X1
|
||||
PSHUFL $0X39,X6,X6
|
||||
XORL 32(SI),DX
|
||||
XORL 36(SI),CX
|
||||
XORL 40(SI),R8
|
||||
XORL 44(SI),R9
|
||||
MOVL DX,32(DI)
|
||||
MOVL CX,36(DI)
|
||||
MOVL R8,40(DI)
|
||||
MOVL R9,44(DI)
|
||||
MOVD X15,DX
|
||||
MOVD X11,CX
|
||||
MOVD X1,R8
|
||||
MOVD X6,R9
|
||||
PSHUFL $0X39,X15,X15
|
||||
PSHUFL $0X39,X11,X11
|
||||
PSHUFL $0X39,X1,X1
|
||||
PSHUFL $0X39,X6,X6
|
||||
XORL 96(SI),DX
|
||||
XORL 100(SI),CX
|
||||
XORL 104(SI),R8
|
||||
XORL 108(SI),R9
|
||||
MOVL DX,96(DI)
|
||||
MOVL CX,100(DI)
|
||||
MOVL R8,104(DI)
|
||||
MOVL R9,108(DI)
|
||||
MOVD X15,DX
|
||||
MOVD X11,CX
|
||||
MOVD X1,R8
|
||||
MOVD X6,R9
|
||||
PSHUFL $0X39,X15,X15
|
||||
PSHUFL $0X39,X11,X11
|
||||
PSHUFL $0X39,X1,X1
|
||||
PSHUFL $0X39,X6,X6
|
||||
XORL 160(SI),DX
|
||||
XORL 164(SI),CX
|
||||
XORL 168(SI),R8
|
||||
XORL 172(SI),R9
|
||||
MOVL DX,160(DI)
|
||||
MOVL CX,164(DI)
|
||||
MOVL R8,168(DI)
|
||||
MOVL R9,172(DI)
|
||||
MOVD X15,DX
|
||||
MOVD X11,CX
|
||||
MOVD X1,R8
|
||||
MOVD X6,R9
|
||||
XORL 224(SI),DX
|
||||
XORL 228(SI),CX
|
||||
XORL 232(SI),R8
|
||||
XORL 236(SI),R9
|
||||
MOVL DX,224(DI)
|
||||
MOVL CX,228(DI)
|
||||
MOVL R8,232(DI)
|
||||
MOVL R9,236(DI)
|
||||
PADDL 160(R12),X13
|
||||
PADDL 208(R12),X9
|
||||
PADDL 256(R12),X3
|
||||
PADDL 96(R12),X2
|
||||
MOVD X13,DX
|
||||
MOVD X9,CX
|
||||
MOVD X3,R8
|
||||
MOVD X2,R9
|
||||
PSHUFL $0X39,X13,X13
|
||||
PSHUFL $0X39,X9,X9
|
||||
PSHUFL $0X39,X3,X3
|
||||
PSHUFL $0X39,X2,X2
|
||||
XORL 48(SI),DX
|
||||
XORL 52(SI),CX
|
||||
XORL 56(SI),R8
|
||||
XORL 60(SI),R9
|
||||
MOVL DX,48(DI)
|
||||
MOVL CX,52(DI)
|
||||
MOVL R8,56(DI)
|
||||
MOVL R9,60(DI)
|
||||
MOVD X13,DX
|
||||
MOVD X9,CX
|
||||
MOVD X3,R8
|
||||
MOVD X2,R9
|
||||
PSHUFL $0X39,X13,X13
|
||||
PSHUFL $0X39,X9,X9
|
||||
PSHUFL $0X39,X3,X3
|
||||
PSHUFL $0X39,X2,X2
|
||||
XORL 112(SI),DX
|
||||
XORL 116(SI),CX
|
||||
XORL 120(SI),R8
|
||||
XORL 124(SI),R9
|
||||
MOVL DX,112(DI)
|
||||
MOVL CX,116(DI)
|
||||
MOVL R8,120(DI)
|
||||
MOVL R9,124(DI)
|
||||
MOVD X13,DX
|
||||
MOVD X9,CX
|
||||
MOVD X3,R8
|
||||
MOVD X2,R9
|
||||
PSHUFL $0X39,X13,X13
|
||||
PSHUFL $0X39,X9,X9
|
||||
PSHUFL $0X39,X3,X3
|
||||
PSHUFL $0X39,X2,X2
|
||||
XORL 176(SI),DX
|
||||
XORL 180(SI),CX
|
||||
XORL 184(SI),R8
|
||||
XORL 188(SI),R9
|
||||
MOVL DX,176(DI)
|
||||
MOVL CX,180(DI)
|
||||
MOVL R8,184(DI)
|
||||
MOVL R9,188(DI)
|
||||
MOVD X13,DX
|
||||
MOVD X9,CX
|
||||
MOVD X3,R8
|
||||
MOVD X2,R9
|
||||
XORL 240(SI),DX
|
||||
XORL 244(SI),CX
|
||||
XORL 248(SI),R8
|
||||
XORL 252(SI),R9
|
||||
MOVL DX,240(DI)
|
||||
MOVL CX,244(DI)
|
||||
MOVL R8,248(DI)
|
||||
MOVL R9,252(DI)
|
||||
MOVQ 352(R12),R9
|
||||
SUBQ $256,R9
|
||||
ADDQ $256,SI
|
||||
ADDQ $256,DI
|
||||
CMPQ R9,$256
|
||||
JAE BYTESATLEAST256
|
||||
CMPQ R9,$0
|
||||
JBE DONE
|
||||
BYTESBETWEEN1AND255:
|
||||
CMPQ R9,$64
|
||||
JAE NOCOPY
|
||||
MOVQ DI,DX
|
||||
LEAQ 360(R12),DI
|
||||
MOVQ R9,CX
|
||||
REP; MOVSB
|
||||
LEAQ 360(R12),DI
|
||||
LEAQ 360(R12),SI
|
||||
NOCOPY:
|
||||
MOVQ R9,352(R12)
|
||||
MOVOA 48(R12),X0
|
||||
MOVOA 0(R12),X1
|
||||
MOVOA 16(R12),X2
|
||||
MOVOA 32(R12),X3
|
||||
MOVOA X1,X4
|
||||
MOVQ $20,CX
|
||||
MAINLOOP2:
|
||||
PADDL X0,X4
|
||||
MOVOA X0,X5
|
||||
MOVOA X4,X6
|
||||
PSLLL $7,X4
|
||||
PSRLL $25,X6
|
||||
PXOR X4,X3
|
||||
PXOR X6,X3
|
||||
PADDL X3,X5
|
||||
MOVOA X3,X4
|
||||
MOVOA X5,X6
|
||||
PSLLL $9,X5
|
||||
PSRLL $23,X6
|
||||
PXOR X5,X2
|
||||
PSHUFL $0X93,X3,X3
|
||||
PXOR X6,X2
|
||||
PADDL X2,X4
|
||||
MOVOA X2,X5
|
||||
MOVOA X4,X6
|
||||
PSLLL $13,X4
|
||||
PSRLL $19,X6
|
||||
PXOR X4,X1
|
||||
PSHUFL $0X4E,X2,X2
|
||||
PXOR X6,X1
|
||||
PADDL X1,X5
|
||||
MOVOA X3,X4
|
||||
MOVOA X5,X6
|
||||
PSLLL $18,X5
|
||||
PSRLL $14,X6
|
||||
PXOR X5,X0
|
||||
PSHUFL $0X39,X1,X1
|
||||
PXOR X6,X0
|
||||
PADDL X0,X4
|
||||
MOVOA X0,X5
|
||||
MOVOA X4,X6
|
||||
PSLLL $7,X4
|
||||
PSRLL $25,X6
|
||||
PXOR X4,X1
|
||||
PXOR X6,X1
|
||||
PADDL X1,X5
|
||||
MOVOA X1,X4
|
||||
MOVOA X5,X6
|
||||
PSLLL $9,X5
|
||||
PSRLL $23,X6
|
||||
PXOR X5,X2
|
||||
PSHUFL $0X93,X1,X1
|
||||
PXOR X6,X2
|
||||
PADDL X2,X4
|
||||
MOVOA X2,X5
|
||||
MOVOA X4,X6
|
||||
PSLLL $13,X4
|
||||
PSRLL $19,X6
|
||||
PXOR X4,X3
|
||||
PSHUFL $0X4E,X2,X2
|
||||
PXOR X6,X3
|
||||
PADDL X3,X5
|
||||
MOVOA X1,X4
|
||||
MOVOA X5,X6
|
||||
PSLLL $18,X5
|
||||
PSRLL $14,X6
|
||||
PXOR X5,X0
|
||||
PSHUFL $0X39,X3,X3
|
||||
PXOR X6,X0
|
||||
PADDL X0,X4
|
||||
MOVOA X0,X5
|
||||
MOVOA X4,X6
|
||||
PSLLL $7,X4
|
||||
PSRLL $25,X6
|
||||
PXOR X4,X3
|
||||
PXOR X6,X3
|
||||
PADDL X3,X5
|
||||
MOVOA X3,X4
|
||||
MOVOA X5,X6
|
||||
PSLLL $9,X5
|
||||
PSRLL $23,X6
|
||||
PXOR X5,X2
|
||||
PSHUFL $0X93,X3,X3
|
||||
PXOR X6,X2
|
||||
PADDL X2,X4
|
||||
MOVOA X2,X5
|
||||
MOVOA X4,X6
|
||||
PSLLL $13,X4
|
||||
PSRLL $19,X6
|
||||
PXOR X4,X1
|
||||
PSHUFL $0X4E,X2,X2
|
||||
PXOR X6,X1
|
||||
PADDL X1,X5
|
||||
MOVOA X3,X4
|
||||
MOVOA X5,X6
|
||||
PSLLL $18,X5
|
||||
PSRLL $14,X6
|
||||
PXOR X5,X0
|
||||
PSHUFL $0X39,X1,X1
|
||||
PXOR X6,X0
|
||||
PADDL X0,X4
|
||||
MOVOA X0,X5
|
||||
MOVOA X4,X6
|
||||
PSLLL $7,X4
|
||||
PSRLL $25,X6
|
||||
PXOR X4,X1
|
||||
PXOR X6,X1
|
||||
PADDL X1,X5
|
||||
MOVOA X1,X4
|
||||
MOVOA X5,X6
|
||||
PSLLL $9,X5
|
||||
PSRLL $23,X6
|
||||
PXOR X5,X2
|
||||
PSHUFL $0X93,X1,X1
|
||||
PXOR X6,X2
|
||||
PADDL X2,X4
|
||||
MOVOA X2,X5
|
||||
MOVOA X4,X6
|
||||
PSLLL $13,X4
|
||||
PSRLL $19,X6
|
||||
PXOR X4,X3
|
||||
PSHUFL $0X4E,X2,X2
|
||||
PXOR X6,X3
|
||||
SUBQ $4,CX
|
||||
PADDL X3,X5
|
||||
MOVOA X1,X4
|
||||
MOVOA X5,X6
|
||||
PSLLL $18,X5
|
||||
PXOR X7,X7
|
||||
PSRLL $14,X6
|
||||
PXOR X5,X0
|
||||
PSHUFL $0X39,X3,X3
|
||||
PXOR X6,X0
|
||||
JA MAINLOOP2
|
||||
PADDL 48(R12),X0
|
||||
PADDL 0(R12),X1
|
||||
PADDL 16(R12),X2
|
||||
PADDL 32(R12),X3
|
||||
MOVD X0,CX
|
||||
MOVD X1,R8
|
||||
MOVD X2,R9
|
||||
MOVD X3,AX
|
||||
PSHUFL $0X39,X0,X0
|
||||
PSHUFL $0X39,X1,X1
|
||||
PSHUFL $0X39,X2,X2
|
||||
PSHUFL $0X39,X3,X3
|
||||
XORL 0(SI),CX
|
||||
XORL 48(SI),R8
|
||||
XORL 32(SI),R9
|
||||
XORL 16(SI),AX
|
||||
MOVL CX,0(DI)
|
||||
MOVL R8,48(DI)
|
||||
MOVL R9,32(DI)
|
||||
MOVL AX,16(DI)
|
||||
MOVD X0,CX
|
||||
MOVD X1,R8
|
||||
MOVD X2,R9
|
||||
MOVD X3,AX
|
||||
PSHUFL $0X39,X0,X0
|
||||
PSHUFL $0X39,X1,X1
|
||||
PSHUFL $0X39,X2,X2
|
||||
PSHUFL $0X39,X3,X3
|
||||
XORL 20(SI),CX
|
||||
XORL 4(SI),R8
|
||||
XORL 52(SI),R9
|
||||
XORL 36(SI),AX
|
||||
MOVL CX,20(DI)
|
||||
MOVL R8,4(DI)
|
||||
MOVL R9,52(DI)
|
||||
MOVL AX,36(DI)
|
||||
MOVD X0,CX
|
||||
MOVD X1,R8
|
||||
MOVD X2,R9
|
||||
MOVD X3,AX
|
||||
PSHUFL $0X39,X0,X0
|
||||
PSHUFL $0X39,X1,X1
|
||||
PSHUFL $0X39,X2,X2
|
||||
PSHUFL $0X39,X3,X3
|
||||
XORL 40(SI),CX
|
||||
XORL 24(SI),R8
|
||||
XORL 8(SI),R9
|
||||
XORL 56(SI),AX
|
||||
MOVL CX,40(DI)
|
||||
MOVL R8,24(DI)
|
||||
MOVL R9,8(DI)
|
||||
MOVL AX,56(DI)
|
||||
MOVD X0,CX
|
||||
MOVD X1,R8
|
||||
MOVD X2,R9
|
||||
MOVD X3,AX
|
||||
XORL 60(SI),CX
|
||||
XORL 44(SI),R8
|
||||
XORL 28(SI),R9
|
||||
XORL 12(SI),AX
|
||||
MOVL CX,60(DI)
|
||||
MOVL R8,44(DI)
|
||||
MOVL R9,28(DI)
|
||||
MOVL AX,12(DI)
|
||||
MOVQ 352(R12),R9
|
||||
MOVL 16(R12),CX
|
||||
MOVL 36 (R12),R8
|
||||
ADDQ $1,CX
|
||||
SHLQ $32,R8
|
||||
ADDQ R8,CX
|
||||
MOVQ CX,R8
|
||||
SHRQ $32,R8
|
||||
MOVL CX,16(R12)
|
||||
MOVL R8, 36 (R12)
|
||||
CMPQ R9,$64
|
||||
JA BYTESATLEAST65
|
||||
JAE BYTESATLEAST64
|
||||
MOVQ DI,SI
|
||||
MOVQ DX,DI
|
||||
MOVQ R9,CX
|
||||
REP; MOVSB
|
||||
BYTESATLEAST64:
|
||||
DONE:
|
||||
RET
|
||||
BYTESATLEAST65:
|
||||
SUBQ $64,R9
|
||||
ADDQ $64,DI
|
||||
ADDQ $64,SI
|
||||
JMP BYTESBETWEEN1AND255
|
15
vendor/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go
generated
vendored
Normal file
15
vendor/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !amd64 || purego || !gc
|
||||
// +build !amd64 purego !gc
|
||||
|
||||
package salsa
|
||||
|
||||
// XORKeyStream crypts bytes from in to out using the given key and counters.
|
||||
// In and out must overlap entirely or not at all. Counter
|
||||
// contains the raw salsa20 counter bytes (both nonce and block counter).
|
||||
func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
|
||||
genericXORKeyStream(out, in, counter, key)
|
||||
}
|
233
vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go
generated
vendored
Normal file
233
vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go
generated
vendored
Normal file
@ -0,0 +1,233 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package salsa
|
||||
|
||||
import "math/bits"
|
||||
|
||||
const rounds = 20
|
||||
|
||||
// core applies the Salsa20 core function to 16-byte input in, 32-byte key k,
|
||||
// and 16-byte constant c, and puts the result into 64-byte array out.
|
||||
func core(out *[64]byte, in *[16]byte, k *[32]byte, c *[16]byte) {
|
||||
j0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24
|
||||
j1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24
|
||||
j2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24
|
||||
j3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24
|
||||
j4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24
|
||||
j5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24
|
||||
j6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24
|
||||
j7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24
|
||||
j8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24
|
||||
j9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24
|
||||
j10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24
|
||||
j11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24
|
||||
j12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24
|
||||
j13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24
|
||||
j14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24
|
||||
j15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24
|
||||
|
||||
x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8
|
||||
x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15
|
||||
|
||||
for i := 0; i < rounds; i += 2 {
|
||||
u := x0 + x12
|
||||
x4 ^= bits.RotateLeft32(u, 7)
|
||||
u = x4 + x0
|
||||
x8 ^= bits.RotateLeft32(u, 9)
|
||||
u = x8 + x4
|
||||
x12 ^= bits.RotateLeft32(u, 13)
|
||||
u = x12 + x8
|
||||
x0 ^= bits.RotateLeft32(u, 18)
|
||||
|
||||
u = x5 + x1
|
||||
x9 ^= bits.RotateLeft32(u, 7)
|
||||
u = x9 + x5
|
||||
x13 ^= bits.RotateLeft32(u, 9)
|
||||
u = x13 + x9
|
||||
x1 ^= bits.RotateLeft32(u, 13)
|
||||
u = x1 + x13
|
||||
x5 ^= bits.RotateLeft32(u, 18)
|
||||
|
||||
u = x10 + x6
|
||||
x14 ^= bits.RotateLeft32(u, 7)
|
||||
u = x14 + x10
|
||||
x2 ^= bits.RotateLeft32(u, 9)
|
||||
u = x2 + x14
|
||||
x6 ^= bits.RotateLeft32(u, 13)
|
||||
u = x6 + x2
|
||||
x10 ^= bits.RotateLeft32(u, 18)
|
||||
|
||||
u = x15 + x11
|
||||
x3 ^= bits.RotateLeft32(u, 7)
|
||||
u = x3 + x15
|
||||
x7 ^= bits.RotateLeft32(u, 9)
|
||||
u = x7 + x3
|
||||
x11 ^= bits.RotateLeft32(u, 13)
|
||||
u = x11 + x7
|
||||
x15 ^= bits.RotateLeft32(u, 18)
|
||||
|
||||
u = x0 + x3
|
||||
x1 ^= bits.RotateLeft32(u, 7)
|
||||
u = x1 + x0
|
||||
x2 ^= bits.RotateLeft32(u, 9)
|
||||
u = x2 + x1
|
||||
x3 ^= bits.RotateLeft32(u, 13)
|
||||
u = x3 + x2
|
||||
x0 ^= bits.RotateLeft32(u, 18)
|
||||
|
||||
u = x5 + x4
|
||||
x6 ^= bits.RotateLeft32(u, 7)
|
||||
u = x6 + x5
|
||||
x7 ^= bits.RotateLeft32(u, 9)
|
||||
u = x7 + x6
|
||||
x4 ^= bits.RotateLeft32(u, 13)
|
||||
u = x4 + x7
|
||||
x5 ^= bits.RotateLeft32(u, 18)
|
||||
|
||||
u = x10 + x9
|
||||
x11 ^= bits.RotateLeft32(u, 7)
|
||||
u = x11 + x10
|
||||
x8 ^= bits.RotateLeft32(u, 9)
|
||||
u = x8 + x11
|
||||
x9 ^= bits.RotateLeft32(u, 13)
|
||||
u = x9 + x8
|
||||
x10 ^= bits.RotateLeft32(u, 18)
|
||||
|
||||
u = x15 + x14
|
||||
x12 ^= bits.RotateLeft32(u, 7)
|
||||
u = x12 + x15
|
||||
x13 ^= bits.RotateLeft32(u, 9)
|
||||
u = x13 + x12
|
||||
x14 ^= bits.RotateLeft32(u, 13)
|
||||
u = x14 + x13
|
||||
x15 ^= bits.RotateLeft32(u, 18)
|
||||
}
|
||||
x0 += j0
|
||||
x1 += j1
|
||||
x2 += j2
|
||||
x3 += j3
|
||||
x4 += j4
|
||||
x5 += j5
|
||||
x6 += j6
|
||||
x7 += j7
|
||||
x8 += j8
|
||||
x9 += j9
|
||||
x10 += j10
|
||||
x11 += j11
|
||||
x12 += j12
|
||||
x13 += j13
|
||||
x14 += j14
|
||||
x15 += j15
|
||||
|
||||
out[0] = byte(x0)
|
||||
out[1] = byte(x0 >> 8)
|
||||
out[2] = byte(x0 >> 16)
|
||||
out[3] = byte(x0 >> 24)
|
||||
|
||||
out[4] = byte(x1)
|
||||
out[5] = byte(x1 >> 8)
|
||||
out[6] = byte(x1 >> 16)
|
||||
out[7] = byte(x1 >> 24)
|
||||
|
||||
out[8] = byte(x2)
|
||||
out[9] = byte(x2 >> 8)
|
||||
out[10] = byte(x2 >> 16)
|
||||
out[11] = byte(x2 >> 24)
|
||||
|
||||
out[12] = byte(x3)
|
||||
out[13] = byte(x3 >> 8)
|
||||
out[14] = byte(x3 >> 16)
|
||||
out[15] = byte(x3 >> 24)
|
||||
|
||||
out[16] = byte(x4)
|
||||
out[17] = byte(x4 >> 8)
|
||||
out[18] = byte(x4 >> 16)
|
||||
out[19] = byte(x4 >> 24)
|
||||
|
||||
out[20] = byte(x5)
|
||||
out[21] = byte(x5 >> 8)
|
||||
out[22] = byte(x5 >> 16)
|
||||
out[23] = byte(x5 >> 24)
|
||||
|
||||
out[24] = byte(x6)
|
||||
out[25] = byte(x6 >> 8)
|
||||
out[26] = byte(x6 >> 16)
|
||||
out[27] = byte(x6 >> 24)
|
||||
|
||||
out[28] = byte(x7)
|
||||
out[29] = byte(x7 >> 8)
|
||||
out[30] = byte(x7 >> 16)
|
||||
out[31] = byte(x7 >> 24)
|
||||
|
||||
out[32] = byte(x8)
|
||||
out[33] = byte(x8 >> 8)
|
||||
out[34] = byte(x8 >> 16)
|
||||
out[35] = byte(x8 >> 24)
|
||||
|
||||
out[36] = byte(x9)
|
||||
out[37] = byte(x9 >> 8)
|
||||
out[38] = byte(x9 >> 16)
|
||||
out[39] = byte(x9 >> 24)
|
||||
|
||||
out[40] = byte(x10)
|
||||
out[41] = byte(x10 >> 8)
|
||||
out[42] = byte(x10 >> 16)
|
||||
out[43] = byte(x10 >> 24)
|
||||
|
||||
out[44] = byte(x11)
|
||||
out[45] = byte(x11 >> 8)
|
||||
out[46] = byte(x11 >> 16)
|
||||
out[47] = byte(x11 >> 24)
|
||||
|
||||
out[48] = byte(x12)
|
||||
out[49] = byte(x12 >> 8)
|
||||
out[50] = byte(x12 >> 16)
|
||||
out[51] = byte(x12 >> 24)
|
||||
|
||||
out[52] = byte(x13)
|
||||
out[53] = byte(x13 >> 8)
|
||||
out[54] = byte(x13 >> 16)
|
||||
out[55] = byte(x13 >> 24)
|
||||
|
||||
out[56] = byte(x14)
|
||||
out[57] = byte(x14 >> 8)
|
||||
out[58] = byte(x14 >> 16)
|
||||
out[59] = byte(x14 >> 24)
|
||||
|
||||
out[60] = byte(x15)
|
||||
out[61] = byte(x15 >> 8)
|
||||
out[62] = byte(x15 >> 16)
|
||||
out[63] = byte(x15 >> 24)
|
||||
}
|
||||
|
||||
// genericXORKeyStream is the generic implementation of XORKeyStream to be used
|
||||
// when no assembly implementation is available.
|
||||
func genericXORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
|
||||
var block [64]byte
|
||||
var counterCopy [16]byte
|
||||
copy(counterCopy[:], counter[:])
|
||||
|
||||
for len(in) >= 64 {
|
||||
core(&block, &counterCopy, key, &Sigma)
|
||||
for i, x := range block {
|
||||
out[i] = in[i] ^ x
|
||||
}
|
||||
u := uint32(1)
|
||||
for i := 8; i < 16; i++ {
|
||||
u += uint32(counterCopy[i])
|
||||
counterCopy[i] = byte(u)
|
||||
u >>= 8
|
||||
}
|
||||
in = in[64:]
|
||||
out = out[64:]
|
||||
}
|
||||
|
||||
if len(in) > 0 {
|
||||
core(&block, &counterCopy, key, &Sigma)
|
||||
for i, v := range in {
|
||||
out[i] = v ^ block[i]
|
||||
}
|
||||
}
|
||||
}
|
106
vendor/golang.org/x/net/websocket/client.go
generated
vendored
Normal file
106
vendor/golang.org/x/net/websocket/client.go
generated
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// DialError is an error that occurs while dialling a websocket server.
|
||||
type DialError struct {
|
||||
*Config
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *DialError) Error() string {
|
||||
return "websocket.Dial " + e.Config.Location.String() + ": " + e.Err.Error()
|
||||
}
|
||||
|
||||
// NewConfig creates a new WebSocket config for client connection.
|
||||
func NewConfig(server, origin string) (config *Config, err error) {
|
||||
config = new(Config)
|
||||
config.Version = ProtocolVersionHybi13
|
||||
config.Location, err = url.ParseRequestURI(server)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
config.Origin, err = url.ParseRequestURI(origin)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
config.Header = http.Header(make(map[string][]string))
|
||||
return
|
||||
}
|
||||
|
||||
// NewClient creates a new WebSocket client connection over rwc.
|
||||
func NewClient(config *Config, rwc io.ReadWriteCloser) (ws *Conn, err error) {
|
||||
br := bufio.NewReader(rwc)
|
||||
bw := bufio.NewWriter(rwc)
|
||||
err = hybiClientHandshake(config, br, bw)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
buf := bufio.NewReadWriter(br, bw)
|
||||
ws = newHybiClientConn(config, buf, rwc)
|
||||
return
|
||||
}
|
||||
|
||||
// Dial opens a new client connection to a WebSocket.
|
||||
func Dial(url_, protocol, origin string) (ws *Conn, err error) {
|
||||
config, err := NewConfig(url_, origin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if protocol != "" {
|
||||
config.Protocol = []string{protocol}
|
||||
}
|
||||
return DialConfig(config)
|
||||
}
|
||||
|
||||
var portMap = map[string]string{
|
||||
"ws": "80",
|
||||
"wss": "443",
|
||||
}
|
||||
|
||||
func parseAuthority(location *url.URL) string {
|
||||
if _, ok := portMap[location.Scheme]; ok {
|
||||
if _, _, err := net.SplitHostPort(location.Host); err != nil {
|
||||
return net.JoinHostPort(location.Host, portMap[location.Scheme])
|
||||
}
|
||||
}
|
||||
return location.Host
|
||||
}
|
||||
|
||||
// DialConfig opens a new client connection to a WebSocket with a config.
|
||||
func DialConfig(config *Config) (ws *Conn, err error) {
|
||||
var client net.Conn
|
||||
if config.Location == nil {
|
||||
return nil, &DialError{config, ErrBadWebSocketLocation}
|
||||
}
|
||||
if config.Origin == nil {
|
||||
return nil, &DialError{config, ErrBadWebSocketOrigin}
|
||||
}
|
||||
dialer := config.Dialer
|
||||
if dialer == nil {
|
||||
dialer = &net.Dialer{}
|
||||
}
|
||||
client, err = dialWithDialer(dialer, config)
|
||||
if err != nil {
|
||||
goto Error
|
||||
}
|
||||
ws, err = NewClient(config, client)
|
||||
if err != nil {
|
||||
client.Close()
|
||||
goto Error
|
||||
}
|
||||
return
|
||||
|
||||
Error:
|
||||
return nil, &DialError{config, err}
|
||||
}
|
24
vendor/golang.org/x/net/websocket/dial.go
generated
vendored
Normal file
24
vendor/golang.org/x/net/websocket/dial.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net"
|
||||
)
|
||||
|
||||
func dialWithDialer(dialer *net.Dialer, config *Config) (conn net.Conn, err error) {
|
||||
switch config.Location.Scheme {
|
||||
case "ws":
|
||||
conn, err = dialer.Dial("tcp", parseAuthority(config.Location))
|
||||
|
||||
case "wss":
|
||||
conn, err = tls.DialWithDialer(dialer, "tcp", parseAuthority(config.Location), config.TlsConfig)
|
||||
|
||||
default:
|
||||
err = ErrBadScheme
|
||||
}
|
||||
return
|
||||
}
|
583
vendor/golang.org/x/net/websocket/hybi.go
generated
vendored
Normal file
583
vendor/golang.org/x/net/websocket/hybi.go
generated
vendored
Normal file
@ -0,0 +1,583 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package websocket
|
||||
|
||||
// This file implements a protocol of hybi draft.
|
||||
// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
websocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
|
||||
|
||||
closeStatusNormal = 1000
|
||||
closeStatusGoingAway = 1001
|
||||
closeStatusProtocolError = 1002
|
||||
closeStatusUnsupportedData = 1003
|
||||
closeStatusFrameTooLarge = 1004
|
||||
closeStatusNoStatusRcvd = 1005
|
||||
closeStatusAbnormalClosure = 1006
|
||||
closeStatusBadMessageData = 1007
|
||||
closeStatusPolicyViolation = 1008
|
||||
closeStatusTooBigData = 1009
|
||||
closeStatusExtensionMismatch = 1010
|
||||
|
||||
maxControlFramePayloadLength = 125
|
||||
)
|
||||
|
||||
var (
|
||||
ErrBadMaskingKey = &ProtocolError{"bad masking key"}
|
||||
ErrBadPongMessage = &ProtocolError{"bad pong message"}
|
||||
ErrBadClosingStatus = &ProtocolError{"bad closing status"}
|
||||
ErrUnsupportedExtensions = &ProtocolError{"unsupported extensions"}
|
||||
ErrNotImplemented = &ProtocolError{"not implemented"}
|
||||
|
||||
handshakeHeader = map[string]bool{
|
||||
"Host": true,
|
||||
"Upgrade": true,
|
||||
"Connection": true,
|
||||
"Sec-Websocket-Key": true,
|
||||
"Sec-Websocket-Origin": true,
|
||||
"Sec-Websocket-Version": true,
|
||||
"Sec-Websocket-Protocol": true,
|
||||
"Sec-Websocket-Accept": true,
|
||||
}
|
||||
)
|
||||
|
||||
// A hybiFrameHeader is a frame header as defined in hybi draft.
|
||||
type hybiFrameHeader struct {
|
||||
Fin bool
|
||||
Rsv [3]bool
|
||||
OpCode byte
|
||||
Length int64
|
||||
MaskingKey []byte
|
||||
|
||||
data *bytes.Buffer
|
||||
}
|
||||
|
||||
// A hybiFrameReader is a reader for hybi frame.
|
||||
type hybiFrameReader struct {
|
||||
reader io.Reader
|
||||
|
||||
header hybiFrameHeader
|
||||
pos int64
|
||||
length int
|
||||
}
|
||||
|
||||
func (frame *hybiFrameReader) Read(msg []byte) (n int, err error) {
|
||||
n, err = frame.reader.Read(msg)
|
||||
if frame.header.MaskingKey != nil {
|
||||
for i := 0; i < n; i++ {
|
||||
msg[i] = msg[i] ^ frame.header.MaskingKey[frame.pos%4]
|
||||
frame.pos++
|
||||
}
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (frame *hybiFrameReader) PayloadType() byte { return frame.header.OpCode }
|
||||
|
||||
func (frame *hybiFrameReader) HeaderReader() io.Reader {
|
||||
if frame.header.data == nil {
|
||||
return nil
|
||||
}
|
||||
if frame.header.data.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
return frame.header.data
|
||||
}
|
||||
|
||||
func (frame *hybiFrameReader) TrailerReader() io.Reader { return nil }
|
||||
|
||||
func (frame *hybiFrameReader) Len() (n int) { return frame.length }
|
||||
|
||||
// A hybiFrameReaderFactory creates new frame reader based on its frame type.
|
||||
type hybiFrameReaderFactory struct {
|
||||
*bufio.Reader
|
||||
}
|
||||
|
||||
// NewFrameReader reads a frame header from the connection, and creates new reader for the frame.
|
||||
// See Section 5.2 Base Framing protocol for detail.
|
||||
// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-5.2
|
||||
func (buf hybiFrameReaderFactory) NewFrameReader() (frame frameReader, err error) {
|
||||
hybiFrame := new(hybiFrameReader)
|
||||
frame = hybiFrame
|
||||
var header []byte
|
||||
var b byte
|
||||
// First byte. FIN/RSV1/RSV2/RSV3/OpCode(4bits)
|
||||
b, err = buf.ReadByte()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
header = append(header, b)
|
||||
hybiFrame.header.Fin = ((header[0] >> 7) & 1) != 0
|
||||
for i := 0; i < 3; i++ {
|
||||
j := uint(6 - i)
|
||||
hybiFrame.header.Rsv[i] = ((header[0] >> j) & 1) != 0
|
||||
}
|
||||
hybiFrame.header.OpCode = header[0] & 0x0f
|
||||
|
||||
// Second byte. Mask/Payload len(7bits)
|
||||
b, err = buf.ReadByte()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
header = append(header, b)
|
||||
mask := (b & 0x80) != 0
|
||||
b &= 0x7f
|
||||
lengthFields := 0
|
||||
switch {
|
||||
case b <= 125: // Payload length 7bits.
|
||||
hybiFrame.header.Length = int64(b)
|
||||
case b == 126: // Payload length 7+16bits
|
||||
lengthFields = 2
|
||||
case b == 127: // Payload length 7+64bits
|
||||
lengthFields = 8
|
||||
}
|
||||
for i := 0; i < lengthFields; i++ {
|
||||
b, err = buf.ReadByte()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if lengthFields == 8 && i == 0 { // MSB must be zero when 7+64 bits
|
||||
b &= 0x7f
|
||||
}
|
||||
header = append(header, b)
|
||||
hybiFrame.header.Length = hybiFrame.header.Length*256 + int64(b)
|
||||
}
|
||||
if mask {
|
||||
// Masking key. 4 bytes.
|
||||
for i := 0; i < 4; i++ {
|
||||
b, err = buf.ReadByte()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
header = append(header, b)
|
||||
hybiFrame.header.MaskingKey = append(hybiFrame.header.MaskingKey, b)
|
||||
}
|
||||
}
|
||||
hybiFrame.reader = io.LimitReader(buf.Reader, hybiFrame.header.Length)
|
||||
hybiFrame.header.data = bytes.NewBuffer(header)
|
||||
hybiFrame.length = len(header) + int(hybiFrame.header.Length)
|
||||
return
|
||||
}
|
||||
|
||||
// A HybiFrameWriter is a writer for hybi frame.
|
||||
type hybiFrameWriter struct {
|
||||
writer *bufio.Writer
|
||||
|
||||
header *hybiFrameHeader
|
||||
}
|
||||
|
||||
func (frame *hybiFrameWriter) Write(msg []byte) (n int, err error) {
|
||||
var header []byte
|
||||
var b byte
|
||||
if frame.header.Fin {
|
||||
b |= 0x80
|
||||
}
|
||||
for i := 0; i < 3; i++ {
|
||||
if frame.header.Rsv[i] {
|
||||
j := uint(6 - i)
|
||||
b |= 1 << j
|
||||
}
|
||||
}
|
||||
b |= frame.header.OpCode
|
||||
header = append(header, b)
|
||||
if frame.header.MaskingKey != nil {
|
||||
b = 0x80
|
||||
} else {
|
||||
b = 0
|
||||
}
|
||||
lengthFields := 0
|
||||
length := len(msg)
|
||||
switch {
|
||||
case length <= 125:
|
||||
b |= byte(length)
|
||||
case length < 65536:
|
||||
b |= 126
|
||||
lengthFields = 2
|
||||
default:
|
||||
b |= 127
|
||||
lengthFields = 8
|
||||
}
|
||||
header = append(header, b)
|
||||
for i := 0; i < lengthFields; i++ {
|
||||
j := uint((lengthFields - i - 1) * 8)
|
||||
b = byte((length >> j) & 0xff)
|
||||
header = append(header, b)
|
||||
}
|
||||
if frame.header.MaskingKey != nil {
|
||||
if len(frame.header.MaskingKey) != 4 {
|
||||
return 0, ErrBadMaskingKey
|
||||
}
|
||||
header = append(header, frame.header.MaskingKey...)
|
||||
frame.writer.Write(header)
|
||||
data := make([]byte, length)
|
||||
for i := range data {
|
||||
data[i] = msg[i] ^ frame.header.MaskingKey[i%4]
|
||||
}
|
||||
frame.writer.Write(data)
|
||||
err = frame.writer.Flush()
|
||||
return length, err
|
||||
}
|
||||
frame.writer.Write(header)
|
||||
frame.writer.Write(msg)
|
||||
err = frame.writer.Flush()
|
||||
return length, err
|
||||
}
|
||||
|
||||
func (frame *hybiFrameWriter) Close() error { return nil }
|
||||
|
||||
type hybiFrameWriterFactory struct {
|
||||
*bufio.Writer
|
||||
needMaskingKey bool
|
||||
}
|
||||
|
||||
func (buf hybiFrameWriterFactory) NewFrameWriter(payloadType byte) (frame frameWriter, err error) {
|
||||
frameHeader := &hybiFrameHeader{Fin: true, OpCode: payloadType}
|
||||
if buf.needMaskingKey {
|
||||
frameHeader.MaskingKey, err = generateMaskingKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &hybiFrameWriter{writer: buf.Writer, header: frameHeader}, nil
|
||||
}
|
||||
|
||||
type hybiFrameHandler struct {
|
||||
conn *Conn
|
||||
payloadType byte
|
||||
}
|
||||
|
||||
func (handler *hybiFrameHandler) HandleFrame(frame frameReader) (frameReader, error) {
|
||||
if handler.conn.IsServerConn() {
|
||||
// The client MUST mask all frames sent to the server.
|
||||
if frame.(*hybiFrameReader).header.MaskingKey == nil {
|
||||
handler.WriteClose(closeStatusProtocolError)
|
||||
return nil, io.EOF
|
||||
}
|
||||
} else {
|
||||
// The server MUST NOT mask all frames.
|
||||
if frame.(*hybiFrameReader).header.MaskingKey != nil {
|
||||
handler.WriteClose(closeStatusProtocolError)
|
||||
return nil, io.EOF
|
||||
}
|
||||
}
|
||||
if header := frame.HeaderReader(); header != nil {
|
||||
io.Copy(ioutil.Discard, header)
|
||||
}
|
||||
switch frame.PayloadType() {
|
||||
case ContinuationFrame:
|
||||
frame.(*hybiFrameReader).header.OpCode = handler.payloadType
|
||||
case TextFrame, BinaryFrame:
|
||||
handler.payloadType = frame.PayloadType()
|
||||
case CloseFrame:
|
||||
return nil, io.EOF
|
||||
case PingFrame, PongFrame:
|
||||
b := make([]byte, maxControlFramePayloadLength)
|
||||
n, err := io.ReadFull(frame, b)
|
||||
if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
|
||||
return nil, err
|
||||
}
|
||||
io.Copy(ioutil.Discard, frame)
|
||||
if frame.PayloadType() == PingFrame {
|
||||
if _, err := handler.WritePong(b[:n]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
func (handler *hybiFrameHandler) WriteClose(status int) (err error) {
|
||||
handler.conn.wio.Lock()
|
||||
defer handler.conn.wio.Unlock()
|
||||
w, err := handler.conn.frameWriterFactory.NewFrameWriter(CloseFrame)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msg := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(msg, uint16(status))
|
||||
_, err = w.Write(msg)
|
||||
w.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
func (handler *hybiFrameHandler) WritePong(msg []byte) (n int, err error) {
|
||||
handler.conn.wio.Lock()
|
||||
defer handler.conn.wio.Unlock()
|
||||
w, err := handler.conn.frameWriterFactory.NewFrameWriter(PongFrame)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
n, err = w.Write(msg)
|
||||
w.Close()
|
||||
return n, err
|
||||
}
|
||||
|
||||
// newHybiConn creates a new WebSocket connection speaking hybi draft protocol.
|
||||
func newHybiConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
|
||||
if buf == nil {
|
||||
br := bufio.NewReader(rwc)
|
||||
bw := bufio.NewWriter(rwc)
|
||||
buf = bufio.NewReadWriter(br, bw)
|
||||
}
|
||||
ws := &Conn{config: config, request: request, buf: buf, rwc: rwc,
|
||||
frameReaderFactory: hybiFrameReaderFactory{buf.Reader},
|
||||
frameWriterFactory: hybiFrameWriterFactory{
|
||||
buf.Writer, request == nil},
|
||||
PayloadType: TextFrame,
|
||||
defaultCloseStatus: closeStatusNormal}
|
||||
ws.frameHandler = &hybiFrameHandler{conn: ws}
|
||||
return ws
|
||||
}
|
||||
|
||||
// generateMaskingKey generates a masking key for a frame.
|
||||
func generateMaskingKey() (maskingKey []byte, err error) {
|
||||
maskingKey = make([]byte, 4)
|
||||
if _, err = io.ReadFull(rand.Reader, maskingKey); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// generateNonce generates a nonce consisting of a randomly selected 16-byte
|
||||
// value that has been base64-encoded.
|
||||
func generateNonce() (nonce []byte) {
|
||||
key := make([]byte, 16)
|
||||
if _, err := io.ReadFull(rand.Reader, key); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
nonce = make([]byte, 24)
|
||||
base64.StdEncoding.Encode(nonce, key)
|
||||
return
|
||||
}
|
||||
|
||||
// removeZone removes IPv6 zone identifier from host.
|
||||
// E.g., "[fe80::1%en0]:8080" to "[fe80::1]:8080"
|
||||
func removeZone(host string) string {
|
||||
if !strings.HasPrefix(host, "[") {
|
||||
return host
|
||||
}
|
||||
i := strings.LastIndex(host, "]")
|
||||
if i < 0 {
|
||||
return host
|
||||
}
|
||||
j := strings.LastIndex(host[:i], "%")
|
||||
if j < 0 {
|
||||
return host
|
||||
}
|
||||
return host[:j] + host[i:]
|
||||
}
|
||||
|
||||
// getNonceAccept computes the base64-encoded SHA-1 of the concatenation of
|
||||
// the nonce ("Sec-WebSocket-Key" value) with the websocket GUID string.
|
||||
func getNonceAccept(nonce []byte) (expected []byte, err error) {
|
||||
h := sha1.New()
|
||||
if _, err = h.Write(nonce); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = h.Write([]byte(websocketGUID)); err != nil {
|
||||
return
|
||||
}
|
||||
expected = make([]byte, 28)
|
||||
base64.StdEncoding.Encode(expected, h.Sum(nil))
|
||||
return
|
||||
}
|
||||
|
||||
// Client handshake described in draft-ietf-hybi-thewebsocket-protocol-17
|
||||
func hybiClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) {
|
||||
bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n")
|
||||
|
||||
// According to RFC 6874, an HTTP client, proxy, or other
|
||||
// intermediary must remove any IPv6 zone identifier attached
|
||||
// to an outgoing URI.
|
||||
bw.WriteString("Host: " + removeZone(config.Location.Host) + "\r\n")
|
||||
bw.WriteString("Upgrade: websocket\r\n")
|
||||
bw.WriteString("Connection: Upgrade\r\n")
|
||||
nonce := generateNonce()
|
||||
if config.handshakeData != nil {
|
||||
nonce = []byte(config.handshakeData["key"])
|
||||
}
|
||||
bw.WriteString("Sec-WebSocket-Key: " + string(nonce) + "\r\n")
|
||||
bw.WriteString("Origin: " + strings.ToLower(config.Origin.String()) + "\r\n")
|
||||
|
||||
if config.Version != ProtocolVersionHybi13 {
|
||||
return ErrBadProtocolVersion
|
||||
}
|
||||
|
||||
bw.WriteString("Sec-WebSocket-Version: " + fmt.Sprintf("%d", config.Version) + "\r\n")
|
||||
if len(config.Protocol) > 0 {
|
||||
bw.WriteString("Sec-WebSocket-Protocol: " + strings.Join(config.Protocol, ", ") + "\r\n")
|
||||
}
|
||||
// TODO(ukai): send Sec-WebSocket-Extensions.
|
||||
err = config.Header.WriteSubset(bw, handshakeHeader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bw.WriteString("\r\n")
|
||||
if err = bw.Flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.StatusCode != 101 {
|
||||
return ErrBadStatus
|
||||
}
|
||||
if strings.ToLower(resp.Header.Get("Upgrade")) != "websocket" ||
|
||||
strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
|
||||
return ErrBadUpgrade
|
||||
}
|
||||
expectedAccept, err := getNonceAccept(nonce)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.Header.Get("Sec-WebSocket-Accept") != string(expectedAccept) {
|
||||
return ErrChallengeResponse
|
||||
}
|
||||
if resp.Header.Get("Sec-WebSocket-Extensions") != "" {
|
||||
return ErrUnsupportedExtensions
|
||||
}
|
||||
offeredProtocol := resp.Header.Get("Sec-WebSocket-Protocol")
|
||||
if offeredProtocol != "" {
|
||||
protocolMatched := false
|
||||
for i := 0; i < len(config.Protocol); i++ {
|
||||
if config.Protocol[i] == offeredProtocol {
|
||||
protocolMatched = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !protocolMatched {
|
||||
return ErrBadWebSocketProtocol
|
||||
}
|
||||
config.Protocol = []string{offeredProtocol}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// newHybiClientConn creates a client WebSocket connection after handshake.
|
||||
func newHybiClientConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn {
|
||||
return newHybiConn(config, buf, rwc, nil)
|
||||
}
|
||||
|
||||
// A HybiServerHandshaker performs a server handshake using hybi draft protocol.
|
||||
type hybiServerHandshaker struct {
|
||||
*Config
|
||||
accept []byte
|
||||
}
|
||||
|
||||
func (c *hybiServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) {
|
||||
c.Version = ProtocolVersionHybi13
|
||||
if req.Method != "GET" {
|
||||
return http.StatusMethodNotAllowed, ErrBadRequestMethod
|
||||
}
|
||||
// HTTP version can be safely ignored.
|
||||
|
||||
if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" ||
|
||||
!strings.Contains(strings.ToLower(req.Header.Get("Connection")), "upgrade") {
|
||||
return http.StatusBadRequest, ErrNotWebSocket
|
||||
}
|
||||
|
||||
key := req.Header.Get("Sec-Websocket-Key")
|
||||
if key == "" {
|
||||
return http.StatusBadRequest, ErrChallengeResponse
|
||||
}
|
||||
version := req.Header.Get("Sec-Websocket-Version")
|
||||
switch version {
|
||||
case "13":
|
||||
c.Version = ProtocolVersionHybi13
|
||||
default:
|
||||
return http.StatusBadRequest, ErrBadWebSocketVersion
|
||||
}
|
||||
var scheme string
|
||||
if req.TLS != nil {
|
||||
scheme = "wss"
|
||||
} else {
|
||||
scheme = "ws"
|
||||
}
|
||||
c.Location, err = url.ParseRequestURI(scheme + "://" + req.Host + req.URL.RequestURI())
|
||||
if err != nil {
|
||||
return http.StatusBadRequest, err
|
||||
}
|
||||
protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol"))
|
||||
if protocol != "" {
|
||||
protocols := strings.Split(protocol, ",")
|
||||
for i := 0; i < len(protocols); i++ {
|
||||
c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
|
||||
}
|
||||
}
|
||||
c.accept, err = getNonceAccept([]byte(key))
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
return http.StatusSwitchingProtocols, nil
|
||||
}
|
||||
|
||||
// Origin parses the Origin header in req.
|
||||
// If the Origin header is not set, it returns nil and nil.
|
||||
func Origin(config *Config, req *http.Request) (*url.URL, error) {
|
||||
var origin string
|
||||
switch config.Version {
|
||||
case ProtocolVersionHybi13:
|
||||
origin = req.Header.Get("Origin")
|
||||
}
|
||||
if origin == "" {
|
||||
return nil, nil
|
||||
}
|
||||
return url.ParseRequestURI(origin)
|
||||
}
|
||||
|
||||
func (c *hybiServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) {
|
||||
if len(c.Protocol) > 0 {
|
||||
if len(c.Protocol) != 1 {
|
||||
// You need choose a Protocol in Handshake func in Server.
|
||||
return ErrBadWebSocketProtocol
|
||||
}
|
||||
}
|
||||
buf.WriteString("HTTP/1.1 101 Switching Protocols\r\n")
|
||||
buf.WriteString("Upgrade: websocket\r\n")
|
||||
buf.WriteString("Connection: Upgrade\r\n")
|
||||
buf.WriteString("Sec-WebSocket-Accept: " + string(c.accept) + "\r\n")
|
||||
if len(c.Protocol) > 0 {
|
||||
buf.WriteString("Sec-WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
|
||||
}
|
||||
// TODO(ukai): send Sec-WebSocket-Extensions.
|
||||
if c.Header != nil {
|
||||
err := c.Header.WriteSubset(buf, handshakeHeader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
buf.WriteString("\r\n")
|
||||
return buf.Flush()
|
||||
}
|
||||
|
||||
func (c *hybiServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
|
||||
return newHybiServerConn(c.Config, buf, rwc, request)
|
||||
}
|
||||
|
||||
// newHybiServerConn returns a new WebSocket connection speaking hybi draft protocol.
|
||||
func newHybiServerConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
|
||||
return newHybiConn(config, buf, rwc, request)
|
||||
}
|
113
vendor/golang.org/x/net/websocket/server.go
generated
vendored
Normal file
113
vendor/golang.org/x/net/websocket/server.go
generated
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func newServerConn(rwc io.ReadWriteCloser, buf *bufio.ReadWriter, req *http.Request, config *Config, handshake func(*Config, *http.Request) error) (conn *Conn, err error) {
|
||||
var hs serverHandshaker = &hybiServerHandshaker{Config: config}
|
||||
code, err := hs.ReadHandshake(buf.Reader, req)
|
||||
if err == ErrBadWebSocketVersion {
|
||||
fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
|
||||
fmt.Fprintf(buf, "Sec-WebSocket-Version: %s\r\n", SupportedProtocolVersion)
|
||||
buf.WriteString("\r\n")
|
||||
buf.WriteString(err.Error())
|
||||
buf.Flush()
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
|
||||
buf.WriteString("\r\n")
|
||||
buf.WriteString(err.Error())
|
||||
buf.Flush()
|
||||
return
|
||||
}
|
||||
if handshake != nil {
|
||||
err = handshake(config, req)
|
||||
if err != nil {
|
||||
code = http.StatusForbidden
|
||||
fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
|
||||
buf.WriteString("\r\n")
|
||||
buf.Flush()
|
||||
return
|
||||
}
|
||||
}
|
||||
err = hs.AcceptHandshake(buf.Writer)
|
||||
if err != nil {
|
||||
code = http.StatusBadRequest
|
||||
fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
|
||||
buf.WriteString("\r\n")
|
||||
buf.Flush()
|
||||
return
|
||||
}
|
||||
conn = hs.NewServerConn(buf, rwc, req)
|
||||
return
|
||||
}
|
||||
|
||||
// Server represents a server of a WebSocket.
|
||||
type Server struct {
|
||||
// Config is a WebSocket configuration for new WebSocket connection.
|
||||
Config
|
||||
|
||||
// Handshake is an optional function in WebSocket handshake.
|
||||
// For example, you can check, or don't check Origin header.
|
||||
// Another example, you can select config.Protocol.
|
||||
Handshake func(*Config, *http.Request) error
|
||||
|
||||
// Handler handles a WebSocket connection.
|
||||
Handler
|
||||
}
|
||||
|
||||
// ServeHTTP implements the http.Handler interface for a WebSocket
|
||||
func (s Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
s.serveWebSocket(w, req)
|
||||
}
|
||||
|
||||
func (s Server) serveWebSocket(w http.ResponseWriter, req *http.Request) {
|
||||
rwc, buf, err := w.(http.Hijacker).Hijack()
|
||||
if err != nil {
|
||||
panic("Hijack failed: " + err.Error())
|
||||
}
|
||||
// The server should abort the WebSocket connection if it finds
|
||||
// the client did not send a handshake that matches with protocol
|
||||
// specification.
|
||||
defer rwc.Close()
|
||||
conn, err := newServerConn(rwc, buf, req, &s.Config, s.Handshake)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if conn == nil {
|
||||
panic("unexpected nil conn")
|
||||
}
|
||||
s.Handler(conn)
|
||||
}
|
||||
|
||||
// Handler is a simple interface to a WebSocket browser client.
|
||||
// It checks if Origin header is valid URL by default.
|
||||
// You might want to verify websocket.Conn.Config().Origin in the func.
|
||||
// If you use Server instead of Handler, you could call websocket.Origin and
|
||||
// check the origin in your Handshake func. So, if you want to accept
|
||||
// non-browser clients, which do not send an Origin header, set a
|
||||
// Server.Handshake that does not check the origin.
|
||||
type Handler func(*Conn)
|
||||
|
||||
func checkOrigin(config *Config, req *http.Request) (err error) {
|
||||
config.Origin, err = Origin(config, req)
|
||||
if err == nil && config.Origin == nil {
|
||||
return fmt.Errorf("null origin")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// ServeHTTP implements the http.Handler interface for a WebSocket
|
||||
func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
s := Server{Handler: h, Handshake: checkOrigin}
|
||||
s.serveWebSocket(w, req)
|
||||
}
|
449
vendor/golang.org/x/net/websocket/websocket.go
generated
vendored
Normal file
449
vendor/golang.org/x/net/websocket/websocket.go
generated
vendored
Normal file
@ -0,0 +1,449 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package websocket implements a client and server for the WebSocket protocol
|
||||
// as specified in RFC 6455.
|
||||
//
|
||||
// This package currently lacks some features found in an alternative
|
||||
// and more actively maintained WebSocket package:
|
||||
//
|
||||
// https://pkg.go.dev/nhooyr.io/websocket
|
||||
package websocket // import "golang.org/x/net/websocket"
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
ProtocolVersionHybi13 = 13
|
||||
ProtocolVersionHybi = ProtocolVersionHybi13
|
||||
SupportedProtocolVersion = "13"
|
||||
|
||||
ContinuationFrame = 0
|
||||
TextFrame = 1
|
||||
BinaryFrame = 2
|
||||
CloseFrame = 8
|
||||
PingFrame = 9
|
||||
PongFrame = 10
|
||||
UnknownFrame = 255
|
||||
|
||||
DefaultMaxPayloadBytes = 32 << 20 // 32MB
|
||||
)
|
||||
|
||||
// ProtocolError represents WebSocket protocol errors.
|
||||
type ProtocolError struct {
|
||||
ErrorString string
|
||||
}
|
||||
|
||||
func (err *ProtocolError) Error() string { return err.ErrorString }
|
||||
|
||||
var (
|
||||
ErrBadProtocolVersion = &ProtocolError{"bad protocol version"}
|
||||
ErrBadScheme = &ProtocolError{"bad scheme"}
|
||||
ErrBadStatus = &ProtocolError{"bad status"}
|
||||
ErrBadUpgrade = &ProtocolError{"missing or bad upgrade"}
|
||||
ErrBadWebSocketOrigin = &ProtocolError{"missing or bad WebSocket-Origin"}
|
||||
ErrBadWebSocketLocation = &ProtocolError{"missing or bad WebSocket-Location"}
|
||||
ErrBadWebSocketProtocol = &ProtocolError{"missing or bad WebSocket-Protocol"}
|
||||
ErrBadWebSocketVersion = &ProtocolError{"missing or bad WebSocket Version"}
|
||||
ErrChallengeResponse = &ProtocolError{"mismatch challenge/response"}
|
||||
ErrBadFrame = &ProtocolError{"bad frame"}
|
||||
ErrBadFrameBoundary = &ProtocolError{"not on frame boundary"}
|
||||
ErrNotWebSocket = &ProtocolError{"not websocket protocol"}
|
||||
ErrBadRequestMethod = &ProtocolError{"bad method"}
|
||||
ErrNotSupported = &ProtocolError{"not supported"}
|
||||
)
|
||||
|
||||
// ErrFrameTooLarge is returned by Codec's Receive method if payload size
|
||||
// exceeds limit set by Conn.MaxPayloadBytes
|
||||
var ErrFrameTooLarge = errors.New("websocket: frame payload size exceeds limit")
|
||||
|
||||
// Addr is an implementation of net.Addr for WebSocket.
|
||||
type Addr struct {
|
||||
*url.URL
|
||||
}
|
||||
|
||||
// Network returns the network type for a WebSocket, "websocket".
|
||||
func (addr *Addr) Network() string { return "websocket" }
|
||||
|
||||
// Config is a WebSocket configuration
|
||||
type Config struct {
|
||||
// A WebSocket server address.
|
||||
Location *url.URL
|
||||
|
||||
// A Websocket client origin.
|
||||
Origin *url.URL
|
||||
|
||||
// WebSocket subprotocols.
|
||||
Protocol []string
|
||||
|
||||
// WebSocket protocol version.
|
||||
Version int
|
||||
|
||||
// TLS config for secure WebSocket (wss).
|
||||
TlsConfig *tls.Config
|
||||
|
||||
// Additional header fields to be sent in WebSocket opening handshake.
|
||||
Header http.Header
|
||||
|
||||
// Dialer used when opening websocket connections.
|
||||
Dialer *net.Dialer
|
||||
|
||||
handshakeData map[string]string
|
||||
}
|
||||
|
||||
// serverHandshaker is an interface to handle WebSocket server side handshake.
|
||||
type serverHandshaker interface {
|
||||
// ReadHandshake reads handshake request message from client.
|
||||
// Returns http response code and error if any.
|
||||
ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error)
|
||||
|
||||
// AcceptHandshake accepts the client handshake request and sends
|
||||
// handshake response back to client.
|
||||
AcceptHandshake(buf *bufio.Writer) (err error)
|
||||
|
||||
// NewServerConn creates a new WebSocket connection.
|
||||
NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn)
|
||||
}
|
||||
|
||||
// frameReader is an interface to read a WebSocket frame.
|
||||
type frameReader interface {
|
||||
// Reader is to read payload of the frame.
|
||||
io.Reader
|
||||
|
||||
// PayloadType returns payload type.
|
||||
PayloadType() byte
|
||||
|
||||
// HeaderReader returns a reader to read header of the frame.
|
||||
HeaderReader() io.Reader
|
||||
|
||||
// TrailerReader returns a reader to read trailer of the frame.
|
||||
// If it returns nil, there is no trailer in the frame.
|
||||
TrailerReader() io.Reader
|
||||
|
||||
// Len returns total length of the frame, including header and trailer.
|
||||
Len() int
|
||||
}
|
||||
|
||||
// frameReaderFactory is an interface to creates new frame reader.
|
||||
type frameReaderFactory interface {
|
||||
NewFrameReader() (r frameReader, err error)
|
||||
}
|
||||
|
||||
// frameWriter is an interface to write a WebSocket frame.
|
||||
type frameWriter interface {
|
||||
// Writer is to write payload of the frame.
|
||||
io.WriteCloser
|
||||
}
|
||||
|
||||
// frameWriterFactory is an interface to create new frame writer.
|
||||
type frameWriterFactory interface {
|
||||
NewFrameWriter(payloadType byte) (w frameWriter, err error)
|
||||
}
|
||||
|
||||
type frameHandler interface {
|
||||
HandleFrame(frame frameReader) (r frameReader, err error)
|
||||
WriteClose(status int) (err error)
|
||||
}
|
||||
|
||||
// Conn represents a WebSocket connection.
|
||||
//
|
||||
// Multiple goroutines may invoke methods on a Conn simultaneously.
|
||||
type Conn struct {
|
||||
config *Config
|
||||
request *http.Request
|
||||
|
||||
buf *bufio.ReadWriter
|
||||
rwc io.ReadWriteCloser
|
||||
|
||||
rio sync.Mutex
|
||||
frameReaderFactory
|
||||
frameReader
|
||||
|
||||
wio sync.Mutex
|
||||
frameWriterFactory
|
||||
|
||||
frameHandler
|
||||
PayloadType byte
|
||||
defaultCloseStatus int
|
||||
|
||||
// MaxPayloadBytes limits the size of frame payload received over Conn
|
||||
// by Codec's Receive method. If zero, DefaultMaxPayloadBytes is used.
|
||||
MaxPayloadBytes int
|
||||
}
|
||||
|
||||
// Read implements the io.Reader interface:
|
||||
// it reads data of a frame from the WebSocket connection.
|
||||
// if msg is not large enough for the frame data, it fills the msg and next Read
|
||||
// will read the rest of the frame data.
|
||||
// it reads Text frame or Binary frame.
|
||||
func (ws *Conn) Read(msg []byte) (n int, err error) {
|
||||
ws.rio.Lock()
|
||||
defer ws.rio.Unlock()
|
||||
again:
|
||||
if ws.frameReader == nil {
|
||||
frame, err := ws.frameReaderFactory.NewFrameReader()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ws.frameReader, err = ws.frameHandler.HandleFrame(frame)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if ws.frameReader == nil {
|
||||
goto again
|
||||
}
|
||||
}
|
||||
n, err = ws.frameReader.Read(msg)
|
||||
if err == io.EOF {
|
||||
if trailer := ws.frameReader.TrailerReader(); trailer != nil {
|
||||
io.Copy(ioutil.Discard, trailer)
|
||||
}
|
||||
ws.frameReader = nil
|
||||
goto again
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Write implements the io.Writer interface:
|
||||
// it writes data as a frame to the WebSocket connection.
|
||||
func (ws *Conn) Write(msg []byte) (n int, err error) {
|
||||
ws.wio.Lock()
|
||||
defer ws.wio.Unlock()
|
||||
w, err := ws.frameWriterFactory.NewFrameWriter(ws.PayloadType)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
n, err = w.Write(msg)
|
||||
w.Close()
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Close implements the io.Closer interface.
|
||||
func (ws *Conn) Close() error {
|
||||
err := ws.frameHandler.WriteClose(ws.defaultCloseStatus)
|
||||
err1 := ws.rwc.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err1
|
||||
}
|
||||
|
||||
// IsClientConn reports whether ws is a client-side connection.
|
||||
func (ws *Conn) IsClientConn() bool { return ws.request == nil }
|
||||
|
||||
// IsServerConn reports whether ws is a server-side connection.
|
||||
func (ws *Conn) IsServerConn() bool { return ws.request != nil }
|
||||
|
||||
// LocalAddr returns the WebSocket Origin for the connection for client, or
|
||||
// the WebSocket location for server.
|
||||
func (ws *Conn) LocalAddr() net.Addr {
|
||||
if ws.IsClientConn() {
|
||||
return &Addr{ws.config.Origin}
|
||||
}
|
||||
return &Addr{ws.config.Location}
|
||||
}
|
||||
|
||||
// RemoteAddr returns the WebSocket location for the connection for client, or
|
||||
// the Websocket Origin for server.
|
||||
func (ws *Conn) RemoteAddr() net.Addr {
|
||||
if ws.IsClientConn() {
|
||||
return &Addr{ws.config.Location}
|
||||
}
|
||||
return &Addr{ws.config.Origin}
|
||||
}
|
||||
|
||||
var errSetDeadline = errors.New("websocket: cannot set deadline: not using a net.Conn")
|
||||
|
||||
// SetDeadline sets the connection's network read & write deadlines.
|
||||
func (ws *Conn) SetDeadline(t time.Time) error {
|
||||
if conn, ok := ws.rwc.(net.Conn); ok {
|
||||
return conn.SetDeadline(t)
|
||||
}
|
||||
return errSetDeadline
|
||||
}
|
||||
|
||||
// SetReadDeadline sets the connection's network read deadline.
|
||||
func (ws *Conn) SetReadDeadline(t time.Time) error {
|
||||
if conn, ok := ws.rwc.(net.Conn); ok {
|
||||
return conn.SetReadDeadline(t)
|
||||
}
|
||||
return errSetDeadline
|
||||
}
|
||||
|
||||
// SetWriteDeadline sets the connection's network write deadline.
|
||||
func (ws *Conn) SetWriteDeadline(t time.Time) error {
|
||||
if conn, ok := ws.rwc.(net.Conn); ok {
|
||||
return conn.SetWriteDeadline(t)
|
||||
}
|
||||
return errSetDeadline
|
||||
}
|
||||
|
||||
// Config returns the WebSocket config.
|
||||
func (ws *Conn) Config() *Config { return ws.config }
|
||||
|
||||
// Request returns the http request upgraded to the WebSocket.
|
||||
// It is nil for client side.
|
||||
func (ws *Conn) Request() *http.Request { return ws.request }
|
||||
|
||||
// Codec represents a symmetric pair of functions that implement a codec.
|
||||
type Codec struct {
|
||||
Marshal func(v interface{}) (data []byte, payloadType byte, err error)
|
||||
Unmarshal func(data []byte, payloadType byte, v interface{}) (err error)
|
||||
}
|
||||
|
||||
// Send sends v marshaled by cd.Marshal as single frame to ws.
|
||||
func (cd Codec) Send(ws *Conn, v interface{}) (err error) {
|
||||
data, payloadType, err := cd.Marshal(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ws.wio.Lock()
|
||||
defer ws.wio.Unlock()
|
||||
w, err := ws.frameWriterFactory.NewFrameWriter(payloadType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = w.Write(data)
|
||||
w.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
// Receive receives single frame from ws, unmarshaled by cd.Unmarshal and stores
|
||||
// in v. The whole frame payload is read to an in-memory buffer; max size of
|
||||
// payload is defined by ws.MaxPayloadBytes. If frame payload size exceeds
|
||||
// limit, ErrFrameTooLarge is returned; in this case frame is not read off wire
|
||||
// completely. The next call to Receive would read and discard leftover data of
|
||||
// previous oversized frame before processing next frame.
|
||||
func (cd Codec) Receive(ws *Conn, v interface{}) (err error) {
|
||||
ws.rio.Lock()
|
||||
defer ws.rio.Unlock()
|
||||
if ws.frameReader != nil {
|
||||
_, err = io.Copy(ioutil.Discard, ws.frameReader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ws.frameReader = nil
|
||||
}
|
||||
again:
|
||||
frame, err := ws.frameReaderFactory.NewFrameReader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
frame, err = ws.frameHandler.HandleFrame(frame)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if frame == nil {
|
||||
goto again
|
||||
}
|
||||
maxPayloadBytes := ws.MaxPayloadBytes
|
||||
if maxPayloadBytes == 0 {
|
||||
maxPayloadBytes = DefaultMaxPayloadBytes
|
||||
}
|
||||
if hf, ok := frame.(*hybiFrameReader); ok && hf.header.Length > int64(maxPayloadBytes) {
|
||||
// payload size exceeds limit, no need to call Unmarshal
|
||||
//
|
||||
// set frameReader to current oversized frame so that
|
||||
// the next call to this function can drain leftover
|
||||
// data before processing the next frame
|
||||
ws.frameReader = frame
|
||||
return ErrFrameTooLarge
|
||||
}
|
||||
payloadType := frame.PayloadType()
|
||||
data, err := ioutil.ReadAll(frame)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return cd.Unmarshal(data, payloadType, v)
|
||||
}
|
||||
|
||||
func marshal(v interface{}) (msg []byte, payloadType byte, err error) {
|
||||
switch data := v.(type) {
|
||||
case string:
|
||||
return []byte(data), TextFrame, nil
|
||||
case []byte:
|
||||
return data, BinaryFrame, nil
|
||||
}
|
||||
return nil, UnknownFrame, ErrNotSupported
|
||||
}
|
||||
|
||||
func unmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
|
||||
switch data := v.(type) {
|
||||
case *string:
|
||||
*data = string(msg)
|
||||
return nil
|
||||
case *[]byte:
|
||||
*data = msg
|
||||
return nil
|
||||
}
|
||||
return ErrNotSupported
|
||||
}
|
||||
|
||||
/*
|
||||
Message is a codec to send/receive text/binary data in a frame on WebSocket connection.
|
||||
To send/receive text frame, use string type.
|
||||
To send/receive binary frame, use []byte type.
|
||||
|
||||
Trivial usage:
|
||||
|
||||
import "websocket"
|
||||
|
||||
// receive text frame
|
||||
var message string
|
||||
websocket.Message.Receive(ws, &message)
|
||||
|
||||
// send text frame
|
||||
message = "hello"
|
||||
websocket.Message.Send(ws, message)
|
||||
|
||||
// receive binary frame
|
||||
var data []byte
|
||||
websocket.Message.Receive(ws, &data)
|
||||
|
||||
// send binary frame
|
||||
data = []byte{0, 1, 2}
|
||||
websocket.Message.Send(ws, data)
|
||||
*/
|
||||
var Message = Codec{marshal, unmarshal}
|
||||
|
||||
func jsonMarshal(v interface{}) (msg []byte, payloadType byte, err error) {
|
||||
msg, err = json.Marshal(v)
|
||||
return msg, TextFrame, err
|
||||
}
|
||||
|
||||
func jsonUnmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
|
||||
return json.Unmarshal(msg, v)
|
||||
}
|
||||
|
||||
/*
|
||||
JSON is a codec to send/receive JSON data in a frame from a WebSocket connection.
|
||||
|
||||
Trivial usage:
|
||||
|
||||
import "websocket"
|
||||
|
||||
type T struct {
|
||||
Msg string
|
||||
Count int
|
||||
}
|
||||
|
||||
// receive JSON type T
|
||||
var data T
|
||||
websocket.JSON.Receive(ws, &data)
|
||||
|
||||
// send JSON type T
|
||||
websocket.JSON.Send(ws, data)
|
||||
*/
|
||||
var JSON = Codec{jsonMarshal, jsonUnmarshal}
|
27
vendor/golang.org/x/sync/LICENSE
generated
vendored
Normal file
27
vendor/golang.org/x/sync/LICENSE
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
22
vendor/golang.org/x/sync/PATENTS
generated
vendored
Normal file
22
vendor/golang.org/x/sync/PATENTS
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
Additional IP Rights Grant (Patents)
|
||||
|
||||
"This implementation" means the copyrightable works distributed by
|
||||
Google as part of the Go project.
|
||||
|
||||
Google hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||
no-charge, royalty-free, irrevocable (except as stated in this section)
|
||||
patent license to make, have made, use, offer to sell, sell, import,
|
||||
transfer and otherwise run, modify and propagate the contents of this
|
||||
implementation of Go, where such license applies only to those patent
|
||||
claims, both currently owned or controlled by Google and acquired in
|
||||
the future, licensable by Google that are necessarily infringed by this
|
||||
implementation of Go. This grant does not include claims that would be
|
||||
infringed only as a consequence of further modification of this
|
||||
implementation. If you or your agent or exclusive licensee institute or
|
||||
order or agree to the institution of patent litigation against any
|
||||
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||
that this implementation of Go or any code incorporated within this
|
||||
implementation of Go constitutes direct or contributory patent
|
||||
infringement, or inducement of patent infringement, then any patent
|
||||
rights granted to you under this License for this implementation of Go
|
||||
shall terminate as of the date such litigation is filed.
|
205
vendor/golang.org/x/sync/singleflight/singleflight.go
generated
vendored
Normal file
205
vendor/golang.org/x/sync/singleflight/singleflight.go
generated
vendored
Normal file
@ -0,0 +1,205 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package singleflight provides a duplicate function call suppression
|
||||
// mechanism.
|
||||
package singleflight // import "golang.org/x/sync/singleflight"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// errGoexit indicates the runtime.Goexit was called in
|
||||
// the user given function.
|
||||
var errGoexit = errors.New("runtime.Goexit was called")
|
||||
|
||||
// A panicError is an arbitrary value recovered from a panic
|
||||
// with the stack trace during the execution of given function.
|
||||
type panicError struct {
|
||||
value interface{}
|
||||
stack []byte
|
||||
}
|
||||
|
||||
// Error implements error interface.
|
||||
func (p *panicError) Error() string {
|
||||
return fmt.Sprintf("%v\n\n%s", p.value, p.stack)
|
||||
}
|
||||
|
||||
func newPanicError(v interface{}) error {
|
||||
stack := debug.Stack()
|
||||
|
||||
// The first line of the stack trace is of the form "goroutine N [status]:"
|
||||
// but by the time the panic reaches Do the goroutine may no longer exist
|
||||
// and its status will have changed. Trim out the misleading line.
|
||||
if line := bytes.IndexByte(stack[:], '\n'); line >= 0 {
|
||||
stack = stack[line+1:]
|
||||
}
|
||||
return &panicError{value: v, stack: stack}
|
||||
}
|
||||
|
||||
// call is an in-flight or completed singleflight.Do call
|
||||
type call struct {
|
||||
wg sync.WaitGroup
|
||||
|
||||
// These fields are written once before the WaitGroup is done
|
||||
// and are only read after the WaitGroup is done.
|
||||
val interface{}
|
||||
err error
|
||||
|
||||
// These fields are read and written with the singleflight
|
||||
// mutex held before the WaitGroup is done, and are read but
|
||||
// not written after the WaitGroup is done.
|
||||
dups int
|
||||
chans []chan<- Result
|
||||
}
|
||||
|
||||
// Group represents a class of work and forms a namespace in
|
||||
// which units of work can be executed with duplicate suppression.
|
||||
type Group struct {
|
||||
mu sync.Mutex // protects m
|
||||
m map[string]*call // lazily initialized
|
||||
}
|
||||
|
||||
// Result holds the results of Do, so they can be passed
|
||||
// on a channel.
|
||||
type Result struct {
|
||||
Val interface{}
|
||||
Err error
|
||||
Shared bool
|
||||
}
|
||||
|
||||
// Do executes and returns the results of the given function, making
|
||||
// sure that only one execution is in-flight for a given key at a
|
||||
// time. If a duplicate comes in, the duplicate caller waits for the
|
||||
// original to complete and receives the same results.
|
||||
// The return value shared indicates whether v was given to multiple callers.
|
||||
func (g *Group) Do(key string, fn func() (interface{}, error)) (v interface{}, err error, shared bool) {
|
||||
g.mu.Lock()
|
||||
if g.m == nil {
|
||||
g.m = make(map[string]*call)
|
||||
}
|
||||
if c, ok := g.m[key]; ok {
|
||||
c.dups++
|
||||
g.mu.Unlock()
|
||||
c.wg.Wait()
|
||||
|
||||
if e, ok := c.err.(*panicError); ok {
|
||||
panic(e)
|
||||
} else if c.err == errGoexit {
|
||||
runtime.Goexit()
|
||||
}
|
||||
return c.val, c.err, true
|
||||
}
|
||||
c := new(call)
|
||||
c.wg.Add(1)
|
||||
g.m[key] = c
|
||||
g.mu.Unlock()
|
||||
|
||||
g.doCall(c, key, fn)
|
||||
return c.val, c.err, c.dups > 0
|
||||
}
|
||||
|
||||
// DoChan is like Do but returns a channel that will receive the
|
||||
// results when they are ready.
|
||||
//
|
||||
// The returned channel will not be closed.
|
||||
func (g *Group) DoChan(key string, fn func() (interface{}, error)) <-chan Result {
|
||||
ch := make(chan Result, 1)
|
||||
g.mu.Lock()
|
||||
if g.m == nil {
|
||||
g.m = make(map[string]*call)
|
||||
}
|
||||
if c, ok := g.m[key]; ok {
|
||||
c.dups++
|
||||
c.chans = append(c.chans, ch)
|
||||
g.mu.Unlock()
|
||||
return ch
|
||||
}
|
||||
c := &call{chans: []chan<- Result{ch}}
|
||||
c.wg.Add(1)
|
||||
g.m[key] = c
|
||||
g.mu.Unlock()
|
||||
|
||||
go g.doCall(c, key, fn)
|
||||
|
||||
return ch
|
||||
}
|
||||
|
||||
// doCall handles the single call for a key.
|
||||
func (g *Group) doCall(c *call, key string, fn func() (interface{}, error)) {
|
||||
normalReturn := false
|
||||
recovered := false
|
||||
|
||||
// use double-defer to distinguish panic from runtime.Goexit,
|
||||
// more details see https://golang.org/cl/134395
|
||||
defer func() {
|
||||
// the given function invoked runtime.Goexit
|
||||
if !normalReturn && !recovered {
|
||||
c.err = errGoexit
|
||||
}
|
||||
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
c.wg.Done()
|
||||
if g.m[key] == c {
|
||||
delete(g.m, key)
|
||||
}
|
||||
|
||||
if e, ok := c.err.(*panicError); ok {
|
||||
// In order to prevent the waiting channels from being blocked forever,
|
||||
// needs to ensure that this panic cannot be recovered.
|
||||
if len(c.chans) > 0 {
|
||||
go panic(e)
|
||||
select {} // Keep this goroutine around so that it will appear in the crash dump.
|
||||
} else {
|
||||
panic(e)
|
||||
}
|
||||
} else if c.err == errGoexit {
|
||||
// Already in the process of goexit, no need to call again
|
||||
} else {
|
||||
// Normal return
|
||||
for _, ch := range c.chans {
|
||||
ch <- Result{c.val, c.err, c.dups > 0}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
func() {
|
||||
defer func() {
|
||||
if !normalReturn {
|
||||
// Ideally, we would wait to take a stack trace until we've determined
|
||||
// whether this is a panic or a runtime.Goexit.
|
||||
//
|
||||
// Unfortunately, the only way we can distinguish the two is to see
|
||||
// whether the recover stopped the goroutine from terminating, and by
|
||||
// the time we know that, the part of the stack trace relevant to the
|
||||
// panic has been discarded.
|
||||
if r := recover(); r != nil {
|
||||
c.err = newPanicError(r)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
c.val, c.err = fn()
|
||||
normalReturn = true
|
||||
}()
|
||||
|
||||
if !normalReturn {
|
||||
recovered = true
|
||||
}
|
||||
}
|
||||
|
||||
// Forget tells the singleflight to forget about a key. Future calls
|
||||
// to Do for this key will call the function rather than waiting for
|
||||
// an earlier call to complete.
|
||||
func (g *Group) Forget(key string) {
|
||||
g.mu.Lock()
|
||||
delete(g.m, key)
|
||||
g.mu.Unlock()
|
||||
}
|
28
vendor/golang.org/x/text/width/kind_string.go
generated
vendored
Normal file
28
vendor/golang.org/x/text/width/kind_string.go
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
// Code generated by "stringer -type=Kind"; DO NOT EDIT.
|
||||
|
||||
package width
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[Neutral-0]
|
||||
_ = x[EastAsianAmbiguous-1]
|
||||
_ = x[EastAsianWide-2]
|
||||
_ = x[EastAsianNarrow-3]
|
||||
_ = x[EastAsianFullwidth-4]
|
||||
_ = x[EastAsianHalfwidth-5]
|
||||
}
|
||||
|
||||
const _Kind_name = "NeutralEastAsianAmbiguousEastAsianWideEastAsianNarrowEastAsianFullwidthEastAsianHalfwidth"
|
||||
|
||||
var _Kind_index = [...]uint8{0, 7, 25, 38, 53, 71, 89}
|
||||
|
||||
func (i Kind) String() string {
|
||||
if i < 0 || i >= Kind(len(_Kind_index)-1) {
|
||||
return "Kind(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _Kind_name[_Kind_index[i]:_Kind_index[i+1]]
|
||||
}
|
1329
vendor/golang.org/x/text/width/tables10.0.0.go
generated
vendored
Normal file
1329
vendor/golang.org/x/text/width/tables10.0.0.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1341
vendor/golang.org/x/text/width/tables11.0.0.go
generated
vendored
Normal file
1341
vendor/golang.org/x/text/width/tables11.0.0.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1361
vendor/golang.org/x/text/width/tables12.0.0.go
generated
vendored
Normal file
1361
vendor/golang.org/x/text/width/tables12.0.0.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1362
vendor/golang.org/x/text/width/tables13.0.0.go
generated
vendored
Normal file
1362
vendor/golang.org/x/text/width/tables13.0.0.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1297
vendor/golang.org/x/text/width/tables9.0.0.go
generated
vendored
Normal file
1297
vendor/golang.org/x/text/width/tables9.0.0.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
239
vendor/golang.org/x/text/width/transform.go
generated
vendored
Normal file
239
vendor/golang.org/x/text/width/transform.go
generated
vendored
Normal file
@ -0,0 +1,239 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package width
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
type foldTransform struct {
|
||||
transform.NopResetter
|
||||
}
|
||||
|
||||
func (foldTransform) Span(src []byte, atEOF bool) (n int, err error) {
|
||||
for n < len(src) {
|
||||
if src[n] < utf8.RuneSelf {
|
||||
// ASCII fast path.
|
||||
for n++; n < len(src) && src[n] < utf8.RuneSelf; n++ {
|
||||
}
|
||||
continue
|
||||
}
|
||||
v, size := trie.lookup(src[n:])
|
||||
if size == 0 { // incomplete UTF-8 encoding
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
} else {
|
||||
n = len(src)
|
||||
}
|
||||
break
|
||||
}
|
||||
if elem(v)&tagNeedsFold != 0 {
|
||||
err = transform.ErrEndOfSpan
|
||||
break
|
||||
}
|
||||
n += size
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (foldTransform) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
for nSrc < len(src) {
|
||||
if src[nSrc] < utf8.RuneSelf {
|
||||
// ASCII fast path.
|
||||
start, end := nSrc, len(src)
|
||||
if d := len(dst) - nDst; d < end-start {
|
||||
end = nSrc + d
|
||||
}
|
||||
for nSrc++; nSrc < end && src[nSrc] < utf8.RuneSelf; nSrc++ {
|
||||
}
|
||||
n := copy(dst[nDst:], src[start:nSrc])
|
||||
if nDst += n; nDst == len(dst) {
|
||||
nSrc = start + n
|
||||
if nSrc == len(src) {
|
||||
return nDst, nSrc, nil
|
||||
}
|
||||
if src[nSrc] < utf8.RuneSelf {
|
||||
return nDst, nSrc, transform.ErrShortDst
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
v, size := trie.lookup(src[nSrc:])
|
||||
if size == 0 { // incomplete UTF-8 encoding
|
||||
if !atEOF {
|
||||
return nDst, nSrc, transform.ErrShortSrc
|
||||
}
|
||||
size = 1 // gobble 1 byte
|
||||
}
|
||||
if elem(v)&tagNeedsFold == 0 {
|
||||
if size != copy(dst[nDst:], src[nSrc:nSrc+size]) {
|
||||
return nDst, nSrc, transform.ErrShortDst
|
||||
}
|
||||
nDst += size
|
||||
} else {
|
||||
data := inverseData[byte(v)]
|
||||
if len(dst)-nDst < int(data[0]) {
|
||||
return nDst, nSrc, transform.ErrShortDst
|
||||
}
|
||||
i := 1
|
||||
for end := int(data[0]); i < end; i++ {
|
||||
dst[nDst] = data[i]
|
||||
nDst++
|
||||
}
|
||||
dst[nDst] = data[i] ^ src[nSrc+size-1]
|
||||
nDst++
|
||||
}
|
||||
nSrc += size
|
||||
}
|
||||
return nDst, nSrc, nil
|
||||
}
|
||||
|
||||
type narrowTransform struct {
|
||||
transform.NopResetter
|
||||
}
|
||||
|
||||
func (narrowTransform) Span(src []byte, atEOF bool) (n int, err error) {
|
||||
for n < len(src) {
|
||||
if src[n] < utf8.RuneSelf {
|
||||
// ASCII fast path.
|
||||
for n++; n < len(src) && src[n] < utf8.RuneSelf; n++ {
|
||||
}
|
||||
continue
|
||||
}
|
||||
v, size := trie.lookup(src[n:])
|
||||
if size == 0 { // incomplete UTF-8 encoding
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
} else {
|
||||
n = len(src)
|
||||
}
|
||||
break
|
||||
}
|
||||
if k := elem(v).kind(); byte(v) == 0 || k != EastAsianFullwidth && k != EastAsianWide && k != EastAsianAmbiguous {
|
||||
} else {
|
||||
err = transform.ErrEndOfSpan
|
||||
break
|
||||
}
|
||||
n += size
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (narrowTransform) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
for nSrc < len(src) {
|
||||
if src[nSrc] < utf8.RuneSelf {
|
||||
// ASCII fast path.
|
||||
start, end := nSrc, len(src)
|
||||
if d := len(dst) - nDst; d < end-start {
|
||||
end = nSrc + d
|
||||
}
|
||||
for nSrc++; nSrc < end && src[nSrc] < utf8.RuneSelf; nSrc++ {
|
||||
}
|
||||
n := copy(dst[nDst:], src[start:nSrc])
|
||||
if nDst += n; nDst == len(dst) {
|
||||
nSrc = start + n
|
||||
if nSrc == len(src) {
|
||||
return nDst, nSrc, nil
|
||||
}
|
||||
if src[nSrc] < utf8.RuneSelf {
|
||||
return nDst, nSrc, transform.ErrShortDst
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
v, size := trie.lookup(src[nSrc:])
|
||||
if size == 0 { // incomplete UTF-8 encoding
|
||||
if !atEOF {
|
||||
return nDst, nSrc, transform.ErrShortSrc
|
||||
}
|
||||
size = 1 // gobble 1 byte
|
||||
}
|
||||
if k := elem(v).kind(); byte(v) == 0 || k != EastAsianFullwidth && k != EastAsianWide && k != EastAsianAmbiguous {
|
||||
if size != copy(dst[nDst:], src[nSrc:nSrc+size]) {
|
||||
return nDst, nSrc, transform.ErrShortDst
|
||||
}
|
||||
nDst += size
|
||||
} else {
|
||||
data := inverseData[byte(v)]
|
||||
if len(dst)-nDst < int(data[0]) {
|
||||
return nDst, nSrc, transform.ErrShortDst
|
||||
}
|
||||
i := 1
|
||||
for end := int(data[0]); i < end; i++ {
|
||||
dst[nDst] = data[i]
|
||||
nDst++
|
||||
}
|
||||
dst[nDst] = data[i] ^ src[nSrc+size-1]
|
||||
nDst++
|
||||
}
|
||||
nSrc += size
|
||||
}
|
||||
return nDst, nSrc, nil
|
||||
}
|
||||
|
||||
type wideTransform struct {
|
||||
transform.NopResetter
|
||||
}
|
||||
|
||||
func (wideTransform) Span(src []byte, atEOF bool) (n int, err error) {
|
||||
for n < len(src) {
|
||||
// TODO: Consider ASCII fast path. Special-casing ASCII handling can
|
||||
// reduce the ns/op of BenchmarkWideASCII by about 30%. This is probably
|
||||
// not enough to warrant the extra code and complexity.
|
||||
v, size := trie.lookup(src[n:])
|
||||
if size == 0 { // incomplete UTF-8 encoding
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
} else {
|
||||
n = len(src)
|
||||
}
|
||||
break
|
||||
}
|
||||
if k := elem(v).kind(); byte(v) == 0 || k != EastAsianHalfwidth && k != EastAsianNarrow {
|
||||
} else {
|
||||
err = transform.ErrEndOfSpan
|
||||
break
|
||||
}
|
||||
n += size
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (wideTransform) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
for nSrc < len(src) {
|
||||
// TODO: Consider ASCII fast path. Special-casing ASCII handling can
|
||||
// reduce the ns/op of BenchmarkWideASCII by about 30%. This is probably
|
||||
// not enough to warrant the extra code and complexity.
|
||||
v, size := trie.lookup(src[nSrc:])
|
||||
if size == 0 { // incomplete UTF-8 encoding
|
||||
if !atEOF {
|
||||
return nDst, nSrc, transform.ErrShortSrc
|
||||
}
|
||||
size = 1 // gobble 1 byte
|
||||
}
|
||||
if k := elem(v).kind(); byte(v) == 0 || k != EastAsianHalfwidth && k != EastAsianNarrow {
|
||||
if size != copy(dst[nDst:], src[nSrc:nSrc+size]) {
|
||||
return nDst, nSrc, transform.ErrShortDst
|
||||
}
|
||||
nDst += size
|
||||
} else {
|
||||
data := inverseData[byte(v)]
|
||||
if len(dst)-nDst < int(data[0]) {
|
||||
return nDst, nSrc, transform.ErrShortDst
|
||||
}
|
||||
i := 1
|
||||
for end := int(data[0]); i < end; i++ {
|
||||
dst[nDst] = data[i]
|
||||
nDst++
|
||||
}
|
||||
dst[nDst] = data[i] ^ src[nSrc+size-1]
|
||||
nDst++
|
||||
}
|
||||
nSrc += size
|
||||
}
|
||||
return nDst, nSrc, nil
|
||||
}
|
30
vendor/golang.org/x/text/width/trieval.go
generated
vendored
Normal file
30
vendor/golang.org/x/text/width/trieval.go
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
package width
|
||||
|
||||
// elem is an entry of the width trie. The high byte is used to encode the type
|
||||
// of the rune. The low byte is used to store the index to a mapping entry in
|
||||
// the inverseData array.
|
||||
type elem uint16
|
||||
|
||||
const (
|
||||
tagNeutral elem = iota << typeShift
|
||||
tagAmbiguous
|
||||
tagWide
|
||||
tagNarrow
|
||||
tagFullwidth
|
||||
tagHalfwidth
|
||||
)
|
||||
|
||||
const (
|
||||
numTypeBits = 3
|
||||
typeShift = 16 - numTypeBits
|
||||
|
||||
// tagNeedsFold is true for all fullwidth and halfwidth runes except for
|
||||
// the Won sign U+20A9.
|
||||
tagNeedsFold = 0x1000
|
||||
|
||||
// The Korean Won sign is halfwidth, but SHOULD NOT be mapped to a wide
|
||||
// variant.
|
||||
wonSign rune = 0x20A9
|
||||
)
|
206
vendor/golang.org/x/text/width/width.go
generated
vendored
Normal file
206
vendor/golang.org/x/text/width/width.go
generated
vendored
Normal file
@ -0,0 +1,206 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate stringer -type=Kind
|
||||
//go:generate go run gen.go gen_common.go gen_trieval.go
|
||||
|
||||
// Package width provides functionality for handling different widths in text.
|
||||
//
|
||||
// Wide characters behave like ideographs; they tend to allow line breaks after
|
||||
// each character and remain upright in vertical text layout. Narrow characters
|
||||
// are kept together in words or runs that are rotated sideways in vertical text
|
||||
// layout.
|
||||
//
|
||||
// For more information, see https://unicode.org/reports/tr11/.
|
||||
package width // import "golang.org/x/text/width"
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// TODO
|
||||
// 1) Reduce table size by compressing blocks.
|
||||
// 2) API proposition for computing display length
|
||||
// (approximation, fixed pitch only).
|
||||
// 3) Implement display length.
|
||||
|
||||
// Kind indicates the type of width property as defined in https://unicode.org/reports/tr11/.
|
||||
type Kind int
|
||||
|
||||
const (
|
||||
// Neutral characters do not occur in legacy East Asian character sets.
|
||||
Neutral Kind = iota
|
||||
|
||||
// EastAsianAmbiguous characters that can be sometimes wide and sometimes
|
||||
// narrow and require additional information not contained in the character
|
||||
// code to further resolve their width.
|
||||
EastAsianAmbiguous
|
||||
|
||||
// EastAsianWide characters are wide in its usual form. They occur only in
|
||||
// the context of East Asian typography. These runes may have explicit
|
||||
// halfwidth counterparts.
|
||||
EastAsianWide
|
||||
|
||||
// EastAsianNarrow characters are narrow in its usual form. They often have
|
||||
// fullwidth counterparts.
|
||||
EastAsianNarrow
|
||||
|
||||
// Note: there exist Narrow runes that do not have fullwidth or wide
|
||||
// counterparts, despite what the definition says (e.g. U+27E6).
|
||||
|
||||
// EastAsianFullwidth characters have a compatibility decompositions of type
|
||||
// wide that map to a narrow counterpart.
|
||||
EastAsianFullwidth
|
||||
|
||||
// EastAsianHalfwidth characters have a compatibility decomposition of type
|
||||
// narrow that map to a wide or ambiguous counterpart, plus U+20A9 ₩ WON
|
||||
// SIGN.
|
||||
EastAsianHalfwidth
|
||||
|
||||
// Note: there exist runes that have a halfwidth counterparts but that are
|
||||
// classified as Ambiguous, rather than wide (e.g. U+2190).
|
||||
)
|
||||
|
||||
// TODO: the generated tries need to return size 1 for invalid runes for the
|
||||
// width to be computed correctly (each byte should render width 1)
|
||||
|
||||
var trie = newWidthTrie(0)
|
||||
|
||||
// Lookup reports the Properties of the first rune in b and the number of bytes
|
||||
// of its UTF-8 encoding.
|
||||
func Lookup(b []byte) (p Properties, size int) {
|
||||
v, sz := trie.lookup(b)
|
||||
return Properties{elem(v), b[sz-1]}, sz
|
||||
}
|
||||
|
||||
// LookupString reports the Properties of the first rune in s and the number of
|
||||
// bytes of its UTF-8 encoding.
|
||||
func LookupString(s string) (p Properties, size int) {
|
||||
v, sz := trie.lookupString(s)
|
||||
return Properties{elem(v), s[sz-1]}, sz
|
||||
}
|
||||
|
||||
// LookupRune reports the Properties of rune r.
|
||||
func LookupRune(r rune) Properties {
|
||||
var buf [4]byte
|
||||
n := utf8.EncodeRune(buf[:], r)
|
||||
v, _ := trie.lookup(buf[:n])
|
||||
last := byte(r)
|
||||
if r >= utf8.RuneSelf {
|
||||
last = 0x80 + byte(r&0x3f)
|
||||
}
|
||||
return Properties{elem(v), last}
|
||||
}
|
||||
|
||||
// Properties provides access to width properties of a rune.
|
||||
type Properties struct {
|
||||
elem elem
|
||||
last byte
|
||||
}
|
||||
|
||||
func (e elem) kind() Kind {
|
||||
return Kind(e >> typeShift)
|
||||
}
|
||||
|
||||
// Kind returns the Kind of a rune as defined in Unicode TR #11.
|
||||
// See https://unicode.org/reports/tr11/ for more details.
|
||||
func (p Properties) Kind() Kind {
|
||||
return p.elem.kind()
|
||||
}
|
||||
|
||||
// Folded returns the folded variant of a rune or 0 if the rune is canonical.
|
||||
func (p Properties) Folded() rune {
|
||||
if p.elem&tagNeedsFold != 0 {
|
||||
buf := inverseData[byte(p.elem)]
|
||||
buf[buf[0]] ^= p.last
|
||||
r, _ := utf8.DecodeRune(buf[1 : 1+buf[0]])
|
||||
return r
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Narrow returns the narrow variant of a rune or 0 if the rune is already
|
||||
// narrow or doesn't have a narrow variant.
|
||||
func (p Properties) Narrow() rune {
|
||||
if k := p.elem.kind(); byte(p.elem) != 0 && (k == EastAsianFullwidth || k == EastAsianWide || k == EastAsianAmbiguous) {
|
||||
buf := inverseData[byte(p.elem)]
|
||||
buf[buf[0]] ^= p.last
|
||||
r, _ := utf8.DecodeRune(buf[1 : 1+buf[0]])
|
||||
return r
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Wide returns the wide variant of a rune or 0 if the rune is already
|
||||
// wide or doesn't have a wide variant.
|
||||
func (p Properties) Wide() rune {
|
||||
if k := p.elem.kind(); byte(p.elem) != 0 && (k == EastAsianHalfwidth || k == EastAsianNarrow) {
|
||||
buf := inverseData[byte(p.elem)]
|
||||
buf[buf[0]] ^= p.last
|
||||
r, _ := utf8.DecodeRune(buf[1 : 1+buf[0]])
|
||||
return r
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// TODO for Properties:
|
||||
// - Add Fullwidth/Halfwidth or Inverted methods for computing variants
|
||||
// mapping.
|
||||
// - Add width information (including information on non-spacing runes).
|
||||
|
||||
// Transformer implements the transform.Transformer interface.
|
||||
type Transformer struct {
|
||||
t transform.SpanningTransformer
|
||||
}
|
||||
|
||||
// Reset implements the transform.Transformer interface.
|
||||
func (t Transformer) Reset() { t.t.Reset() }
|
||||
|
||||
// Transform implements the transform.Transformer interface.
|
||||
func (t Transformer) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
return t.t.Transform(dst, src, atEOF)
|
||||
}
|
||||
|
||||
// Span implements the transform.SpanningTransformer interface.
|
||||
func (t Transformer) Span(src []byte, atEOF bool) (n int, err error) {
|
||||
return t.t.Span(src, atEOF)
|
||||
}
|
||||
|
||||
// Bytes returns a new byte slice with the result of applying t to b.
|
||||
func (t Transformer) Bytes(b []byte) []byte {
|
||||
b, _, _ = transform.Bytes(t, b)
|
||||
return b
|
||||
}
|
||||
|
||||
// String returns a string with the result of applying t to s.
|
||||
func (t Transformer) String(s string) string {
|
||||
s, _, _ = transform.String(t, s)
|
||||
return s
|
||||
}
|
||||
|
||||
var (
|
||||
// Fold is a transform that maps all runes to their canonical width.
|
||||
//
|
||||
// Note that the NFKC and NFKD transforms in golang.org/x/text/unicode/norm
|
||||
// provide a more generic folding mechanism.
|
||||
Fold Transformer = Transformer{foldTransform{}}
|
||||
|
||||
// Widen is a transform that maps runes to their wide variant, if
|
||||
// available.
|
||||
Widen Transformer = Transformer{wideTransform{}}
|
||||
|
||||
// Narrow is a transform that maps runes to their narrow variant, if
|
||||
// available.
|
||||
Narrow Transformer = Transformer{narrowTransform{}}
|
||||
)
|
||||
|
||||
// TODO: Consider the following options:
|
||||
// - Treat Ambiguous runes that have a halfwidth counterpart as wide, or some
|
||||
// generalized variant of this.
|
||||
// - Consider a wide Won character to be the default width (or some generalized
|
||||
// variant of this).
|
||||
// - Filter the set of characters that gets converted (the preferred approach is
|
||||
// to allow applying filters to transforms).
|
Reference in New Issue
Block a user