Updating server dependancies. Also adding github.com/jaytaylor/html2text and gopkg.in/gomail.v2 (#5748)

Этот коммит содержится в:
Christopher Speller
2017-03-13 12:54:22 -04:00
коммит произвёл GitHub
родитель 3ada7a41a7
Коммит c281ee3b61
356 изменённых файлов: 26671 добавлений и 14262 удалений

119
vendor/golang.org/x/crypto/acme/acme.go сгенерированный поставляемый
Просмотреть файл

@@ -47,6 +47,10 @@ const LetsEncryptURL = "https://acme-v01.api.letsencrypt.org/directory"
const (
maxChainLen = 5 // max depth and breadth of a certificate chain
maxCertSize = 1 << 20 // max size of a certificate, in bytes
// Max number of collected nonces kept in memory.
// Expect usual peak of 1 or 2.
maxNonces = 100
)
// CertOption is an optional argument type for Client methods which manipulate
@@ -108,6 +112,9 @@ type Client struct {
dirMu sync.Mutex // guards writes to dir
dir *Directory // cached result of Client's Discover method
noncesMu sync.Mutex
nonces map[string]struct{} // nonces collected from previous responses
}
// Discover performs ACME server discovery using c.DirectoryURL.
@@ -131,6 +138,7 @@ func (c *Client) Discover(ctx context.Context) (Directory, error) {
return Directory{}, err
}
defer res.Body.Close()
c.addNonce(res.Header)
if res.StatusCode != http.StatusOK {
return Directory{}, responseError(res)
}
@@ -192,7 +200,7 @@ func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration,
req.NotAfter = now.Add(exp).Format(time.RFC3339)
}
res, err := postJWS(ctx, c.HTTPClient, c.Key, c.dir.CertURL, req)
res, err := c.postJWS(ctx, c.Key, c.dir.CertURL, req)
if err != nil {
return nil, "", err
}
@@ -267,7 +275,7 @@ func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte,
if key == nil {
key = c.Key
}
res, err := postJWS(ctx, c.HTTPClient, key, c.dir.RevokeURL, body)
res, err := c.postJWS(ctx, key, c.dir.RevokeURL, body)
if err != nil {
return err
}
@@ -355,7 +363,7 @@ func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization,
Resource: "new-authz",
Identifier: authzID{Type: "dns", Value: domain},
}
res, err := postJWS(ctx, c.HTTPClient, c.Key, c.dir.AuthzURL, req)
res, err := c.postJWS(ctx, c.Key, c.dir.AuthzURL, req)
if err != nil {
return nil, err
}
@@ -413,7 +421,7 @@ func (c *Client) RevokeAuthorization(ctx context.Context, url string) error {
Status: "deactivated",
Delete: true,
}
res, err := postJWS(ctx, c.HTTPClient, c.Key, url, req)
res, err := c.postJWS(ctx, c.Key, url, req)
if err != nil {
return err
}
@@ -519,7 +527,7 @@ func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error
Type: chal.Type,
Auth: auth,
}
res, err := postJWS(ctx, c.HTTPClient, c.Key, chal.URI, req)
res, err := c.postJWS(ctx, c.Key, chal.URI, req)
if err != nil {
return nil, err
}
@@ -652,7 +660,7 @@ func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Accoun
req.Contact = acct.Contact
req.Agreement = acct.AgreedTerms
}
res, err := postJWS(ctx, c.HTTPClient, c.Key, url, req)
res, err := c.postJWS(ctx, c.Key, url, req)
if err != nil {
return nil, err
}
@@ -689,6 +697,78 @@ func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Accoun
}, nil
}
// postJWS signs the body with the given key and POSTs it to the provided url.
// The body argument must be JSON-serializable.
func (c *Client) postJWS(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, error) {
nonce, err := c.popNonce(ctx, url)
if err != nil {
return nil, err
}
b, err := jwsEncodeJSON(body, key, nonce)
if err != nil {
return nil, err
}
res, err := ctxhttp.Post(ctx, c.HTTPClient, url, "application/jose+json", bytes.NewReader(b))
if err != nil {
return nil, err
}
c.addNonce(res.Header)
return res, nil
}
// popNonce returns a nonce value previously stored with c.addNonce
// or fetches a fresh one from the given URL.
func (c *Client) popNonce(ctx context.Context, url string) (string, error) {
c.noncesMu.Lock()
defer c.noncesMu.Unlock()
if len(c.nonces) == 0 {
return fetchNonce(ctx, c.HTTPClient, url)
}
var nonce string
for nonce = range c.nonces {
delete(c.nonces, nonce)
break
}
return nonce, nil
}
// addNonce stores a nonce value found in h (if any) for future use.
func (c *Client) addNonce(h http.Header) {
v := nonceFromHeader(h)
if v == "" {
return
}
c.noncesMu.Lock()
defer c.noncesMu.Unlock()
if len(c.nonces) >= maxNonces {
return
}
if c.nonces == nil {
c.nonces = make(map[string]struct{})
}
c.nonces[v] = struct{}{}
}
func fetchNonce(ctx context.Context, client *http.Client, url string) (string, error) {
resp, err := ctxhttp.Head(ctx, client, url)
if err != nil {
return "", err
}
defer resp.Body.Close()
nonce := nonceFromHeader(resp.Header)
if nonce == "" {
if resp.StatusCode > 299 {
return "", responseError(resp)
}
return "", errors.New("acme: nonce not found")
}
return nonce, nil
}
func nonceFromHeader(h http.Header) string {
return h.Get("Replay-Nonce")
}
func responseCert(ctx context.Context, client *http.Client, res *http.Response, bundle bool) ([][]byte, error) {
b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1))
if err != nil {
@@ -793,33 +873,6 @@ func chainCert(ctx context.Context, client *http.Client, url string, depth int)
return chain, nil
}
// postJWS signs the body with the given key and POSTs it to the provided url.
// The body argument must be JSON-serializable.
func postJWS(ctx context.Context, client *http.Client, key crypto.Signer, url string, body interface{}) (*http.Response, error) {
nonce, err := fetchNonce(ctx, client, url)
if err != nil {
return nil, err
}
b, err := jwsEncodeJSON(body, key, nonce)
if err != nil {
return nil, err
}
return ctxhttp.Post(ctx, client, url, "application/jose+json", bytes.NewReader(b))
}
func fetchNonce(ctx context.Context, client *http.Client, url string) (string, error) {
resp, err := ctxhttp.Head(ctx, client, url)
if err != nil {
return "", nil
}
defer resp.Body.Close()
enc := resp.Header.Get("replay-nonce")
if enc == "" {
return "", errors.New("acme: nonce not found")
}
return enc, nil
}
// linkHeader returns URI-Reference values of all Link headers
// with relation-type rel.
// See https://tools.ietf.org/html/rfc5988#section-5 for details.

117
vendor/golang.org/x/crypto/acme/acme_test.go сгенерированный поставляемый
Просмотреть файл

@@ -45,6 +45,28 @@ func decodeJWSRequest(t *testing.T, v interface{}, r *http.Request) {
}
}
type jwsHead struct {
Alg string
Nonce string
JWK map[string]string `json:"jwk"`
}
func decodeJWSHead(r *http.Request) (*jwsHead, error) {
var req struct{ Protected string }
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
return nil, err
}
b, err := base64.RawURLEncoding.DecodeString(req.Protected)
if err != nil {
return nil, err
}
var head jwsHead
if err := json.Unmarshal(b, &head); err != nil {
return nil, err
}
return &head, nil
}
func TestDiscover(t *testing.T) {
const (
reg = "https://example.com/acme/new-reg"
@@ -916,7 +938,30 @@ func TestRevokeCert(t *testing.T) {
}
}
func TestFetchNonce(t *testing.T) {
func TestNonce_add(t *testing.T) {
var c Client
c.addNonce(http.Header{"Replay-Nonce": {"nonce"}})
c.addNonce(http.Header{"Replay-Nonce": {}})
c.addNonce(http.Header{"Replay-Nonce": {"nonce"}})
nonces := map[string]struct{}{"nonce": struct{}{}}
if !reflect.DeepEqual(c.nonces, nonces) {
t.Errorf("c.nonces = %q; want %q", c.nonces, nonces)
}
}
func TestNonce_addMax(t *testing.T) {
c := &Client{nonces: make(map[string]struct{})}
for i := 0; i < maxNonces; i++ {
c.nonces[fmt.Sprintf("%d", i)] = struct{}{}
}
c.addNonce(http.Header{"Replay-Nonce": {"nonce"}})
if n := len(c.nonces); n != maxNonces {
t.Errorf("len(c.nonces) = %d; want %d", n, maxNonces)
}
}
func TestNonce_fetch(t *testing.T) {
tests := []struct {
code int
nonce string
@@ -949,6 +994,76 @@ func TestFetchNonce(t *testing.T) {
}
}
func TestNonce_fetchError(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusTooManyRequests)
}))
defer ts.Close()
_, err := fetchNonce(context.Background(), http.DefaultClient, ts.URL)
e, ok := err.(*Error)
if !ok {
t.Fatalf("err is %T; want *Error", err)
}
if e.StatusCode != http.StatusTooManyRequests {
t.Errorf("e.StatusCode = %d; want %d", e.StatusCode, http.StatusTooManyRequests)
}
}
func TestNonce_postJWS(t *testing.T) {
var count int
seen := make(map[string]bool)
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
count++
w.Header().Set("replay-nonce", fmt.Sprintf("nonce%d", count))
if r.Method == "HEAD" {
// We expect the client do a HEAD request
// but only to fetch the first nonce.
return
}
// Make client.Authorize happy; we're not testing its result.
defer func() {
w.WriteHeader(http.StatusCreated)
w.Write([]byte(`{"status":"valid"}`))
}()
head, err := decodeJWSHead(r)
if err != nil {
t.Errorf("decodeJWSHead: %v", err)
return
}
if head.Nonce == "" {
t.Error("head.Nonce is empty")
return
}
if seen[head.Nonce] {
t.Errorf("nonce is already used: %q", head.Nonce)
}
seen[head.Nonce] = true
}))
defer ts.Close()
client := Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}}
if _, err := client.Authorize(context.Background(), "example.com"); err != nil {
t.Errorf("client.Authorize 1: %v", err)
}
// The second call should not generate another extra HEAD request.
if _, err := client.Authorize(context.Background(), "example.com"); err != nil {
t.Errorf("client.Authorize 2: %v", err)
}
if count != 3 {
t.Errorf("total requests count: %d; want 3", count)
}
if n := len(client.nonces); n != 1 {
t.Errorf("len(client.nonces) = %d; want 1", n)
}
for k := range seen {
if _, exist := client.nonces[k]; exist {
t.Errorf("used nonce %q in client.nonces", k)
}
}
}
func TestLinkHeader(t *testing.T) {
h := http.Header{"Link": {
`<https://example.com/acme/new-authz>;rel="next"`,

41
vendor/golang.org/x/crypto/acme/autocert/autocert_test.go сгенерированный поставляемый
Просмотреть файл

@@ -22,6 +22,7 @@ import (
"net/http"
"net/http/httptest"
"reflect"
"sync"
"testing"
"time"
@@ -51,26 +52,44 @@ var authzTmpl = template.Must(template.New("authz").Parse(`{
]
}`))
type memCache map[string][]byte
type memCache struct {
mu sync.Mutex
keyData map[string][]byte
}
func (m memCache) Get(ctx context.Context, key string) ([]byte, error) {
v, ok := m[key]
func (m *memCache) Get(ctx context.Context, key string) ([]byte, error) {
m.mu.Lock()
defer m.mu.Unlock()
v, ok := m.keyData[key]
if !ok {
return nil, ErrCacheMiss
}
return v, nil
}
func (m memCache) Put(ctx context.Context, key string, data []byte) error {
m[key] = data
func (m *memCache) Put(ctx context.Context, key string, data []byte) error {
m.mu.Lock()
defer m.mu.Unlock()
m.keyData[key] = data
return nil
}
func (m memCache) Delete(ctx context.Context, key string) error {
delete(m, key)
func (m *memCache) Delete(ctx context.Context, key string) error {
m.mu.Lock()
defer m.mu.Unlock()
delete(m.keyData, key)
return nil
}
func newMemCache() *memCache {
return &memCache{
keyData: make(map[string][]byte),
}
}
func dummyCert(pub interface{}, san ...string) ([]byte, error) {
return dateDummyCert(pub, time.Now(), time.Now().Add(90*24*time.Hour), san...)
}
@@ -124,7 +143,7 @@ func TestGetCertificate_trailingDot(t *testing.T) {
func TestGetCertificate_ForceRSA(t *testing.T) {
man := &Manager{
Prompt: AcceptTOS,
Cache: make(memCache),
Cache: newMemCache(),
ForceRSA: true,
}
defer man.stopRenew()
@@ -280,8 +299,7 @@ func testGetCertificate(t *testing.T, man *Manager, domain string, hello *tls.Cl
}
func TestAccountKeyCache(t *testing.T) {
cache := make(memCache)
m := Manager{Cache: cache}
m := Manager{Cache: newMemCache()}
ctx := context.Background()
k1, err := m.accountKey(ctx)
if err != nil {
@@ -315,8 +333,7 @@ func TestCache(t *testing.T) {
PrivateKey: privKey,
}
cache := make(memCache)
man := &Manager{Cache: cache}
man := &Manager{Cache: newMemCache()}
defer man.stopRenew()
if err := man.cachePut("example.org", tlscert); err != nil {
t.Fatalf("man.cachePut: %v", err)

2
vendor/golang.org/x/crypto/acme/autocert/renewal_test.go сгенерированный поставляемый
Просмотреть файл

@@ -111,7 +111,7 @@ func TestRenewFromCache(t *testing.T) {
}
man := &Manager{
Prompt: AcceptTOS,
Cache: make(memCache),
Cache: newMemCache(),
RenewBefore: 24 * time.Hour,
Client: &acme.Client{
Key: key,

688
vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s сгенерированный поставляемый
Просмотреть файл

@@ -54,68 +54,223 @@ DATA ·AVX_c48<>+0x00(SB)/8, $0x0100070605040302
DATA ·AVX_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a
GLOBL ·AVX_c48<>(SB), (NOPTR+RODATA), $16
// unfortunately the BYTE representation of VPERMQ must be used
#define ROUND_AVX2(m0, m1, m2, m3, t, c40, c48) \
VPADDQ m0, Y0, Y0; \
VPADDQ Y1, Y0, Y0; \
VPXOR Y0, Y3, Y3; \
VPSHUFD $-79, Y3, Y3; \
VPADDQ Y3, Y2, Y2; \
VPXOR Y2, Y1, Y1; \
VPSHUFB c40, Y1, Y1; \
VPADDQ m1, Y0, Y0; \
VPADDQ Y1, Y0, Y0; \
VPXOR Y0, Y3, Y3; \
VPSHUFB c48, Y3, Y3; \
VPADDQ Y3, Y2, Y2; \
VPXOR Y2, Y1, Y1; \
VPADDQ Y1, Y1, t; \
VPSRLQ $63, Y1, Y1; \
VPXOR t, Y1, Y1; \
BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x39 \ // VPERMQ 0x39, Y1, Y1
BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e \ // VPERMQ 0x4e, Y2, Y2
BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x93 \ // VPERMQ 0x93, Y3, Y3
VPADDQ m2, Y0, Y0; \
VPADDQ Y1, Y0, Y0; \
VPXOR Y0, Y3, Y3; \
VPSHUFD $-79, Y3, Y3; \
VPADDQ Y3, Y2, Y2; \
VPXOR Y2, Y1, Y1; \
VPSHUFB c40, Y1, Y1; \
VPADDQ m3, Y0, Y0; \
VPADDQ Y1, Y0, Y0; \
VPXOR Y0, Y3, Y3; \
VPSHUFB c48, Y3, Y3; \
VPADDQ Y3, Y2, Y2; \
VPXOR Y2, Y1, Y1; \
VPADDQ Y1, Y1, t; \
VPSRLQ $63, Y1, Y1; \
VPXOR t, Y1, Y1; \
BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x39 \ // VPERMQ 0x39, Y3, Y3
BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e \ // VPERMQ 0x4e, Y2, Y2
BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x93 \ // VPERMQ 0x93, Y1, Y1
#define VPERMQ_0x39_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x39
#define VPERMQ_0x93_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x93
#define VPERMQ_0x4E_Y2_Y2 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e
#define VPERMQ_0x93_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x93
#define VPERMQ_0x39_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x39
// load msg into Y12, Y13, Y14, Y15
#define LOAD_MSG_AVX2(src, i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15) \
MOVQ i0*8(src), X12; \
PINSRQ $1, i1*8(src), X12; \
MOVQ i2*8(src), X11; \
PINSRQ $1, i3*8(src), X11; \
VINSERTI128 $1, X11, Y12, Y12; \
MOVQ i4*8(src), X13; \
PINSRQ $1, i5*8(src), X13; \
MOVQ i6*8(src), X11; \
PINSRQ $1, i7*8(src), X11; \
VINSERTI128 $1, X11, Y13, Y13; \
MOVQ i8*8(src), X14; \
PINSRQ $1, i9*8(src), X14; \
MOVQ i10*8(src), X11; \
PINSRQ $1, i11*8(src), X11; \
#define ROUND_AVX2(m0, m1, m2, m3, t, c40, c48) \
VPADDQ m0, Y0, Y0; \
VPADDQ Y1, Y0, Y0; \
VPXOR Y0, Y3, Y3; \
VPSHUFD $-79, Y3, Y3; \
VPADDQ Y3, Y2, Y2; \
VPXOR Y2, Y1, Y1; \
VPSHUFB c40, Y1, Y1; \
VPADDQ m1, Y0, Y0; \
VPADDQ Y1, Y0, Y0; \
VPXOR Y0, Y3, Y3; \
VPSHUFB c48, Y3, Y3; \
VPADDQ Y3, Y2, Y2; \
VPXOR Y2, Y1, Y1; \
VPADDQ Y1, Y1, t; \
VPSRLQ $63, Y1, Y1; \
VPXOR t, Y1, Y1; \
VPERMQ_0x39_Y1_Y1; \
VPERMQ_0x4E_Y2_Y2; \
VPERMQ_0x93_Y3_Y3; \
VPADDQ m2, Y0, Y0; \
VPADDQ Y1, Y0, Y0; \
VPXOR Y0, Y3, Y3; \
VPSHUFD $-79, Y3, Y3; \
VPADDQ Y3, Y2, Y2; \
VPXOR Y2, Y1, Y1; \
VPSHUFB c40, Y1, Y1; \
VPADDQ m3, Y0, Y0; \
VPADDQ Y1, Y0, Y0; \
VPXOR Y0, Y3, Y3; \
VPSHUFB c48, Y3, Y3; \
VPADDQ Y3, Y2, Y2; \
VPXOR Y2, Y1, Y1; \
VPADDQ Y1, Y1, t; \
VPSRLQ $63, Y1, Y1; \
VPXOR t, Y1, Y1; \
VPERMQ_0x39_Y3_Y3; \
VPERMQ_0x4E_Y2_Y2; \
VPERMQ_0x93_Y1_Y1
#define VMOVQ_SI_X11_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x1E
#define VMOVQ_SI_X12_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x26
#define VMOVQ_SI_X13_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x2E
#define VMOVQ_SI_X14_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x36
#define VMOVQ_SI_X15_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x3E
#define VMOVQ_SI_X11(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x5E; BYTE $n
#define VMOVQ_SI_X12(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x66; BYTE $n
#define VMOVQ_SI_X13(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x6E; BYTE $n
#define VMOVQ_SI_X14(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x76; BYTE $n
#define VMOVQ_SI_X15(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x7E; BYTE $n
#define VPINSRQ_1_SI_X11_0 BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x1E; BYTE $0x01
#define VPINSRQ_1_SI_X12_0 BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x26; BYTE $0x01
#define VPINSRQ_1_SI_X13_0 BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x2E; BYTE $0x01
#define VPINSRQ_1_SI_X14_0 BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x36; BYTE $0x01
#define VPINSRQ_1_SI_X15_0 BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x3E; BYTE $0x01
#define VPINSRQ_1_SI_X11(n) BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x5E; BYTE $n; BYTE $0x01
#define VPINSRQ_1_SI_X12(n) BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x66; BYTE $n; BYTE $0x01
#define VPINSRQ_1_SI_X13(n) BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x6E; BYTE $n; BYTE $0x01
#define VPINSRQ_1_SI_X14(n) BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x76; BYTE $n; BYTE $0x01
#define VPINSRQ_1_SI_X15(n) BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x7E; BYTE $n; BYTE $0x01
#define VMOVQ_R8_X15 BYTE $0xC4; BYTE $0x41; BYTE $0xF9; BYTE $0x6E; BYTE $0xF8
#define VPINSRQ_1_R9_X15 BYTE $0xC4; BYTE $0x43; BYTE $0x81; BYTE $0x22; BYTE $0xF9; BYTE $0x01
// load msg: Y12 = (i0, i1, i2, i3)
// i0, i1, i2, i3 must not be 0
#define LOAD_MSG_AVX2_Y12(i0, i1, i2, i3) \
VMOVQ_SI_X12(i0*8); \
VMOVQ_SI_X11(i2*8); \
VPINSRQ_1_SI_X12(i1*8); \
VPINSRQ_1_SI_X11(i3*8); \
VINSERTI128 $1, X11, Y12, Y12
// load msg: Y13 = (i0, i1, i2, i3)
// i0, i1, i2, i3 must not be 0
#define LOAD_MSG_AVX2_Y13(i0, i1, i2, i3) \
VMOVQ_SI_X13(i0*8); \
VMOVQ_SI_X11(i2*8); \
VPINSRQ_1_SI_X13(i1*8); \
VPINSRQ_1_SI_X11(i3*8); \
VINSERTI128 $1, X11, Y13, Y13
// load msg: Y14 = (i0, i1, i2, i3)
// i0, i1, i2, i3 must not be 0
#define LOAD_MSG_AVX2_Y14(i0, i1, i2, i3) \
VMOVQ_SI_X14(i0*8); \
VMOVQ_SI_X11(i2*8); \
VPINSRQ_1_SI_X14(i1*8); \
VPINSRQ_1_SI_X11(i3*8); \
VINSERTI128 $1, X11, Y14, Y14
// load msg: Y15 = (i0, i1, i2, i3)
// i0, i1, i2, i3 must not be 0
#define LOAD_MSG_AVX2_Y15(i0, i1, i2, i3) \
VMOVQ_SI_X15(i0*8); \
VMOVQ_SI_X11(i2*8); \
VPINSRQ_1_SI_X15(i1*8); \
VPINSRQ_1_SI_X11(i3*8); \
VINSERTI128 $1, X11, Y15, Y15
#define LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() \
VMOVQ_SI_X12_0; \
VMOVQ_SI_X11(4*8); \
VPINSRQ_1_SI_X12(2*8); \
VPINSRQ_1_SI_X11(6*8); \
VINSERTI128 $1, X11, Y12, Y12; \
LOAD_MSG_AVX2_Y13(1, 3, 5, 7); \
LOAD_MSG_AVX2_Y14(8, 10, 12, 14); \
LOAD_MSG_AVX2_Y15(9, 11, 13, 15)
#define LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() \
LOAD_MSG_AVX2_Y12(14, 4, 9, 13); \
LOAD_MSG_AVX2_Y13(10, 8, 15, 6); \
VMOVQ_SI_X11(11*8); \
VPSHUFD $0x4E, 0*8(SI), X14; \
VPINSRQ_1_SI_X11(5*8); \
VINSERTI128 $1, X11, Y14, Y14; \
MOVQ i12*8(src), X15; \
PINSRQ $1, i13*8(src), X15; \
MOVQ i14*8(src), X11; \
PINSRQ $1, i15*8(src), X11; \
LOAD_MSG_AVX2_Y15(12, 2, 7, 3)
#define LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() \
VMOVQ_SI_X11(5*8); \
VMOVDQU 11*8(SI), X12; \
VPINSRQ_1_SI_X11(15*8); \
VINSERTI128 $1, X11, Y12, Y12; \
VMOVQ_SI_X13(8*8); \
VMOVQ_SI_X11(2*8); \
VPINSRQ_1_SI_X13_0; \
VPINSRQ_1_SI_X11(13*8); \
VINSERTI128 $1, X11, Y13, Y13; \
LOAD_MSG_AVX2_Y14(10, 3, 7, 9); \
LOAD_MSG_AVX2_Y15(14, 6, 1, 4)
#define LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() \
LOAD_MSG_AVX2_Y12(7, 3, 13, 11); \
LOAD_MSG_AVX2_Y13(9, 1, 12, 14); \
LOAD_MSG_AVX2_Y14(2, 5, 4, 15); \
VMOVQ_SI_X15(6*8); \
VMOVQ_SI_X11_0; \
VPINSRQ_1_SI_X15(10*8); \
VPINSRQ_1_SI_X11(8*8); \
VINSERTI128 $1, X11, Y15, Y15
#define LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() \
LOAD_MSG_AVX2_Y12(9, 5, 2, 10); \
VMOVQ_SI_X13_0; \
VMOVQ_SI_X11(4*8); \
VPINSRQ_1_SI_X13(7*8); \
VPINSRQ_1_SI_X11(15*8); \
VINSERTI128 $1, X11, Y13, Y13; \
LOAD_MSG_AVX2_Y14(14, 11, 6, 3); \
LOAD_MSG_AVX2_Y15(1, 12, 8, 13)
#define LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() \
VMOVQ_SI_X12(2*8); \
VMOVQ_SI_X11_0; \
VPINSRQ_1_SI_X12(6*8); \
VPINSRQ_1_SI_X11(8*8); \
VINSERTI128 $1, X11, Y12, Y12; \
LOAD_MSG_AVX2_Y13(12, 10, 11, 3); \
LOAD_MSG_AVX2_Y14(4, 7, 15, 1); \
LOAD_MSG_AVX2_Y15(13, 5, 14, 9)
#define LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() \
LOAD_MSG_AVX2_Y12(12, 1, 14, 4); \
LOAD_MSG_AVX2_Y13(5, 15, 13, 10); \
VMOVQ_SI_X14_0; \
VPSHUFD $0x4E, 8*8(SI), X11; \
VPINSRQ_1_SI_X14(6*8); \
VINSERTI128 $1, X11, Y14, Y14; \
LOAD_MSG_AVX2_Y15(7, 3, 2, 11)
#define LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() \
LOAD_MSG_AVX2_Y12(13, 7, 12, 3); \
LOAD_MSG_AVX2_Y13(11, 14, 1, 9); \
LOAD_MSG_AVX2_Y14(5, 15, 8, 2); \
VMOVQ_SI_X15_0; \
VMOVQ_SI_X11(6*8); \
VPINSRQ_1_SI_X15(4*8); \
VPINSRQ_1_SI_X11(10*8); \
VINSERTI128 $1, X11, Y15, Y15
#define LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() \
VMOVQ_SI_X12(6*8); \
VMOVQ_SI_X11(11*8); \
VPINSRQ_1_SI_X12(14*8); \
VPINSRQ_1_SI_X11_0; \
VINSERTI128 $1, X11, Y12, Y12; \
LOAD_MSG_AVX2_Y13(15, 9, 3, 8); \
VMOVQ_SI_X11(1*8); \
VMOVDQU 12*8(SI), X14; \
VPINSRQ_1_SI_X11(10*8); \
VINSERTI128 $1, X11, Y14, Y14; \
VMOVQ_SI_X15(2*8); \
VMOVDQU 4*8(SI), X11; \
VPINSRQ_1_SI_X15(7*8); \
VINSERTI128 $1, X11, Y15, Y15
#define LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() \
LOAD_MSG_AVX2_Y12(10, 8, 7, 1); \
VMOVQ_SI_X13(2*8); \
VPSHUFD $0x4E, 5*8(SI), X11; \
VPINSRQ_1_SI_X13(4*8); \
VINSERTI128 $1, X11, Y13, Y13; \
LOAD_MSG_AVX2_Y14(15, 9, 3, 13); \
VMOVQ_SI_X15(11*8); \
VMOVQ_SI_X11(12*8); \
VPINSRQ_1_SI_X15(14*8); \
VPINSRQ_1_SI_X11_0; \
VINSERTI128 $1, X11, Y15, Y15
// func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
@@ -162,34 +317,34 @@ noinc:
VMOVDQA Y6, Y2
VPXOR 0(SP), Y7, Y3
LOAD_MSG_AVX2(SI, 0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15)
LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15()
VMOVDQA Y12, 32(SP)
VMOVDQA Y13, 64(SP)
VMOVDQA Y14, 96(SP)
VMOVDQA Y15, 128(SP)
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
LOAD_MSG_AVX2(SI, 14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3)
LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3()
VMOVDQA Y12, 160(SP)
VMOVDQA Y13, 192(SP)
VMOVDQA Y14, 224(SP)
VMOVDQA Y15, 256(SP)
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
LOAD_MSG_AVX2(SI, 11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4)
LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
LOAD_MSG_AVX2(SI, 7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8)
LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
LOAD_MSG_AVX2(SI, 9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13)
LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
LOAD_MSG_AVX2(SI, 2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9)
LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
LOAD_MSG_AVX2(SI, 12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11)
LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
LOAD_MSG_AVX2(SI, 13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10)
LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
LOAD_MSG_AVX2(SI, 6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5)
LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
LOAD_MSG_AVX2(SI, 10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0)
LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
ROUND_AVX2(32(SP), 64(SP), 96(SP), 128(SP), Y10, Y4, Y5)
@@ -209,56 +364,55 @@ noinc:
VMOVDQU Y8, 0(AX)
VMOVDQU Y9, 32(AX)
VZEROUPPER
MOVQ DX, SP
RET
// unfortunately the BYTE representation of VPUNPCKLQDQ and VPUNPCKHQDQ must be used
#define VPUNPCKLQDQ_X8_X8_X10 BYTE $0xC4; BYTE $0x41; BYTE $0x39; BYTE $0x6C; BYTE $0xD0
#define VPUNPCKHQDQ_X7_X10_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xF2
#define VPUNPCKLQDQ_X7_X7_X10 BYTE $0xC5; BYTE $0x41; BYTE $0x6C; BYTE $0xD7
#define VPUNPCKHQDQ_X8_X10_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x39; BYTE $0x6D; BYTE $0xFA
#define VPUNPCKLQDQ_X3_X3_X10 BYTE $0xC5; BYTE $0x61; BYTE $0x6C; BYTE $0xD3
#define VPUNPCKHQDQ_X2_X10_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x69; BYTE $0x6D; BYTE $0xD2
#define VPUNPCKLQDQ_X9_X9_X10 BYTE $0xC4; BYTE $0x41; BYTE $0x31; BYTE $0x6C; BYTE $0xD1
#define VPUNPCKHQDQ_X3_X10_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xDA
#define VPUNPCKLQDQ_X2_X2_X10 BYTE $0xC5; BYTE $0x69; BYTE $0x6C; BYTE $0xD2
#define VPUNPCKHQDQ_X3_X10_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xD2
#define VPUNPCKHQDQ_X8_X10_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x39; BYTE $0x6D; BYTE $0xDA
#define VPUNPCKHQDQ_X6_X10_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x49; BYTE $0x6D; BYTE $0xF2
#define VPUNPCKHQDQ_X7_X10_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xFA
#define VPUNPCKLQDQ_X2_X2_X15 BYTE $0xC5; BYTE $0x69; BYTE $0x6C; BYTE $0xFA
#define VPUNPCKLQDQ_X3_X3_X15 BYTE $0xC5; BYTE $0x61; BYTE $0x6C; BYTE $0xFB
#define VPUNPCKLQDQ_X7_X7_X15 BYTE $0xC5; BYTE $0x41; BYTE $0x6C; BYTE $0xFF
#define VPUNPCKLQDQ_X13_X13_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x11; BYTE $0x6C; BYTE $0xFD
#define VPUNPCKLQDQ_X14_X14_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x09; BYTE $0x6C; BYTE $0xFE
#define VPUNPCKHQDQ_X15_X2_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x69; BYTE $0x6D; BYTE $0xD7
#define VPUNPCKHQDQ_X15_X3_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xDF
#define VPUNPCKHQDQ_X15_X6_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x49; BYTE $0x6D; BYTE $0xF7
#define VPUNPCKHQDQ_X15_X7_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xFF
#define VPUNPCKHQDQ_X15_X3_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xD7
#define VPUNPCKHQDQ_X15_X7_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xF7
#define VPUNPCKHQDQ_X15_X13_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xDF
#define VPUNPCKHQDQ_X15_X13_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xFF
// shuffle X2 and X6 using the temp registers X8, X9, X10
#define SHUFFLE_AVX() \
VMOVDQA X4, X9; \
VMOVDQA X5, X4; \
VMOVDQA X9, X5; \
VMOVDQA X6, X8; \
VPUNPCKLQDQ_X8_X8_X10; \
VPUNPCKHQDQ_X7_X10_X6; \
VPUNPCKLQDQ_X7_X7_X10; \
VPUNPCKHQDQ_X8_X10_X7; \
VPUNPCKLQDQ_X3_X3_X10; \
VMOVDQA X2, X9; \
VPUNPCKHQDQ_X2_X10_X2; \
VPUNPCKLQDQ_X9_X9_X10; \
VPUNPCKHQDQ_X3_X10_X3; \
VMOVDQA X6, X13; \
VMOVDQA X2, X14; \
VMOVDQA X4, X6; \
VPUNPCKLQDQ_X13_X13_X15; \
VMOVDQA X5, X4; \
VMOVDQA X6, X5; \
VPUNPCKHQDQ_X15_X7_X6; \
VPUNPCKLQDQ_X7_X7_X15; \
VPUNPCKHQDQ_X15_X13_X7; \
VPUNPCKLQDQ_X3_X3_X15; \
VPUNPCKHQDQ_X15_X2_X2; \
VPUNPCKLQDQ_X14_X14_X15; \
VPUNPCKHQDQ_X15_X3_X3; \
// inverse shuffle X2 and X6 using the temp registers X8, X9, X10
#define SHUFFLE_AVX_INV() \
VMOVDQA X4, X9; \
VMOVDQA X5, X4; \
VMOVDQA X9, X5; \
VMOVDQA X2, X8; \
VPUNPCKLQDQ_X2_X2_X10; \
VPUNPCKHQDQ_X3_X10_X2; \
VPUNPCKLQDQ_X3_X3_X10; \
VPUNPCKHQDQ_X8_X10_X3; \
VPUNPCKLQDQ_X7_X7_X10; \
VMOVDQA X6, X9; \
VPUNPCKHQDQ_X6_X10_X6; \
VPUNPCKLQDQ_X9_X9_X10; \
VPUNPCKHQDQ_X7_X10_X7; \
VMOVDQA X2, X13; \
VMOVDQA X4, X14; \
VPUNPCKLQDQ_X2_X2_X15; \
VMOVDQA X5, X4; \
VPUNPCKHQDQ_X15_X3_X2; \
VMOVDQA X14, X5; \
VPUNPCKLQDQ_X3_X3_X15; \
VMOVDQA X6, X14; \
VPUNPCKHQDQ_X15_X13_X3; \
VPUNPCKLQDQ_X7_X7_X15; \
VPUNPCKHQDQ_X15_X6_X6; \
VPUNPCKLQDQ_X14_X14_X15; \
VPUNPCKHQDQ_X15_X7_X7; \
#define HALF_ROUND_AVX(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \
VPADDQ m0, v0, v0; \
@@ -294,28 +448,133 @@ noinc:
VPSRLQ $63, v3, v3; \
VPXOR t0, v3, v3
// unfortunately the BYTE representation of VPINSRQ must be used
#define VPINSRQ_1_R10_X8_X8 BYTE $0xC4; BYTE $0x43; BYTE $0xB9; BYTE $0x22; BYTE $0xC2; BYTE $0x01
#define VPINSRQ_1_R11_X9_X9 BYTE $0xC4; BYTE $0x43; BYTE $0xB1; BYTE $0x22; BYTE $0xCB; BYTE $0x01
#define VPINSRQ_1_R12_X10_X10 BYTE $0xC4; BYTE $0x43; BYTE $0xA9; BYTE $0x22; BYTE $0xD4; BYTE $0x01
#define VPINSRQ_1_R13_X11_X11 BYTE $0xC4; BYTE $0x43; BYTE $0xA1; BYTE $0x22; BYTE $0xDD; BYTE $0x01
// load msg: X12 = (i0, i1), X13 = (i2, i3), X14 = (i4, i5), X15 = (i6, i7)
// i0, i1, i2, i3, i4, i5, i6, i7 must not be 0
#define LOAD_MSG_AVX(i0, i1, i2, i3, i4, i5, i6, i7) \
VMOVQ_SI_X12(i0*8); \
VMOVQ_SI_X13(i2*8); \
VMOVQ_SI_X14(i4*8); \
VMOVQ_SI_X15(i6*8); \
VPINSRQ_1_SI_X12(i1*8); \
VPINSRQ_1_SI_X13(i3*8); \
VPINSRQ_1_SI_X14(i5*8); \
VPINSRQ_1_SI_X15(i7*8)
#define VPINSRQ_1_R9_X8_X8 BYTE $0xC4; BYTE $0x43; BYTE $0xB9; BYTE $0x22; BYTE $0xC1; BYTE $0x01
// load msg: X12 = (0, 2), X13 = (4, 6), X14 = (1, 3), X15 = (5, 7)
#define LOAD_MSG_AVX_0_2_4_6_1_3_5_7() \
VMOVQ_SI_X12_0; \
VMOVQ_SI_X13(4*8); \
VMOVQ_SI_X14(1*8); \
VMOVQ_SI_X15(5*8); \
VPINSRQ_1_SI_X12(2*8); \
VPINSRQ_1_SI_X13(6*8); \
VPINSRQ_1_SI_X14(3*8); \
VPINSRQ_1_SI_X15(7*8)
// load src into X8, X9, X10 and X11 using R10, R11, R12 and R13 for temp registers
#define LOAD_MSG_AVX(src, i0, i1, i2, i3, i4, i5, i6, i7) \
MOVQ i0*8(src), X8; \
MOVQ i1*8(src), R10; \
MOVQ i2*8(src), X9; \
MOVQ i3*8(src), R11; \
MOVQ i4*8(src), X10; \
MOVQ i5*8(src), R12; \
MOVQ i6*8(src), X11; \
MOVQ i7*8(src), R13; \
VPINSRQ_1_R10_X8_X8; \
VPINSRQ_1_R11_X9_X9; \
VPINSRQ_1_R12_X10_X10; \
VPINSRQ_1_R13_X11_X11
// load msg: X12 = (1, 0), X13 = (11, 5), X14 = (12, 2), X15 = (7, 3)
#define LOAD_MSG_AVX_1_0_11_5_12_2_7_3() \
VPSHUFD $0x4E, 0*8(SI), X12; \
VMOVQ_SI_X13(11*8); \
VMOVQ_SI_X14(12*8); \
VMOVQ_SI_X15(7*8); \
VPINSRQ_1_SI_X13(5*8); \
VPINSRQ_1_SI_X14(2*8); \
VPINSRQ_1_SI_X15(3*8)
// load msg: X12 = (11, 12), X13 = (5, 15), X14 = (8, 0), X15 = (2, 13)
#define LOAD_MSG_AVX_11_12_5_15_8_0_2_13() \
VMOVDQU 11*8(SI), X12; \
VMOVQ_SI_X13(5*8); \
VMOVQ_SI_X14(8*8); \
VMOVQ_SI_X15(2*8); \
VPINSRQ_1_SI_X13(15*8); \
VPINSRQ_1_SI_X14_0; \
VPINSRQ_1_SI_X15(13*8)
// load msg: X12 = (2, 5), X13 = (4, 15), X14 = (6, 10), X15 = (0, 8)
#define LOAD_MSG_AVX_2_5_4_15_6_10_0_8() \
VMOVQ_SI_X12(2*8); \
VMOVQ_SI_X13(4*8); \
VMOVQ_SI_X14(6*8); \
VMOVQ_SI_X15_0; \
VPINSRQ_1_SI_X12(5*8); \
VPINSRQ_1_SI_X13(15*8); \
VPINSRQ_1_SI_X14(10*8); \
VPINSRQ_1_SI_X15(8*8)
// load msg: X12 = (9, 5), X13 = (2, 10), X14 = (0, 7), X15 = (4, 15)
#define LOAD_MSG_AVX_9_5_2_10_0_7_4_15() \
VMOVQ_SI_X12(9*8); \
VMOVQ_SI_X13(2*8); \
VMOVQ_SI_X14_0; \
VMOVQ_SI_X15(4*8); \
VPINSRQ_1_SI_X12(5*8); \
VPINSRQ_1_SI_X13(10*8); \
VPINSRQ_1_SI_X14(7*8); \
VPINSRQ_1_SI_X15(15*8)
// load msg: X12 = (2, 6), X13 = (0, 8), X14 = (12, 10), X15 = (11, 3)
#define LOAD_MSG_AVX_2_6_0_8_12_10_11_3() \
VMOVQ_SI_X12(2*8); \
VMOVQ_SI_X13_0; \
VMOVQ_SI_X14(12*8); \
VMOVQ_SI_X15(11*8); \
VPINSRQ_1_SI_X12(6*8); \
VPINSRQ_1_SI_X13(8*8); \
VPINSRQ_1_SI_X14(10*8); \
VPINSRQ_1_SI_X15(3*8)
// load msg: X12 = (0, 6), X13 = (9, 8), X14 = (7, 3), X15 = (2, 11)
#define LOAD_MSG_AVX_0_6_9_8_7_3_2_11() \
MOVQ 0*8(SI), X12; \
VPSHUFD $0x4E, 8*8(SI), X13; \
MOVQ 7*8(SI), X14; \
MOVQ 2*8(SI), X15; \
VPINSRQ_1_SI_X12(6*8); \
VPINSRQ_1_SI_X14(3*8); \
VPINSRQ_1_SI_X15(11*8)
// load msg: X12 = (6, 14), X13 = (11, 0), X14 = (15, 9), X15 = (3, 8)
#define LOAD_MSG_AVX_6_14_11_0_15_9_3_8() \
MOVQ 6*8(SI), X12; \
MOVQ 11*8(SI), X13; \
MOVQ 15*8(SI), X14; \
MOVQ 3*8(SI), X15; \
VPINSRQ_1_SI_X12(14*8); \
VPINSRQ_1_SI_X13_0; \
VPINSRQ_1_SI_X14(9*8); \
VPINSRQ_1_SI_X15(8*8)
// load msg: X12 = (5, 15), X13 = (8, 2), X14 = (0, 4), X15 = (6, 10)
#define LOAD_MSG_AVX_5_15_8_2_0_4_6_10() \
MOVQ 5*8(SI), X12; \
MOVQ 8*8(SI), X13; \
MOVQ 0*8(SI), X14; \
MOVQ 6*8(SI), X15; \
VPINSRQ_1_SI_X12(15*8); \
VPINSRQ_1_SI_X13(2*8); \
VPINSRQ_1_SI_X14(4*8); \
VPINSRQ_1_SI_X15(10*8)
// load msg: X12 = (12, 13), X13 = (1, 10), X14 = (2, 7), X15 = (4, 5)
#define LOAD_MSG_AVX_12_13_1_10_2_7_4_5() \
VMOVDQU 12*8(SI), X12; \
MOVQ 1*8(SI), X13; \
MOVQ 2*8(SI), X14; \
VPINSRQ_1_SI_X13(10*8); \
VPINSRQ_1_SI_X14(7*8); \
VMOVDQU 4*8(SI), X15
// load msg: X12 = (15, 9), X13 = (3, 13), X14 = (11, 14), X15 = (12, 0)
#define LOAD_MSG_AVX_15_9_3_13_11_14_12_0() \
MOVQ 15*8(SI), X12; \
MOVQ 3*8(SI), X13; \
MOVQ 11*8(SI), X14; \
MOVQ 12*8(SI), X15; \
VPINSRQ_1_SI_X12(9*8); \
VPINSRQ_1_SI_X13(13*8); \
VPINSRQ_1_SI_X14(14*8); \
VPINSRQ_1_SI_X15_0
// func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
TEXT ·hashBlocksAVX(SB), 4, $288-48 // frame size = 272 + 16 byte alignment
@@ -331,15 +590,17 @@ TEXT ·hashBlocksAVX(SB), 4, $288-48 // frame size = 272 + 16 byte alignment
ANDQ $~15, R9
MOVQ R9, SP
MOVOU ·AVX_c40<>(SB), X13
MOVOU ·AVX_c48<>(SB), X14
VMOVDQU ·AVX_c40<>(SB), X0
VMOVDQU ·AVX_c48<>(SB), X1
VMOVDQA X0, X8
VMOVDQA X1, X9
VMOVDQU ·AVX_iv3<>(SB), X0
VMOVDQA X0, 0(SP)
XORQ CX, 0(SP) // 0(SP) = ·AVX_iv3 ^ (CX || 0)
VMOVDQU 0(AX), X12
VMOVDQU 16(AX), X15
VMOVDQU 0(AX), X10
VMOVDQU 16(AX), X11
VMOVDQU 32(AX), X2
VMOVDQU 48(AX), X3
@@ -353,124 +614,124 @@ loop:
INCQ R9
noinc:
MOVQ R8, X8
VPINSRQ_1_R9_X8_X8
VMOVQ_R8_X15
VPINSRQ_1_R9_X15
VMOVDQA X12, X0
VMOVDQA X15, X1
VMOVDQA X10, X0
VMOVDQA X11, X1
VMOVDQU ·AVX_iv0<>(SB), X4
VMOVDQU ·AVX_iv1<>(SB), X5
VMOVDQU ·AVX_iv2<>(SB), X6
VPXOR X8, X6, X6
VPXOR X15, X6, X6
VMOVDQA 0(SP), X7
LOAD_MSG_AVX(SI, 0, 2, 4, 6, 1, 3, 5, 7)
VMOVDQA X8, 16(SP)
VMOVDQA X9, 32(SP)
VMOVDQA X10, 48(SP)
VMOVDQA X11, 64(SP)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
LOAD_MSG_AVX_0_2_4_6_1_3_5_7()
VMOVDQA X12, 16(SP)
VMOVDQA X13, 32(SP)
VMOVDQA X14, 48(SP)
VMOVDQA X15, 64(SP)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
LOAD_MSG_AVX(SI, 8, 10, 12, 14, 9, 11, 13, 15)
VMOVDQA X8, 80(SP)
VMOVDQA X9, 96(SP)
VMOVDQA X10, 112(SP)
VMOVDQA X11, 128(SP)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
LOAD_MSG_AVX(8, 10, 12, 14, 9, 11, 13, 15)
VMOVDQA X12, 80(SP)
VMOVDQA X13, 96(SP)
VMOVDQA X14, 112(SP)
VMOVDQA X15, 128(SP)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
LOAD_MSG_AVX(SI, 14, 4, 9, 13, 10, 8, 15, 6)
VMOVDQA X8, 144(SP)
VMOVDQA X9, 160(SP)
VMOVDQA X10, 176(SP)
VMOVDQA X11, 192(SP)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
LOAD_MSG_AVX(14, 4, 9, 13, 10, 8, 15, 6)
VMOVDQA X12, 144(SP)
VMOVDQA X13, 160(SP)
VMOVDQA X14, 176(SP)
VMOVDQA X15, 192(SP)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
LOAD_MSG_AVX(SI, 1, 0, 11, 5, 12, 2, 7, 3)
VMOVDQA X8, 208(SP)
VMOVDQA X9, 224(SP)
VMOVDQA X10, 240(SP)
VMOVDQA X11, 256(SP)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
LOAD_MSG_AVX_1_0_11_5_12_2_7_3()
VMOVDQA X12, 208(SP)
VMOVDQA X13, 224(SP)
VMOVDQA X14, 240(SP)
VMOVDQA X15, 256(SP)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
LOAD_MSG_AVX(SI, 11, 12, 5, 15, 8, 0, 2, 13)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
LOAD_MSG_AVX_11_12_5_15_8_0_2_13()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
LOAD_MSG_AVX(SI, 10, 3, 7, 9, 14, 6, 1, 4)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
LOAD_MSG_AVX(10, 3, 7, 9, 14, 6, 1, 4)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
LOAD_MSG_AVX(SI, 7, 3, 13, 11, 9, 1, 12, 14)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
LOAD_MSG_AVX(7, 3, 13, 11, 9, 1, 12, 14)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
LOAD_MSG_AVX(SI, 2, 5, 4, 15, 6, 10, 0, 8)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
LOAD_MSG_AVX_2_5_4_15_6_10_0_8()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
LOAD_MSG_AVX(SI, 9, 5, 2, 10, 0, 7, 4, 15)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
LOAD_MSG_AVX_9_5_2_10_0_7_4_15()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
LOAD_MSG_AVX(SI, 14, 11, 6, 3, 1, 12, 8, 13)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
LOAD_MSG_AVX(14, 11, 6, 3, 1, 12, 8, 13)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
LOAD_MSG_AVX(SI, 2, 6, 0, 8, 12, 10, 11, 3)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
LOAD_MSG_AVX_2_6_0_8_12_10_11_3()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
LOAD_MSG_AVX(SI, 4, 7, 15, 1, 13, 5, 14, 9)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
LOAD_MSG_AVX(4, 7, 15, 1, 13, 5, 14, 9)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
LOAD_MSG_AVX(SI, 12, 1, 14, 4, 5, 15, 13, 10)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
LOAD_MSG_AVX(12, 1, 14, 4, 5, 15, 13, 10)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
LOAD_MSG_AVX(SI, 0, 6, 9, 8, 7, 3, 2, 11)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
LOAD_MSG_AVX_0_6_9_8_7_3_2_11()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
LOAD_MSG_AVX(SI, 13, 7, 12, 3, 11, 14, 1, 9)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
LOAD_MSG_AVX(13, 7, 12, 3, 11, 14, 1, 9)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
LOAD_MSG_AVX(SI, 5, 15, 8, 2, 0, 4, 6, 10)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
LOAD_MSG_AVX_5_15_8_2_0_4_6_10()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
LOAD_MSG_AVX(SI, 6, 14, 11, 0, 15, 9, 3, 8)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
LOAD_MSG_AVX_6_14_11_0_15_9_3_8()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
LOAD_MSG_AVX(SI, 12, 13, 1, 10, 2, 7, 4, 5)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
LOAD_MSG_AVX_12_13_1_10_2_7_4_5()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
LOAD_MSG_AVX(SI, 10, 8, 7, 1, 2, 4, 6, 5)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
LOAD_MSG_AVX(10, 8, 7, 1, 2, 4, 6, 5)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
LOAD_MSG_AVX(SI, 15, 9, 3, 13, 11, 14, 12, 0)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
LOAD_MSG_AVX_15_9_3_13_11_14_12_0()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X11, X13, X14)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X15, X8, X9)
SHUFFLE_AVX()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 80(SP), 96(SP), 112(SP), 128(SP), X11, X13, X14)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 80(SP), 96(SP), 112(SP), 128(SP), X15, X8, X9)
SHUFFLE_AVX_INV()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 144(SP), 160(SP), 176(SP), 192(SP), X11, X13, X14)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 144(SP), 160(SP), 176(SP), 192(SP), X15, X8, X9)
SHUFFLE_AVX()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 208(SP), 224(SP), 240(SP), 256(SP), X11, X13, X14)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 208(SP), 224(SP), 240(SP), 256(SP), X15, X8, X9)
SHUFFLE_AVX_INV()
VMOVDQU 32(AX), X10
VMOVDQU 48(AX), X11
VPXOR X0, X12, X12
VPXOR X1, X15, X15
VPXOR X2, X10, X10
VPXOR X3, X11, X11
VPXOR X4, X12, X12
VPXOR X5, X15, X15
VPXOR X6, X10, X2
VPXOR X7, X11, X3
VMOVDQU 32(AX), X14
VMOVDQU 48(AX), X15
VPXOR X0, X10, X10
VPXOR X1, X11, X11
VPXOR X2, X14, X14
VPXOR X3, X15, X15
VPXOR X4, X10, X10
VPXOR X5, X11, X11
VPXOR X6, X14, X2
VPXOR X7, X15, X3
VMOVDQU X2, 32(AX)
VMOVDQU X3, 48(AX)
@@ -478,12 +739,11 @@ noinc:
SUBQ $128, DI
JNE loop
VMOVDQU X12, 0(AX)
VMOVDQU X15, 16(AX)
VMOVDQU X10, 0(AX)
VMOVDQU X11, 16(AX)
MOVQ R8, 0(BX)
MOVQ R9, 8(BX)
VZEROUPPER
MOVQ BP, SP

32
vendor/golang.org/x/crypto/blake2b/register.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,32 @@
// 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.
// +build go1.9
package blake2b
import (
"crypto"
"hash"
)
func init() {
newHash256 := func() hash.Hash {
h, _ := New256(nil)
return h
}
newHash384 := func() hash.Hash {
h, _ := New384(nil)
return h
}
newHash512 := func() hash.Hash {
h, _ := New512(nil)
return h
}
crypto.RegisterHash(crypto.BLAKE2b_256, newHash256)
crypto.RegisterHash(crypto.BLAKE2b_384, newHash384)
crypto.RegisterHash(crypto.BLAKE2b_512, newHash512)
}

21
vendor/golang.org/x/crypto/blake2s/register.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,21 @@
// 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.
// +build go1.9
package blake2s
import (
"crypto"
"hash"
)
func init() {
newHash256 := func() hash.Hash {
h, _ := New256(nil)
return h
}
crypto.RegisterHash(crypto.BLAKE2s_256, newHash256)
}

604
vendor/golang.org/x/crypto/cryptobyte/asn1.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,604 @@
// 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"
"fmt"
"math/big"
"reflect"
"time"
)
// This file contains ASN.1-related methods for String and Builder.
// Tag represents an ASN.1 tag number and class (together also referred to as
// identifier octets). Methods in this 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
// Contructed returns t with the context-specific class bit set.
func (t Tag) ContextSpecific() Tag { return t | 0x80 }
// Contructed returns t with the constructed class bit set.
func (t Tag) Constructed() Tag { return t | 0x20 }
// Builder
// AddASN1Int64 appends a DER-encoded ASN.1 INTEGER.
func (b *Builder) AddASN1Int64(v int64) {
b.addASN1Signed(asn1.TagInteger, v)
}
// AddASN1Enum appends a DER-encoded ASN.1 ENUMERATION.
func (b *Builder) AddASN1Enum(v int64) {
b.addASN1Signed(asn1.TagEnum, v)
}
func (b *Builder) addASN1Signed(tag 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.TagInteger, 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.TagInteger, 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 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.TagOctetString, 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.TagGeneralizedTime, func(c *Builder) {
c.AddBytes([]byte(t.Format(generalizedTimeFormatStr)))
})
}
// AddASN1BitString appends a DER-encoded ASN.1 BIT STRING.
func (b *Builder) AddASN1BitString(s asn1.BitString) {
// TODO(martinkr): Implement.
b.MarshalASN1(s)
}
// MarshalASN1 calls 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
// 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 := 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 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
var bigIntType = reflect.TypeOf((*big.Int)(nil)).Elem()
// ReadASN1Integer decodes an ASN.1 INTEGER into out and advances. If out does
// not point to an integer or to a big.Int, it panics. It returns true on
// success and false on error.
func (s *String) ReadASN1Integer(out interface{}) bool {
if reflect.TypeOf(out).Kind() != reflect.Ptr {
panic("out is not a pointer")
}
switch reflect.ValueOf(out).Elem().Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.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 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.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 reflect.Struct:
if reflect.TypeOf(out).Elem() == bigIntType {
return s.readASN1BigInt(out.(*big.Int))
}
}
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.TagInteger) || !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) readASN1Int64(out *int64) bool {
var bytes String
if !s.ReadASN1(&bytes, asn1.TagInteger) || !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.TagInteger) || !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
}
// ReadASN1Enum decodes an ASN.1 ENUMERATION into out and advances. It returns
// true on success and false on error.
func (s *String) ReadASN1Enum(out *int) bool {
var bytes String
var i int64
if !s.ReadASN1(&bytes, asn1.TagEnum) || !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 == 4 {
return false
}
ret <<= 7
b := s.read(1)[0]
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 returns true on success and false on error.
func (s *String) ReadASN1ObjectIdentifier(out *asn1.ObjectIdentifier) bool {
var bytes String
if !s.ReadASN1(&bytes, asn1.TagOID) || 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 returns true on success and false on error.
func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool {
var bytes String
if !s.ReadASN1(&bytes, asn1.TagGeneralizedTime) {
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
}
// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. It
// returns true on success and false on error.
func (s *String) ReadASN1BitString(out *asn1.BitString) bool {
var bytes String
if !s.ReadASN1(&bytes, asn1.TagBitString) || len(bytes) == 0 {
return false
}
paddingBits := uint8(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
}
// 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 returns true on success and false on error.
func (s *String) ReadASN1Bytes(out *[]byte, tag 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 returns true on success and false on error.
//
// Tags greater than 30 are not supported (i.e. low-tag-number format only).
func (s *String) ReadASN1(out *String, tag Tag) bool {
var t 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 returns true on success and false on error.
//
// Tags greater than 30 are not supported (i.e. low-tag-number format only).
func (s *String) ReadASN1Element(out *String, tag Tag) bool {
var t 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
// returns true on success and false on error.
//
// Tags greater than 30 are not supported (i.e. low-tag-number format only).
func (s *String) ReadAnyASN1(out *String, outTag *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 returns true on success and false on error.
//
// Tags greater than 30 are not supported (i.e. low-tag-number format only).
func (s *String) ReadAnyASN1Element(out *String, outTag *Tag) bool {
return s.readASN1(out, outTag, false /* include header */)
}
// PeekASN1Tag returns true if the next ASN.1 value on the string starts with
// the given tag.
func (s String) PeekASN1Tag(tag Tag) bool {
if len(s) == 0 {
return false
}
return Tag(s[0]) == tag
}
// ReadOptionalASN1 attempts to read the contents of a DER-encoded ASN.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 returns true on success and false on error.
func (s *String) ReadOptionalASN1(out *String, outPresent *bool, tag Tag) bool {
present := s.PeekASN1Tag(tag)
if outPresent != nil {
*outPresent = present
}
if present && !s.ReadASN1(out, tag) {
return false
}
return true
}
// 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. If out
// does not point to an integer or to a big.Int, it panics. It returns true on
// success and false on error.
func (s *String) ReadOptionalASN1Integer(out interface{}, tag Tag, defaultValue interface{}) bool {
if reflect.TypeOf(out).Kind() != reflect.Ptr {
panic("out is not a pointer")
}
var present bool
var i String
if !s.ReadOptionalASN1(&i, &present, tag) {
return false
}
if !present {
switch reflect.ValueOf(out).Elem().Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
reflect.ValueOf(out).Elem().Set(reflect.ValueOf(defaultValue))
case reflect.Struct:
if reflect.TypeOf(out).Elem() != bigIntType {
panic("invalid integer type")
}
if reflect.TypeOf(defaultValue).Kind() != reflect.Ptr ||
reflect.TypeOf(defaultValue).Elem() != bigIntType {
panic("out points to big.Int, but defaultValue does not")
}
out.(*big.Int).Set(defaultValue.(*big.Int))
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 writes defaultValue into out instead. It returns
// true on success and false on error.
func (s *String) ReadOptionalASN1OctetString(out *[]byte, outPresent *bool, tag 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.TagOctetString) || !child.Empty() {
return false
}
*out = oct
} else {
*out = nil
}
return true
}
func (s *String) readASN1(out *String, outTag *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 = 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 uint32(int(length)) != length || !s.ReadBytes((*[]byte)(out), int(length)) {
return false
}
if skipHeader && !out.Skip(int(headerLen)) {
panic("cryptobyte: internal error")
}
return true
}

285
vendor/golang.org/x/crypto/cryptobyte/asn1_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,285 @@
// 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 (
"bytes"
"encoding/asn1"
"math/big"
"reflect"
"testing"
"time"
)
type readASN1Test struct {
name string
in []byte
tag Tag
ok bool
out interface{}
}
var readASN1TestData = []readASN1Test{
{"valid", []byte{0x30, 2, 1, 2}, 0x30, true, []byte{1, 2}},
{"truncated", []byte{0x30, 3, 1, 2}, 0x30, false, nil},
{"zero length of length", []byte{0x30, 0x80}, 0x30, false, nil},
{"invalid long form length", []byte{0x30, 0x81, 1, 1}, 0x30, false, nil},
{"non-minimal length", append([]byte{0x30, 0x82, 0, 0x80}, make([]byte, 0x80)...), 0x30, false, nil},
{"invalid tag", []byte{0xa1, 3, 0x4, 1, 1}, 31, false, nil},
{"high tag", []byte{0x1f, 0x81, 0x80, 0x01, 2, 1, 2}, 0xff /* actually 0x4001, but tag is uint8 */, false, nil},
}
func TestReadASN1(t *testing.T) {
for _, test := range readASN1TestData {
t.Run(test.name, func(t *testing.T) {
var in, out String = test.in, nil
ok := in.ReadASN1(&out, test.tag)
if ok != test.ok || ok && !bytes.Equal(out, test.out.([]byte)) {
t.Errorf("in.ReadASN1() = %v, want %v; out = %v, want %v", ok, test.ok, out, test.out)
}
})
}
}
func TestReadASN1Optional(t *testing.T) {
var empty String
var present bool
ok := empty.ReadOptionalASN1(nil, &present, 0xa0)
if !ok || present {
t.Errorf("empty.ReadOptionalASN1() = %v, want true; present = %v want false", ok, present)
}
var in, out String = []byte{0xa1, 3, 0x4, 1, 1}, nil
ok = in.ReadOptionalASN1(&out, &present, 0xa0)
if !ok || present {
t.Errorf("in.ReadOptionalASN1() = %v, want true, present = %v, want false", ok, present)
}
ok = in.ReadOptionalASN1(&out, &present, 0xa1)
wantBytes := []byte{4, 1, 1}
if !ok || !present || !bytes.Equal(out, wantBytes) {
t.Errorf("in.ReadOptionalASN1() = %v, want true; present = %v, want true; out = %v, want = %v", ok, present, out, wantBytes)
}
}
var optionalOctetStringTestData = []struct {
readASN1Test
present bool
}{
{readASN1Test{"empty", []byte{}, 0xa0, true, []byte{}}, false},
{readASN1Test{"invalid", []byte{0xa1, 3, 0x4, 2, 1}, 0xa1, false, []byte{}}, true},
{readASN1Test{"missing", []byte{0xa1, 3, 0x4, 1, 1}, 0xa0, true, []byte{}}, false},
{readASN1Test{"present", []byte{0xa1, 3, 0x4, 1, 1}, 0xa1, true, []byte{1}}, true},
}
func TestReadASN1OptionalOctetString(t *testing.T) {
for _, test := range optionalOctetStringTestData {
t.Run(test.name, func(t *testing.T) {
in := String(test.in)
var out []byte
var present bool
ok := in.ReadOptionalASN1OctetString(&out, &present, test.tag)
if ok != test.ok || present != test.present || !bytes.Equal(out, test.out.([]byte)) {
t.Errorf("in.ReadOptionalASN1OctetString() = %v, want %v; present = %v want %v; out = %v, want %v", ok, test.ok, present, test.present, out, test.out)
}
})
}
}
const defaultInt = -1
var optionalIntTestData = []readASN1Test{
{"empty", []byte{}, 0xa0, true, defaultInt},
{"invalid", []byte{0xa1, 3, 0x2, 2, 127}, 0xa1, false, 0},
{"missing", []byte{0xa1, 3, 0x2, 1, 127}, 0xa0, true, defaultInt},
{"present", []byte{0xa1, 3, 0x2, 1, 42}, 0xa1, true, 42},
}
func TestReadASN1OptionalInteger(t *testing.T) {
for _, test := range optionalIntTestData {
t.Run(test.name, func(t *testing.T) {
in := String(test.in)
var out int
ok := in.ReadOptionalASN1Integer(&out, test.tag, defaultInt)
if ok != test.ok || ok && out != test.out.(int) {
t.Errorf("in.ReadOptionalASN1Integer() = %v, want %v; out = %v, want %v", ok, test.ok, out, test.out)
}
})
}
}
func TestReadASN1IntegerSigned(t *testing.T) {
testData64 := []struct {
in []byte
out int64
}{
{[]byte{2, 3, 128, 0, 0}, -0x800000},
{[]byte{2, 2, 255, 0}, -256},
{[]byte{2, 2, 255, 127}, -129},
{[]byte{2, 1, 128}, -128},
{[]byte{2, 1, 255}, -1},
{[]byte{2, 1, 0}, 0},
{[]byte{2, 1, 1}, 1},
{[]byte{2, 1, 2}, 2},
{[]byte{2, 1, 127}, 127},
{[]byte{2, 2, 0, 128}, 128},
{[]byte{2, 2, 1, 0}, 256},
{[]byte{2, 4, 0, 128, 0, 0}, 0x800000},
}
for i, test := range testData64 {
in := String(test.in)
var out int64
ok := in.ReadASN1Integer(&out)
if !ok || out != test.out {
t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %d, want %d", i, ok, out, test.out)
}
}
// Repeat the same cases, reading into a big.Int.
t.Run("big.Int", func(t *testing.T) {
for i, test := range testData64 {
in := String(test.in)
var out big.Int
ok := in.ReadASN1Integer(&out)
if !ok || out.Int64() != test.out {
t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %d, want %d", i, ok, out.Int64(), test.out)
}
}
})
}
func TestReadASN1IntegerUnsigned(t *testing.T) {
testData := []struct {
in []byte
out uint64
}{
{[]byte{2, 1, 0}, 0},
{[]byte{2, 1, 1}, 1},
{[]byte{2, 1, 2}, 2},
{[]byte{2, 1, 127}, 127},
{[]byte{2, 2, 0, 128}, 128},
{[]byte{2, 2, 1, 0}, 256},
{[]byte{2, 4, 0, 128, 0, 0}, 0x800000},
{[]byte{2, 8, 127, 255, 255, 255, 255, 255, 255, 255}, 0x7fffffffffffffff},
{[]byte{2, 9, 0, 128, 0, 0, 0, 0, 0, 0, 0}, 0x8000000000000000},
{[]byte{2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255}, 0xffffffffffffffff},
}
for i, test := range testData {
in := String(test.in)
var out uint64
ok := in.ReadASN1Integer(&out)
if !ok || out != test.out {
t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %d, want %d", i, ok, out, test.out)
}
}
}
func TestReadASN1IntegerInvalid(t *testing.T) {
testData := []String{
[]byte{3, 1, 0}, // invalid tag
// truncated
[]byte{2, 1},
[]byte{2, 2, 0},
// not minimally encoded
[]byte{2, 2, 0, 1},
[]byte{2, 2, 0xff, 0xff},
}
for i, test := range testData {
var out int64
if test.ReadASN1Integer(&out) {
t.Errorf("#%d: in.ReadASN1Integer() = true, want false (out = %d)", i, out)
}
}
}
func TestReadASN1ObjectIdentifier(t *testing.T) {
testData := []struct {
in []byte
ok bool
out []int
}{
{[]byte{}, false, []int{}},
{[]byte{6, 0}, false, []int{}},
{[]byte{5, 1, 85}, false, []int{2, 5}},
{[]byte{6, 1, 85}, true, []int{2, 5}},
{[]byte{6, 2, 85, 0x02}, true, []int{2, 5, 2}},
{[]byte{6, 4, 85, 0x02, 0xc0, 0x00}, true, []int{2, 5, 2, 0x2000}},
{[]byte{6, 3, 0x81, 0x34, 0x03}, true, []int{2, 100, 3}},
{[]byte{6, 7, 85, 0x02, 0xc0, 0x80, 0x80, 0x80, 0x80}, false, []int{}},
}
for i, test := range testData {
in := String(test.in)
var out asn1.ObjectIdentifier
ok := in.ReadASN1ObjectIdentifier(&out)
if ok != test.ok || ok && !out.Equal(test.out) {
t.Errorf("#%d: in.ReadASN1ObjectIdentifier() = %v, want %v; out = %v, want %v", i, ok, test.ok, out, test.out)
}
}
}
func TestReadASN1GeneralizedTime(t *testing.T) {
testData := []struct {
in string
ok bool
out time.Time
}{
{"20100102030405Z", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.UTC)},
{"20100102030405", false, time.Time{}},
{"20100102030405+0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", 6*60*60+7*60))},
{"20100102030405-0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", -6*60*60-7*60))},
/* These are invalid times. However, the time package normalises times
* and they were accepted in some versions. See #11134. */
{"00000100000000Z", false, time.Time{}},
{"20101302030405Z", false, time.Time{}},
{"20100002030405Z", false, time.Time{}},
{"20100100030405Z", false, time.Time{}},
{"20100132030405Z", false, time.Time{}},
{"20100231030405Z", false, time.Time{}},
{"20100102240405Z", false, time.Time{}},
{"20100102036005Z", false, time.Time{}},
{"20100102030460Z", false, time.Time{}},
{"-20100102030410Z", false, time.Time{}},
{"2010-0102030410Z", false, time.Time{}},
{"2010-0002030410Z", false, time.Time{}},
{"201001-02030410Z", false, time.Time{}},
{"20100102-030410Z", false, time.Time{}},
{"2010010203-0410Z", false, time.Time{}},
{"201001020304-10Z", false, time.Time{}},
}
for i, test := range testData {
in := String(append([]byte{asn1.TagGeneralizedTime, byte(len(test.in))}, test.in...))
var out time.Time
ok := in.ReadASN1GeneralizedTime(&out)
if ok != test.ok || ok && !reflect.DeepEqual(out, test.out) {
t.Errorf("#%d: in.ReadASN1GeneralizedTime() = %v, want %v; out = %q, want %q", i, ok, test.ok, out, test.out)
}
}
}
func TestReadASN1BitString(t *testing.T) {
testData := []struct {
in []byte
ok bool
out asn1.BitString
}{
{[]byte{}, false, asn1.BitString{}},
{[]byte{0x00}, true, asn1.BitString{}},
{[]byte{0x07, 0x00}, true, asn1.BitString{Bytes: []byte{0}, BitLength: 1}},
{[]byte{0x07, 0x01}, false, asn1.BitString{}},
{[]byte{0x07, 0x40}, false, asn1.BitString{}},
{[]byte{0x08, 0x00}, false, asn1.BitString{}},
{[]byte{0xff}, false, asn1.BitString{}},
{[]byte{0xfe, 0x00}, false, asn1.BitString{}},
}
for i, test := range testData {
in := String(append([]byte{3, byte(len(test.in))}, test.in...))
var out asn1.BitString
ok := in.ReadASN1BitString(&out)
if ok != test.ok || ok && (!bytes.Equal(out.Bytes, test.out.Bytes) || out.BitLength != test.out.BitLength) {
t.Errorf("#%d: in.ReadASN1BitString() = %v, want %v; out = %v, want %v", i, ok, test.ok, out, test.out)
}
}
}

255
vendor/golang.org/x/crypto/cryptobyte/builder.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,255 @@
// 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.
// The zero value is a usable Builder that allocates space as needed.
type Builder struct {
err error
result []byte
fixedSize bool
child *Builder
offset int
pendingLenLen int
pendingIsASN1 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,
}
}
// Bytes returns the bytes written by the builder or an error if one has
// occurred during 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))
}
// AddBytes appends a sequence of bytes to the byte string.
func (b *Builder) AddBytes(v []byte) {
b.add(v...)
}
// BuilderContinuation is 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. 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.
type BuilderContinuation func(child *Builder)
// 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)
}
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)...)
b.child = &Builder{
result: b.result,
fixedSize: b.fixedSize,
offset: offset,
pendingLenLen: lenLen,
pendingIsASN1: isASN1,
}
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 = child.result // In case child reallocated result.
}
}
func (b *Builder) add(bytes ...byte) {
if b.err != nil {
return
}
if b.child != nil {
panic("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...)
}
// 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
}
}

379
vendor/golang.org/x/crypto/cryptobyte/cryptobyte_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,379 @@
// 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 (
"bytes"
"fmt"
"testing"
)
func builderBytesEq(b *Builder, want ...byte) error {
got := b.BytesOrPanic()
if !bytes.Equal(got, want) {
return fmt.Errorf("Bytes() = %v, want %v", got, want)
}
return nil
}
func TestBytes(t *testing.T) {
var b Builder
v := []byte("foobarbaz")
b.AddBytes(v[0:3])
b.AddBytes(v[3:4])
b.AddBytes(v[4:9])
if err := builderBytesEq(&b, v...); err != nil {
t.Error(err)
}
s := String(b.BytesOrPanic())
for _, w := range []string{"foo", "bar", "baz"} {
var got []byte
if !s.ReadBytes(&got, 3) {
t.Errorf("ReadBytes() = false, want true (w = %v)", w)
}
want := []byte(w)
if !bytes.Equal(got, want) {
t.Errorf("ReadBytes(): got = %v, want %v", got, want)
}
}
if len(s) != 0 {
t.Errorf("len(s) = %d, want 0", len(s))
}
}
func TestUint8(t *testing.T) {
var b Builder
b.AddUint8(42)
if err := builderBytesEq(&b, 42); err != nil {
t.Error(err)
}
var s String = b.BytesOrPanic()
var v uint8
if !s.ReadUint8(&v) {
t.Error("ReadUint8() = false, want true")
}
if v != 42 {
t.Errorf("v = %d, want 42", v)
}
if len(s) != 0 {
t.Errorf("len(s) = %d, want 0", len(s))
}
}
func TestUint16(t *testing.T) {
var b Builder
b.AddUint16(65534)
if err := builderBytesEq(&b, 255, 254); err != nil {
t.Error(err)
}
var s String = b.BytesOrPanic()
var v uint16
if !s.ReadUint16(&v) {
t.Error("ReadUint16() == false, want true")
}
if v != 65534 {
t.Errorf("v = %d, want 65534", v)
}
if len(s) != 0 {
t.Errorf("len(s) = %d, want 0", len(s))
}
}
func TestUint24(t *testing.T) {
var b Builder
b.AddUint24(0xfffefd)
if err := builderBytesEq(&b, 255, 254, 253); err != nil {
t.Error(err)
}
var s String = b.BytesOrPanic()
var v uint32
if !s.ReadUint24(&v) {
t.Error("ReadUint8() = false, want true")
}
if v != 0xfffefd {
t.Errorf("v = %d, want fffefd", v)
}
if len(s) != 0 {
t.Errorf("len(s) = %d, want 0", len(s))
}
}
func TestUint24Truncation(t *testing.T) {
var b Builder
b.AddUint24(0x10111213)
if err := builderBytesEq(&b, 0x11, 0x12, 0x13); err != nil {
t.Error(err)
}
}
func TestUint32(t *testing.T) {
var b Builder
b.AddUint32(0xfffefdfc)
if err := builderBytesEq(&b, 255, 254, 253, 252); err != nil {
t.Error(err)
}
var s String = b.BytesOrPanic()
var v uint32
if !s.ReadUint32(&v) {
t.Error("ReadUint8() = false, want true")
}
if v != 0xfffefdfc {
t.Errorf("v = %x, want fffefdfc", v)
}
if len(s) != 0 {
t.Errorf("len(s) = %d, want 0", len(s))
}
}
func TestUMultiple(t *testing.T) {
var b Builder
b.AddUint8(23)
b.AddUint32(0xfffefdfc)
b.AddUint16(42)
if err := builderBytesEq(&b, 23, 255, 254, 253, 252, 0, 42); err != nil {
t.Error(err)
}
var s String = b.BytesOrPanic()
var (
x uint8
y uint32
z uint16
)
if !s.ReadUint8(&x) || !s.ReadUint32(&y) || !s.ReadUint16(&z) {
t.Error("ReadUint8() = false, want true")
}
if x != 23 || y != 0xfffefdfc || z != 42 {
t.Errorf("x, y, z = %d, %d, %d; want 23, 4294901244, 5", x, y, z)
}
if len(s) != 0 {
t.Errorf("len(s) = %d, want 0", len(s))
}
}
func TestUint8LengthPrefixedSimple(t *testing.T) {
var b Builder
b.AddUint8LengthPrefixed(func(c *Builder) {
c.AddUint8(23)
c.AddUint8(42)
})
if err := builderBytesEq(&b, 2, 23, 42); err != nil {
t.Error(err)
}
var base, child String = b.BytesOrPanic(), nil
var x, y uint8
if !base.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&x) ||
!child.ReadUint8(&y) {
t.Error("parsing failed")
}
if x != 23 || y != 42 {
t.Errorf("want x, y == 23, 42; got %d, %d", x, y)
}
if len(base) != 0 {
t.Errorf("len(base) = %d, want 0", len(base))
}
if len(child) != 0 {
t.Errorf("len(child) = %d, want 0", len(child))
}
}
func TestUint8LengthPrefixedMulti(t *testing.T) {
var b Builder
b.AddUint8LengthPrefixed(func(c *Builder) {
c.AddUint8(23)
c.AddUint8(42)
})
b.AddUint8(5)
b.AddUint8LengthPrefixed(func(c *Builder) {
c.AddUint8(123)
c.AddUint8(234)
})
if err := builderBytesEq(&b, 2, 23, 42, 5, 2, 123, 234); err != nil {
t.Error(err)
}
var s, child String = b.BytesOrPanic(), nil
var u, v, w, x, y uint8
if !s.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&u) || !child.ReadUint8(&v) ||
!s.ReadUint8(&w) || !s.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&x) || !child.ReadUint8(&y) {
t.Error("parsing failed")
}
if u != 23 || v != 42 || w != 5 || x != 123 || y != 234 {
t.Errorf("u, v, w, x, y = %d, %d, %d, %d, %d; want 23, 42, 5, 123, 234",
u, v, w, x, y)
}
if len(s) != 0 {
t.Errorf("len(s) = %d, want 0", len(s))
}
if len(child) != 0 {
t.Errorf("len(child) = %d, want 0", len(child))
}
}
func TestUint8LengthPrefixedNested(t *testing.T) {
var b Builder
b.AddUint8LengthPrefixed(func(c *Builder) {
c.AddUint8(5)
c.AddUint8LengthPrefixed(func(d *Builder) {
d.AddUint8(23)
d.AddUint8(42)
})
c.AddUint8(123)
})
if err := builderBytesEq(&b, 5, 5, 2, 23, 42, 123); err != nil {
t.Error(err)
}
var base, child1, child2 String = b.BytesOrPanic(), nil, nil
var u, v, w, x uint8
if !base.ReadUint8LengthPrefixed(&child1) {
t.Error("parsing base failed")
}
if !child1.ReadUint8(&u) || !child1.ReadUint8LengthPrefixed(&child2) || !child1.ReadUint8(&x) {
t.Error("parsing child1 failed")
}
if !child2.ReadUint8(&v) || !child2.ReadUint8(&w) {
t.Error("parsing child2 failed")
}
if u != 5 || v != 23 || w != 42 || x != 123 {
t.Errorf("u, v, w, x = %d, %d, %d, %d, want 5, 23, 42, 123",
u, v, w, x)
}
if len(base) != 0 {
t.Errorf("len(base) = %d, want 0", len(base))
}
if len(child1) != 0 {
t.Errorf("len(child1) = %d, want 0", len(child1))
}
if len(base) != 0 {
t.Errorf("len(child2) = %d, want 0", len(child2))
}
}
func TestPreallocatedBuffer(t *testing.T) {
var buf [5]byte
b := NewBuilder(buf[0:0])
b.AddUint8(1)
b.AddUint8LengthPrefixed(func(c *Builder) {
c.AddUint8(3)
c.AddUint8(4)
})
b.AddUint16(1286) // Outgrow buf by one byte.
want := []byte{1, 2, 3, 4, 0}
if !bytes.Equal(buf[:], want) {
t.Errorf("buf = %v want %v", buf, want)
}
if err := builderBytesEq(b, 1, 2, 3, 4, 5, 6); err != nil {
t.Error(err)
}
}
func TestWriteWithPendingChild(t *testing.T) {
var b Builder
b.AddUint8LengthPrefixed(func(c *Builder) {
c.AddUint8LengthPrefixed(func(d *Builder) {
defer func() {
if recover() == nil {
t.Errorf("recover() = nil, want error; c.AddUint8() did not panic")
}
}()
c.AddUint8(2) // panics
defer func() {
if recover() == nil {
t.Errorf("recover() = nil, want error; b.AddUint8() did not panic")
}
}()
b.AddUint8(2) // panics
})
defer func() {
if recover() == nil {
t.Errorf("recover() = nil, want error; b.AddUint8() did not panic")
}
}()
b.AddUint8(2) // panics
})
}
// ASN.1
func TestASN1Int64(t *testing.T) {
tests := []struct {
in int64
want []byte
}{
{-0x800000, []byte{2, 3, 128, 0, 0}},
{-256, []byte{2, 2, 255, 0}},
{-129, []byte{2, 2, 255, 127}},
{-128, []byte{2, 1, 128}},
{-1, []byte{2, 1, 255}},
{0, []byte{2, 1, 0}},
{1, []byte{2, 1, 1}},
{2, []byte{2, 1, 2}},
{127, []byte{2, 1, 127}},
{128, []byte{2, 2, 0, 128}},
{256, []byte{2, 2, 1, 0}},
{0x800000, []byte{2, 4, 0, 128, 0, 0}},
}
for i, tt := range tests {
var b Builder
b.AddASN1Int64(tt.in)
if err := builderBytesEq(&b, tt.want...); err != nil {
t.Errorf("%v, (i = %d; in = %v)", err, i, tt.in)
}
var n int64
s := String(b.BytesOrPanic())
ok := s.ReadASN1Integer(&n)
if !ok || n != tt.in {
t.Errorf("s.ReadASN1Integer(&n) = %v, n = %d; want true, n = %d (i = %d)",
ok, n, tt.in, i)
}
if len(s) != 0 {
t.Errorf("len(s) = %d, want 0", len(s))
}
}
}
func TestASN1Uint64(t *testing.T) {
tests := []struct {
in uint64
want []byte
}{
{0, []byte{2, 1, 0}},
{1, []byte{2, 1, 1}},
{2, []byte{2, 1, 2}},
{127, []byte{2, 1, 127}},
{128, []byte{2, 2, 0, 128}},
{256, []byte{2, 2, 1, 0}},
{0x800000, []byte{2, 4, 0, 128, 0, 0}},
{0x7fffffffffffffff, []byte{2, 8, 127, 255, 255, 255, 255, 255, 255, 255}},
{0x8000000000000000, []byte{2, 9, 0, 128, 0, 0, 0, 0, 0, 0, 0}},
{0xffffffffffffffff, []byte{2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255}},
}
for i, tt := range tests {
var b Builder
b.AddASN1Uint64(tt.in)
if err := builderBytesEq(&b, tt.want...); err != nil {
t.Errorf("%v, (i = %d; in = %v)", err, i, tt.in)
}
var n uint64
s := String(b.BytesOrPanic())
ok := s.ReadASN1Integer(&n)
if !ok || n != tt.in {
t.Errorf("s.ReadASN1Integer(&n) = %v, n = %d; want true, n = %d (i = %d)",
ok, n, tt.in, i)
}
if len(s) != 0 {
t.Errorf("len(s) = %d, want 0", len(s))
}
}
}

120
vendor/golang.org/x/crypto/cryptobyte/example_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,120 @@
// 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_test
import (
"encoding/asn1"
"fmt"
"golang.org/x/crypto/cryptobyte"
)
func ExampleString_lengthPrefixed() {
// This is an example of parsing length-prefixed data (as found in, for
// example, TLS). Imagine a 16-bit prefixed series of 8-bit prefixed
// strings.
input := cryptobyte.String([]byte{0, 12, 5, 'h', 'e', 'l', 'l', 'o', 5, 'w', 'o', 'r', 'l', 'd'})
var result []string
var values cryptobyte.String
if !input.ReadUint16LengthPrefixed(&values) ||
!input.Empty() {
panic("bad format")
}
for !values.Empty() {
var value cryptobyte.String
if !values.ReadUint8LengthPrefixed(&value) {
panic("bad format")
}
result = append(result, string(value))
}
// Output: []string{"hello", "world"}
fmt.Printf("%#v\n", result)
}
func ExampleString_asn1() {
// This is an example of parsing ASN.1 data that looks like:
// Foo ::= SEQUENCE {
// version [6] INTEGER DEFAULT 0
// data OCTET STRING
// }
input := cryptobyte.String([]byte{0x30, 12, 0xa6, 3, 2, 1, 2, 4, 5, 'h', 'e', 'l', 'l', 'o'})
var (
version int64
data, inner, versionBytes cryptobyte.String
haveVersion bool
)
if !input.ReadASN1(&inner, cryptobyte.Tag(asn1.TagSequence).Constructed()) ||
!input.Empty() ||
!inner.ReadOptionalASN1(&versionBytes, &haveVersion, cryptobyte.Tag(6).Constructed().ContextSpecific()) ||
(haveVersion && !versionBytes.ReadASN1Integer(&version)) ||
(haveVersion && !versionBytes.Empty()) ||
!inner.ReadASN1(&data, asn1.TagOctetString) ||
!inner.Empty() {
panic("bad format")
}
// Output: haveVersion: true, version: 2, data: hello
fmt.Printf("haveVersion: %t, version: %d, data: %s\n", haveVersion, version, string(data))
}
func ExampleBuilder_asn1() {
// This is an example of building ASN.1 data that looks like:
// Foo ::= SEQUENCE {
// version [6] INTEGER DEFAULT 0
// data OCTET STRING
// }
version := int64(2)
data := []byte("hello")
const defaultVersion = 0
var b cryptobyte.Builder
b.AddASN1(cryptobyte.Tag(asn1.TagSequence).Constructed(), func(b *cryptobyte.Builder) {
if version != defaultVersion {
b.AddASN1(cryptobyte.Tag(6).Constructed().ContextSpecific(), func(b *cryptobyte.Builder) {
b.AddASN1Int64(version)
})
}
b.AddASN1OctetString(data)
})
result, err := b.Bytes()
if err != nil {
panic(err)
}
// Output: 300ca603020102040568656c6c6f
fmt.Printf("%x\n", result)
}
func ExampleBuilder_lengthPrefixed() {
// This is an example of building length-prefixed data (as found in,
// for example, TLS). Imagine a 16-bit prefixed series of 8-bit
// prefixed strings.
input := []string{"hello", "world"}
var b cryptobyte.Builder
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
for _, value := range input {
b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
b.AddBytes([]byte(value))
})
}
})
result, err := b.Bytes()
if err != nil {
panic(err)
}
// Output: 000c0568656c6c6f05776f726c64
fmt.Printf("%x\n", result)
}

157
vendor/golang.org/x/crypto/cryptobyte/string.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,157 @@
// 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 implements building and parsing of byte strings for
// DER-encoded ASN.1 and TLS messages. See the examples for the Builder and
// String types to get started.
package 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 {
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
// returns true on success and false on error.
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 returns true on success and false on error.
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 returns true on success and false on error.
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 returns true on success and false on error.
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
}
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)
}
if int(length) < 0 {
// This currently cannot overflow because we read uint24 at most, but check
// anyway in case that changes in the future.
return false
}
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 returns true on success and false on
// error.
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 returns true on
// success and false on error.
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 returns true on
// success and false on error.
func (s *String) ReadUint24LengthPrefixed(out *String) bool {
return s.readLengthPrefixed(3, out)
}
// ReadBytes reads n bytes into out and advances over them. It returns true on
// success and false and error.
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 returns
// true on success and false on error.
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
}

8
vendor/golang.org/x/crypto/curve25519/const_amd64.h сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,8 @@
// 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.
// This code was translated into a form compatible with 6a from the public
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
#define REDMASK51 0x0007FFFFFFFFFFFF

4
vendor/golang.org/x/crypto/curve25519/const_amd64.s сгенерированный поставляемый
Просмотреть файл

@@ -7,8 +7,8 @@
// +build amd64,!gccgo,!appengine
DATA ·REDMASK51(SB)/8, $0x0007FFFFFFFFFFFF
GLOBL ·REDMASK51(SB), 8, $8
// These constants cannot be encoded in non-MOVQ immediates.
// We access them directly from memory instead.
DATA ·_121666_213(SB)/8, $996687872
GLOBL ·_121666_213(SB), 8, $8

4
vendor/golang.org/x/crypto/curve25519/freeze_amd64.s сгенерированный поставляемый
Просмотреть файл

@@ -7,6 +7,8 @@
// +build amd64,!gccgo,!appengine
#include "const_amd64.h"
// func freeze(inout *[5]uint64)
TEXT ·freeze(SB),7,$0-8
MOVQ inout+0(FP), DI
@@ -16,7 +18,7 @@ TEXT ·freeze(SB),7,$0-8
MOVQ 16(DI),CX
MOVQ 24(DI),R8
MOVQ 32(DI),R9
MOVQ ·REDMASK51(SB),AX
MOVQ $REDMASK51,AX
MOVQ AX,R10
SUBQ $18,R10
MOVQ $3,R11

20
vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s сгенерированный поставляемый
Просмотреть файл

@@ -7,6 +7,8 @@
// +build amd64,!gccgo,!appengine
#include "const_amd64.h"
// func ladderstep(inout *[5][5]uint64)
TEXT ·ladderstep(SB),0,$296-8
MOVQ inout+0(FP),DI
@@ -118,7 +120,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 72(SP)
ADDQ AX,R12
ADCQ DX,R13
MOVQ ·REDMASK51(SB),DX
MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -233,7 +235,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 32(SP)
ADDQ AX,R12
ADCQ DX,R13
MOVQ ·REDMASK51(SB),DX
MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -438,7 +440,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 72(SP)
ADDQ AX,R12
ADCQ DX,R13
MOVQ ·REDMASK51(SB),DX
MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -588,7 +590,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 32(SP)
ADDQ AX,R12
ADCQ DX,R13
MOVQ ·REDMASK51(SB),DX
MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -728,7 +730,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 152(DI)
ADDQ AX,R12
ADCQ DX,R13
MOVQ ·REDMASK51(SB),DX
MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -843,7 +845,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 192(DI)
ADDQ AX,R12
ADCQ DX,R13
MOVQ ·REDMASK51(SB),DX
MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -993,7 +995,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 32(DI)
ADDQ AX,R12
ADCQ DX,R13
MOVQ ·REDMASK51(SB),DX
MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -1143,7 +1145,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 112(SP)
ADDQ AX,R12
ADCQ DX,R13
MOVQ ·REDMASK51(SB),DX
MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -1329,7 +1331,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 192(SP)
ADDQ AX,R12
ADCQ DX,R13
MOVQ ·REDMASK51(SB),DX
MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8

4
vendor/golang.org/x/crypto/curve25519/mul_amd64.s сгенерированный поставляемый
Просмотреть файл

@@ -7,6 +7,8 @@
// +build amd64,!gccgo,!appengine
#include "const_amd64.h"
// func mul(dest, a, b *[5]uint64)
TEXT ·mul(SB),0,$16-24
MOVQ dest+0(FP), DI
@@ -121,7 +123,7 @@ TEXT ·mul(SB),0,$16-24
MULQ 32(CX)
ADDQ AX,R14
ADCQ DX,R15
MOVQ ·REDMASK51(SB),SI
MOVQ $REDMASK51,SI
SHLQ $13,R9:R8
ANDQ SI,R8
SHLQ $13,R11:R10

4
vendor/golang.org/x/crypto/curve25519/square_amd64.s сгенерированный поставляемый
Просмотреть файл

@@ -7,6 +7,8 @@
// +build amd64,!gccgo,!appengine
#include "const_amd64.h"
// func square(out, in *[5]uint64)
TEXT ·square(SB),7,$0-16
MOVQ out+0(FP), DI
@@ -84,7 +86,7 @@ TEXT ·square(SB),7,$0-16
MULQ 32(SI)
ADDQ AX,R13
ADCQ DX,R14
MOVQ ·REDMASK51(SB),SI
MOVQ $REDMASK51,SI
SHLQ $13,R8:CX
ANDQ SI,CX
SHLQ $13,R10:R9

6
vendor/golang.org/x/crypto/ocsp/ocsp_test.go сгенерированный поставляемый
Просмотреть файл

@@ -225,7 +225,6 @@ func TestOCSPResponse(t *testing.T) {
},
}
producedAt := time.Now().Truncate(time.Minute)
thisUpdate := time.Date(2010, 7, 7, 15, 1, 5, 0, time.UTC)
nextUpdate := time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC)
template := Response{
@@ -284,8 +283,9 @@ func TestOCSPResponse(t *testing.T) {
t.Errorf("resp.Extensions: got %v, want %v", resp.Extensions, template.ExtraExtensions)
}
if !resp.ProducedAt.Equal(producedAt) {
t.Errorf("resp.ProducedAt: got %d, want %d", resp.ProducedAt, producedAt)
delay := time.Since(resp.ProducedAt)
if delay < -time.Hour || delay > time.Hour {
t.Errorf("resp.ProducedAt: got %s, want close to current time (%s)", resp.ProducedAt, time.Now())
}
if resp.Status != template.Status {

37
vendor/golang.org/x/crypto/poly1305/poly1305_test.go сгенерированный поставляемый
Просмотреть файл

@@ -6,10 +6,14 @@ package poly1305
import (
"bytes"
"encoding/hex"
"flag"
"testing"
"unsafe"
)
var stressFlag = flag.Bool("stress", false, "run slow stress tests")
var testData = []struct {
in, k, correct []byte
}{
@@ -88,6 +92,39 @@ func testSum(t *testing.T, unaligned bool) {
}
}
func TestBurnin(t *testing.T) {
// This test can be used to sanity-check significant changes. It can
// take about many minutes to run, even on fast machines. It's disabled
// by default.
if !*stressFlag {
t.Skip("skipping without -stress")
}
var key [32]byte
var input [25]byte
var output [16]byte
for i := range key {
key[i] = 1
}
for i := range input {
input[i] = 2
}
for i := uint64(0); i < 1e10; i++ {
Sum(&output, input[:], &key)
copy(key[0:], output[:])
copy(key[16:], output[:])
copy(input[:], output[:])
copy(input[16:], output[:])
}
const expected = "5e3b866aea0b636d240c83c428f84bfa"
if got := hex.EncodeToString(output[:]); got != expected {
t.Errorf("expected %s, got %s", expected, got)
}
}
func TestSum(t *testing.T) { testSum(t, false) }
func TestSumUnaligned(t *testing.T) { testSum(t, true) }

1614
vendor/golang.org/x/crypto/poly1305/sum_ref.go сгенерированный поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

2
vendor/golang.org/x/crypto/ssh/agent/client_test.go сгенерированный поставляемый
Просмотреть файл

@@ -180,7 +180,7 @@ func TestCert(t *testing.T) {
// therefore is buffered (net.Pipe deadlocks if both sides start with
// a write.)
func netPipe() (net.Conn, net.Conn, error) {
listener, err := net.Listen("tcp", "127.0.0.1:0")
listener, err := net.Listen("tcp", ":0")
if err != nil {
return nil, nil, err
}

64
vendor/golang.org/x/crypto/ssh/cipher.go сгенерированный поставляемый
Просмотреть файл

@@ -135,6 +135,7 @@ const prefixLen = 5
type streamPacketCipher struct {
mac hash.Hash
cipher cipher.Stream
etm bool
// The following members are to avoid per-packet allocations.
prefix [prefixLen]byte
@@ -150,7 +151,14 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
return nil, err
}
s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
var encryptedPaddingLength [1]byte
if s.mac != nil && s.etm {
copy(encryptedPaddingLength[:], s.prefix[4:5])
s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
} else {
s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
}
length := binary.BigEndian.Uint32(s.prefix[0:4])
paddingLength := uint32(s.prefix[4])
@@ -159,7 +167,12 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
s.mac.Reset()
binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
s.mac.Write(s.seqNumBytes[:])
s.mac.Write(s.prefix[:])
if s.etm {
s.mac.Write(s.prefix[:4])
s.mac.Write(encryptedPaddingLength[:])
} else {
s.mac.Write(s.prefix[:])
}
macSize = uint32(s.mac.Size())
}
@@ -184,10 +197,17 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
}
mac := s.packetData[length-1:]
data := s.packetData[:length-1]
if s.mac != nil && s.etm {
s.mac.Write(data)
}
s.cipher.XORKeyStream(data, data)
if s.mac != nil {
s.mac.Write(data)
if !s.etm {
s.mac.Write(data)
}
s.macResult = s.mac.Sum(s.macResult[:0])
if subtle.ConstantTimeCompare(s.macResult, mac) != 1 {
return nil, errors.New("ssh: MAC failure")
@@ -203,7 +223,13 @@ func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Rea
return errors.New("ssh: packet too large")
}
paddingLength := packetSizeMultiple - (prefixLen+len(packet))%packetSizeMultiple
aadlen := 0
if s.mac != nil && s.etm {
// packet length is not encrypted for EtM modes
aadlen = 4
}
paddingLength := packetSizeMultiple - (prefixLen+len(packet)-aadlen)%packetSizeMultiple
if paddingLength < 4 {
paddingLength += packetSizeMultiple
}
@@ -220,15 +246,37 @@ func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Rea
s.mac.Reset()
binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
s.mac.Write(s.seqNumBytes[:])
if s.etm {
// For EtM algorithms, the packet length must stay unencrypted,
// but the following data (padding length) must be encrypted
s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
}
s.mac.Write(s.prefix[:])
if !s.etm {
// For non-EtM algorithms, the algorithm is applied on unencrypted data
s.mac.Write(packet)
s.mac.Write(padding)
}
}
if !(s.mac != nil && s.etm) {
// For EtM algorithms, the padding length has already been encrypted
// and the packet length must remain unencrypted
s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
}
s.cipher.XORKeyStream(packet, packet)
s.cipher.XORKeyStream(padding, padding)
if s.mac != nil && s.etm {
// For EtM algorithms, packet and padding must be encrypted
s.mac.Write(packet)
s.mac.Write(padding)
}
s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
s.cipher.XORKeyStream(packet, packet)
s.cipher.XORKeyStream(padding, padding)
if _, err := w.Write(s.prefix[:]); err != nil {
return err
}

62
vendor/golang.org/x/crypto/ssh/cipher_test.go сгенерированный поставляемый
Просмотреть файл

@@ -26,39 +26,41 @@ func TestPacketCiphers(t *testing.T) {
defer delete(cipherModes, aes128cbcID)
for cipher := range cipherModes {
kr := &kexResult{Hash: crypto.SHA1}
algs := directionAlgorithms{
Cipher: cipher,
MAC: "hmac-sha1",
Compression: "none",
}
client, err := newPacketCipher(clientKeys, algs, kr)
if err != nil {
t.Errorf("newPacketCipher(client, %q): %v", cipher, err)
continue
}
server, err := newPacketCipher(clientKeys, algs, kr)
if err != nil {
t.Errorf("newPacketCipher(client, %q): %v", cipher, err)
continue
}
for mac := range macModes {
kr := &kexResult{Hash: crypto.SHA1}
algs := directionAlgorithms{
Cipher: cipher,
MAC: mac,
Compression: "none",
}
client, err := newPacketCipher(clientKeys, algs, kr)
if err != nil {
t.Errorf("newPacketCipher(client, %q, %q): %v", cipher, mac, err)
continue
}
server, err := newPacketCipher(clientKeys, algs, kr)
if err != nil {
t.Errorf("newPacketCipher(client, %q, %q): %v", cipher, mac, err)
continue
}
want := "bla bla"
input := []byte(want)
buf := &bytes.Buffer{}
if err := client.writePacket(0, buf, rand.Reader, input); err != nil {
t.Errorf("writePacket(%q): %v", cipher, err)
continue
}
want := "bla bla"
input := []byte(want)
buf := &bytes.Buffer{}
if err := client.writePacket(0, buf, rand.Reader, input); err != nil {
t.Errorf("writePacket(%q, %q): %v", cipher, mac, err)
continue
}
packet, err := server.readPacket(0, buf)
if err != nil {
t.Errorf("readPacket(%q): %v", cipher, err)
continue
}
packet, err := server.readPacket(0, buf)
if err != nil {
t.Errorf("readPacket(%q, %q): %v", cipher, mac, err)
continue
}
if string(packet) != want {
t.Errorf("roundtrip(%q): got %q, want %q", cipher, packet, want)
if string(packet) != want {
t.Errorf("roundtrip(%q, %q): got %q, want %q", cipher, mac, packet, want)
}
}
}
}

4
vendor/golang.org/x/crypto/ssh/client_auth_test.go сгенерированный поставляемый
Просмотреть файл

@@ -333,14 +333,14 @@ func TestClientLoginCert(t *testing.T) {
}
// allowed source address
cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24"}
cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24,::42/120"}
cert.SignCert(rand.Reader, testSigners["ecdsa"])
if err := tryAuth(t, clientConfig); err != nil {
t.Errorf("cert login with source-address failed: %v", err)
}
// disallowed source address
cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42"}
cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42,::42"}
cert.SignCert(rand.Reader, testSigners["ecdsa"])
if err := tryAuth(t, clientConfig); err == nil {
t.Errorf("cert login with source-address succeeded")

2
vendor/golang.org/x/crypto/ssh/common.go сгенерированный поставляемый
Просмотреть файл

@@ -56,7 +56,7 @@ var supportedHostKeyAlgos = []string{
// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed
// because they have reached the end of their useful life.
var supportedMACs = []string{
"hmac-sha2-256", "hmac-sha1", "hmac-sha1-96",
"hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96",
}
var supportedCompressions = []string{compressionNone}

49
vendor/golang.org/x/crypto/ssh/handshake.go сгенерированный поставляемый
Просмотреть файл

@@ -66,8 +66,8 @@ type handshakeTransport struct {
// If the read loop wants to schedule a kex, it pings this
// channel, and the write loop will send out a kex
// message. The boolean is whether this is the first request or not.
requestKex chan bool
// message.
requestKex chan struct{}
// If the other side requests or confirms a kex, its kexInit
// packet is sent here for the write loop to find it.
@@ -102,14 +102,14 @@ func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion,
serverVersion: serverVersion,
clientVersion: clientVersion,
incoming: make(chan []byte, chanSize),
requestKex: make(chan bool, 1),
requestKex: make(chan struct{}, 1),
startKex: make(chan *pendingKex, 1),
config: config,
}
// We always start with a mandatory key exchange.
t.requestKex <- true
t.requestKex <- struct{}{}
return t
}
@@ -166,6 +166,7 @@ func (t *handshakeTransport) printPacket(p []byte, write bool) {
if write {
action = "sent"
}
if p[0] == msgChannelData || p[0] == msgChannelExtendedData {
log.Printf("%s %s data (packet %d bytes)", t.id(), action, len(p))
} else {
@@ -230,14 +231,13 @@ func (t *handshakeTransport) recordWriteError(err error) {
func (t *handshakeTransport) requestKeyExchange() {
select {
case t.requestKex <- false:
case t.requestKex <- struct{}{}:
default:
// something already requested a kex, so do nothing.
}
}
func (t *handshakeTransport) kexLoop() {
firstSent := false
write:
for t.getWriteError() == nil {
@@ -251,18 +251,8 @@ write:
if !ok {
break write
}
case requestFirst := <-t.requestKex:
// For the first key exchange, both
// sides will initiate a key exchange,
// and both channels will fire. To
// avoid doing two key exchanges in a
// row, ignore our own request for an
// initial kex if we have already sent
// it out.
if firstSent && requestFirst {
continue
}
case <-t.requestKex:
break
}
if !sent {
@@ -270,7 +260,6 @@ write:
t.recordWriteError(err)
break
}
firstSent = true
sent = true
}
}
@@ -287,7 +276,8 @@ write:
// We're not servicing t.startKex, but the remote end
// has just sent us a kexInitMsg, so it can't send
// another key change request.
// another key change request, until we close the done
// channel on the pendingKex request.
err := t.enterKeyExchange(request.otherInit)
@@ -301,6 +291,23 @@ write:
} else if t.algorithms != nil {
t.writeBytesLeft = t.algorithms.w.rekeyBytes()
}
// we have completed the key exchange. Since the
// reader is still blocked, it is safe to clear out
// the requestKex channel. This avoids the situation
// where: 1) we consumed our own request for the
// initial kex, and 2) the kex from the remote side
// caused another send on the requestKex channel,
clear:
for {
select {
case <-t.requestKex:
//
default:
break clear
}
}
request.done <- t.writeError
// kex finished. Push packets that we received while
@@ -314,7 +321,7 @@ write:
break
}
}
t.pendingPackets = t.pendingPackets[0:]
t.pendingPackets = t.pendingPackets[:0]
t.mu.Unlock()
}

61
vendor/golang.org/x/crypto/ssh/handshake_test.go сгенерированный поставляемый
Просмотреть файл

@@ -40,7 +40,7 @@ func (t *testChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error
// therefore is buffered (net.Pipe deadlocks if both sides start with
// a write.)
func netPipe() (net.Conn, net.Conn, error) {
listener, err := net.Listen("tcp", "127.0.0.1:0")
listener, err := net.Listen("tcp", ":0")
if err != nil {
return nil, nil, err
}
@@ -125,7 +125,12 @@ func TestHandshakeBasic(t *testing.T) {
t.Skip("see golang.org/issue/7237")
}
checker := &syncChecker{make(chan int, 10)}
checker := &syncChecker{
waitCall: make(chan int, 10),
called: make(chan int, 10),
}
checker.waitCall <- 1
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false)
if err != nil {
t.Fatalf("handshakePair: %v", err)
@@ -134,22 +139,25 @@ func TestHandshakeBasic(t *testing.T) {
defer trC.Close()
defer trS.Close()
// Let first kex complete normally.
<-checker.called
clientDone := make(chan int, 0)
gotHalf := make(chan int, 0)
const N = 20
go func() {
defer close(clientDone)
// Client writes a bunch of stuff, and does a key
// change in the middle. This should not confuse the
// handshake in progress
for i := 0; i < 10; i++ {
// handshake in progress. We do this twice, so we test
// that the packet buffer is reset correctly.
for i := 0; i < N; i++ {
p := []byte{msgRequestSuccess, byte(i)}
if err := trC.writePacket(p); err != nil {
t.Fatalf("sendPacket: %v", err)
}
if i == 5 {
if (i % 10) == 5 {
<-gotHalf
// halfway through, we request a key change.
trC.requestKeyExchange()
@@ -159,32 +167,38 @@ func TestHandshakeBasic(t *testing.T) {
// write more.
<-checker.called
}
if (i % 10) == 7 {
// write some packets until the kex
// completes, to test buffering of
// packets.
checker.waitCall <- 1
}
}
}()
// Server checks that client messages come in cleanly
i := 0
err = nil
for ; i < 10; i++ {
for ; i < N; i++ {
var p []byte
p, err = trS.readPacket()
if err != nil {
break
}
if i == 5 {
if (i % 10) == 5 {
gotHalf <- 1
}
want := []byte{msgRequestSuccess, byte(i)}
if bytes.Compare(p, want) != 0 {
t.Errorf("message %d: got %q, want %q", i, p, want)
t.Errorf("message %d: got %v, want %v", i, p, want)
}
}
<-clientDone
if err != nil && err != io.EOF {
t.Fatalf("server error: %v", err)
}
if i != 10 {
if i != N {
t.Errorf("received %d messages, want 10.", i)
}
@@ -239,7 +253,10 @@ func TestForceFirstKex(t *testing.T) {
}
func TestHandshakeAutoRekeyWrite(t *testing.T) {
checker := &syncChecker{make(chan int, 10)}
checker := &syncChecker{
called: make(chan int, 10),
waitCall: nil,
}
clientConf := &ClientConfig{HostKeyCallback: checker.Check}
clientConf.RekeyThreshold = 500
trC, trS, err := handshakePair(clientConf, "addr", false)
@@ -249,14 +266,19 @@ func TestHandshakeAutoRekeyWrite(t *testing.T) {
defer trC.Close()
defer trS.Close()
input := make([]byte, 251)
input[0] = msgRequestSuccess
done := make(chan int, 1)
const numPacket = 5
go func() {
defer close(done)
j := 0
for ; j < numPacket; j++ {
if _, err := trS.readPacket(); err != nil {
if p, err := trS.readPacket(); err != nil {
break
} else if !bytes.Equal(input, p) {
t.Errorf("got packet type %d, want %d", p[0], input[0])
}
}
@@ -268,9 +290,9 @@ func TestHandshakeAutoRekeyWrite(t *testing.T) {
<-checker.called
for i := 0; i < numPacket; i++ {
packet := make([]byte, 251)
packet[0] = msgRequestSuccess
if err := trC.writePacket(packet); err != nil {
p := make([]byte, len(input))
copy(p, input)
if err := trC.writePacket(p); err != nil {
t.Errorf("writePacket: %v", err)
}
if i == 2 {
@@ -283,16 +305,23 @@ func TestHandshakeAutoRekeyWrite(t *testing.T) {
}
type syncChecker struct {
called chan int
waitCall chan int
called chan int
}
func (c *syncChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error {
c.called <- 1
if c.waitCall != nil {
<-c.waitCall
}
return nil
}
func TestHandshakeAutoRekeyRead(t *testing.T) {
sync := &syncChecker{make(chan int, 2)}
sync := &syncChecker{
called: make(chan int, 2),
waitCall: nil,
}
clientConf := &ClientConfig{
HostKeyCallback: sync.Check,
}

10
vendor/golang.org/x/crypto/ssh/mac.go сгенерированный поставляемый
Просмотреть файл

@@ -15,6 +15,7 @@ import (
type macMode struct {
keySize int
etm bool
new func(key []byte) hash.Hash
}
@@ -45,13 +46,16 @@ func (t truncatingMAC) Size() int {
func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
var macModes = map[string]*macMode{
"hmac-sha2-256": {32, func(key []byte) hash.Hash {
"hmac-sha2-256-etm@openssh.com": {32, true, func(key []byte) hash.Hash {
return hmac.New(sha256.New, key)
}},
"hmac-sha1": {20, func(key []byte) hash.Hash {
"hmac-sha2-256": {32, false, func(key []byte) hash.Hash {
return hmac.New(sha256.New, key)
}},
"hmac-sha1": {20, false, func(key []byte) hash.Hash {
return hmac.New(sha1.New, key)
}},
"hmac-sha1-96": {20, func(key []byte) hash.Hash {
"hmac-sha1-96": {20, false, func(key []byte) hash.Hash {
return truncatingMAC{12, hmac.New(sha1.New, key)}
}},
}

3
vendor/golang.org/x/crypto/ssh/mux_test.go сгенерированный поставляемый
Просмотреть файл

@@ -499,4 +499,7 @@ func TestDebug(t *testing.T) {
if debugHandshake {
t.Error("handshake debug switched on")
}
if debugTransport {
t.Error("transport debug switched on")
}
}

27
vendor/golang.org/x/crypto/ssh/server.go сгенерированный поставляемый
Просмотреть файл

@@ -10,6 +10,7 @@ import (
"fmt"
"io"
"net"
"strings"
)
// The Permissions type holds fine-grained permissions that are
@@ -231,7 +232,7 @@ func isAcceptableAlgo(algo string) bool {
return false
}
func checkSourceAddress(addr net.Addr, sourceAddr string) error {
func checkSourceAddress(addr net.Addr, sourceAddrs string) error {
if addr == nil {
return errors.New("ssh: no address known for client, but source-address match required")
}
@@ -241,18 +242,20 @@ func checkSourceAddress(addr net.Addr, sourceAddr string) error {
return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr)
}
if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil {
if allowedIP.Equal(tcpAddr.IP) {
return nil
}
} else {
_, ipNet, err := net.ParseCIDR(sourceAddr)
if err != nil {
return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err)
}
for _, sourceAddr := range strings.Split(sourceAddrs, ",") {
if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil {
if allowedIP.Equal(tcpAddr.IP) {
return nil
}
} else {
_, ipNet, err := net.ParseCIDR(sourceAddr)
if err != nil {
return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err)
}
if ipNet.Contains(tcpAddr.IP) {
return nil
if ipNet.Contains(tcpAddr.IP) {
return nil
}
}
}

32
vendor/golang.org/x/crypto/ssh/transport.go сгенерированный поставляемый
Просмотреть файл

@@ -8,8 +8,13 @@ import (
"bufio"
"errors"
"io"
"log"
)
// debugTransport if set, will print packet types as they go over the
// wire. No message decoding is done, to minimize the impact on timing.
const debugTransport = false
const (
gcmCipherID = "aes128-gcm@openssh.com"
aes128cbcID = "aes128-cbc"
@@ -40,7 +45,7 @@ type transport struct {
bufReader *bufio.Reader
bufWriter *bufio.Writer
rand io.Reader
isClient bool
io.Closer
}
@@ -86,6 +91,22 @@ func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) err
return nil
}
func (t *transport) printPacket(p []byte, write bool) {
if len(p) == 0 {
return
}
who := "server"
if t.isClient {
who = "client"
}
what := "read"
if write {
what = "write"
}
log.Println(what, who, p[0])
}
// Read and decrypt next packet.
func (t *transport) readPacket() (p []byte, err error) {
for {
@@ -97,6 +118,9 @@ func (t *transport) readPacket() (p []byte, err error) {
break
}
}
if debugTransport {
t.printPacket(p, false)
}
return p, err
}
@@ -141,6 +165,9 @@ func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
}
func (t *transport) writePacket(packet []byte) error {
if debugTransport {
t.printPacket(packet, true)
}
return t.writer.writePacket(t.bufWriter, t.rand, packet)
}
@@ -181,6 +208,8 @@ func newTransport(rwc io.ReadWriteCloser, rand io.Reader, isClient bool) *transp
},
Closer: rwc,
}
t.isClient = isClient
if isClient {
t.reader.dir = serverKeys
t.writer.dir = clientKeys
@@ -238,6 +267,7 @@ func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (pac
c := &streamPacketCipher{
mac: macModes[algs.MAC].new(macKey),
etm: macModes[algs.MAC].etm,
}
c.macResult = make([]byte, c.mac.Size())

42
vendor/golang.org/x/image/draw/draw.go сгенерированный поставляемый
Просмотреть файл

@@ -11,12 +11,12 @@
// package in the standard library.
package draw
// This file just contains the API exported by the image/draw package in the
// standard library. Other files in this package provide additional features.
// This file, and the go1_*.go files, just contains the API exported by the
// image/draw package in the standard library. Other files in this package
// provide additional features.
import (
"image"
"image/color"
"image/draw"
)
@@ -32,13 +32,6 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
draw.DrawMask(dst, r, src, sp, mask, mp, draw.Op(op))
}
// Drawer contains the Draw method.
type Drawer interface {
// Draw aligns r.Min in dst with sp in src and then replaces the
// rectangle r in dst with the result of drawing src on dst.
Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point)
}
// FloydSteinberg is a Drawer that is the Src Op with Floyd-Steinberg error
// diffusion.
var FloydSteinberg Drawer = floydSteinberg{}
@@ -48,32 +41,3 @@ type floydSteinberg struct{}
func (floydSteinberg) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) {
draw.FloydSteinberg.Draw(dst, r, src, sp)
}
// Image is an image.Image with a Set method to change a single pixel.
type Image interface {
image.Image
Set(x, y int, c color.Color)
}
// Op is a Porter-Duff compositing operator.
type Op int
const (
// Over specifies ``(src in mask) over dst''.
Over Op = Op(draw.Over)
// Src specifies ``src in mask''.
Src Op = Op(draw.Src)
)
// Draw implements the Drawer interface by calling the Draw function with
// this Op.
func (op Op) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) {
(draw.Op(op)).Draw(dst, r, src, sp)
}
// Quantizer produces a palette for an image.
type Quantizer interface {
// Quantize appends up to cap(p) - len(p) colors to p and returns the
// updated palette suitable for converting m to a paletted image.
Quantize(p color.Palette, m image.Image) color.Palette
}

2
vendor/golang.org/x/image/draw/gen.go сгенерированный поставляемый
Просмотреть файл

@@ -804,7 +804,7 @@ func cOffset(x, y, sratio string) string {
func ycbcrToRGB(lhs, tmp string) string {
s := `
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
$yy1 := int(src.Y[$i]) * 0x10100
$yy1 := int(src.Y[$i]) * 0x10101
$cb1 := int(src.Cb[$j]) - 128
$cr1 := int(src.Cr[$j]) - 128
$r@ := ($yy1 + 91881*$cr1) >> 8

49
vendor/golang.org/x/image/draw/go1_8.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,49 @@
// 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.
// +build !go1.9,!go1.8.typealias
package draw
import (
"image"
"image/color"
"image/draw"
)
// Drawer contains the Draw method.
type Drawer interface {
// Draw aligns r.Min in dst with sp in src and then replaces the
// rectangle r in dst with the result of drawing src on dst.
Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point)
}
// Image is an image.Image with a Set method to change a single pixel.
type Image interface {
image.Image
Set(x, y int, c color.Color)
}
// Op is a Porter-Duff compositing operator.
type Op int
const (
// Over specifies ``(src in mask) over dst''.
Over Op = Op(draw.Over)
// Src specifies ``src in mask''.
Src Op = Op(draw.Src)
)
// Draw implements the Drawer interface by calling the Draw function with
// this Op.
func (op Op) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) {
(draw.Op(op)).Draw(dst, r, src, sp)
}
// Quantizer produces a palette for an image.
type Quantizer interface {
// Quantize appends up to cap(p) - len(p) colors to p and returns the
// updated palette suitable for converting m to a paletted image.
Quantize(p color.Palette, m image.Image) color.Palette
}

57
vendor/golang.org/x/image/draw/go1_9.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,57 @@
// Copyright 2016 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.
// +build go1.9 go1.8.typealias
package draw
import (
"image/draw"
)
// We use type aliases (new in Go 1.9) for the exported names from the standard
// library's image/draw package. This is not merely syntactic sugar for
//
// type Drawer draw.Drawer
//
// as aliasing means that the types in this package, such as draw.Image and
// draw.Op, are identical to the corresponding draw.Image and draw.Op types in
// the standard library. In comparison, prior to Go 1.9, the code in go1_8.go
// defines new types that mimic the old but are different types.
//
// The package documentation, in draw.go, explicitly gives the intent of this
// package:
//
// This package is a superset of and a drop-in replacement for the
// image/draw package in the standard library.
//
// Drop-in replacement means that I can replace all of my "image/draw" imports
// with "golang.org/x/image/draw", to access additional features in this
// package, and no further changes are required. That's mostly true, but not
// completely true unless we use type aliases.
//
// Without type aliases, users might need to import both "image/draw" and
// "golang.org/x/image/draw" in order to convert from two conceptually
// equivalent but different (from the compiler's point of view) types, such as
// from one draw.Op type to another draw.Op type, to satisfy some other
// interface or function signature.
// Drawer contains the Draw method.
type Drawer = draw.Drawer
// Image is an image.Image with a Set method to change a single pixel.
type Image = draw.Image
// Op is a Porter-Duff compositing operator.
type Op = draw.Op
const (
// Over specifies ``(src in mask) over dst''.
Over Op = draw.Over
// Src specifies ``src in mask''.
Src Op = draw.Src
)
// Quantizer produces a palette for an image.
type Quantizer = draw.Quantizer

96
vendor/golang.org/x/image/draw/impl.go сгенерированный поставляемый
Просмотреть файл

@@ -343,7 +343,7 @@ func (nnInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rec
pj := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
pyy1 := int(src.Y[pi]) * 0x10100
pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -386,7 +386,7 @@ func (nnInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rec
pj := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
pyy1 := int(src.Y[pi]) * 0x10100
pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -429,7 +429,7 @@ func (nnInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rec
pj := ((sr.Min.Y+int(sy))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
pyy1 := int(src.Y[pi]) * 0x10100
pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -472,7 +472,7 @@ func (nnInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rec
pj := ((sr.Min.Y+int(sy))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
pyy1 := int(src.Y[pi]) * 0x10100
pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -759,7 +759,7 @@ func (nnInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image
pj := (sy0-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
pyy1 := int(src.Y[pi]) * 0x10100
pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -803,7 +803,7 @@ func (nnInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image
pj := (sy0-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
pyy1 := int(src.Y[pi]) * 0x10100
pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -847,7 +847,7 @@ func (nnInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image
pj := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
pyy1 := int(src.Y[pi]) * 0x10100
pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -891,7 +891,7 @@ func (nnInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image
pj := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
pyy1 := int(src.Y[pi]) * 0x10100
pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -1756,7 +1756,7 @@ func (ablInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Re
s00j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s00yy1 := int(src.Y[s00i]) * 0x10100
s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -1785,7 +1785,7 @@ func (ablInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Re
s10j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s10yy1 := int(src.Y[s10i]) * 0x10100
s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -1817,7 +1817,7 @@ func (ablInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Re
s01j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s01yy1 := int(src.Y[s01i]) * 0x10100
s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -1846,7 +1846,7 @@ func (ablInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Re
s11j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s11yy1 := int(src.Y[s11i]) * 0x10100
s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -1931,7 +1931,7 @@ func (ablInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Re
s00j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s00yy1 := int(src.Y[s00i]) * 0x10100
s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -1960,7 +1960,7 @@ func (ablInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Re
s10j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s10yy1 := int(src.Y[s10i]) * 0x10100
s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -1992,7 +1992,7 @@ func (ablInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Re
s01j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s01yy1 := int(src.Y[s01i]) * 0x10100
s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -2021,7 +2021,7 @@ func (ablInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Re
s11j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s11yy1 := int(src.Y[s11i]) * 0x10100
s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -2106,7 +2106,7 @@ func (ablInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Re
s00j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s00yy1 := int(src.Y[s00i]) * 0x10100
s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -2135,7 +2135,7 @@ func (ablInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Re
s10j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s10yy1 := int(src.Y[s10i]) * 0x10100
s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -2167,7 +2167,7 @@ func (ablInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Re
s01j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s01yy1 := int(src.Y[s01i]) * 0x10100
s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -2196,7 +2196,7 @@ func (ablInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Re
s11j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s11yy1 := int(src.Y[s11i]) * 0x10100
s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -2281,7 +2281,7 @@ func (ablInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Re
s00j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s00yy1 := int(src.Y[s00i]) * 0x10100
s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -2310,7 +2310,7 @@ func (ablInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Re
s10j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s10yy1 := int(src.Y[s10i]) * 0x10100
s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -2342,7 +2342,7 @@ func (ablInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Re
s01j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s01yy1 := int(src.Y[s01i]) * 0x10100
s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -2371,7 +2371,7 @@ func (ablInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Re
s11j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s11yy1 := int(src.Y[s11i]) * 0x10100
s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -3345,7 +3345,7 @@ func (ablInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr imag
s00j := (sy0-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s00yy1 := int(src.Y[s00i]) * 0x10100
s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -3374,7 +3374,7 @@ func (ablInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr imag
s10j := (sy0-src.Rect.Min.Y)*src.CStride + (sx1 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s10yy1 := int(src.Y[s10i]) * 0x10100
s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -3406,7 +3406,7 @@ func (ablInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr imag
s01j := (sy1-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s01yy1 := int(src.Y[s01i]) * 0x10100
s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -3435,7 +3435,7 @@ func (ablInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr imag
s11j := (sy1-src.Rect.Min.Y)*src.CStride + (sx1 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s11yy1 := int(src.Y[s11i]) * 0x10100
s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -3521,7 +3521,7 @@ func (ablInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr imag
s00j := (sy0-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s00yy1 := int(src.Y[s00i]) * 0x10100
s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -3550,7 +3550,7 @@ func (ablInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr imag
s10j := (sy0-src.Rect.Min.Y)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s10yy1 := int(src.Y[s10i]) * 0x10100
s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -3582,7 +3582,7 @@ func (ablInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr imag
s01j := (sy1-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s01yy1 := int(src.Y[s01i]) * 0x10100
s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -3611,7 +3611,7 @@ func (ablInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr imag
s11j := (sy1-src.Rect.Min.Y)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s11yy1 := int(src.Y[s11i]) * 0x10100
s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -3697,7 +3697,7 @@ func (ablInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr imag
s00j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s00yy1 := int(src.Y[s00i]) * 0x10100
s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -3726,7 +3726,7 @@ func (ablInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr imag
s10j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s10yy1 := int(src.Y[s10i]) * 0x10100
s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -3758,7 +3758,7 @@ func (ablInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr imag
s01j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s01yy1 := int(src.Y[s01i]) * 0x10100
s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -3787,7 +3787,7 @@ func (ablInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr imag
s11j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s11yy1 := int(src.Y[s11i]) * 0x10100
s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -3873,7 +3873,7 @@ func (ablInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr imag
s00j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s00yy1 := int(src.Y[s00i]) * 0x10100
s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -3902,7 +3902,7 @@ func (ablInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr imag
s10j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx1 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s10yy1 := int(src.Y[s10i]) * 0x10100
s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -3934,7 +3934,7 @@ func (ablInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr imag
s01j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s01yy1 := int(src.Y[s01i]) * 0x10100
s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -3963,7 +3963,7 @@ func (ablInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr imag
s11j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + (sx1 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s11yy1 := int(src.Y[s11i]) * 0x10100
s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -4729,7 +4729,7 @@ func (z *kernelScaler) scaleX_YCbCr444(tmp [][4]float64, src *image.YCbCr, sr im
pj := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
pyy1 := int(src.Y[pi]) * 0x10100
pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
@@ -4776,7 +4776,7 @@ func (z *kernelScaler) scaleX_YCbCr422(tmp [][4]float64, src *image.YCbCr, sr im
pj := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(c.coord))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
pyy1 := int(src.Y[pi]) * 0x10100
pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
@@ -4823,7 +4823,7 @@ func (z *kernelScaler) scaleX_YCbCr420(tmp [][4]float64, src *image.YCbCr, sr im
pj := ((sr.Min.Y+int(y))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(c.coord))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
pyy1 := int(src.Y[pi]) * 0x10100
pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
@@ -4870,7 +4870,7 @@ func (z *kernelScaler) scaleX_YCbCr440(tmp [][4]float64, src *image.YCbCr, sr im
pj := ((sr.Min.Y+int(y))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
pyy1 := int(src.Y[pi]) * 0x10100
pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
@@ -5759,7 +5759,7 @@ func (q *Kernel) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rect
pj := (ky-src.Rect.Min.Y)*src.CStride + (kx - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
pyy1 := int(src.Y[pi]) * 0x10100
pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
@@ -5883,7 +5883,7 @@ func (q *Kernel) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rect
pj := (ky-src.Rect.Min.Y)*src.CStride + ((kx)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
pyy1 := int(src.Y[pi]) * 0x10100
pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
@@ -6007,7 +6007,7 @@ func (q *Kernel) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rect
pj := ((ky)/2-src.Rect.Min.Y/2)*src.CStride + ((kx)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
pyy1 := int(src.Y[pi]) * 0x10100
pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
@@ -6131,7 +6131,7 @@ func (q *Kernel) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rect
pj := ((ky)/2-src.Rect.Min.Y/2)*src.CStride + (kx - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
pyy1 := int(src.Y[pi]) * 0x10100
pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8

6
vendor/golang.org/x/image/draw/stdlib_test.go сгенерированный поставляемый
Просмотреть файл

@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.5
// +build go1.9
package draw
// This file contains tests that depend on the exact behavior of the
// image/color package in the standard library. The color conversion formula
// from YCbCr to RGBA changed between Go 1.4 and Go 1.5, so this file's tests
// are only enabled for Go 1.5 and above.
// from YCbCr to RGBA changed between Go 1.4 and Go 1.5, and between Go 1.8 and
// Go 1.9, so this file's tests are only enabled for Go 1.9 and above.
import (
"bytes"

269
vendor/golang.org/x/image/font/sfnt/cmap.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,269 @@
// 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 sfnt
import (
"unicode/utf8"
"golang.org/x/text/encoding/charmap"
)
// Platform IDs and Platform Specific IDs as per
// https://www.microsoft.com/typography/otspec/name.htm
const (
pidUnicode = 0
pidMacintosh = 1
pidWindows = 3
psidUnicode2BMPOnly = 3
psidUnicode2FullRepertoire = 4
// Note that FontForge may generate a bogus Platform Specific ID (value 10)
// for the Unicode Platform ID (value 0). See
// https://github.com/fontforge/fontforge/issues/2728
psidMacintoshRoman = 0
psidWindowsSymbol = 0
psidWindowsUCS2 = 1
psidWindowsUCS4 = 10
)
// platformEncodingWidth returns the number of bytes per character assumed by
// the given Platform ID and Platform Specific ID.
//
// Very old fonts, from before Unicode was widely adopted, assume only 1 byte
// per character: a character map.
//
// Old fonts, from when Unicode meant the Basic Multilingual Plane (BMP),
// assume that 2 bytes per character is sufficient.
//
// Recent fonts naturally support the full range of Unicode code points, which
// can take up to 4 bytes per character. Such fonts might still choose one of
// the legacy encodings if e.g. their repertoire is limited to the BMP, for
// greater compatibility with older software, or because the resultant file
// size can be smaller.
func platformEncodingWidth(pid, psid uint16) int {
switch pid {
case pidUnicode:
switch psid {
case psidUnicode2BMPOnly:
return 2
case psidUnicode2FullRepertoire:
return 4
}
case pidMacintosh:
switch psid {
case psidMacintoshRoman:
return 1
}
case pidWindows:
switch psid {
case psidWindowsSymbol:
return 2
case psidWindowsUCS2:
return 2
case psidWindowsUCS4:
return 4
}
}
return 0
}
// The various cmap formats are described at
// https://www.microsoft.com/typography/otspec/cmap.htm
var supportedCmapFormat = func(format, pid, psid uint16) bool {
switch format {
case 0:
return pid == pidMacintosh && psid == psidMacintoshRoman
case 4:
return true
case 12:
return true
}
return false
}
func (f *Font) makeCachedGlyphIndex(buf []byte, offset, length uint32, format uint16) ([]byte, glyphIndexFunc, error) {
switch format {
case 0:
return f.makeCachedGlyphIndexFormat0(buf, offset, length)
case 4:
return f.makeCachedGlyphIndexFormat4(buf, offset, length)
case 12:
return f.makeCachedGlyphIndexFormat12(buf, offset, length)
}
panic("unreachable")
}
func (f *Font) makeCachedGlyphIndexFormat0(buf []byte, offset, length uint32) ([]byte, glyphIndexFunc, error) {
if length != 6+256 || offset+length > f.cmap.length {
return nil, nil, errInvalidCmapTable
}
var err error
buf, err = f.src.view(buf, int(f.cmap.offset+offset), int(length))
if err != nil {
return nil, nil, err
}
var table [256]byte
copy(table[:], buf[6:])
return buf, func(f *Font, b *Buffer, r rune) (GlyphIndex, error) {
// TODO: for this closure to be goroutine-safe, the
// golang.org/x/text/encoding/charmap API needs to allocate a new
// Encoder and new []byte buffers, for every call to this closure, even
// though all we want to do is to encode one rune as one byte. We could
// possibly add some fields in the Buffer struct to re-use these
// allocations, but a better solution is to improve the charmap API.
var dst, src [utf8.UTFMax]byte
n := utf8.EncodeRune(src[:], r)
_, _, err = charmap.Macintosh.NewEncoder().Transform(dst[:], src[:n], true)
if err != nil {
// The source rune r is not representable in the Macintosh-Roman encoding.
return 0, nil
}
return GlyphIndex(table[dst[0]]), nil
}, nil
}
func (f *Font) makeCachedGlyphIndexFormat4(buf []byte, offset, length uint32) ([]byte, glyphIndexFunc, error) {
const headerSize = 14
if offset+headerSize > f.cmap.length {
return nil, nil, errInvalidCmapTable
}
var err error
buf, err = f.src.view(buf, int(f.cmap.offset+offset), headerSize)
if err != nil {
return nil, nil, err
}
offset += headerSize
segCount := u16(buf[6:])
if segCount&1 != 0 {
return nil, nil, errInvalidCmapTable
}
segCount /= 2
if segCount > maxCmapSegments {
return nil, nil, errUnsupportedNumberOfCmapSegments
}
eLength := 8*uint32(segCount) + 2
if offset+eLength > f.cmap.length {
return nil, nil, errInvalidCmapTable
}
buf, err = f.src.view(buf, int(f.cmap.offset+offset), int(eLength))
if err != nil {
return nil, nil, err
}
offset += eLength
entries := make([]cmapEntry16, segCount)
for i := range entries {
entries[i] = cmapEntry16{
end: u16(buf[0*len(entries)+0+2*i:]),
start: u16(buf[2*len(entries)+2+2*i:]),
delta: u16(buf[4*len(entries)+2+2*i:]),
offset: u16(buf[6*len(entries)+2+2*i:]),
}
}
indexesBase := f.cmap.offset + offset
indexesLength := f.cmap.length - offset
return buf, func(f *Font, b *Buffer, r rune) (GlyphIndex, error) {
if uint32(r) > 0xffff {
return 0, nil
}
c := uint16(r)
for i, j := 0, len(entries); i < j; {
h := i + (j-i)/2
entry := &entries[h]
if c < entry.start {
j = h
} else if entry.end < c {
i = h + 1
} else if entry.offset == 0 {
return GlyphIndex(c + entry.delta), nil
} else {
offset := uint32(entry.offset) + 2*uint32(h-len(entries)+int(c-entry.start))
if offset > indexesLength || offset+2 > indexesLength {
return 0, errInvalidCmapTable
}
x, err := b.view(&f.src, int(indexesBase+offset), 2)
if err != nil {
return 0, err
}
return GlyphIndex(u16(x)), nil
}
}
return 0, nil
}, nil
}
func (f *Font) makeCachedGlyphIndexFormat12(buf []byte, offset, _ uint32) ([]byte, glyphIndexFunc, error) {
const headerSize = 16
if offset+headerSize > f.cmap.length {
return nil, nil, errInvalidCmapTable
}
var err error
buf, err = f.src.view(buf, int(f.cmap.offset+offset), headerSize)
if err != nil {
return nil, nil, err
}
length := u32(buf[4:])
if f.cmap.length < offset || length > f.cmap.length-offset {
return nil, nil, errInvalidCmapTable
}
offset += headerSize
numGroups := u32(buf[12:])
if numGroups > maxCmapSegments {
return nil, nil, errUnsupportedNumberOfCmapSegments
}
eLength := 12 * numGroups
if headerSize+eLength != length {
return nil, nil, errInvalidCmapTable
}
buf, err = f.src.view(buf, int(f.cmap.offset+offset), int(eLength))
if err != nil {
return nil, nil, err
}
offset += eLength
entries := make([]cmapEntry32, numGroups)
for i := range entries {
entries[i] = cmapEntry32{
start: u32(buf[0+12*i:]),
end: u32(buf[4+12*i:]),
delta: u32(buf[8+12*i:]),
}
}
return buf, func(f *Font, b *Buffer, r rune) (GlyphIndex, error) {
c := uint32(r)
for i, j := 0, len(entries); i < j; {
h := i + (j-i)/2
entry := &entries[h]
if c < entry.start {
j = h
} else if entry.end < c {
i = h + 1
} else {
return GlyphIndex(c - entry.start + entry.delta), nil
}
}
return 0, nil
}, nil
}
type cmapEntry16 struct {
end, start, delta, offset uint16
}
type cmapEntry32 struct {
start, end, delta uint32
}

68
vendor/golang.org/x/image/font/sfnt/data.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,68 @@
// generated by go run gen.go; DO NOT EDIT
package sfnt
const numBuiltInPostNames = 258
const builtInPostNamesData = "" +
".notdef.nullnonmarkingreturnspaceexclamquotedblnumbersigndollarp" +
"ercentampersandquotesingleparenleftparenrightasteriskpluscommahy" +
"phenperiodslashzeroonetwothreefourfivesixseveneightninecolonsemi" +
"colonlessequalgreaterquestionatABCDEFGHIJKLMNOPQRSTUVWXYZbracket" +
"leftbackslashbracketrightasciicircumunderscoregraveabcdefghijklm" +
"nopqrstuvwxyzbraceleftbarbracerightasciitildeAdieresisAringCcedi" +
"llaEacuteNtildeOdieresisUdieresisaacuteagraveacircumflexadieresi" +
"satildearingccedillaeacuteegraveecircumflexedieresisiacuteigrave" +
"icircumflexidieresisntildeoacuteograveocircumflexodieresisotilde" +
"uacuteugraveucircumflexudieresisdaggerdegreecentsterlingsectionb" +
"ulletparagraphgermandblsregisteredcopyrighttrademarkacutedieresi" +
"snotequalAEOslashinfinityplusminuslessequalgreaterequalyenmupart" +
"ialdiffsummationproductpiintegralordfeminineordmasculineOmegaaeo" +
"slashquestiondownexclamdownlogicalnotradicalflorinapproxequalDel" +
"taguillemotleftguillemotrightellipsisnonbreakingspaceAgraveAtild" +
"eOtildeOEoeendashemdashquotedblleftquotedblrightquoteleftquoteri" +
"ghtdividelozengeydieresisYdieresisfractioncurrencyguilsinglleftg" +
"uilsinglrightfifldaggerdblperiodcenteredquotesinglbasequotedblba" +
"seperthousandAcircumflexEcircumflexAacuteEdieresisEgraveIacuteIc" +
"ircumflexIdieresisIgraveOacuteOcircumflexappleOgraveUacuteUcircu" +
"mflexUgravedotlessicircumflextildemacronbrevedotaccentringcedill" +
"ahungarumlautogonekcaronLslashlslashScaronscaronZcaronzcaronbrok" +
"enbarEthethYacuteyacuteThornthornminusmultiplyonesuperiortwosupe" +
"riorthreesuperioronehalfonequarterthreequartersfrancGbrevegbreve" +
"IdotaccentScedillascedillaCacutecacuteCcaronccarondcroat"
var builtInPostNamesOffsets = [...]uint16{
0x0000, 0x0007, 0x000c, 0x001c, 0x0021, 0x0027, 0x002f, 0x0039,
0x003f, 0x0046, 0x004f, 0x005a, 0x0063, 0x006d, 0x0075, 0x0079,
0x007e, 0x0084, 0x008a, 0x008f, 0x0093, 0x0096, 0x0099, 0x009e,
0x00a2, 0x00a6, 0x00a9, 0x00ae, 0x00b3, 0x00b7, 0x00bc, 0x00c5,
0x00c9, 0x00ce, 0x00d5, 0x00dd, 0x00df, 0x00e0, 0x00e1, 0x00e2,
0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea,
0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, 0x00f0, 0x00f1, 0x00f2,
0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x0104,
0x010d, 0x0119, 0x0124, 0x012e, 0x0133, 0x0134, 0x0135, 0x0136,
0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d, 0x013e,
0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146,
0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d, 0x0156,
0x0159, 0x0163, 0x016d, 0x0176, 0x017b, 0x0183, 0x0189, 0x018f,
0x0198, 0x01a1, 0x01a7, 0x01ad, 0x01b8, 0x01c1, 0x01c7, 0x01cc,
0x01d4, 0x01da, 0x01e0, 0x01eb, 0x01f4, 0x01fa, 0x0200, 0x020b,
0x0214, 0x021a, 0x0220, 0x0226, 0x0231, 0x023a, 0x0240, 0x0246,
0x024c, 0x0257, 0x0260, 0x0266, 0x026c, 0x0270, 0x0278, 0x027f,
0x0285, 0x028e, 0x0298, 0x02a2, 0x02ab, 0x02b4, 0x02b9, 0x02c1,
0x02c9, 0x02cb, 0x02d1, 0x02d9, 0x02e2, 0x02eb, 0x02f7, 0x02fa,
0x02fc, 0x0307, 0x0310, 0x0317, 0x0319, 0x0321, 0x032c, 0x0338,
0x033d, 0x033f, 0x0345, 0x0351, 0x035b, 0x0365, 0x036c, 0x0372,
0x037d, 0x0382, 0x038f, 0x039d, 0x03a5, 0x03b5, 0x03bb, 0x03c1,
0x03c7, 0x03c9, 0x03cb, 0x03d1, 0x03d7, 0x03e3, 0x03f0, 0x03f9,
0x0403, 0x0409, 0x0410, 0x0419, 0x0422, 0x042a, 0x0432, 0x043f,
0x044d, 0x044f, 0x0451, 0x045a, 0x0468, 0x0476, 0x0482, 0x048d,
0x0498, 0x04a3, 0x04a9, 0x04b2, 0x04b8, 0x04be, 0x04c9, 0x04d2,
0x04d8, 0x04de, 0x04e9, 0x04ee, 0x04f4, 0x04fa, 0x0505, 0x050b,
0x0513, 0x051d, 0x0522, 0x0528, 0x052d, 0x0536, 0x053a, 0x0541,
0x054d, 0x0553, 0x0558, 0x055e, 0x0564, 0x056a, 0x0570, 0x0576,
0x057c, 0x0585, 0x0588, 0x058b, 0x0591, 0x0597, 0x059c, 0x05a1,
0x05a6, 0x05ae, 0x05b9, 0x05c4, 0x05d1, 0x05d8, 0x05e2, 0x05ef,
0x05f4, 0x05fa, 0x0600, 0x060a, 0x0612, 0x061a, 0x0620, 0x0626,
0x062c, 0x0632, 0x0638,
}

128
vendor/golang.org/x/image/font/sfnt/example_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,128 @@
// 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 sfnt_test
import (
"image"
"image/draw"
"log"
"os"
"golang.org/x/image/font/gofont/goregular"
"golang.org/x/image/font/sfnt"
"golang.org/x/image/math/fixed"
"golang.org/x/image/vector"
)
func ExampleRasterizeGlyph() {
const (
ppem = 32
width = 24
height = 32
originX = 0
originY = 28
)
f, err := sfnt.Parse(goregular.TTF)
if err != nil {
log.Fatalf("Parse: %v", err)
}
var b sfnt.Buffer
x, err := f.GlyphIndex(&b, 'G')
if err != nil {
log.Fatalf("GlyphIndex: %v", err)
}
if x == 0 {
log.Fatalf("GlyphIndex: no glyph index found for the rune 'G'")
}
segments, err := f.LoadGlyph(&b, x, fixed.I(ppem), nil)
if err != nil {
log.Fatalf("LoadGlyph: %v", err)
}
r := vector.NewRasterizer(width, height)
r.DrawOp = draw.Src
for _, seg := range segments {
// The divisions by 64 below is because the seg.Args values have type
// fixed.Int26_6, a 26.6 fixed point number, and 1<<6 == 64.
switch seg.Op {
case sfnt.SegmentOpMoveTo:
r.MoveTo(
originX+float32(seg.Args[0])/64,
originY-float32(seg.Args[1])/64,
)
case sfnt.SegmentOpLineTo:
r.LineTo(
originX+float32(seg.Args[0])/64,
originY-float32(seg.Args[1])/64,
)
case sfnt.SegmentOpQuadTo:
r.QuadTo(
originX+float32(seg.Args[0])/64,
originY-float32(seg.Args[1])/64,
originX+float32(seg.Args[2])/64,
originY-float32(seg.Args[3])/64,
)
case sfnt.SegmentOpCubeTo:
r.CubeTo(
originX+float32(seg.Args[0])/64,
originY-float32(seg.Args[1])/64,
originX+float32(seg.Args[2])/64,
originY-float32(seg.Args[3])/64,
originX+float32(seg.Args[4])/64,
originY-float32(seg.Args[5])/64,
)
}
}
// TODO: call ClosePath? Once overall or once per contour (i.e. MoveTo)?
dst := image.NewAlpha(image.Rect(0, 0, width, height))
r.Draw(dst, dst.Bounds(), image.Opaque, image.Point{})
const asciiArt = ".++8"
buf := make([]byte, 0, height*(width+1))
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
a := dst.AlphaAt(x, y).A
buf = append(buf, asciiArt[a>>6])
}
buf = append(buf, '\n')
}
os.Stdout.Write(buf)
// Output:
// ........................
// ........................
// ........................
// ........................
// ..........+++++++++.....
// .......+8888888888888+..
// ......8888888888888888..
// ....+8888+........++88..
// ....8888................
// ...8888.................
// ..+888+.................
// ..+888..................
// ..888+..................
// .+888+..................
// .+888...................
// .+888...................
// .+888...................
// .+888..........+++++++..
// .+888..........8888888..
// .+888+.........+++8888..
// ..888+............+888..
// ..8888............+888..
// ..+888+...........+888..
// ...8888+..........+888..
// ...+8888+.........+888..
// ....+88888+.......+888..
// .....+8888888888888888..
// .......+888888888888++..
// ..........++++++++......
// ........................
// ........................
// ........................
}

321
vendor/golang.org/x/image/font/sfnt/gen.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,321 @@
// 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.
// +build ignore
package main
import (
"bytes"
"fmt"
"go/format"
"io/ioutil"
"log"
)
func main() {
data, offsets := []byte(nil), []int{0}
for _, name := range names {
data = append(data, name...)
offsets = append(offsets, len(data))
}
b := new(bytes.Buffer)
fmt.Fprintf(b, "// generated by go run gen.go; DO NOT EDIT\n\n")
fmt.Fprintf(b, "package sfnt\n\n")
fmt.Fprintf(b, "const numBuiltInPostNames = %d\n\n", len(names))
fmt.Fprintf(b, "const builtInPostNamesData = \"\" +\n")
for s := data; ; {
if len(s) <= 64 {
fmt.Fprintf(b, "%q\n", s)
break
}
fmt.Fprintf(b, "%q +\n", s[:64])
s = s[64:]
}
fmt.Fprintf(b, "\n")
fmt.Fprintf(b, "var builtInPostNamesOffsets = [...]uint16{\n")
for i, o := range offsets {
fmt.Fprintf(b, "%#04x,", o)
if i%8 == 7 {
fmt.Fprintf(b, "\n")
}
}
fmt.Fprintf(b, "\n}\n")
dstUnformatted := b.Bytes()
dst, err := format.Source(dstUnformatted)
if err != nil {
log.Fatalf("format.Source: %v\n\n----\n%s\n----", err, dstUnformatted)
}
if err := ioutil.WriteFile("data.go", dst, 0666); err != nil {
log.Fatalf("ioutil.WriteFile: %v", err)
}
}
// names is the built-in post table names listed at
// https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6post.html
var names = [258]string{
".notdef",
".null",
"nonmarkingreturn",
"space",
"exclam",
"quotedbl",
"numbersign",
"dollar",
"percent",
"ampersand",
"quotesingle",
"parenleft",
"parenright",
"asterisk",
"plus",
"comma",
"hyphen",
"period",
"slash",
"zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine",
"colon",
"semicolon",
"less",
"equal",
"greater",
"question",
"at",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
"bracketleft",
"backslash",
"bracketright",
"asciicircum",
"underscore",
"grave",
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
"braceleft",
"bar",
"braceright",
"asciitilde",
"Adieresis",
"Aring",
"Ccedilla",
"Eacute",
"Ntilde",
"Odieresis",
"Udieresis",
"aacute",
"agrave",
"acircumflex",
"adieresis",
"atilde",
"aring",
"ccedilla",
"eacute",
"egrave",
"ecircumflex",
"edieresis",
"iacute",
"igrave",
"icircumflex",
"idieresis",
"ntilde",
"oacute",
"ograve",
"ocircumflex",
"odieresis",
"otilde",
"uacute",
"ugrave",
"ucircumflex",
"udieresis",
"dagger",
"degree",
"cent",
"sterling",
"section",
"bullet",
"paragraph",
"germandbls",
"registered",
"copyright",
"trademark",
"acute",
"dieresis",
"notequal",
"AE",
"Oslash",
"infinity",
"plusminus",
"lessequal",
"greaterequal",
"yen",
"mu",
"partialdiff",
"summation",
"product",
"pi",
"integral",
"ordfeminine",
"ordmasculine",
"Omega",
"ae",
"oslash",
"questiondown",
"exclamdown",
"logicalnot",
"radical",
"florin",
"approxequal",
"Delta",
"guillemotleft",
"guillemotright",
"ellipsis",
"nonbreakingspace",
"Agrave",
"Atilde",
"Otilde",
"OE",
"oe",
"endash",
"emdash",
"quotedblleft",
"quotedblright",
"quoteleft",
"quoteright",
"divide",
"lozenge",
"ydieresis",
"Ydieresis",
"fraction",
"currency",
"guilsinglleft",
"guilsinglright",
"fi",
"fl",
"daggerdbl",
"periodcentered",
"quotesinglbase",
"quotedblbase",
"perthousand",
"Acircumflex",
"Ecircumflex",
"Aacute",
"Edieresis",
"Egrave",
"Iacute",
"Icircumflex",
"Idieresis",
"Igrave",
"Oacute",
"Ocircumflex",
"apple",
"Ograve",
"Uacute",
"Ucircumflex",
"Ugrave",
"dotlessi",
"circumflex",
"tilde",
"macron",
"breve",
"dotaccent",
"ring",
"cedilla",
"hungarumlaut",
"ogonek",
"caron",
"Lslash",
"lslash",
"Scaron",
"scaron",
"Zcaron",
"zcaron",
"brokenbar",
"Eth",
"eth",
"Yacute",
"yacute",
"Thorn",
"thorn",
"minus",
"multiply",
"onesuperior",
"twosuperior",
"threesuperior",
"onehalf",
"onequarter",
"threequarters",
"franc",
"Gbreve",
"gbreve",
"Idotaccent",
"Scedilla",
"scedilla",
"Cacute",
"cacute",
"Ccaron",
"ccaron",
"dcroat",
}

117
vendor/golang.org/x/image/font/sfnt/postscript.go сгенерированный поставляемый
Просмотреть файл

@@ -566,8 +566,8 @@ var psOperators = [...][2][]psOperator{
23: {-1, "vstemhm", t2CStem},
24: {}, // rcurveline.
25: {}, // rlinecurve.
26: {}, // vvcurveto.
27: {}, // hhcurveto.
26: {-1, "vvcurveto", t2CVvcurveto},
27: {-1, "hhcurveto", t2CHhcurveto},
28: {}, // shortint.
29: {}, // callgsubr.
30: {-1, "vhcurveto", t2CVhcurveto},
@@ -653,8 +653,8 @@ func t2CAppendMoveto(p *psInterpreter) {
p.type2Charstrings.segments = append(p.type2Charstrings.segments, Segment{
Op: SegmentOpMoveTo,
Args: [6]fixed.Int26_6{
0: fixed.Int26_6(p.type2Charstrings.x) << 6,
1: fixed.Int26_6(p.type2Charstrings.y) << 6,
0: fixed.Int26_6(p.type2Charstrings.x),
1: fixed.Int26_6(p.type2Charstrings.y),
},
})
}
@@ -663,8 +663,8 @@ func t2CAppendLineto(p *psInterpreter) {
p.type2Charstrings.segments = append(p.type2Charstrings.segments, Segment{
Op: SegmentOpLineTo,
Args: [6]fixed.Int26_6{
0: fixed.Int26_6(p.type2Charstrings.x) << 6,
1: fixed.Int26_6(p.type2Charstrings.y) << 6,
0: fixed.Int26_6(p.type2Charstrings.x),
1: fixed.Int26_6(p.type2Charstrings.y),
},
})
}
@@ -685,12 +685,12 @@ func t2CAppendCubeto(p *psInterpreter, dxa, dya, dxb, dyb, dxc, dyc int32) {
p.type2Charstrings.segments = append(p.type2Charstrings.segments, Segment{
Op: SegmentOpCubeTo,
Args: [6]fixed.Int26_6{
0: fixed.Int26_6(xa) << 6,
1: fixed.Int26_6(ya) << 6,
2: fixed.Int26_6(xb) << 6,
3: fixed.Int26_6(yb) << 6,
4: fixed.Int26_6(xc) << 6,
5: fixed.Int26_6(yc) << 6,
0: fixed.Int26_6(xa),
1: fixed.Int26_6(ya),
2: fixed.Int26_6(xb),
3: fixed.Int26_6(yb),
4: fixed.Int26_6(xc),
5: fixed.Int26_6(yc),
},
})
}
@@ -770,6 +770,12 @@ func t2CRlineto(p *psInterpreter) error {
// As per 5177.Type2.pdf section 4.1 "Path Construction Operators",
//
// hhcurveto is:
// - dy1 {dxa dxb dyb dxc}+
//
// vvcurveto is:
// - dx1 {dya dxb dyb dyc}+
//
// hvcurveto is one of:
// - dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* dxf?
// - {dxa dxb dyb dyc dyd dxe dye dxf}+ dyf?
@@ -778,59 +784,84 @@ func t2CRlineto(p *psInterpreter) error {
// - dy1 dx2 dy2 dx3 {dxa dxb dyb dyc dyd dxe dye dxf}* dyf?
// - {dya dxb dyb dxc dxd dxe dye dyf}+ dxf?
func t2CHvcurveto(p *psInterpreter) error { return t2CCurveto(p, false) }
func t2CVhcurveto(p *psInterpreter) error { return t2CCurveto(p, true) }
func t2CHhcurveto(p *psInterpreter) error { return t2CCurveto(p, false, false) }
func t2CVvcurveto(p *psInterpreter) error { return t2CCurveto(p, false, true) }
func t2CHvcurveto(p *psInterpreter) error { return t2CCurveto(p, true, false) }
func t2CVhcurveto(p *psInterpreter) error { return t2CCurveto(p, true, true) }
func t2CCurveto(p *psInterpreter, vertical bool) error {
// t2CCurveto implements the hh / vv / hv / vh xxcurveto operators. N relative
// cubic curve requires 6*N control points, but only 4*N+0 or 4*N+1 are used
// here: all (or all but one) of the piecewise cubic curve's tangents are
// implicitly horizontal or vertical.
//
// swap is whether that implicit horizontal / vertical constraint swaps as you
// move along the piecewise cubic curve. If swap is false, the constraints are
// either all horizontal or all vertical. If swap is true, it alternates.
//
// vertical is whether the first implicit constraint is vertical.
func t2CCurveto(p *psInterpreter, swap, vertical bool) error {
if !p.type2Charstrings.seenWidth || p.stack.top < 4 {
return errInvalidCFFTable
}
for i := int32(0); i != p.stack.top; vertical = !vertical {
if vertical {
i = t2CVcurveto(p, i)
} else {
i = t2CHcurveto(p, i)
i := int32(0)
switch p.stack.top & 3 {
case 0:
// No-op.
case 1:
if swap {
break
}
i = 1
if vertical {
p.type2Charstrings.x += p.stack.a[0]
} else {
p.type2Charstrings.y += p.stack.a[0]
}
default:
return errInvalidCFFTable
}
for i != p.stack.top {
i = t2CCurveto4(p, swap, vertical, i)
if i < 0 {
return errInvalidCFFTable
}
if swap {
vertical = !vertical
}
}
return nil
}
func t2CHcurveto(p *psInterpreter, i int32) (j int32) {
func t2CCurveto4(p *psInterpreter, swap bool, vertical bool, i int32) (j int32) {
if i+4 > p.stack.top {
return -1
}
dxa := p.stack.a[i+0]
dxb := p.stack.a[i+1]
dyb := p.stack.a[i+2]
dyc := p.stack.a[i+3]
dxc := int32(0)
i += 4
if i+1 == p.stack.top {
dxc = p.stack.a[i]
i++
}
t2CAppendCubeto(p, dxa, 0, dxb, dyb, dxc, dyc)
return i
}
func t2CVcurveto(p *psInterpreter, i int32) (j int32) {
if i+4 > p.stack.top {
return -1
}
dya := p.stack.a[i+0]
dya := int32(0)
dxb := p.stack.a[i+1]
dyb := p.stack.a[i+2]
dxc := p.stack.a[i+3]
dyc := int32(0)
i += 4
if i+1 == p.stack.top {
dyc = p.stack.a[i]
i++
if vertical {
dxa, dya = dya, dxa
}
t2CAppendCubeto(p, 0, dya, dxb, dyb, dxc, dyc)
if swap {
if i+1 == p.stack.top {
dyc = p.stack.a[i]
i++
}
}
if swap != vertical {
dxc, dyc = dyc, dxc
}
t2CAppendCubeto(p, dxa, dya, dxb, dyb, dxc, dyc)
return i
}

479
vendor/golang.org/x/image/font/sfnt/proprietary_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,479 @@
// 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 sfnt
/*
This file contains opt-in tests for popular, high quality, proprietary fonts,
made by companies such as Adobe and Microsoft. These fonts are generally
available, but copies are not explicitly included in this repository due to
licensing differences or file size concerns. To opt-in, run:
go test golang.org/x/image/font/sfnt -args -proprietary
Not all tests pass out-of-the-box on all systems. For example, the Microsoft
Times New Roman font is downloadable gratis even on non-Windows systems, but as
per the ttf-mscorefonts-installer Debian package, this requires accepting an
End User License Agreement (EULA) and a CAB format decoder. These tests assume
that such fonts have already been installed. You may need to specify the
directories for these fonts:
go test golang.org/x/image/font/sfnt -args -proprietary -adobeDir=/foo/bar/aFonts -microsoftDir=/foo/bar/mFonts
To only run those tests for the Microsoft fonts:
go test golang.org/x/image/font/sfnt -test.run=ProprietaryMicrosoft -args -proprietary
*/
// TODO: add Apple system fonts? Google fonts (Droid? Noto?)? Emoji fonts?
// TODO: enable Apple/Microsoft tests by default on Darwin/Windows?
import (
"errors"
"flag"
"io/ioutil"
"path/filepath"
"testing"
"golang.org/x/image/font"
"golang.org/x/image/math/fixed"
)
var (
proprietary = flag.Bool("proprietary", false, "test proprietary fonts not included in this repository")
adobeDir = flag.String(
"adobeDir",
// This needs to be set explicitly. There is no default dir on Debian:
// https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=736680
//
// Get the fonts from https://github.com/adobe-fonts, e.g.:
// - https://github.com/adobe-fonts/source-code-pro/releases/latest
// - https://github.com/adobe-fonts/source-han-sans/releases/latest
// - https://github.com/adobe-fonts/source-sans-pro/releases/latest
//
// Copy all of the TTF and OTF files to the one directory, such as
// $HOME/adobe-fonts, and pass that as the -adobeDir flag here.
"",
"directory name for the Adobe proprietary fonts",
)
microsoftDir = flag.String(
"microsoftDir",
"/usr/share/fonts/truetype/msttcorefonts",
"directory name for the Microsoft proprietary fonts",
)
)
func TestProprietaryAdobeSourceCodeProOTF(t *testing.T) {
testProprietary(t, "adobe", "SourceCodePro-Regular.otf", 1500, 2)
}
func TestProprietaryAdobeSourceCodeProTTF(t *testing.T) {
testProprietary(t, "adobe", "SourceCodePro-Regular.ttf", 1500, 36)
}
func TestProprietaryAdobeSourceHanSansSC(t *testing.T) {
testProprietary(t, "adobe", "SourceHanSansSC-Regular.otf", 65535, 2)
}
func TestProprietaryAdobeSourceSansProOTF(t *testing.T) {
testProprietary(t, "adobe", "SourceSansPro-Regular.otf", 1800, 2)
}
func TestProprietaryAdobeSourceSansProTTF(t *testing.T) {
testProprietary(t, "adobe", "SourceSansPro-Regular.ttf", 1800, 54)
}
func TestProprietaryMicrosoftArial(t *testing.T) {
testProprietary(t, "microsoft", "Arial.ttf", 1200, 98)
}
func TestProprietaryMicrosoftComicSansMS(t *testing.T) {
testProprietary(t, "microsoft", "Comic_Sans_MS.ttf", 550, 98)
}
func TestProprietaryMicrosoftTimesNewRoman(t *testing.T) {
testProprietary(t, "microsoft", "Times_New_Roman.ttf", 1200, 98)
}
func TestProprietaryMicrosoftWebdings(t *testing.T) {
testProprietary(t, "microsoft", "Webdings.ttf", 200, -1)
}
// testProprietary tests that we can load every glyph in the named font.
//
// The exact number of glyphs in the font can differ across its various
// versions, but as a sanity check, there should be at least minNumGlyphs.
//
// While this package is a work-in-progress, not every glyph can be loaded. The
// firstUnsupportedGlyph argument, if non-negative, is the index of the first
// unsupported glyph in the font. This number should increase over time (or set
// negative), as the TODO's in this package are done.
func testProprietary(t *testing.T, proprietor, filename string, minNumGlyphs, firstUnsupportedGlyph int) {
if !*proprietary {
t.Skip("skipping proprietary font test")
}
file, err := []byte(nil), error(nil)
switch proprietor {
case "adobe":
file, err = ioutil.ReadFile(filepath.Join(*adobeDir, filename))
if err != nil {
t.Fatalf("%v\nPerhaps you need to set the -adobeDir=%v flag?", err, *adobeDir)
}
case "microsoft":
file, err = ioutil.ReadFile(filepath.Join(*microsoftDir, filename))
if err != nil {
t.Fatalf("%v\nPerhaps you need to set the -microsoftDir=%v flag?", err, *microsoftDir)
}
default:
panic("unreachable")
}
f, err := Parse(file)
if err != nil {
t.Fatalf("Parse: %v", err)
}
ppem := fixed.Int26_6(f.UnitsPerEm())
qualifiedFilename := proprietor + "/" + filename
var buf Buffer
// Some of the tests below, such as which glyph index a particular rune
// maps to, can depend on the specific version of the proprietary font. If
// tested against a different version of that font, the test might (but not
// necessarily will) fail, even though the Go code is good. If so, log a
// message, but don't automatically fail (i.e. dont' call t.Fatalf).
gotVersion, err := f.Name(&buf, NameIDVersion)
if err != nil {
t.Fatalf("Name: %v", err)
}
wantVersion := proprietaryVersions[qualifiedFilename]
if gotVersion != wantVersion {
t.Logf("font version provided differs from the one the tests were written against:"+
"\ngot %q\nwant %q", gotVersion, wantVersion)
}
numGlyphs := f.NumGlyphs()
if numGlyphs < minNumGlyphs {
t.Fatalf("NumGlyphs: got %d, want at least %d", numGlyphs, minNumGlyphs)
}
iMax := numGlyphs
if firstUnsupportedGlyph >= 0 {
iMax = firstUnsupportedGlyph
}
for i, numErrors := 0, 0; i < iMax; i++ {
if _, err := f.LoadGlyph(&buf, GlyphIndex(i), ppem, nil); err != nil {
t.Errorf("LoadGlyph(%d): %v", i, err)
numErrors++
}
if numErrors == 10 {
t.Fatal("LoadGlyph: too many errors")
}
}
for r, want := range proprietaryGlyphIndexTestCases[qualifiedFilename] {
got, err := f.GlyphIndex(&buf, r)
if err != nil {
t.Errorf("GlyphIndex(%q): %v", r, err)
continue
}
if got != want {
t.Errorf("GlyphIndex(%q): got %d, want %d", r, got, want)
continue
}
}
for r, want := range proprietaryGlyphTestCases[qualifiedFilename] {
x, err := f.GlyphIndex(&buf, r)
if err != nil {
t.Errorf("GlyphIndex(%q): %v", r, err)
continue
}
got, err := f.LoadGlyph(&buf, x, ppem, nil)
if err != nil {
t.Errorf("LoadGlyph(%q): %v", r, err)
continue
}
if err := checkSegmentsEqual(got, want); err != nil {
t.Errorf("LoadGlyph(%q): %v", r, err)
continue
}
}
kernLoop:
for _, tc := range proprietaryKernTestCases[qualifiedFilename] {
var indexes [2]GlyphIndex
for i := range indexes {
x, err := f.GlyphIndex(&buf, tc.runes[i])
if x == 0 && err == nil {
err = errors.New("no glyph index found")
}
if err != nil {
t.Errorf("GlyphIndex(%q): %v", tc.runes[0], err)
continue kernLoop
}
indexes[i] = x
}
kern, err := f.Kern(&buf, indexes[0], indexes[1], tc.ppem, tc.hinting)
if err != nil {
t.Errorf("Kern(%q, %q, ppem=%d, hinting=%v): %v",
tc.runes[0], tc.runes[1], tc.ppem, tc.hinting, err)
continue
}
if got := Units(kern); got != tc.want {
t.Errorf("Kern(%q, %q, ppem=%d, hinting=%v): got %d, want %d",
tc.runes[0], tc.runes[1], tc.ppem, tc.hinting, got, tc.want)
continue
}
}
}
// proprietaryVersions holds the expected version string of each proprietary
// font tested. If third parties such as Adobe or Microsoft update their fonts,
// and the tests subsequently fail, these versions should be updated too.
//
// Updates are expected to be infrequent. For example, as of 2017, the fonts
// installed by the Debian ttf-mscorefonts-installer package have last modified
// times no later than 2001.
var proprietaryVersions = map[string]string{
"adobe/SourceCodePro-Regular.otf": "Version 2.030;PS 1.0;hotconv 16.6.51;makeotf.lib2.5.65220",
"adobe/SourceCodePro-Regular.ttf": "Version 2.030;PS 1.000;hotconv 16.6.51;makeotf.lib2.5.65220",
"adobe/SourceHanSansSC-Regular.otf": "Version 1.004;PS 1.004;hotconv 1.0.82;makeotf.lib2.5.63406",
"adobe/SourceSansPro-Regular.otf": "Version 2.020;PS 2.0;hotconv 1.0.86;makeotf.lib2.5.63406",
"adobe/SourceSansPro-Regular.ttf": "Version 2.020;PS 2.000;hotconv 1.0.86;makeotf.lib2.5.63406",
"microsoft/Arial.ttf": "Version 2.82",
"microsoft/Comic_Sans_MS.ttf": "Version 2.10",
"microsoft/Times_New_Roman.ttf": "Version 2.82",
"microsoft/Webdings.ttf": "Version 1.03",
}
// proprietaryGlyphIndexTestCases hold a sample of each font's rune to glyph
// index cmap. The numerical values can be verified by running the ttx tool.
var proprietaryGlyphIndexTestCases = map[string]map[rune]GlyphIndex{
"adobe/SourceCodePro-Regular.otf": {
'\u0030': 877, // U+0030 DIGIT ZERO
'\u0041': 2, // U+0041 LATIN CAPITAL LETTER A
'\u0061': 28, // U+0061 LATIN SMALL LETTER A
'\u0104': 64, // U+0104 LATIN CAPITAL LETTER A WITH OGONEK
'\u0125': 323, // U+0125 LATIN SMALL LETTER H WITH CIRCUMFLEX
'\u01f4': 111, // U+01F4 LATIN CAPITAL LETTER G WITH ACUTE
'\u03a3': 623, // U+03A3 GREEK CAPITAL LETTER SIGMA
'\u2569': 1500, // U+2569 BOX DRAWINGS DOUBLE UP AND HORIZONTAL
'\U0001f100': 0, // U+0001F100 DIGIT ZERO FULL STOP
},
"adobe/SourceCodePro-Regular.ttf": {
'\u0030': 877, // U+0030 DIGIT ZERO
'\u0041': 2, // U+0041 LATIN CAPITAL LETTER A
'\u01f4': 111, // U+01F4 LATIN CAPITAL LETTER G WITH ACUTE
},
"adobe/SourceHanSansSC-Regular.otf": {
'\u0030': 17, // U+0030 DIGIT ZERO
'\u0041': 34, // U+0041 LATIN CAPITAL LETTER A
'\u00d7': 150, // U+00D7 MULTIPLICATION SIGN
'\u1100': 365, // U+1100 HANGUL CHOSEONG KIYEOK
'\u25ca': 1254, // U+25CA LOZENGE
'\u2e9c': 1359, // U+2E9C CJK RADICAL SUN
'\u304b': 1463, // U+304B HIRAGANA LETTER KA
'\u4e2d': 9893, // U+4E2D <CJK Ideograph>, 中
'\ua960': 47537, // U+A960 HANGUL CHOSEONG TIKEUT-MIEUM
'\ufb00': 58919, // U+FB00 LATIN SMALL LIGATURE FF
'\uffee': 59213, // U+FFEE HALFWIDTH WHITE CIRCLE
'\U0001f100': 59214, // U+0001F100 DIGIT ZERO FULL STOP
'\U0001f248': 59449, // U+0001F248 TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557
'\U0002f9f4': 61768, // U+0002F9F4 CJK COMPATIBILITY IDEOGRAPH-2F9F4
},
"adobe/SourceSansPro-Regular.otf": {
'\u0041': 2, // U+0041 LATIN CAPITAL LETTER A
'\u03a3': 592, // U+03A3 GREEK CAPITAL LETTER SIGMA
'\u0435': 999, // U+0435 CYRILLIC SMALL LETTER IE
'\u2030': 1728, // U+2030 PER MILLE SIGN
},
"adobe/SourceSansPro-Regular.ttf": {
'\u0041': 2, // U+0041 LATIN CAPITAL LETTER A
'\u03a3': 592, // U+03A3 GREEK CAPITAL LETTER SIGMA
'\u0435': 999, // U+0435 CYRILLIC SMALL LETTER IE
'\u2030': 1728, // U+2030 PER MILLE SIGN
},
"microsoft/Arial.ttf": {
'\u0041': 36, // U+0041 LATIN CAPITAL LETTER A
'\u00f1': 120, // U+00F1 LATIN SMALL LETTER N WITH TILDE
'\u0401': 556, // U+0401 CYRILLIC CAPITAL LETTER IO
'\u200d': 745, // U+200D ZERO WIDTH JOINER
'\u20ab': 1150, // U+20AB DONG SIGN
'\u2229': 320, // U+2229 INTERSECTION
'\u04e9': 1319, // U+04E9 CYRILLIC SMALL LETTER BARRED O
'\U0001f100': 0, // U+0001F100 DIGIT ZERO FULL STOP
},
"microsoft/Comic_Sans_MS.ttf": {
'\u0041': 36, // U+0041 LATIN CAPITAL LETTER A
'\u03af': 573, // U+03AF GREEK SMALL LETTER IOTA WITH TONOS
},
"microsoft/Times_New_Roman.ttf": {
'\u0041': 36, // U+0041 LATIN CAPITAL LETTER A
'\u0042': 37, // U+0041 LATIN CAPITAL LETTER B
'\u266a': 392, // U+266A EIGHTH NOTE
'\uf041': 0, // PRIVATE USE AREA
'\uf042': 0, // PRIVATE USE AREA
},
"microsoft/Webdings.ttf": {
'\u0041': 0, // U+0041 LATIN CAPITAL LETTER A
'\u0042': 0, // U+0041 LATIN CAPITAL LETTER B
'\u266a': 0, // U+266A EIGHTH NOTE
'\uf041': 36, // PRIVATE USE AREA
'\uf042': 37, // PRIVATE USE AREA
},
}
// proprietaryGlyphTestCases hold a sample of each font's glyph vectors. The
// numerical values can be verified by running the ttx tool, remembering that:
// - for PostScript glyphs, ttx coordinates are relative, and hstem / vstem
// operators are hinting-related and can be ignored.
// - for TrueType glyphs, ttx coordinates are absolute, and consecutive
// off-curve points implies an on-curve point at the midpoint.
var proprietaryGlyphTestCases = map[string]map[rune][]Segment{
"adobe/SourceSansPro-Regular.otf": {
',': {
// - contour #0
// 67 -170 rmoveto
moveTo(67, -170),
// 81 34 50 67 86 vvcurveto
cubeTo(148, -136, 198, -69, 198, 17),
// 60 -26 37 -43 -33 -28 -22 -36 -37 27 -20 32 3 4 0 1 3 vhcurveto
cubeTo(198, 77, 172, 114, 129, 114),
cubeTo(96, 114, 68, 92, 68, 56),
cubeTo(68, 19, 95, -1, 127, -1),
cubeTo(130, -1, 134, -1, 137, 0),
// 1 -53 -34 -44 -57 -25 rrcurveto
cubeTo(138, -53, 104, -97, 47, -122),
},
'Q': {
// - contour #0
// 332 57 rmoveto
moveTo(332, 57),
// -117 -77 106 168 163 77 101 117 117 77 -101 -163 -168 -77 -106 -117 hvcurveto
cubeTo(215, 57, 138, 163, 138, 331),
cubeTo(138, 494, 215, 595, 332, 595),
cubeTo(449, 595, 526, 494, 526, 331),
cubeTo(526, 163, 449, 57, 332, 57),
// - contour #1
// 201 -222 rmoveto
moveTo(533, -165),
// 39 35 7 8 20 hvcurveto
cubeTo(572, -165, 607, -158, 627, -150),
// -16 64 rlineto
lineTo(611, -86),
// -5 -18 -22 -4 -29 hhcurveto
cubeTo(593, -91, 571, -95, 542, -95),
// -71 -60 29 58 -30 hvcurveto
cubeTo(471, -95, 411, -66, 381, -8),
// 139 24 93 126 189 vvcurveto
cubeTo(520, 16, 613, 142, 613, 331),
// 209 -116 128 -165 -165 -115 -127 -210 -193 96 -127 143 -20 vhcurveto
cubeTo(613, 540, 497, 668, 332, 668),
cubeTo(167, 668, 52, 541, 52, 331),
cubeTo(52, 138, 148, 11, 291, -9),
// -90 38 83 -66 121 hhcurveto
cubeTo(329, -99, 412, -165, 533, -165),
},
},
"microsoft/Arial.ttf": {
',': {
// - contour #0
moveTo(182, 0),
lineTo(182, 205),
lineTo(387, 205),
lineTo(387, 0),
quadTo(387, -113, 347, -182),
quadTo(307, -252, 220, -290),
lineTo(170, -213),
quadTo(227, -188, 254, -139),
quadTo(281, -91, 284, 0),
lineTo(182, 0),
},
'i': {
// - contour #0
moveTo(136, 1259),
lineTo(136, 1466),
lineTo(316, 1466),
lineTo(316, 1259),
lineTo(136, 1259),
// - contour #1
moveTo(136, 0),
lineTo(136, 1062),
lineTo(316, 1062),
lineTo(316, 0),
lineTo(136, 0),
},
'o': {
// - contour #0
moveTo(68, 531),
quadTo(68, 826, 232, 968),
quadTo(369, 1086, 566, 1086),
quadTo(785, 1086, 924, 942),
quadTo(1063, 799, 1063, 546),
quadTo(1063, 341, 1001, 223),
quadTo(940, 106, 822, 41),
quadTo(705, -24, 566, -24),
quadTo(343, -24, 205, 119),
quadTo(68, 262, 68, 531),
// - contour #1
moveTo(253, 531),
quadTo(253, 327, 342, 225),
quadTo(431, 124, 566, 124),
quadTo(700, 124, 789, 226),
quadTo(878, 328, 878, 537),
quadTo(878, 734, 788, 835),
quadTo(699, 937, 566, 937),
quadTo(431, 937, 342, 836),
quadTo(253, 735, 253, 531),
},
},
}
type kernTestCase struct {
ppem fixed.Int26_6
hinting font.Hinting
runes [2]rune
want Units
}
// proprietaryKernTestCases hold a sample of each font's kerning pairs. The
// numerical values can be verified by running the ttx tool.
var proprietaryKernTestCases = map[string][]kernTestCase{
"microsoft/Arial.ttf": {
{2048, font.HintingNone, [2]rune{'A', 'V'}, -152},
// U+03B8 GREEK SMALL LETTER THETA
// U+03BB GREEK SMALL LETTER LAMDA
{2048, font.HintingNone, [2]rune{'\u03b8', '\u03bb'}, -39},
{2048, font.HintingNone, [2]rune{'\u03bb', '\u03b8'}, -0},
},
"microsoft/Comic_Sans_MS.ttf": {
{2048, font.HintingNone, [2]rune{'A', 'V'}, 0},
},
"microsoft/Times_New_Roman.ttf": {
{768, font.HintingNone, [2]rune{'A', 'V'}, -99},
{768, font.HintingFull, [2]rune{'A', 'V'}, -128},
{2048, font.HintingNone, [2]rune{'A', 'A'}, 0},
{2048, font.HintingNone, [2]rune{'A', 'T'}, -227},
{2048, font.HintingNone, [2]rune{'A', 'V'}, -264},
{2048, font.HintingNone, [2]rune{'T', 'A'}, -164},
{2048, font.HintingNone, [2]rune{'T', 'T'}, 0},
{2048, font.HintingNone, [2]rune{'T', 'V'}, 0},
{2048, font.HintingNone, [2]rune{'V', 'A'}, -264},
{2048, font.HintingNone, [2]rune{'V', 'T'}, 0},
{2048, font.HintingNone, [2]rune{'V', 'V'}, 0},
// U+0390 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
// U+0393 GREEK CAPITAL LETTER GAMMA
{2048, font.HintingNone, [2]rune{'\u0390', '\u0393'}, 0},
{2048, font.HintingNone, [2]rune{'\u0393', '\u0390'}, 76},
},
"microsoft/Webdings.ttf": {
{2048, font.HintingNone, [2]rune{'\uf041', '\uf042'}, 0},
},
}

571
vendor/golang.org/x/image/font/sfnt/sfnt.go сгенерированный поставляемый
Просмотреть файл

@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:generate go run gen.go
// Package sfnt implements a decoder for SFNT font file formats, including
// TrueType and OpenType.
package sfnt // import "golang.org/x/image/font/sfnt"
@@ -13,11 +15,15 @@ package sfnt // import "golang.org/x/image/font/sfnt"
//
// The pyftinspect tool from https://github.com/fonttools/fonttools is useful
// for inspecting SFNT fonts.
//
// The ttfdump tool is also useful. For example:
// ttfdump -t cmap ../testdata/CFFTest.otf dump.txt
import (
"errors"
"io"
"golang.org/x/image/font"
"golang.org/x/image/math/fixed"
"golang.org/x/text/encoding/charmap"
)
@@ -25,6 +31,20 @@ import (
// These constants are not part of the specifications, but are limitations used
// by this implementation.
const (
// This value is arbitrary, but defends against parsing malicious font
// files causing excessive memory allocations. For reference, Adobe's
// SourceHanSansSC-Regular.otf has 65535 glyphs and:
// - its format-4 cmap table has 1581 segments.
// - its format-12 cmap table has 16498 segments.
//
// TODO: eliminate this constraint? If the cmap table is very large, load
// some or all of it lazily (at the time Font.GlyphIndex is called) instead
// of all of it eagerly (at the time Font.initialize is called), while
// keeping an upper bound on the memory used? This will make the code in
// cmap.go more complicated, considering that all of the Font methods are
// safe to call concurrently, as long as each call has a different *Buffer.
maxCmapSegments = 20000
maxGlyphDataLength = 64 * 1024
maxHintBits = 256
maxNumTables = 256
@@ -41,27 +61,34 @@ var (
errInvalidBounds = errors.New("sfnt: invalid bounds")
errInvalidCFFTable = errors.New("sfnt: invalid CFF table")
errInvalidCmapTable = errors.New("sfnt: invalid cmap table")
errInvalidGlyphData = errors.New("sfnt: invalid glyph data")
errInvalidHeadTable = errors.New("sfnt: invalid head table")
errInvalidKernTable = errors.New("sfnt: invalid kern table")
errInvalidLocaTable = errors.New("sfnt: invalid loca table")
errInvalidLocationData = errors.New("sfnt: invalid location data")
errInvalidMaxpTable = errors.New("sfnt: invalid maxp table")
errInvalidNameTable = errors.New("sfnt: invalid name table")
errInvalidPostTable = errors.New("sfnt: invalid post table")
errInvalidSourceData = errors.New("sfnt: invalid source data")
errInvalidTableOffset = errors.New("sfnt: invalid table offset")
errInvalidTableTagOrder = errors.New("sfnt: invalid table tag order")
errInvalidUCS2String = errors.New("sfnt: invalid UCS-2 string")
errInvalidVersion = errors.New("sfnt: invalid version")
errUnsupportedCFFVersion = errors.New("sfnt: unsupported CFF version")
errUnsupportedCompoundGlyph = errors.New("sfnt: unsupported compound glyph")
errUnsupportedGlyphDataLength = errors.New("sfnt: unsupported glyph data length")
errUnsupportedRealNumberEncoding = errors.New("sfnt: unsupported real number encoding")
errUnsupportedNumberOfHints = errors.New("sfnt: unsupported number of hints")
errUnsupportedNumberOfTables = errors.New("sfnt: unsupported number of tables")
errUnsupportedPlatformEncoding = errors.New("sfnt: unsupported platform encoding")
errUnsupportedTableOffsetLength = errors.New("sfnt: unsupported table offset or length")
errUnsupportedType2Charstring = errors.New("sfnt: unsupported Type 2 Charstring")
errUnsupportedCFFVersion = errors.New("sfnt: unsupported CFF version")
errUnsupportedCmapEncodings = errors.New("sfnt: unsupported cmap encodings")
errUnsupportedCompoundGlyph = errors.New("sfnt: unsupported compound glyph")
errUnsupportedGlyphDataLength = errors.New("sfnt: unsupported glyph data length")
errUnsupportedKernTable = errors.New("sfnt: unsupported kern table")
errUnsupportedRealNumberEncoding = errors.New("sfnt: unsupported real number encoding")
errUnsupportedNumberOfCmapSegments = errors.New("sfnt: unsupported number of cmap segments")
errUnsupportedNumberOfHints = errors.New("sfnt: unsupported number of hints")
errUnsupportedNumberOfTables = errors.New("sfnt: unsupported number of tables")
errUnsupportedPlatformEncoding = errors.New("sfnt: unsupported platform encoding")
errUnsupportedPostTable = errors.New("sfnt: unsupported post table")
errUnsupportedTableOffsetLength = errors.New("sfnt: unsupported table offset or length")
errUnsupportedType2Charstring = errors.New("sfnt: unsupported Type 2 Charstring")
)
// GlyphIndex is a glyph index in a Font.
@@ -107,16 +134,16 @@ const (
// display resolution (DPI) and font size (e.g. a 12 point font).
type Units int32
// Platform IDs and Platform Specific IDs as per
// https://www.microsoft.com/typography/otspec/name.htm
const (
pidMacintosh = 1
pidWindows = 3
psidMacintoshRoman = 0
psidWindowsUCS2 = 1
)
// scale returns x divided by unitsPerEm, rounded to the nearest fixed.Int26_6
// value (1/64th of a pixel).
func scale(x fixed.Int26_6, unitsPerEm Units) fixed.Int26_6 {
if x >= 0 {
x += fixed.Int26_6(unitsPerEm) / 2
} else {
x -= fixed.Int26_6(unitsPerEm) / 2
}
return x / fixed.Int26_6(unitsPerEm)
}
func u16(b []byte) uint16 {
_ = b[1] // Bounds check hint to compiler.
@@ -208,6 +235,20 @@ func (s *source) u16(buf []byte, t table, i int) (uint16, error) {
return u16(buf), nil
}
// u32 returns the uint32 in the table t at the relative offset i.
//
// buf is an optional scratch buffer as per the source.view method.
func (s *source) u32(buf []byte, t table, i int) (uint32, error) {
if i < 0 || uint(t.length) < uint(i+4) {
return 0, errInvalidBounds
}
buf, err := s.view(buf, int(t.offset)+i, 4)
if err != nil {
return 0, err
}
return u32(buf), nil
}
// table is a section of the font data.
type table struct {
offset, length uint32
@@ -247,6 +288,18 @@ func ParseReaderAt(src io.ReaderAt) (*Font, error) {
//
// The Font methods that don't take a *Buffer argument are always safe to call
// concurrently.
//
// Some methods provide lengths or coordinates, e.g. bounds, font metrics and
// control points. All of these methods take a ppem parameter, which is the
// number of pixels in 1 em, expressed as a 26.6 fixed point value. For
// example, if 1 em is 10 pixels then ppem is fixed.I(10), which equals
// fixed.Int26_6(10 << 6).
//
// To get those lengths or coordinates in terms of font units instead of
// pixels, use ppem = fixed.Int26_6(f.UnitsPerEm()) and if those methods take a
// font.Hinting parameter, use font.HintingNone. The return values will have
// type fixed.Int26_6, but those numbers can be converted back to Units with no
// further scaling necessary.
type Font struct {
src source
@@ -283,11 +336,16 @@ type Font struct {
// https://www.microsoft.com/typography/otspec/otff.htm#otttables
// "Other OpenType Tables".
//
// TODO: hdmx, kern, vmtx? Others?
// TODO: hdmx, vmtx? Others?
kern table
cached struct {
glyphIndex glyphIndexFunc
indexToLocFormat bool // false means short, true means long.
isPostScript bool
kernNumPairs int32
kernOffset int32
postTableVersion uint32
unitsPerEm Units
// The glyph data for the glyph index i is in
@@ -306,51 +364,96 @@ func (f *Font) initialize() error {
if !f.src.valid() {
return errInvalidSourceData
}
var buf []byte
// https://www.microsoft.com/typography/otspec/otff.htm "Organization of an
// OpenType Font" says that "The OpenType font starts with the Offset
// Table", which is 12 bytes.
buf, err := f.src.view(buf, 0, 12)
buf, isPostScript, err := f.initializeTables(nil)
if err != nil {
return err
}
// The order of these parseXxx calls matters. Later calls may depend on
// information parsed by earlier calls, such as the maxp table's numGlyphs.
// To enforce these dependencies, such information is passed and returned
// explicitly, and the f.cached fields are only set afterwards.
//
// When implementing new parseXxx methods, take care not to call methods
// such as Font.NumGlyphs that implicitly depend on f.cached fields.
buf, indexToLocFormat, unitsPerEm, err := f.parseHead(buf)
if err != nil {
return err
}
buf, numGlyphs, locations, err := f.parseMaxp(buf, indexToLocFormat, isPostScript)
if err != nil {
return err
}
buf, glyphIndex, err := f.parseCmap(buf)
if err != nil {
return err
}
buf, kernNumPairs, kernOffset, err := f.parseKern(buf)
if err != nil {
return err
}
buf, postTableVersion, err := f.parsePost(buf, numGlyphs)
if err != nil {
return err
}
f.cached.glyphIndex = glyphIndex
f.cached.indexToLocFormat = indexToLocFormat
f.cached.isPostScript = isPostScript
f.cached.kernNumPairs = kernNumPairs
f.cached.kernOffset = kernOffset
f.cached.postTableVersion = postTableVersion
f.cached.unitsPerEm = unitsPerEm
f.cached.locations = locations
return nil
}
func (f *Font) initializeTables(buf []byte) (buf1 []byte, isPostScript bool, err error) {
// https://www.microsoft.com/typography/otspec/otff.htm "Organization of an
// OpenType Font" says that "The OpenType font starts with the Offset
// Table", which is 12 bytes.
buf, err = f.src.view(buf, 0, 12)
if err != nil {
return nil, false, err
}
switch u32(buf) {
default:
return errInvalidVersion
return nil, false, errInvalidVersion
case 0x00010000:
// No-op.
case 0x4f54544f: // "OTTO".
f.cached.isPostScript = true
isPostScript = true
}
numTables := int(u16(buf[4:]))
if numTables > maxNumTables {
return errUnsupportedNumberOfTables
return nil, false, errUnsupportedNumberOfTables
}
// "The Offset Table is followed immediately by the Table Record entries...
// sorted in ascending order by tag", 16 bytes each.
buf, err = f.src.view(buf, 12, 16*numTables)
if err != nil {
return err
return nil, false, err
}
for b, first, prevTag := buf, true, uint32(0); len(b) > 0; b = b[16:] {
tag := u32(b)
if first {
first = false
} else if tag <= prevTag {
return errInvalidTableTagOrder
return nil, false, errInvalidTableTagOrder
}
prevTag = tag
o, n := u32(b[8:12]), u32(b[12:16])
if o > maxTableOffset || n > maxTableLength {
return errUnsupportedTableOffsetLength
return nil, false, errUnsupportedTableOffsetLength
}
// We ignore the checksums, but "all tables must begin on four byte
// boundries [sic]".
if o&3 != 0 {
return errInvalidTableOffset
return nil, false, errInvalidTableOffset
}
// Match the 4-byte tag as a uint32. For example, "OS/2" is 0x4f532f32.
@@ -369,6 +472,8 @@ func (f *Font) initialize() error {
f.hhea = table{o, n}
case 0x686d7478:
f.hmtx = table{o, n}
case 0x6b65726e:
f.kern = table{o, n}
case 0x6c6f6361:
f.loca = table{o, n}
case 0x6d617870:
@@ -379,69 +484,258 @@ func (f *Font) initialize() error {
f.post = table{o, n}
}
}
return buf, isPostScript, nil
}
var u uint16
func (f *Font) parseCmap(buf []byte) (buf1 []byte, glyphIndex glyphIndexFunc, err error) {
// https://www.microsoft.com/typography/OTSPEC/cmap.htm
// https://www.microsoft.com/typography/otspec/head.htm
if f.head.length != 54 {
return errInvalidHeadTable
const headerSize, entrySize = 4, 8
if f.cmap.length < headerSize {
return nil, nil, errInvalidCmapTable
}
u, err = f.src.u16(buf, f.head, 18)
u, err := f.src.u16(buf, f.cmap, 2)
if err != nil {
return err
return nil, nil, err
}
numSubtables := int(u)
if f.cmap.length < headerSize+entrySize*uint32(numSubtables) {
return nil, nil, errInvalidCmapTable
}
var (
bestWidth int
bestOffset uint32
bestLength uint32
bestFormat uint16
)
// Scan all of the subtables, picking the widest supported one. See the
// platformEncodingWidth comment for more discussion of width.
for i := 0; i < numSubtables; i++ {
buf, err = f.src.view(buf, int(f.cmap.offset)+headerSize+entrySize*i, entrySize)
if err != nil {
return nil, nil, err
}
pid := u16(buf)
psid := u16(buf[2:])
width := platformEncodingWidth(pid, psid)
if width <= bestWidth {
continue
}
offset := u32(buf[4:])
if offset > f.cmap.length-4 {
return nil, nil, errInvalidCmapTable
}
buf, err = f.src.view(buf, int(f.cmap.offset+offset), 4)
if err != nil {
return nil, nil, err
}
format := u16(buf)
if !supportedCmapFormat(format, pid, psid) {
continue
}
length := uint32(u16(buf[2:]))
bestWidth = width
bestOffset = offset
bestLength = length
bestFormat = format
}
if bestWidth == 0 {
return nil, nil, errUnsupportedCmapEncodings
}
return f.makeCachedGlyphIndex(buf, bestOffset, bestLength, bestFormat)
}
func (f *Font) parseHead(buf []byte) (buf1 []byte, indexToLocFormat bool, unitsPerEm Units, err error) {
// https://www.microsoft.com/typography/otspec/head.htm
if f.head.length != 54 {
return nil, false, 0, errInvalidHeadTable
}
u, err := f.src.u16(buf, f.head, 18)
if err != nil {
return nil, false, 0, err
}
if u == 0 {
return errInvalidHeadTable
return nil, false, 0, errInvalidHeadTable
}
f.cached.unitsPerEm = Units(u)
unitsPerEm = Units(u)
u, err = f.src.u16(buf, f.head, 50)
if err != nil {
return err
return nil, false, 0, err
}
f.cached.indexToLocFormat = u != 0
indexToLocFormat = u != 0
return buf, indexToLocFormat, unitsPerEm, nil
}
func (f *Font) parseKern(buf []byte) (buf1 []byte, kernNumPairs, kernOffset int32, err error) {
// https://www.microsoft.com/typography/otspec/kern.htm
if f.kern.length == 0 {
return buf, 0, 0, nil
}
const headerSize = 4
if f.kern.length < headerSize {
return nil, 0, 0, errInvalidKernTable
}
buf, err = f.src.view(buf, int(f.kern.offset), headerSize)
if err != nil {
return nil, 0, 0, err
}
offset := int(f.kern.offset) + headerSize
length := int(f.kern.length) - headerSize
switch version := u16(buf); version {
case 0:
// TODO: support numTables != 1. Testing that requires finding such a font.
if numTables := int(u16(buf[2:])); numTables != 1 {
return nil, 0, 0, errUnsupportedKernTable
}
return f.parseKernVersion0(buf, offset, length)
case 1:
// TODO: find such a (proprietary?) font, and support it. Both of
// https://www.microsoft.com/typography/otspec/kern.htm
// https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kern.html
// say that such fonts work on Mac OS but not on Windows.
}
return nil, 0, 0, errUnsupportedKernTable
}
func (f *Font) parseKernVersion0(buf []byte, offset, length int) (buf1 []byte, kernNumPairs, kernOffset int32, err error) {
const headerSize = 6
if length < headerSize {
return nil, 0, 0, errInvalidKernTable
}
buf, err = f.src.view(buf, offset, headerSize)
if err != nil {
return nil, 0, 0, err
}
if version := u16(buf); version != 0 {
return nil, 0, 0, errUnsupportedKernTable
}
subtableLength := int(u16(buf[2:]))
if subtableLength < headerSize || length < subtableLength {
return nil, 0, 0, errInvalidKernTable
}
if coverageBits := buf[5]; coverageBits != 0x01 {
// We only support horizontal kerning.
return nil, 0, 0, errUnsupportedKernTable
}
offset += headerSize
length -= headerSize
subtableLength -= headerSize
switch format := buf[4]; format {
case 0:
return f.parseKernFormat0(buf, offset, subtableLength)
case 2:
// TODO: find such a (proprietary?) font, and support it.
}
return nil, 0, 0, errUnsupportedKernTable
}
func (f *Font) parseKernFormat0(buf []byte, offset, length int) (buf1 []byte, kernNumPairs, kernOffset int32, err error) {
const headerSize, entrySize = 8, 6
if length < headerSize {
return nil, 0, 0, errInvalidKernTable
}
buf, err = f.src.view(buf, offset, headerSize)
if err != nil {
return nil, 0, 0, err
}
kernNumPairs = int32(u16(buf))
if length != headerSize+entrySize*int(kernNumPairs) {
return nil, 0, 0, errInvalidKernTable
}
return buf, kernNumPairs, int32(offset) + headerSize, nil
}
func (f *Font) parseMaxp(buf []byte, indexToLocFormat, isPostScript bool) (buf1 []byte, numGlyphs int, locations []uint32, err error) {
// https://www.microsoft.com/typography/otspec/maxp.htm
if f.cached.isPostScript {
if isPostScript {
if f.maxp.length != 6 {
return errInvalidMaxpTable
return nil, 0, nil, errInvalidMaxpTable
}
} else {
if f.maxp.length != 32 {
return errInvalidMaxpTable
return nil, 0, nil, errInvalidMaxpTable
}
}
u, err = f.src.u16(buf, f.maxp, 4)
u, err := f.src.u16(buf, f.maxp, 4)
if err != nil {
return err
return nil, 0, nil, err
}
numGlyphs := int(u)
numGlyphs = int(u)
if f.cached.isPostScript {
if isPostScript {
p := cffParser{
src: &f.src,
base: int(f.cff.offset),
offset: int(f.cff.offset),
end: int(f.cff.offset + f.cff.length),
}
f.cached.locations, err = p.parse()
locations, err = p.parse()
if err != nil {
return err
return nil, 0, nil, err
}
} else {
f.cached.locations, err = parseLoca(
&f.src, f.loca, f.glyf.offset, f.cached.indexToLocFormat, numGlyphs)
locations, err = parseLoca(&f.src, f.loca, f.glyf.offset, indexToLocFormat, numGlyphs)
if err != nil {
return err
return nil, 0, nil, err
}
}
if len(f.cached.locations) != numGlyphs+1 {
return errInvalidLocationData
if len(locations) != numGlyphs+1 {
return nil, 0, nil, errInvalidLocationData
}
return nil
return buf, numGlyphs, locations, nil
}
// TODO: func (f *Font) GlyphIndex(r rune) (x GlyphIndex, ok bool)
// This will require parsing the cmap table.
func (f *Font) parsePost(buf []byte, numGlyphs int) (buf1 []byte, postTableVersion uint32, err error) {
// https://www.microsoft.com/typography/otspec/post.htm
const headerSize = 32
if f.post.length < headerSize {
return nil, 0, errInvalidPostTable
}
u, err := f.src.u32(buf, f.post, 0)
if err != nil {
return nil, 0, err
}
switch u {
case 0x20000:
if f.post.length < headerSize+2+2*uint32(numGlyphs) {
return nil, 0, errInvalidPostTable
}
case 0x30000:
// No-op.
default:
return nil, 0, errUnsupportedPostTable
}
return buf, u, nil
}
// TODO: API for looking up glyph variants?? For example, some fonts may
// provide both slashed and dotted zero glyphs ('0'), or regular and 'old
// style' numerals, and users can direct software to choose a variant.
type glyphIndexFunc func(f *Font, b *Buffer, r rune) (GlyphIndex, error)
// GlyphIndex returns the glyph index for the given rune.
//
// It returns (0, nil) if there is no glyph for r.
// https://www.microsoft.com/typography/OTSPEC/cmap.htm says that "Character
// codes that do not correspond to any glyph in the font should be mapped to
// glyph index 0. The glyph at this location must be a special glyph
// representing a missing character, commonly known as .notdef."
func (f *Font) GlyphIndex(b *Buffer, r rune) (GlyphIndex, error) {
return f.cached.glyphIndex(f, b, r)
}
func (f *Font) viewGlyphData(b *Buffer, x GlyphIndex) ([]byte, error) {
xx := int(x)
@@ -458,15 +752,16 @@ func (f *Font) viewGlyphData(b *Buffer, x GlyphIndex) ([]byte, error) {
// LoadGlyphOptions are the options to the Font.LoadGlyph method.
type LoadGlyphOptions struct {
// TODO: scale / transform / hinting.
// TODO: transform / hinting.
}
// LoadGlyph returns the vector segments for the x'th glyph.
// LoadGlyph returns the vector segments for the x'th glyph. ppem is the number
// of pixels in 1 em.
//
// If b is non-nil, the segments become invalid to use once b is re-used.
//
// It returns ErrNotFound if the glyph index is out of range.
func (f *Font) LoadGlyph(b *Buffer, x GlyphIndex, opts *LoadGlyphOptions) ([]Segment, error) {
func (f *Font) LoadGlyph(b *Buffer, x GlyphIndex, ppem fixed.Int26_6, opts *LoadGlyphOptions) ([]Segment, error) {
if b == nil {
b = &Buffer{}
}
@@ -491,11 +786,153 @@ func (f *Font) LoadGlyph(b *Buffer, x GlyphIndex, opts *LoadGlyphOptions) ([]Seg
b.segments = segments
}
// TODO: look at opts to scale / transform / hint the Buffer.segments.
// Scale the segments. If we want to support hinting, we'll have to push
// the scaling computation into the PostScript / TrueType specific glyph
// loading code, such as the appendGlyfSegments body, since TrueType
// hinting bytecode works on the scaled glyph vectors. For now, though,
// it's simpler to scale as a post-processing step.
for i := range b.segments {
s := &b.segments[i]
for j := range s.Args {
s.Args[j] = scale(s.Args[j]*ppem, f.cached.unitsPerEm)
}
}
// TODO: look at opts to transform / hint the Buffer.segments.
return b.segments, nil
}
// GlyphName returns the name of the x'th glyph.
//
// Not every font contains glyph names. If not present, GlyphName will return
// ("", nil).
//
// If present, the glyph name, provided by the font, is assumed to follow the
// Adobe Glyph List Specification:
// https://github.com/adobe-type-tools/agl-specification/blob/master/README.md
//
// This is also known as the "Adobe Glyph Naming convention", the "Adobe
// document [for] Unicode and Glyph Names" or "PostScript glyph names".
//
// It returns ErrNotFound if the glyph index is out of range.
func (f *Font) GlyphName(b *Buffer, x GlyphIndex) (string, error) {
if int(x) >= f.NumGlyphs() {
return "", ErrNotFound
}
if f.cached.postTableVersion != 0x20000 {
return "", nil
}
if b == nil {
b = &Buffer{}
}
// The wire format for a Version 2 post table is documented at:
// https://www.microsoft.com/typography/otspec/post.htm
const glyphNameIndexOffset = 34
buf, err := b.view(&f.src, int(f.post.offset)+glyphNameIndexOffset+2*int(x), 2)
if err != nil {
return "", err
}
u := u16(buf)
if u < numBuiltInPostNames {
i := builtInPostNamesOffsets[u+0]
j := builtInPostNamesOffsets[u+1]
return builtInPostNamesData[i:j], nil
}
// https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6post.html
// says that "32768 through 65535 are reserved for future use".
if u > 32767 {
return "", errUnsupportedPostTable
}
u -= numBuiltInPostNames
// Iterate through the list of Pascal-formatted strings. A linear scan is
// clearly O(u), which isn't great (as the obvious loop, calling
// Font.GlyphName, to get all of the glyph names in a font has quadratic
// complexity), but the wire format doesn't suggest a better alternative.
offset := glyphNameIndexOffset + 2*f.NumGlyphs()
buf, err = b.view(&f.src, int(f.post.offset)+offset, int(f.post.length)-offset)
if err != nil {
return "", err
}
for {
if len(buf) == 0 {
return "", errInvalidPostTable
}
n := 1 + int(buf[0])
if len(buf) < n {
return "", errInvalidPostTable
}
if u == 0 {
return string(buf[1:n]), nil
}
buf = buf[n:]
u--
}
}
// Kern returns the horizontal adjustment for the kerning pair (x0, x1). A
// positive kern means to move the glyphs further apart. ppem is the number of
// pixels in 1 em.
//
// It returns ErrNotFound if either glyph index is out of range.
func (f *Font) Kern(b *Buffer, x0, x1 GlyphIndex, ppem fixed.Int26_6, h font.Hinting) (fixed.Int26_6, error) {
// TODO: how should this work with the GPOS table and CFF fonts?
// https://www.microsoft.com/typography/otspec/kern.htm says that
// "OpenType™ fonts containing CFF outlines are not supported by the 'kern'
// table and must use the 'GPOS' OpenType Layout table."
if n := f.NumGlyphs(); int(x0) >= n || int(x1) >= n {
return 0, ErrNotFound
}
// Not every font has a kern table. If it doesn't, there's no need to
// allocate a Buffer.
if f.kern.length == 0 {
return 0, nil
}
if b == nil {
b = &Buffer{}
}
key := uint32(x0)<<16 | uint32(x1)
lo, hi := int32(0), f.cached.kernNumPairs
for lo < hi {
i := (lo + hi) / 2
// TODO: this view call inside the inner loop can lead to many small
// reads instead of fewer larger reads, which can be expensive. We
// should be able to do better, although we don't want to make (one)
// arbitrarily large read. Perhaps we should round up reads to 4K or 8K
// chunks. For reference, Arial.ttf's kern table is 5472 bytes.
// Times_New_Roman.ttf's kern table is 5220 bytes.
const entrySize = 6
buf, err := b.view(&f.src, int(f.cached.kernOffset+i*entrySize), entrySize)
if err != nil {
return 0, err
}
k := u32(buf)
if k < key {
lo = i + 1
} else if k > key {
hi = i
} else {
kern := fixed.Int26_6(int16(u16(buf[4:])))
kern = scale(kern*ppem, f.cached.unitsPerEm)
if h == font.HintingFull {
// Quantize the fixed.Int26_6 value to the nearest pixel.
kern = (kern + 32) &^ 63
}
return kern, nil
}
}
return 0, nil
}
// Name returns the name value keyed by the given NameID.
//
// It returns ErrNotFound if there is no value for that key.
@@ -512,14 +949,14 @@ func (f *Font) Name(b *Buffer, id NameID) (string, error) {
if err != nil {
return "", err
}
nSubtables := u16(buf[2:])
if f.name.length < headerSize+entrySize*uint32(nSubtables) {
numSubtables := u16(buf[2:])
if f.name.length < headerSize+entrySize*uint32(numSubtables) {
return "", errInvalidNameTable
}
stringOffset := u16(buf[4:])
seen := false
for i, n := 0, int(nSubtables); i < n; i++ {
for i, n := 0, int(numSubtables); i < n; i++ {
buf, err := b.view(&f.src, int(f.name.offset)+headerSize+entrySize*i, entrySize)
if err != nil {
return "", err

370
vendor/golang.org/x/image/font/sfnt/sfnt_test.go сгенерированный поставляемый
Просмотреть файл

@@ -6,6 +6,7 @@ package sfnt
import (
"bytes"
"fmt"
"io/ioutil"
"path/filepath"
"testing"
@@ -14,52 +15,48 @@ import (
"golang.org/x/image/math/fixed"
)
func moveTo(xa, ya int) Segment {
func moveTo(xa, ya fixed.Int26_6) Segment {
return Segment{
Op: SegmentOpMoveTo,
Args: [6]fixed.Int26_6{
0: fixed.I(xa),
1: fixed.I(ya),
},
Op: SegmentOpMoveTo,
Args: [6]fixed.Int26_6{xa, ya},
}
}
func lineTo(xa, ya int) Segment {
func lineTo(xa, ya fixed.Int26_6) Segment {
return Segment{
Op: SegmentOpLineTo,
Args: [6]fixed.Int26_6{
0: fixed.I(xa),
1: fixed.I(ya),
},
Op: SegmentOpLineTo,
Args: [6]fixed.Int26_6{xa, ya},
}
}
func quadTo(xa, ya, xb, yb int) Segment {
func quadTo(xa, ya, xb, yb fixed.Int26_6) Segment {
return Segment{
Op: SegmentOpQuadTo,
Args: [6]fixed.Int26_6{
0: fixed.I(xa),
1: fixed.I(ya),
2: fixed.I(xb),
3: fixed.I(yb),
},
Op: SegmentOpQuadTo,
Args: [6]fixed.Int26_6{xa, ya, xb, yb},
}
}
func cubeTo(xa, ya, xb, yb, xc, yc int) Segment {
func cubeTo(xa, ya, xb, yb, xc, yc fixed.Int26_6) Segment {
return Segment{
Op: SegmentOpCubeTo,
Args: [6]fixed.Int26_6{
0: fixed.I(xa),
1: fixed.I(ya),
2: fixed.I(xb),
3: fixed.I(yb),
4: fixed.I(xc),
5: fixed.I(yc),
},
Op: SegmentOpCubeTo,
Args: [6]fixed.Int26_6{xa, ya, xb, yb, xc, yc},
}
}
func checkSegmentsEqual(got, want []Segment) error {
if len(got) != len(want) {
return fmt.Errorf("got %d elements, want %d\noverall:\ngot %v\nwant %v",
len(got), len(want), got, want)
}
for i, g := range got {
if w := want[i]; g != w {
return fmt.Errorf("element %d:\ngot %v\nwant %v\noverall:\ngot %v\nwant %v",
i, g, w, got, want)
}
}
return nil
}
func TestTrueTypeParse(t *testing.T) {
f, err := Parse(goregular.TTF)
if err != nil {
@@ -88,6 +85,167 @@ func testTrueType(t *testing.T, f *Font) {
}
}
func TestGoRegularGlyphIndex(t *testing.T) {
f, err := Parse(goregular.TTF)
if err != nil {
t.Fatalf("Parse: %v", err)
}
testCases := []struct {
r rune
want GlyphIndex
}{
// Glyphs that aren't present in Go Regular.
{'\u001f', 0}, // U+001F <control>
{'\u0200', 0}, // U+0200 LATIN CAPITAL LETTER A WITH DOUBLE GRAVE
{'\u2000', 0}, // U+2000 EN QUAD
// The want values below can be verified by running the ttx tool on
// Go-Regular.ttf.
//
// The actual values are ad hoc, and result from whatever tools the
// Bigelow & Holmes type foundry used and the order in which they
// crafted the glyphs. They may change over time as newer versions of
// the font are released. In practice, though, running this test with
// coverage analysis suggests that it covers both the zero and non-zero
// cmapEntry16.offset cases for a format-4 cmap table.
{'\u0020', 3}, // U+0020 SPACE
{'\u0021', 4}, // U+0021 EXCLAMATION MARK
{'\u0022', 5}, // U+0022 QUOTATION MARK
{'\u0023', 6}, // U+0023 NUMBER SIGN
{'\u0024', 223}, // U+0024 DOLLAR SIGN
{'\u0025', 7}, // U+0025 PERCENT SIGN
{'\u0026', 8}, // U+0026 AMPERSAND
{'\u0027', 9}, // U+0027 APOSTROPHE
{'\u03bd', 423}, // U+03BD GREEK SMALL LETTER NU
{'\u03be', 424}, // U+03BE GREEK SMALL LETTER XI
{'\u03bf', 438}, // U+03BF GREEK SMALL LETTER OMICRON
{'\u03c0', 208}, // U+03C0 GREEK SMALL LETTER PI
{'\u03c1', 425}, // U+03C1 GREEK SMALL LETTER RHO
{'\u03c2', 426}, // U+03C2 GREEK SMALL LETTER FINAL SIGMA
}
var b Buffer
for _, tc := range testCases {
got, err := f.GlyphIndex(&b, tc.r)
if err != nil {
t.Errorf("r=%q: %v", tc.r, err)
continue
}
if got != tc.want {
t.Errorf("r=%q: got %d, want %d", tc.r, got, tc.want)
continue
}
}
}
func TestGlyphIndex(t *testing.T) {
data, err := ioutil.ReadFile(filepath.FromSlash("../testdata/cmapTest.ttf"))
if err != nil {
t.Fatal(err)
}
for _, format := range []int{-1, 0, 4, 12} {
testGlyphIndex(t, data, format)
}
}
func testGlyphIndex(t *testing.T, data []byte, cmapFormat int) {
if cmapFormat >= 0 {
originalSupportedCmapFormat := supportedCmapFormat
defer func() {
supportedCmapFormat = originalSupportedCmapFormat
}()
supportedCmapFormat = func(format, pid, psid uint16) bool {
return int(format) == cmapFormat && originalSupportedCmapFormat(format, pid, psid)
}
}
f, err := Parse(data)
if err != nil {
t.Errorf("cmapFormat=%d: %v", cmapFormat, err)
return
}
testCases := []struct {
r rune
want GlyphIndex
}{
// Glyphs that aren't present in cmapTest.ttf.
{'?', 0},
{'\ufffd', 0},
{'\U0001f4a9', 0},
// For a .TTF file, FontForge maps:
// - ".notdef" to glyph index 0.
// - ".null" to glyph index 1.
// - "nonmarkingreturn" to glyph index 2.
{'/', 0},
{'0', 3},
{'1', 4},
{'2', 5},
{'3', 0},
{'@', 0},
{'A', 6},
{'B', 7},
{'C', 0},
{'`', 0},
{'a', 8},
{'b', 0},
// Of the remaining runes, only U+00FF LATIN SMALL LETTER Y WITH
// DIAERESIS is in both the Mac Roman encoding and the cmapTest.ttf
// font file.
{'\u00fe', 0},
{'\u00ff', 9},
{'\u0100', 10},
{'\u0101', 11},
{'\u0102', 0},
{'\u4e2c', 0},
{'\u4e2d', 12},
{'\u4e2e', 0},
{'\U0001f0a0', 0},
{'\U0001f0a1', 13},
{'\U0001f0a2', 0},
{'\U0001f0b0', 0},
{'\U0001f0b1', 14},
{'\U0001f0b2', 15},
{'\U0001f0b3', 0},
}
var b Buffer
for _, tc := range testCases {
want := tc.want
switch {
case cmapFormat == 0 && tc.r > '\u007f' && tc.r != '\u00ff':
// cmap format 0, with the Macintosh Roman encoding, can only
// represent a limited set of non-ASCII runes, e.g. U+00FF.
want = 0
case cmapFormat == 4 && tc.r > '\uffff':
// cmap format 4 only supports the Basic Multilingual Plane (BMP).
want = 0
}
got, err := f.GlyphIndex(&b, tc.r)
if err != nil {
t.Errorf("cmapFormat=%d, r=%q: %v", cmapFormat, tc.r, err)
continue
}
if got != want {
t.Errorf("cmapFormat=%d, r=%q: got %d, want %d", cmapFormat, tc.r, got, want)
continue
}
}
}
func TestPostScriptSegments(t *testing.T) {
// wants' vectors correspond 1-to-1 to what's in the CFFTest.sfd file,
// although OpenType/CFF and FontForge's SFD have reversed orders.
@@ -226,40 +384,32 @@ func TestTrueTypeSegments(t *testing.T) {
}
func testSegments(t *testing.T, filename string, wants [][]Segment) {
data, err := ioutil.ReadFile(filepath.Join("..", "testdata", filename))
data, err := ioutil.ReadFile(filepath.FromSlash("../testdata/" + filename))
if err != nil {
t.Fatal(err)
t.Fatalf("ReadFile: %v", err)
}
f, err := Parse(data)
if err != nil {
t.Fatal(err)
t.Fatalf("Parse: %v", err)
}
ppem := fixed.Int26_6(f.UnitsPerEm())
if ng := f.NumGlyphs(); ng != len(wants) {
t.Fatalf("NumGlyphs: got %d, want %d", ng, len(wants))
}
var b Buffer
loop:
for i, want := range wants {
got, err := f.LoadGlyph(&b, GlyphIndex(i), nil)
got, err := f.LoadGlyph(&b, GlyphIndex(i), ppem, nil)
if err != nil {
t.Errorf("i=%d: LoadGlyph: %v", i, err)
continue
}
if len(got) != len(want) {
t.Errorf("i=%d: got %d elements, want %d\noverall:\ngot %v\nwant %v",
i, len(got), len(want), got, want)
if err := checkSegmentsEqual(got, want); err != nil {
t.Errorf("i=%d: %v", i, err)
continue
}
for j, g := range got {
if w := want[j]; g != w {
t.Errorf("i=%d: element %d:\ngot %v\nwant %v\noverall:\ngot %v\nwant %v",
i, j, g, w, got, want)
continue loop
}
}
}
if _, err := f.LoadGlyph(nil, 0xffff, nil); err != ErrNotFound {
if _, err := f.LoadGlyph(nil, 0xffff, ppem, nil); err != ErrNotFound {
t.Errorf("LoadGlyph(..., 0xffff, ...):\ngot %v\nwant %v", err, ErrNotFound)
}
@@ -270,3 +420,131 @@ loop:
t.Errorf("Name:\ngot %q\nwant %q", name, want)
}
}
func TestPPEM(t *testing.T) {
data, err := ioutil.ReadFile(filepath.FromSlash("../testdata/glyfTest.ttf"))
if err != nil {
t.Fatalf("ReadFile: %v", err)
}
f, err := Parse(data)
if err != nil {
t.Fatalf("Parse: %v", err)
}
var b Buffer
x, err := f.GlyphIndex(&b, '1')
if err != nil {
t.Fatalf("GlyphIndex: %v", err)
}
if x == 0 {
t.Fatalf("GlyphIndex: no glyph index found for the rune '1'")
}
testCases := []struct {
ppem fixed.Int26_6
want []Segment
}{{
ppem: fixed.Int26_6(12 << 6),
want: []Segment{
moveTo(77, 0),
lineTo(77, 614),
lineTo(230, 614),
lineTo(230, 0),
lineTo(77, 0),
},
}, {
ppem: fixed.Int26_6(2048),
want: []Segment{
moveTo(205, 0),
lineTo(205, 1638),
lineTo(614, 1638),
lineTo(614, 0),
lineTo(205, 0),
},
}}
for i, tc := range testCases {
got, err := f.LoadGlyph(&b, x, tc.ppem, nil)
if err != nil {
t.Errorf("i=%d: LoadGlyph: %v", i, err)
continue
}
if err := checkSegmentsEqual(got, tc.want); err != nil {
t.Errorf("i=%d: %v", i, err)
continue
}
}
}
func TestGlyphName(t *testing.T) {
f, err := Parse(goregular.TTF)
if err != nil {
t.Fatalf("Parse: %v", err)
}
testCases := []struct {
r rune
want string
}{
{'\x00', "NULL"},
{'!', "exclam"},
{'A', "A"},
{'{', "braceleft"},
{'\u00c4', "Adieresis"}, // U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS
{'\u2020', "dagger"}, // U+2020 DAGGER
{'\u2660', "spade"}, // U+2660 BLACK SPADE SUIT
{'\uf800', "gopher"}, // U+F800 <Private Use>
{'\ufffe', ".notdef"}, // Not in the Go Regular font, so GlyphIndex returns (0, nil).
}
var b Buffer
for _, tc := range testCases {
x, err := f.GlyphIndex(&b, tc.r)
if err != nil {
t.Errorf("r=%q: GlyphIndex: %v", tc.r, err)
continue
}
got, err := f.GlyphName(&b, x)
if err != nil {
t.Errorf("r=%q: GlyphName: %v", tc.r, err)
continue
}
if got != tc.want {
t.Errorf("r=%q: got %q, want %q", tc.r, got, tc.want)
continue
}
}
}
func TestBuiltInPostNames(t *testing.T) {
testCases := []struct {
x GlyphIndex
want string
}{
{0, ".notdef"},
{1, ".null"},
{2, "nonmarkingreturn"},
{13, "asterisk"},
{36, "A"},
{93, "z"},
{123, "ocircumflex"},
{202, "Edieresis"},
{255, "Ccaron"},
{256, "ccaron"},
{257, "dcroat"},
{258, ""},
{999, ""},
{0xffff, ""},
}
for _, tc := range testCases {
if tc.x >= numBuiltInPostNames {
continue
}
i := builtInPostNamesOffsets[tc.x+0]
j := builtInPostNamesOffsets[tc.x+1]
got := builtInPostNamesData[i:j]
if got != tc.want {
t.Errorf("x=%d: got %q, want %q", tc.x, got, tc.want)
}
}
}

29
vendor/golang.org/x/image/font/sfnt/truetype.go сгенерированный поставляемый
Просмотреть файл

@@ -113,6 +113,11 @@ func appendGlyfSegments(dst []Segment, data []byte) ([]Segment, error) {
return nil, errInvalidGlyphData
}
// TODO: support compound glyphs.
if numContours < 0 {
return nil, errUnsupportedCompoundGlyph
}
// Skip the hinting instructions.
index += 2
if index > len(data) {
@@ -124,19 +129,14 @@ func appendGlyfSegments(dst []Segment, data []byte) ([]Segment, error) {
return nil, errInvalidGlyphData
}
// TODO: support compound glyphs.
if numContours < 0 {
return nil, errUnsupportedCompoundGlyph
}
// For simple (non-compound) glyphs, the remainder of the glyf data
// consists of (flags, x, y) points: the Bézier curve segments. These are
// stored in columns (all the flags first, then all the x co-ordinates,
// then all the y co-ordinates), not rows, as it compresses better.
// stored in columns (all the flags first, then all the x coordinates, then
// all the y coordinates), not rows, as it compresses better.
//
// Decoding those points in row order involves two passes. The first pass
// determines the indexes (relative to the data slice) of where the flags,
// the x co-ordinates and the y co-ordinates each start.
// the x coordinates and the y coordinates each start.
flagIndex := int32(index)
xIndex, yIndex, ok := findXYIndexes(data, index, numPoints)
if !ok {
@@ -357,9 +357,18 @@ func (g *glyfIter) nextSegment() (ok bool) {
return true
}
// Convert the tuple (g.x, g.y) to a fixed.Point26_6, since the latter
// is what's held in a Segment. The input (g.x, g.y) is a pair of int16
// values, measured in font units, since that is what the underlying
// format provides. The output is a pair of fixed.Int26_6 values. A
// fixed.Int26_6 usually represents a 26.6 fixed number of pixels, but
// this here is just a straight numerical conversion, with no scaling
// factor. A later step scales the Segment.Args values by such a factor
// to convert e.g. 1792 font units to 10.5 pixels at 2048 font units
// per em and 12 ppem (pixels per em).
p := fixed.Point26_6{
X: fixed.Int26_6(g.x) << 6,
Y: fixed.Int26_6(g.y) << 6,
X: fixed.Int26_6(g.x),
Y: fixed.Int26_6(g.y),
}
if !g.firstOnCurveValid {

265
vendor/golang.org/x/image/font/testdata/cmapTest.sfd сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,265 @@
SplineFontDB: 3.0
FontName: cmapTest
FullName: cmapTest
FamilyName: cmapTest
Weight: Regular
Copyright: Copyright 2016 The Go Authors. All rights reserved.\nUse of this font is governed by a BSD-style license that can be found at https://golang.org/LICENSE.
Version: 001.000
ItalicAngle: -11.25
UnderlinePosition: -204
UnderlineWidth: 102
Ascent: 1638
Descent: 410
LayerCount: 2
Layer: 0 1 "Back" 1
Layer: 1 1 "Fore" 0
XUID: [1021 367 888937226 7862908]
FSType: 8
OS2Version: 0
OS2_WeightWidthSlopeOnly: 0
OS2_UseTypoMetrics: 1
CreationTime: 1484386143
ModificationTime: 1486021330
PfmFamily: 17
TTFWeight: 400
TTFWidth: 5
LineGap: 184
VLineGap: 0
OS2TypoAscent: 0
OS2TypoAOffset: 1
OS2TypoDescent: 0
OS2TypoDOffset: 1
OS2TypoLinegap: 184
OS2WinAscent: 0
OS2WinAOffset: 1
OS2WinDescent: 0
OS2WinDOffset: 1
HheadAscent: 0
HheadAOffset: 1
HheadDescent: 0
HheadDOffset: 1
OS2Vendor: 'PfEd'
MarkAttachClasses: 1
DEI: 91125
LangName: 1033
Encoding: UnicodeFull
UnicodeInterp: none
NameList: Adobe Glyph List
DisplaySize: -24
AntiAlias: 1
FitToEm: 1
WinInfo: 126976 32 23
BeginPrivate: 0
EndPrivate
TeXData: 1 0 0 346030 173015 115343 0 -1048576 115343 783286 444596 497025 792723 393216 433062 380633 303038 157286 324010 404750 52429 2506097 1059062 262144
BeginChars: 1114112 13
StartChar: zero
Encoding: 48 48 0
Width: 800
VWidth: 0
Flags: W
LayerCount: 2
Fore
SplineSet
0 0 m 29,0,-1
400 800 l 25,1,-1
800 0 l 25,2,-1
0 0 l 29,0,-1
EndSplineSet
Validated: 1
EndChar
StartChar: one
Encoding: 49 49 1
Width: 800
VWidth: 0
Flags: W
LayerCount: 2
Fore
SplineSet
0 0 m 29,0,-1
400 800 l 25,1,-1
800 0 l 25,2,-1
0 0 l 29,0,-1
EndSplineSet
Validated: 1
EndChar
StartChar: two
Encoding: 50 50 2
Width: 800
VWidth: 0
Flags: W
LayerCount: 2
Fore
SplineSet
0 0 m 29,0,-1
400 800 l 25,1,-1
800 0 l 25,2,-1
0 0 l 29,0,-1
EndSplineSet
Validated: 1
EndChar
StartChar: A
Encoding: 65 65 3
Width: 800
VWidth: 0
Flags: W
LayerCount: 2
Fore
SplineSet
0 0 m 29,0,-1
400 800 l 25,1,-1
800 0 l 25,2,-1
0 0 l 29,0,-1
EndSplineSet
Validated: 1
EndChar
StartChar: uni4E2D
Encoding: 20013 20013 4
Width: 800
VWidth: 0
Flags: W
LayerCount: 2
Fore
SplineSet
0 0 m 29,0,-1
400 800 l 25,1,-1
800 0 l 25,2,-1
0 0 l 29,0,-1
EndSplineSet
Validated: 1
EndChar
StartChar: u1F0A1
Encoding: 127137 127137 5
Width: 800
VWidth: 0
Flags: W
LayerCount: 2
Fore
SplineSet
0 0 m 29,0,-1
400 800 l 25,1,-1
800 0 l 25,2,-1
0 0 l 29,0,-1
EndSplineSet
Validated: 1
EndChar
StartChar: ydieresis
Encoding: 255 255 6
Width: 800
VWidth: 0
Flags: W
LayerCount: 2
Fore
SplineSet
0 0 m 29,0,-1
400 800 l 25,1,-1
800 0 l 25,2,-1
0 0 l 29,0,-1
EndSplineSet
Validated: 1
EndChar
StartChar: Amacron
Encoding: 256 256 7
Width: 800
VWidth: 0
Flags: W
LayerCount: 2
Fore
SplineSet
0 0 m 29,0,-1
400 800 l 25,1,-1
800 0 l 25,2,-1
0 0 l 29,0,-1
EndSplineSet
Validated: 1
EndChar
StartChar: amacron
Encoding: 257 257 8
Width: 800
VWidth: 0
Flags: W
LayerCount: 2
Fore
SplineSet
0 0 m 29,0,-1
400 800 l 25,1,-1
800 0 l 25,2,-1
0 0 l 29,0,-1
EndSplineSet
Validated: 1
EndChar
StartChar: B
Encoding: 66 66 9
Width: 800
VWidth: 0
Flags: W
LayerCount: 2
Fore
SplineSet
0 0 m 29,0,-1
400 800 l 25,1,-1
800 0 l 25,2,-1
0 0 l 29,0,-1
EndSplineSet
Validated: 1
EndChar
StartChar: a
Encoding: 97 97 10
Width: 800
VWidth: 0
Flags: W
LayerCount: 2
Fore
SplineSet
0 0 m 29,0,-1
400 800 l 25,1,-1
800 0 l 25,2,-1
0 0 l 29,0,-1
EndSplineSet
Validated: 1
EndChar
StartChar: u1F0B1
Encoding: 127153 127153 11
Width: 800
VWidth: 0
Flags: W
LayerCount: 2
Fore
SplineSet
0 0 m 29,0,-1
400 800 l 25,1,-1
800 0 l 25,2,-1
0 0 l 29,0,-1
EndSplineSet
Validated: 1
EndChar
StartChar: u1F0B2
Encoding: 127154 127154 12
Width: 800
VWidth: 0
Flags: W
LayerCount: 2
Fore
SplineSet
0 0 m 29,0,-1
400 800 l 25,1,-1
800 0 l 25,2,-1
0 0 l 29,0,-1
EndSplineSet
Validated: 1
EndChar
EndChars
EndSplineFont

Двоичные данные
vendor/golang.org/x/image/font/testdata/cmapTest.ttf сгенерированный поставляемый Обычный файл

Двоичный файл не отображается.

Двоичные данные
vendor/golang.org/x/image/testdata/go-turns-two-down-ab.png сгенерированный поставляемый

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 21 KiB

После

Ширина:  |  Высота:  |  Размер: 21 KiB

Двоичные данные
vendor/golang.org/x/image/testdata/go-turns-two-down-bl.png сгенерированный поставляемый

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 18 KiB

После

Ширина:  |  Высота:  |  Размер: 18 KiB

Двоичные данные
vendor/golang.org/x/image/testdata/go-turns-two-down-cr.png сгенерированный поставляемый

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 19 KiB

После

Ширина:  |  Высота:  |  Размер: 19 KiB

Двоичные данные
vendor/golang.org/x/image/testdata/go-turns-two-down-nn.png сгенерированный поставляемый

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 21 KiB

После

Ширина:  |  Высота:  |  Размер: 21 KiB

Двоичные данные
vendor/golang.org/x/image/testdata/go-turns-two-rotate-ab.png сгенерированный поставляемый

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 7.5 KiB

После

Ширина:  |  Высота:  |  Размер: 7.2 KiB

Двоичные данные
vendor/golang.org/x/image/testdata/go-turns-two-rotate-bl.png сгенерированный поставляемый

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 7.5 KiB

После

Ширина:  |  Высота:  |  Размер: 7.2 KiB

Двоичные данные
vendor/golang.org/x/image/testdata/go-turns-two-rotate-cr.png сгенерированный поставляемый

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 7.6 KiB

После

Ширина:  |  Высота:  |  Размер: 7.4 KiB

Двоичные данные
vendor/golang.org/x/image/testdata/go-turns-two-rotate-nn.png сгенерированный поставляемый

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 4.8 KiB

После

Ширина:  |  Высота:  |  Размер: 5.0 KiB

Двоичные данные
vendor/golang.org/x/image/testdata/go-turns-two-up-ab.png сгенерированный поставляемый

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 9.4 KiB

После

Ширина:  |  Высота:  |  Размер: 9.2 KiB

Двоичные данные
vendor/golang.org/x/image/testdata/go-turns-two-up-bl.png сгенерированный поставляемый

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 9.4 KiB

После

Ширина:  |  Высота:  |  Размер: 9.2 KiB

Двоичные данные
vendor/golang.org/x/image/testdata/go-turns-two-up-cr.png сгенерированный поставляемый

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 11 KiB

После

Ширина:  |  Высота:  |  Размер: 10 KiB

Двоичные данные
vendor/golang.org/x/image/testdata/go-turns-two-up-nn.png сгенерированный поставляемый

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.3 KiB

После

Ширина:  |  Высота:  |  Размер: 1.3 KiB

Двоичные данные
vendor/golang.org/x/image/testdata/tux-rotate-ab.png сгенерированный поставляемый

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 3.2 KiB

После

Ширина:  |  Высота:  |  Размер: 3.3 KiB

Двоичные данные
vendor/golang.org/x/image/testdata/tux-rotate-bl.png сгенерированный поставляемый

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 3.7 KiB

После

Ширина:  |  Высота:  |  Размер: 3.7 KiB

Двоичные данные
vendor/golang.org/x/image/testdata/tux-rotate-cr.png сгенерированный поставляемый

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 3.7 KiB

После

Ширина:  |  Высота:  |  Размер: 3.8 KiB

Двоичные данные
vendor/golang.org/x/image/testdata/tux-rotate-nn.png сгенерированный поставляемый

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 3.0 KiB

После

Ширина:  |  Высота:  |  Размер: 3.1 KiB

7
vendor/golang.org/x/net/bpf/vm_bpf_test.go сгенерированный поставляемый
Просмотреть файл

@@ -33,7 +33,7 @@ func canUseOSVM() bool {
}
// All BPF tests against both the Go VM and OS VM are assumed to
// be used with a UDP socket. As a result, the entire contents
// be used with a UDP socket. As a result, the entire contents
// of a UDP datagram is sent through the BPF program, but only
// the body after the UDP header will ever be returned in output.
@@ -85,7 +85,7 @@ func (mvm *multiVirtualMachine) Run(in []byte) (int, error) {
}
// All tests have a UDP header as part of input, because the OS VM
// packets always will. For the Go VM, this output is trimmed before
// packets always will. For the Go VM, this output is trimmed before
// being sent back to tests.
goOut, goErr := mvm.goVM.Run(in)
if goOut >= udpHeaderLen {
@@ -149,6 +149,9 @@ func testOSVM(t *testing.T, filter []bpf.Instruction) (virtualMachine, func()) {
p := ipv4.NewPacketConn(l)
if err = p.SetBPF(prog); err != nil {
if err.Error() == "operation not supported" { // TODO: gross. remove once 19051 fixed.
t.Skip("Skipping until Issue 19051 is fixed.")
}
t.Fatalf("failed to attach BPF program to listener: %v", err)
}

30
vendor/golang.org/x/net/context/context.go сгенерированный поставляемый
Просмотреть файл

@@ -7,7 +7,7 @@
// and between processes.
//
// Incoming requests to a server should create a Context, and outgoing calls to
// servers should accept a Context. The chain of function calls between must
// servers should accept a Context. The chain of function calls between must
// propagate the Context, optionally replacing it with a modified copy created
// using WithDeadline, WithTimeout, WithCancel, or WithValue.
//
@@ -16,14 +16,14 @@
// propagation:
//
// Do not store Contexts inside a struct type; instead, pass a Context
// explicitly to each function that needs it. The Context should be the first
// explicitly to each function that needs it. The Context should be the first
// parameter, typically named ctx:
//
// func DoSomething(ctx context.Context, arg Arg) error {
// // ... use ctx ...
// }
//
// Do not pass a nil Context, even if a function permits it. Pass context.TODO
// Do not pass a nil Context, even if a function permits it. Pass context.TODO
// if you are unsure about which Context to use.
//
// Use context Values only for request-scoped data that transits processes and
@@ -44,13 +44,13 @@ import "time"
// Context's methods may be called by multiple goroutines simultaneously.
type Context interface {
// Deadline returns the time when work done on behalf of this context
// should be canceled. Deadline returns ok==false when no deadline is
// set. Successive calls to Deadline return the same results.
// should be canceled. Deadline returns ok==false when no deadline is
// set. Successive calls to Deadline return the same results.
Deadline() (deadline time.Time, ok bool)
// Done returns a channel that's closed when work done on behalf of this
// context should be canceled. Done may return nil if this context can
// never be canceled. Successive calls to Done return the same value.
// context should be canceled. Done may return nil if this context can
// never be canceled. Successive calls to Done return the same value.
//
// WithCancel arranges for Done to be closed when cancel is called;
// WithDeadline arranges for Done to be closed when the deadline
@@ -79,24 +79,24 @@ type Context interface {
// a Done channel for cancelation.
Done() <-chan struct{}
// Err returns a non-nil error value after Done is closed. Err returns
// Err returns a non-nil error value after Done is closed. Err returns
// Canceled if the context was canceled or DeadlineExceeded if the
// context's deadline passed. No other values for Err are defined.
// context's deadline passed. No other values for Err are defined.
// After Done is closed, successive calls to Err return the same value.
Err() error
// Value returns the value associated with this context for key, or nil
// if no value is associated with key. Successive calls to Value with
// if no value is associated with key. Successive calls to Value with
// the same key returns the same result.
//
// Use context values only for request-scoped data that transits
// processes and API boundaries, not for passing optional parameters to
// functions.
//
// A key identifies a specific value in a Context. Functions that wish
// A key identifies a specific value in a Context. Functions that wish
// to store values in Context typically allocate a key in a global
// variable then use that key as the argument to context.WithValue and
// Context.Value. A key can be any type that supports equality;
// Context.Value. A key can be any type that supports equality;
// packages should define keys as an unexported type to avoid
// collisions.
//
@@ -115,7 +115,7 @@ type Context interface {
// // This prevents collisions with keys defined in other packages.
// type key int
//
// // userKey is the key for user.User values in Contexts. It is
// // userKey is the key for user.User values in Contexts. It is
// // unexported; clients use user.NewContext and user.FromContext
// // instead of using this key directly.
// var userKey key = 0
@@ -134,14 +134,14 @@ type Context interface {
}
// Background returns a non-nil, empty Context. It is never canceled, has no
// values, and has no deadline. It is typically used by the main function,
// values, and has no deadline. It is typically used by the main function,
// initialization, and tests, and as the top-level Context for incoming
// requests.
func Background() Context {
return background
}
// TODO returns a non-nil, empty Context. Code should use context.TODO when
// TODO returns a non-nil, empty Context. Code should use context.TODO when
// it's unclear which Context to use or it is not yet available (because the
// surrounding function has not yet been extended to accept a Context
// parameter). TODO is recognized by static analysis tools that determine

1
vendor/golang.org/x/net/context/ctxhttp/ctxhttp_17_test.go сгенерированный поставляемый
Просмотреть файл

@@ -19,6 +19,7 @@ func TestGo17Context(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "ok")
}))
defer ts.Close()
ctx := context.Background()
resp, err := Get(ctx, http.DefaultClient, ts.URL)
if resp == nil || err != nil {

4
vendor/golang.org/x/net/context/go17.go сгенерированный поставляемый
Просмотреть файл

@@ -35,8 +35,8 @@ func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
}
// WithDeadline returns a copy of the parent context with the deadline adjusted
// to be no later than d. If the parent's deadline is already earlier than d,
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
// to be no later than d. If the parent's deadline is already earlier than d,
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
// context's Done channel is closed when the deadline expires, when the returned
// cancel function is called, or when the parent context's Done channel is
// closed, whichever happens first.

18
vendor/golang.org/x/net/context/pre_go17.go сгенерированный поставляемый
Просмотреть файл

@@ -13,7 +13,7 @@ import (
"time"
)
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
// struct{}, since vars of this type must have distinct addresses.
type emptyCtx int
@@ -104,7 +104,7 @@ func propagateCancel(parent Context, child canceler) {
}
// parentCancelCtx follows a chain of parent references until it finds a
// *cancelCtx. This function understands how each of the concrete types in this
// *cancelCtx. This function understands how each of the concrete types in this
// package represents its parent.
func parentCancelCtx(parent Context) (*cancelCtx, bool) {
for {
@@ -134,14 +134,14 @@ func removeChild(parent Context, child canceler) {
p.mu.Unlock()
}
// A canceler is a context type that can be canceled directly. The
// A canceler is a context type that can be canceled directly. The
// implementations are *cancelCtx and *timerCtx.
type canceler interface {
cancel(removeFromParent bool, err error)
Done() <-chan struct{}
}
// A cancelCtx can be canceled. When canceled, it also cancels any children
// A cancelCtx can be canceled. When canceled, it also cancels any children
// that implement canceler.
type cancelCtx struct {
Context
@@ -193,8 +193,8 @@ func (c *cancelCtx) cancel(removeFromParent bool, err error) {
}
// WithDeadline returns a copy of the parent context with the deadline adjusted
// to be no later than d. If the parent's deadline is already earlier than d,
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
// to be no later than d. If the parent's deadline is already earlier than d,
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
// context's Done channel is closed when the deadline expires, when the returned
// cancel function is called, or when the parent context's Done channel is
// closed, whichever happens first.
@@ -226,8 +226,8 @@ func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
return c, func() { c.cancel(true, Canceled) }
}
// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
// implement Done and Err. It implements cancel by stopping its timer then
// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
// implement Done and Err. It implements cancel by stopping its timer then
// delegating to cancelCtx.cancel.
type timerCtx struct {
*cancelCtx
@@ -281,7 +281,7 @@ func WithValue(parent Context, key interface{}, val interface{}) Context {
return &valueCtx{parent, key, val}
}
// A valueCtx carries a key-value pair. It implements Value for that key and
// A valueCtx carries a key-value pair. It implements Value for that key and
// delegates all other calls to the embedded Context.
type valueCtx struct {
Context

1418
vendor/golang.org/x/net/dns/dnsmessage/message.go сгенерированный поставляемый Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

575
vendor/golang.org/x/net/dns/dnsmessage/message_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,575 @@
// 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 dnsmessage
import (
"fmt"
"net"
"reflect"
"strings"
"testing"
)
func (m *Message) String() string {
s := fmt.Sprintf("Message: %#v\n", &m.Header)
if len(m.Questions) > 0 {
s += "-- Questions\n"
for _, q := range m.Questions {
s += fmt.Sprintf("%#v\n", q)
}
}
if len(m.Answers) > 0 {
s += "-- Answers\n"
for _, a := range m.Answers {
s += fmt.Sprintf("%#v\n", a)
}
}
if len(m.Authorities) > 0 {
s += "-- Authorities\n"
for _, ns := range m.Authorities {
s += fmt.Sprintf("%#v\n", ns)
}
}
if len(m.Additionals) > 0 {
s += "-- Additionals\n"
for _, e := range m.Additionals {
s += fmt.Sprintf("%#v\n", e)
}
}
return s
}
func TestQuestionPackUnpack(t *testing.T) {
want := Question{
Name: ".",
Type: TypeA,
Class: ClassINET,
}
buf, err := want.pack(make([]byte, 1, 50), map[string]int{})
if err != nil {
t.Fatal("Packing failed:", err)
}
var p Parser
p.msg = buf
p.header.questions = 1
p.section = sectionQuestions
p.off = 1
got, err := p.Question()
if err != nil {
t.Fatalf("Unpacking failed: %v\n%s", err, string(buf[1:]))
}
if p.off != len(buf) {
t.Errorf("Unpacked different amount than packed: got n = %d, want = %d", p.off, len(buf))
}
if !reflect.DeepEqual(got, want) {
t.Errorf("Got = %+v, want = %+v", got, want)
}
}
func TestNamePackUnpack(t *testing.T) {
tests := []struct {
in string
want string
err error
}{
{"", ".", nil},
{".", ".", nil},
{"google..com", "", errZeroSegLen},
{"google.com", "google.com.", nil},
{"google..com.", "", errZeroSegLen},
{"google.com.", "google.com.", nil},
{".google.com.", "", errZeroSegLen},
{"www..google.com.", "", errZeroSegLen},
{"www.google.com.", "www.google.com.", nil},
}
for _, test := range tests {
buf, err := packName(make([]byte, 0, 30), test.in, map[string]int{})
if err != test.err {
t.Errorf("Packing of %s: got err = %v, want err = %v", test.in, err, test.err)
continue
}
if test.err != nil {
continue
}
got, n, err := unpackName(buf, 0)
if err != nil {
t.Errorf("Unpacking for %s failed: %v", test.in, err)
continue
}
if n != len(buf) {
t.Errorf(
"Unpacked different amount than packed for %s: got n = %d, want = %d",
test.in,
n,
len(buf),
)
}
if got != test.want {
t.Errorf("Unpacking packing of %s: got = %s, want = %s", test.in, got, test.want)
}
}
}
func TestDNSPackUnpack(t *testing.T) {
wants := []Message{
{
Questions: []Question{
{
Name: ".",
Type: TypeAAAA,
Class: ClassINET,
},
},
Answers: []Resource{},
Authorities: []Resource{},
Additionals: []Resource{},
},
largeTestMsg(),
}
for i, want := range wants {
b, err := want.Pack()
if err != nil {
t.Fatalf("%d: packing failed: %v", i, err)
}
var got Message
err = got.Unpack(b)
if err != nil {
t.Fatalf("%d: unpacking failed: %v", i, err)
}
if !reflect.DeepEqual(got, want) {
t.Errorf("%d: got = %+v, want = %+v", i, &got, &want)
}
}
}
func TestSkipAll(t *testing.T) {
msg := largeTestMsg()
buf, err := msg.Pack()
if err != nil {
t.Fatal("Packing large test message:", err)
}
var p Parser
if _, err := p.Start(buf); err != nil {
t.Fatal(err)
}
tests := []struct {
name string
f func() error
}{
{"SkipAllQuestions", p.SkipAllQuestions},
{"SkipAllAnswers", p.SkipAllAnswers},
{"SkipAllAuthorities", p.SkipAllAuthorities},
{"SkipAllAdditionals", p.SkipAllAdditionals},
}
for _, test := range tests {
for i := 1; i <= 3; i++ {
if err := test.f(); err != nil {
t.Errorf("Call #%d to %s(): %v", i, test.name, err)
}
}
}
}
func TestSkipNotStarted(t *testing.T) {
var p Parser
tests := []struct {
name string
f func() error
}{
{"SkipAllQuestions", p.SkipAllQuestions},
{"SkipAllAnswers", p.SkipAllAnswers},
{"SkipAllAuthorities", p.SkipAllAuthorities},
{"SkipAllAdditionals", p.SkipAllAdditionals},
}
for _, test := range tests {
if err := test.f(); err != ErrNotStarted {
t.Errorf("Got %s() = %v, want = %v", test.name, err, ErrNotStarted)
}
}
}
func TestTooManyRecords(t *testing.T) {
const recs = int(^uint16(0)) + 1
tests := []struct {
name string
msg Message
want error
}{
{
"Questions",
Message{
Questions: make([]Question, recs),
},
errTooManyQuestions,
},
{
"Answers",
Message{
Answers: make([]Resource, recs),
},
errTooManyAnswers,
},
{
"Authorities",
Message{
Authorities: make([]Resource, recs),
},
errTooManyAuthorities,
},
{
"Additionals",
Message{
Additionals: make([]Resource, recs),
},
errTooManyAdditionals,
},
}
for _, test := range tests {
if _, got := test.msg.Pack(); got != test.want {
t.Errorf("Packing %d %s: got = %v, want = %v", recs, test.name, got, test.want)
}
}
}
func TestVeryLongTxt(t *testing.T) {
want := &TXTResource{
ResourceHeader: ResourceHeader{
Name: "foo.bar.example.com.",
Type: TypeTXT,
Class: ClassINET,
},
Txt: loremIpsum,
}
buf, err := packResource(make([]byte, 0, 8000), want, map[string]int{})
if err != nil {
t.Fatal("Packing failed:", err)
}
var hdr ResourceHeader
off, err := hdr.unpack(buf, 0)
if err != nil {
t.Fatal("Unpacking ResourceHeader failed:", err)
}
got, n, err := unpackResource(buf, off, hdr)
if err != nil {
t.Fatal("Unpacking failed:", err)
}
if n != len(buf) {
t.Errorf("Unpacked different amount than packed: got n = %d, want = %d", n, len(buf))
}
if !reflect.DeepEqual(got, want) {
t.Errorf("Got = %+v, want = %+v", got, want)
}
}
func ExampleHeaderSearch() {
msg := Message{
Header: Header{Response: true, Authoritative: true},
Questions: []Question{
{
Name: "foo.bar.example.com.",
Type: TypeA,
Class: ClassINET,
},
{
Name: "bar.example.com.",
Type: TypeA,
Class: ClassINET,
},
},
Answers: []Resource{
&AResource{
ResourceHeader: ResourceHeader{
Name: "foo.bar.example.com.",
Type: TypeA,
Class: ClassINET,
},
A: [4]byte{127, 0, 0, 1},
},
&AResource{
ResourceHeader: ResourceHeader{
Name: "bar.example.com.",
Type: TypeA,
Class: ClassINET,
},
A: [4]byte{127, 0, 0, 2},
},
},
}
buf, err := msg.Pack()
if err != nil {
panic(err)
}
wantName := "bar.example.com."
var p Parser
if _, err := p.Start(buf); err != nil {
panic(err)
}
for {
q, err := p.Question()
if err == ErrSectionDone {
break
}
if err != nil {
panic(err)
}
if q.Name != wantName {
continue
}
fmt.Println("Found question for name", wantName)
if err := p.SkipAllQuestions(); err != nil {
panic(err)
}
break
}
var gotIPs []net.IP
for {
h, err := p.AnswerHeader()
if err == ErrSectionDone {
break
}
if err != nil {
panic(err)
}
if (h.Type != TypeA && h.Type != TypeAAAA) || h.Class != ClassINET {
continue
}
if !strings.EqualFold(h.Name, wantName) {
if err := p.SkipAnswer(); err != nil {
panic(err)
}
continue
}
a, err := p.Answer()
if err != nil {
panic(err)
}
switch r := a.(type) {
default:
panic(fmt.Sprintf("unknown type: %T", r))
case *AResource:
gotIPs = append(gotIPs, r.A[:])
case *AAAAResource:
gotIPs = append(gotIPs, r.AAAA[:])
}
}
fmt.Printf("Found A/AAAA records for name %s: %v\n", wantName, gotIPs)
// Output:
// Found question for name bar.example.com.
// Found A/AAAA records for name bar.example.com.: [127.0.0.2]
}
func largeTestMsg() Message {
return Message{
Header: Header{Response: true, Authoritative: true},
Questions: []Question{
{
Name: "foo.bar.example.com.",
Type: TypeA,
Class: ClassINET,
},
},
Answers: []Resource{
&AResource{
ResourceHeader: ResourceHeader{
Name: "foo.bar.example.com.",
Type: TypeA,
Class: ClassINET,
},
A: [4]byte{127, 0, 0, 1},
},
&AResource{
ResourceHeader: ResourceHeader{
Name: "foo.bar.example.com.",
Type: TypeA,
Class: ClassINET,
},
A: [4]byte{127, 0, 0, 2},
},
},
Authorities: []Resource{
&NSResource{
ResourceHeader: ResourceHeader{
Name: "foo.bar.example.com.",
Type: TypeNS,
Class: ClassINET,
},
NS: "ns1.example.com.",
},
&NSResource{
ResourceHeader: ResourceHeader{
Name: "foo.bar.example.com.",
Type: TypeNS,
Class: ClassINET,
},
NS: "ns2.example.com.",
},
},
Additionals: []Resource{
&TXTResource{
ResourceHeader: ResourceHeader{
Name: "foo.bar.example.com.",
Type: TypeTXT,
Class: ClassINET,
},
Txt: "So Long, and Thanks for All the Fish",
},
&TXTResource{
ResourceHeader: ResourceHeader{
Name: "foo.bar.example.com.",
Type: TypeTXT,
Class: ClassINET,
},
Txt: "Hamster Huey and the Gooey Kablooie",
},
},
}
}
const loremIpsum = `
Lorem ipsum dolor sit amet, nec enim antiopam id, an ullum choro
nonumes qui, pro eu debet honestatis mediocritatem. No alia enim eos,
magna signiferumque ex vis. Mei no aperiri dissentias, cu vel quas
regione. Malorum quaeque vim ut, eum cu semper aliquid invidunt, ei
nam ipsum assentior.
Nostrum appellantur usu no, vis ex probatus adipiscing. Cu usu illum
facilis eleifend. Iusto conceptam complectitur vim id. Tale omnesque
no usu, ei oblique sadipscing vim. At nullam voluptua usu, mei laudem
reformidans et. Qui ei eros porro reformidans, ius suas veritus
torquatos ex. Mea te facer alterum consequat.
Soleat torquatos democritum sed et, no mea congue appareat, facer
aliquam nec in. Has te ipsum tritani. At justo dicta option nec, movet
phaedrum ad nam. Ea detracto verterem liberavisse has, delectus
suscipiantur in mei. Ex nam meliore complectitur. Ut nam omnis
honestatis quaerendum, ea mea nihil affert detracto, ad vix rebum
mollis.
Ut epicurei praesent neglegentur pri, prima fuisset intellegebat ad
vim. An habemus comprehensam usu, at enim dignissim pro. Eam reque
vivendum adipisci ea. Vel ne odio choro minimum. Sea admodum
dissentiet ex. Mundi tamquam evertitur ius cu. Homero postea iisque ut
pro, vel ne saepe senserit consetetur.
Nulla utamur facilisis ius ea, in viderer diceret pertinax eum. Mei no
enim quodsi facilisi, ex sed aeterno appareat mediocritatem, eum
sententiae deterruisset ut. At suas timeam euismod cum, offendit
appareat interpretaris ne vix. Vel ea civibus albucius, ex vim quidam
accusata intellegebat, noluisse instructior sea id. Nec te nonumes
habemus appellantur, quis dignissim vituperata eu nam.
At vix apeirian patrioque vituperatoribus, an usu agam assum. Debet
iisque an mea. Per eu dicant ponderum accommodare. Pri alienum
placerat senserit an, ne eum ferri abhorreant vituperatoribus. Ut mea
eligendi disputationi. Ius no tation everti impedit, ei magna quidam
mediocritatem pri.
Legendos perpetua iracundia ne usu, no ius ullum epicurei intellegam,
ad modus epicuri lucilius eam. In unum quaerendum usu. Ne diam paulo
has, ea veri virtute sed. Alia honestatis conclusionemque mea eu, ut
iudico albucius his.
Usu essent probatus eu, sed omnis dolor delicatissimi ex. No qui augue
dissentias dissentiet. Laudem recteque no usu, vel an velit noluisse,
an sed utinam eirmod appetere. Ne mea fuisset inimicus ocurreret. At
vis dicant abhorreant, utinam forensibus nec ne, mei te docendi
consequat. Brute inermis persecuti cum id. Ut ipsum munere propriae
usu, dicit graeco disputando id has.
Eros dolore quaerendum nam ei. Timeam ornatus inciderint pro id. Nec
torquatos sadipscing ei, ancillae molestie per in. Malis principes duo
ea, usu liber postulant ei.
Graece timeam voluptatibus eu eam. Alia probatus quo no, ea scripta
feugiat duo. Congue option meliore ex qui, noster invenire appellantur
ea vel. Eu exerci legendos vel. Consetetur repudiandae vim ut. Vix an
probo minimum, et nam illud falli tempor.
Cum dico signiferumque eu. Sed ut regione maiorum, id veritus insolens
tacimates vix. Eu mel sint tamquam lucilius, duo no oporteat
tacimates. Atqui augue concludaturque vix ei, id mel utroque menandri.
Ad oratio blandit aliquando pro. Vis et dolorum rationibus
philosophia, ad cum nulla molestie. Hinc fuisset adversarium eum et,
ne qui nisl verear saperet, vel te quaestio forensibus. Per odio
option delenit an. Alii placerat has no, in pri nihil platonem
cotidieque. Est ut elit copiosae scaevola, debet tollit maluisset sea
an.
Te sea hinc debet pericula, liber ridens fabulas cu sed, quem mutat
accusam mea et. Elitr labitur albucius et pri, an labore feugait mel.
Velit zril melius usu ea. Ad stet putent interpretaris qui. Mel no
error volumus scripserit. In pro paulo iudico, quo ei dolorem
verterem, affert fabellas dissentiet ea vix.
Vis quot deserunt te. Error aliquid detraxit eu usu, vis alia eruditi
salutatus cu. Est nostrud bonorum an, ei usu alii salutatus. Vel at
nisl primis, eum ex aperiri noluisse reformidans. Ad veri velit
utroque vis, ex equidem detraxit temporibus has.
Inermis appareat usu ne. Eros placerat periculis mea ad, in dictas
pericula pro. Errem postulant at usu, ea nec amet ornatus mentitum. Ad
mazim graeco eum, vel ex percipit volutpat iudicabit, sit ne delicata
interesset. Mel sapientem prodesset abhorreant et, oblique suscipit
eam id.
An maluisset disputando mea, vidit mnesarchum pri et. Malis insolens
inciderint no sea. Ea persius maluisset vix, ne vim appellantur
instructior, consul quidam definiebas pri id. Cum integre feugiat
pericula in, ex sed persius similique, mel ne natum dicit percipitur.
Primis discere ne pri, errem putent definitionem at vis. Ei mel dolore
neglegentur, mei tincidunt percipitur ei. Pro ad simul integre
rationibus. Eu vel alii honestatis definitiones, mea no nonumy
reprehendunt.
Dicta appareat legendos est cu. Eu vel congue dicunt omittam, no vix
adhuc minimum constituam, quot noluisse id mel. Eu quot sale mutat
duo, ex nisl munere invenire duo. Ne nec ullum utamur. Pro alterum
debitis nostrum no, ut vel aliquid vivendo.
Aliquip fierent praesent quo ne, id sit audiam recusabo delicatissimi.
Usu postulant incorrupte cu. At pro dicit tibique intellegam, cibo
dolore impedit id eam, et aeque feugait assentior has. Quando sensibus
nec ex. Possit sensibus pri ad, unum mutat periculis cu vix.
Mundi tibique vix te, duo simul partiendo qualisque id, est at vidit
sonet tempor. No per solet aeterno deseruisse. Petentium salutandi
definiebas pri cu. Munere vivendum est in. Ei justo congue eligendi
vis, modus offendit omittantur te mel.
Integre voluptaria in qui, sit habemus tractatos constituam no. Utinam
melius conceptam est ne, quo in minimum apeirian delicata, ut ius
porro recusabo. Dicant expetenda vix no, ludus scripserit sed ex, eu
his modo nostro. Ut etiam sonet his, quodsi inciderint philosophia te
per. Nullam lobortis eu cum, vix an sonet efficiendi repudiandae. Vis
ad idque fabellas intellegebat.
Eum commodo senserit conclusionemque ex. Sed forensibus sadipscing ut,
mei in facer delicata periculis, sea ne hinc putent cetero. Nec ne
alia corpora invenire, alia prima soleat te cum. Eleifend posidonium
nam at.
Dolorum indoctum cu quo, ex dolor legendos recteque eam, cu pri zril
discere. Nec civibus officiis dissentiunt ex, est te liber ludus
elaboraret. Cum ea fabellas invenire. Ex vim nostrud eripuit
comprehensam, nam te inermis delectus, saepe inermis senserit.
`

2
vendor/golang.org/x/net/http2/client_conn_pool.go сгенерированный поставляемый
Просмотреть файл

@@ -247,7 +247,7 @@ func filterOutClientConn(in []*ClientConn, exclude *ClientConn) []*ClientConn {
}
// noDialClientConnPool is an implementation of http2.ClientConnPool
// which never dials. We let the HTTP/1.1 client dial and use its TLS
// which never dials. We let the HTTP/1.1 client dial and use its TLS
// connection instead.
type noDialClientConnPool struct{ *clientConnPool }

146
vendor/golang.org/x/net/http2/databuffer.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,146 @@
// Copyright 2014 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 http2
import (
"errors"
"fmt"
"sync"
)
// Buffer chunks are allocated from a pool to reduce pressure on GC.
// The maximum wasted space per dataBuffer is 2x the largest size class,
// which happens when the dataBuffer has multiple chunks and there is
// one unread byte in both the first and last chunks. We use a few size
// classes to minimize overheads for servers that typically receive very
// small request bodies.
//
// TODO: Benchmark to determine if the pools are necessary. The GC may have
// improved enough that we can instead allocate chunks like this:
// make([]byte, max(16<<10, expectedBytesRemaining))
var (
dataChunkSizeClasses = []int{
1 << 10,
2 << 10,
4 << 10,
8 << 10,
16 << 10,
}
dataChunkPools = [...]sync.Pool{
{New: func() interface{} { return make([]byte, 1<<10) }},
{New: func() interface{} { return make([]byte, 2<<10) }},
{New: func() interface{} { return make([]byte, 4<<10) }},
{New: func() interface{} { return make([]byte, 8<<10) }},
{New: func() interface{} { return make([]byte, 16<<10) }},
}
)
func getDataBufferChunk(size int64) []byte {
i := 0
for ; i < len(dataChunkSizeClasses)-1; i++ {
if size <= int64(dataChunkSizeClasses[i]) {
break
}
}
return dataChunkPools[i].Get().([]byte)
}
func putDataBufferChunk(p []byte) {
for i, n := range dataChunkSizeClasses {
if len(p) == n {
dataChunkPools[i].Put(p)
return
}
}
panic(fmt.Sprintf("unexpected buffer len=%v", len(p)))
}
// dataBuffer is an io.ReadWriter backed by a list of data chunks.
// Each dataBuffer is used to read DATA frames on a single stream.
// The buffer is divided into chunks so the server can limit the
// total memory used by a single connection without limiting the
// request body size on any single stream.
type dataBuffer struct {
chunks [][]byte
r int // next byte to read is chunks[0][r]
w int // next byte to write is chunks[len(chunks)-1][w]
size int // total buffered bytes
expected int64 // we expect at least this many bytes in future Write calls (ignored if <= 0)
}
var errReadEmpty = errors.New("read from empty dataBuffer")
// Read copies bytes from the buffer into p.
// It is an error to read when no data is available.
func (b *dataBuffer) Read(p []byte) (int, error) {
if b.size == 0 {
return 0, errReadEmpty
}
var ntotal int
for len(p) > 0 && b.size > 0 {
readFrom := b.bytesFromFirstChunk()
n := copy(p, readFrom)
p = p[n:]
ntotal += n
b.r += n
b.size -= n
// If the first chunk has been consumed, advance to the next chunk.
if b.r == len(b.chunks[0]) {
putDataBufferChunk(b.chunks[0])
end := len(b.chunks) - 1
copy(b.chunks[:end], b.chunks[1:])
b.chunks[end] = nil
b.chunks = b.chunks[:end]
b.r = 0
}
}
return ntotal, nil
}
func (b *dataBuffer) bytesFromFirstChunk() []byte {
if len(b.chunks) == 1 {
return b.chunks[0][b.r:b.w]
}
return b.chunks[0][b.r:]
}
// Len returns the number of bytes of the unread portion of the buffer.
func (b *dataBuffer) Len() int {
return b.size
}
// Write appends p to the buffer.
func (b *dataBuffer) Write(p []byte) (int, error) {
ntotal := len(p)
for len(p) > 0 {
// If the last chunk is empty, allocate a new chunk. Try to allocate
// enough to fully copy p plus any additional bytes we expect to
// receive. However, this may allocate less than len(p).
want := int64(len(p))
if b.expected > want {
want = b.expected
}
chunk := b.lastChunkOrAlloc(want)
n := copy(chunk[b.w:], p)
p = p[n:]
b.w += n
b.size += n
b.expected -= int64(n)
}
return ntotal, nil
}
func (b *dataBuffer) lastChunkOrAlloc(want int64) []byte {
if len(b.chunks) != 0 {
last := b.chunks[len(b.chunks)-1]
if b.w < len(last) {
return last
}
}
chunk := getDataBufferChunk(want)
b.chunks = append(b.chunks, chunk)
b.w = 0
return chunk
}

155
vendor/golang.org/x/net/http2/databuffer_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,155 @@
// 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 http2
import (
"bytes"
"fmt"
"reflect"
"testing"
)
func fmtDataChunk(chunk []byte) string {
out := ""
var last byte
var count int
for _, c := range chunk {
if c != last {
if count > 0 {
out += fmt.Sprintf(" x %d ", count)
count = 0
}
out += string([]byte{c})
last = c
}
count++
}
if count > 0 {
out += fmt.Sprintf(" x %d", count)
}
return out
}
func fmtDataChunks(chunks [][]byte) string {
var out string
for _, chunk := range chunks {
out += fmt.Sprintf("{%q}", fmtDataChunk(chunk))
}
return out
}
func testDataBuffer(t *testing.T, wantBytes []byte, setup func(t *testing.T) *dataBuffer) {
// Run setup, then read the remaining bytes from the dataBuffer and check
// that they match wantBytes. We use different read sizes to check corner
// cases in Read.
for _, readSize := range []int{1, 2, 1 * 1024, 32 * 1024} {
t.Run(fmt.Sprintf("ReadSize=%d", readSize), func(t *testing.T) {
b := setup(t)
buf := make([]byte, readSize)
var gotRead bytes.Buffer
for {
n, err := b.Read(buf)
gotRead.Write(buf[:n])
if err == errReadEmpty {
break
}
if err != nil {
t.Fatalf("error after %v bytes: %v", gotRead.Len(), err)
}
}
if got, want := gotRead.Bytes(), wantBytes; !bytes.Equal(got, want) {
t.Errorf("FinalRead=%q, want %q", fmtDataChunk(got), fmtDataChunk(want))
}
})
}
}
func TestDataBufferAllocation(t *testing.T) {
writes := [][]byte{
bytes.Repeat([]byte("a"), 1*1024-1),
[]byte{'a'},
bytes.Repeat([]byte("b"), 4*1024-1),
[]byte{'b'},
bytes.Repeat([]byte("c"), 8*1024-1),
[]byte{'c'},
bytes.Repeat([]byte("d"), 16*1024-1),
[]byte{'d'},
bytes.Repeat([]byte("e"), 32*1024),
}
var wantRead bytes.Buffer
for _, p := range writes {
wantRead.Write(p)
}
testDataBuffer(t, wantRead.Bytes(), func(t *testing.T) *dataBuffer {
b := &dataBuffer{}
for _, p := range writes {
if n, err := b.Write(p); n != len(p) || err != nil {
t.Fatalf("Write(%q x %d)=%v,%v want %v,nil", p[:1], len(p), n, err, len(p))
}
}
want := [][]byte{
bytes.Repeat([]byte("a"), 1*1024),
bytes.Repeat([]byte("b"), 4*1024),
bytes.Repeat([]byte("c"), 8*1024),
bytes.Repeat([]byte("d"), 16*1024),
bytes.Repeat([]byte("e"), 16*1024),
bytes.Repeat([]byte("e"), 16*1024),
}
if !reflect.DeepEqual(b.chunks, want) {
t.Errorf("dataBuffer.chunks\ngot: %s\nwant: %s", fmtDataChunks(b.chunks), fmtDataChunks(want))
}
return b
})
}
func TestDataBufferAllocationWithExpected(t *testing.T) {
writes := [][]byte{
bytes.Repeat([]byte("a"), 1*1024), // allocates 16KB
bytes.Repeat([]byte("b"), 14*1024),
bytes.Repeat([]byte("c"), 15*1024), // allocates 16KB more
bytes.Repeat([]byte("d"), 2*1024),
bytes.Repeat([]byte("e"), 1*1024), // overflows 32KB expectation, allocates just 1KB
}
var wantRead bytes.Buffer
for _, p := range writes {
wantRead.Write(p)
}
testDataBuffer(t, wantRead.Bytes(), func(t *testing.T) *dataBuffer {
b := &dataBuffer{expected: 32 * 1024}
for _, p := range writes {
if n, err := b.Write(p); n != len(p) || err != nil {
t.Fatalf("Write(%q x %d)=%v,%v want %v,nil", p[:1], len(p), n, err, len(p))
}
}
want := [][]byte{
append(bytes.Repeat([]byte("a"), 1*1024), append(bytes.Repeat([]byte("b"), 14*1024), bytes.Repeat([]byte("c"), 1*1024)...)...),
append(bytes.Repeat([]byte("c"), 14*1024), bytes.Repeat([]byte("d"), 2*1024)...),
bytes.Repeat([]byte("e"), 1*1024),
}
if !reflect.DeepEqual(b.chunks, want) {
t.Errorf("dataBuffer.chunks\ngot: %s\nwant: %s", fmtDataChunks(b.chunks), fmtDataChunks(want))
}
return b
})
}
func TestDataBufferWriteAfterPartialRead(t *testing.T) {
testDataBuffer(t, []byte("cdxyz"), func(t *testing.T) *dataBuffer {
b := &dataBuffer{}
if n, err := b.Write([]byte("abcd")); n != 4 || err != nil {
t.Fatalf("Write(\"abcd\")=%v,%v want 4,nil", n, err)
}
p := make([]byte, 2)
if n, err := b.Read(p); n != 2 || err != nil || !bytes.Equal(p, []byte("ab")) {
t.Fatalf("Read()=%q,%v,%v want \"ab\",2,nil", p, n, err)
}
if n, err := b.Write([]byte("xyz")); n != 3 || err != nil {
t.Fatalf("Write(\"xyz\")=%v,%v want 3,nil", n, err)
}
return b
})
}

60
vendor/golang.org/x/net/http2/fixed_buffer.go сгенерированный поставляемый
Просмотреть файл

@@ -1,60 +0,0 @@
// Copyright 2014 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 http2
import (
"errors"
)
// fixedBuffer is an io.ReadWriter backed by a fixed size buffer.
// It never allocates, but moves old data as new data is written.
type fixedBuffer struct {
buf []byte
r, w int
}
var (
errReadEmpty = errors.New("read from empty fixedBuffer")
errWriteFull = errors.New("write on full fixedBuffer")
)
// Read copies bytes from the buffer into p.
// It is an error to read when no data is available.
func (b *fixedBuffer) Read(p []byte) (n int, err error) {
if b.r == b.w {
return 0, errReadEmpty
}
n = copy(p, b.buf[b.r:b.w])
b.r += n
if b.r == b.w {
b.r = 0
b.w = 0
}
return n, nil
}
// Len returns the number of bytes of the unread portion of the buffer.
func (b *fixedBuffer) Len() int {
return b.w - b.r
}
// Write copies bytes from p into the buffer.
// It is an error to write more data than the buffer can hold.
func (b *fixedBuffer) Write(p []byte) (n int, err error) {
// Slide existing data to beginning.
if b.r > 0 && len(p) > len(b.buf)-b.w {
copy(b.buf, b.buf[b.r:b.w])
b.w -= b.r
b.r = 0
}
// Write new data.
n = copy(b.buf[b.w:], p)
b.w += n
if n < len(p) {
err = errWriteFull
}
return n, err
}

128
vendor/golang.org/x/net/http2/fixed_buffer_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,128 +0,0 @@
// Copyright 2014 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 http2
import (
"reflect"
"testing"
)
var bufferReadTests = []struct {
buf fixedBuffer
read, wn int
werr error
wp []byte
wbuf fixedBuffer
}{
{
fixedBuffer{[]byte{'a', 0}, 0, 1},
5, 1, nil, []byte{'a'},
fixedBuffer{[]byte{'a', 0}, 0, 0},
},
{
fixedBuffer{[]byte{0, 'a'}, 1, 2},
5, 1, nil, []byte{'a'},
fixedBuffer{[]byte{0, 'a'}, 0, 0},
},
{
fixedBuffer{[]byte{'a', 'b'}, 0, 2},
1, 1, nil, []byte{'a'},
fixedBuffer{[]byte{'a', 'b'}, 1, 2},
},
{
fixedBuffer{[]byte{}, 0, 0},
5, 0, errReadEmpty, []byte{},
fixedBuffer{[]byte{}, 0, 0},
},
}
func TestBufferRead(t *testing.T) {
for i, tt := range bufferReadTests {
read := make([]byte, tt.read)
n, err := tt.buf.Read(read)
if n != tt.wn {
t.Errorf("#%d: wn = %d want %d", i, n, tt.wn)
continue
}
if err != tt.werr {
t.Errorf("#%d: werr = %v want %v", i, err, tt.werr)
continue
}
read = read[:n]
if !reflect.DeepEqual(read, tt.wp) {
t.Errorf("#%d: read = %+v want %+v", i, read, tt.wp)
}
if !reflect.DeepEqual(tt.buf, tt.wbuf) {
t.Errorf("#%d: buf = %+v want %+v", i, tt.buf, tt.wbuf)
}
}
}
var bufferWriteTests = []struct {
buf fixedBuffer
write, wn int
werr error
wbuf fixedBuffer
}{
{
buf: fixedBuffer{
buf: []byte{},
},
wbuf: fixedBuffer{
buf: []byte{},
},
},
{
buf: fixedBuffer{
buf: []byte{1, 'a'},
},
write: 1,
wn: 1,
wbuf: fixedBuffer{
buf: []byte{0, 'a'},
w: 1,
},
},
{
buf: fixedBuffer{
buf: []byte{'a', 1},
r: 1,
w: 1,
},
write: 2,
wn: 2,
wbuf: fixedBuffer{
buf: []byte{0, 0},
w: 2,
},
},
{
buf: fixedBuffer{
buf: []byte{},
},
write: 5,
werr: errWriteFull,
wbuf: fixedBuffer{
buf: []byte{},
},
},
}
func TestBufferWrite(t *testing.T) {
for i, tt := range bufferWriteTests {
n, err := tt.buf.Write(make([]byte, tt.write))
if n != tt.wn {
t.Errorf("#%d: wrote %d bytes; want %d", i, n, tt.wn)
continue
}
if err != tt.werr {
t.Errorf("#%d: error = %v; want %v", i, err, tt.werr)
continue
}
if !reflect.DeepEqual(tt.buf, tt.wbuf) {
t.Errorf("#%d: buf = %+v; want %+v", i, tt.buf, tt.wbuf)
}
}
}

81
vendor/golang.org/x/net/http2/frame.go сгенерированный поставляемый
Просмотреть файл

@@ -122,7 +122,7 @@ var flagName = map[FrameType]map[Flags]string{
// a frameParser parses a frame given its FrameHeader and payload
// bytes. The length of payload will always equal fh.Length (which
// might be 0).
type frameParser func(fh FrameHeader, payload []byte) (Frame, error)
type frameParser func(fc *frameCache, fh FrameHeader, payload []byte) (Frame, error)
var frameParsers = map[FrameType]frameParser{
FrameData: parseDataFrame,
@@ -312,7 +312,7 @@ type Framer struct {
MaxHeaderListSize uint32
// TODO: track which type of frame & with which flags was sent
// last. Then return an error (unless AllowIllegalWrites) if
// last. Then return an error (unless AllowIllegalWrites) if
// we're in the middle of a header block and a
// non-Continuation or Continuation on a different stream is
// attempted to be written.
@@ -323,6 +323,8 @@ type Framer struct {
debugFramerBuf *bytes.Buffer
debugReadLoggerf func(string, ...interface{})
debugWriteLoggerf func(string, ...interface{})
frameCache *frameCache // nil if frames aren't reused (default)
}
func (fr *Framer) maxHeaderListSize() uint32 {
@@ -398,6 +400,27 @@ const (
maxFrameSize = 1<<24 - 1
)
// SetReuseFrames allows the Framer to reuse Frames.
// If called on a Framer, Frames returned by calls to ReadFrame are only
// valid until the next call to ReadFrame.
func (fr *Framer) SetReuseFrames() {
if fr.frameCache != nil {
return
}
fr.frameCache = &frameCache{}
}
type frameCache struct {
dataFrame DataFrame
}
func (fc *frameCache) getDataFrame() *DataFrame {
if fc == nil {
return &DataFrame{}
}
return &fc.dataFrame
}
// NewFramer returns a Framer that writes frames to w and reads them from r.
func NewFramer(w io.Writer, r io.Reader) *Framer {
fr := &Framer{
@@ -477,7 +500,7 @@ func (fr *Framer) ReadFrame() (Frame, error) {
if _, err := io.ReadFull(fr.r, payload); err != nil {
return nil, err
}
f, err := typeFrameParser(fh.Type)(fh, payload)
f, err := typeFrameParser(fh.Type)(fr.frameCache, fh, payload)
if err != nil {
if ce, ok := err.(connError); ok {
return nil, fr.connError(ce.Code, ce.Reason)
@@ -565,7 +588,7 @@ func (f *DataFrame) Data() []byte {
return f.data
}
func parseDataFrame(fh FrameHeader, payload []byte) (Frame, error) {
func parseDataFrame(fc *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
if fh.StreamID == 0 {
// DATA frames MUST be associated with a stream. If a
// DATA frame is received whose stream identifier
@@ -574,9 +597,9 @@ func parseDataFrame(fh FrameHeader, payload []byte) (Frame, error) {
// PROTOCOL_ERROR.
return nil, connError{ErrCodeProtocol, "DATA frame with stream ID 0"}
}
f := &DataFrame{
FrameHeader: fh,
}
f := fc.getDataFrame()
f.FrameHeader = fh
var padSize byte
if fh.Flags.Has(FlagDataPadded) {
var err error
@@ -600,6 +623,7 @@ var (
errStreamID = errors.New("invalid stream ID")
errDepStreamID = errors.New("invalid dependent stream ID")
errPadLength = errors.New("pad length too large")
errPadBytes = errors.New("padding bytes must all be zeros unless AllowIllegalWrites is enabled")
)
func validStreamIDOrZero(streamID uint32) bool {
@@ -623,6 +647,7 @@ func (f *Framer) WriteData(streamID uint32, endStream bool, data []byte) error {
//
// If pad is nil, the padding bit is not sent.
// The length of pad must not exceed 255 bytes.
// The bytes of pad must all be zero, unless f.AllowIllegalWrites is set.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility not to violate the maximum frame size
@@ -631,8 +656,18 @@ func (f *Framer) WriteDataPadded(streamID uint32, endStream bool, data, pad []by
if !validStreamID(streamID) && !f.AllowIllegalWrites {
return errStreamID
}
if len(pad) > 255 {
return errPadLength
if len(pad) > 0 {
if len(pad) > 255 {
return errPadLength
}
if !f.AllowIllegalWrites {
for _, b := range pad {
if b != 0 {
// "Padding octets MUST be set to zero when sending."
return errPadBytes
}
}
}
}
var flags Flags
if endStream {
@@ -660,10 +695,10 @@ type SettingsFrame struct {
p []byte
}
func parseSettingsFrame(fh FrameHeader, p []byte) (Frame, error) {
func parseSettingsFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
if fh.Flags.Has(FlagSettingsAck) && fh.Length > 0 {
// When this (ACK 0x1) bit is set, the payload of the
// SETTINGS frame MUST be empty. Receipt of a
// SETTINGS frame MUST be empty. Receipt of a
// SETTINGS frame with the ACK flag set and a length
// field value other than 0 MUST be treated as a
// connection error (Section 5.4.1) of type
@@ -672,7 +707,7 @@ func parseSettingsFrame(fh FrameHeader, p []byte) (Frame, error) {
}
if fh.StreamID != 0 {
// SETTINGS frames always apply to a connection,
// never a single stream. The stream identifier for a
// never a single stream. The stream identifier for a
// SETTINGS frame MUST be zero (0x0). If an endpoint
// receives a SETTINGS frame whose stream identifier
// field is anything other than 0x0, the endpoint MUST
@@ -762,7 +797,7 @@ type PingFrame struct {
func (f *PingFrame) IsAck() bool { return f.Flags.Has(FlagPingAck) }
func parsePingFrame(fh FrameHeader, payload []byte) (Frame, error) {
func parsePingFrame(_ *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
if len(payload) != 8 {
return nil, ConnectionError(ErrCodeFrameSize)
}
@@ -802,7 +837,7 @@ func (f *GoAwayFrame) DebugData() []byte {
return f.debugData
}
func parseGoAwayFrame(fh FrameHeader, p []byte) (Frame, error) {
func parseGoAwayFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
if fh.StreamID != 0 {
return nil, ConnectionError(ErrCodeProtocol)
}
@@ -842,7 +877,7 @@ func (f *UnknownFrame) Payload() []byte {
return f.p
}
func parseUnknownFrame(fh FrameHeader, p []byte) (Frame, error) {
func parseUnknownFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
return &UnknownFrame{fh, p}, nil
}
@@ -853,7 +888,7 @@ type WindowUpdateFrame struct {
Increment uint32 // never read with high bit set
}
func parseWindowUpdateFrame(fh FrameHeader, p []byte) (Frame, error) {
func parseWindowUpdateFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
if len(p) != 4 {
return nil, ConnectionError(ErrCodeFrameSize)
}
@@ -918,12 +953,12 @@ func (f *HeadersFrame) HasPriority() bool {
return f.FrameHeader.Flags.Has(FlagHeadersPriority)
}
func parseHeadersFrame(fh FrameHeader, p []byte) (_ Frame, err error) {
func parseHeadersFrame(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err error) {
hf := &HeadersFrame{
FrameHeader: fh,
}
if fh.StreamID == 0 {
// HEADERS frames MUST be associated with a stream. If a HEADERS frame
// HEADERS frames MUST be associated with a stream. If a HEADERS frame
// is received whose stream identifier field is 0x0, the recipient MUST
// respond with a connection error (Section 5.4.1) of type
// PROTOCOL_ERROR.
@@ -1045,7 +1080,7 @@ type PriorityParam struct {
Exclusive bool
// Weight is the stream's zero-indexed weight. It should be
// set together with StreamDep, or neither should be set. Per
// set together with StreamDep, or neither should be set. Per
// the spec, "Add one to the value to obtain a weight between
// 1 and 256."
Weight uint8
@@ -1055,7 +1090,7 @@ func (p PriorityParam) IsZero() bool {
return p == PriorityParam{}
}
func parsePriorityFrame(fh FrameHeader, payload []byte) (Frame, error) {
func parsePriorityFrame(_ *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
if fh.StreamID == 0 {
return nil, connError{ErrCodeProtocol, "PRIORITY frame with stream ID 0"}
}
@@ -1102,7 +1137,7 @@ type RSTStreamFrame struct {
ErrCode ErrCode
}
func parseRSTStreamFrame(fh FrameHeader, p []byte) (Frame, error) {
func parseRSTStreamFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
if len(p) != 4 {
return nil, ConnectionError(ErrCodeFrameSize)
}
@@ -1132,7 +1167,7 @@ type ContinuationFrame struct {
headerFragBuf []byte
}
func parseContinuationFrame(fh FrameHeader, p []byte) (Frame, error) {
func parseContinuationFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
if fh.StreamID == 0 {
return nil, connError{ErrCodeProtocol, "CONTINUATION frame with stream ID 0"}
}
@@ -1182,7 +1217,7 @@ func (f *PushPromiseFrame) HeadersEnded() bool {
return f.FrameHeader.Flags.Has(FlagPushPromiseEndHeaders)
}
func parsePushPromise(fh FrameHeader, p []byte) (_ Frame, err error) {
func parsePushPromise(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err error) {
pp := &PushPromiseFrame{
FrameHeader: fh,
}

91
vendor/golang.org/x/net/http2/frame_test.go сгенерированный поставляемый
Просмотреть файл

@@ -141,7 +141,7 @@ func TestWriteDataPadded(t *testing.T) {
streamID: 1,
endStream: false,
data: []byte("foo"),
pad: []byte("bar"),
pad: []byte{0, 0, 0},
wantHeader: FrameHeader{
Type: FrameData,
Flags: FlagDataPadded,
@@ -1096,6 +1096,95 @@ func TestMetaFrameHeader(t *testing.T) {
}
}
func TestSetReuseFrames(t *testing.T) {
fr, buf := testFramer()
fr.SetReuseFrames()
// Check that DataFrames are reused. Note that
// SetReuseFrames only currently implements reuse of DataFrames.
firstDf := readAndVerifyDataFrame("ABC", 3, fr, buf, t)
for i := 0; i < 10; i++ {
df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
if df != firstDf {
t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
}
}
for i := 0; i < 10; i++ {
df := readAndVerifyDataFrame("", 0, fr, buf, t)
if df != firstDf {
t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
}
}
for i := 0; i < 10; i++ {
df := readAndVerifyDataFrame("HHH", 3, fr, buf, t)
if df != firstDf {
t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
}
}
}
func TestSetReuseFramesMoreThanOnce(t *testing.T) {
fr, buf := testFramer()
fr.SetReuseFrames()
firstDf := readAndVerifyDataFrame("ABC", 3, fr, buf, t)
fr.SetReuseFrames()
for i := 0; i < 10; i++ {
df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
// SetReuseFrames should be idempotent
fr.SetReuseFrames()
if df != firstDf {
t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
}
}
}
func TestNoSetReuseFrames(t *testing.T) {
fr, buf := testFramer()
const numNewDataFrames = 10
dfSoFar := make([]interface{}, numNewDataFrames)
// Check that DataFrames are not reused if SetReuseFrames wasn't called.
// SetReuseFrames only currently implements reuse of DataFrames.
for i := 0; i < numNewDataFrames; i++ {
df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
for _, item := range dfSoFar {
if df == item {
t.Errorf("Expected Framer to return new DataFrames since SetNoReuseFrames not set.")
}
}
dfSoFar[i] = df
}
}
func readAndVerifyDataFrame(data string, length byte, fr *Framer, buf *bytes.Buffer, t *testing.T) *DataFrame {
var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4
fr.WriteData(streamID, true, []byte(data))
wantEnc := "\x00\x00" + string(length) + "\x00\x01\x01\x02\x03\x04" + data
if buf.String() != wantEnc {
t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
}
f, err := fr.ReadFrame()
if err != nil {
t.Fatal(err)
}
df, ok := f.(*DataFrame)
if !ok {
t.Fatalf("got %T; want *DataFrame", f)
}
if !bytes.Equal(df.Data(), []byte(data)) {
t.Errorf("got %q; want %q", df.Data(), []byte(data))
}
if f.Header().Flags&1 == 0 {
t.Errorf("didn't see END_STREAM flag")
}
return df
}
func encodeHeaderRaw(t *testing.T, pairs ...string) []byte {
var he hpackEncoder
return he.encodeHeaderRaw(t, pairs...)

6
vendor/golang.org/x/net/http2/go18.go сгенерированный поставляемый
Просмотреть файл

@@ -12,7 +12,11 @@ import (
"net/http"
)
func cloneTLSConfig(c *tls.Config) *tls.Config { return c.Clone() }
func cloneTLSConfig(c *tls.Config) *tls.Config {
c2 := c.Clone()
c2.GetClientCertificate = c.GetClientCertificate // golang.org/issue/19264
return c2
}
var _ http.Pusher = (*responseWriter)(nil)

13
vendor/golang.org/x/net/http2/go18_test.go сгенерированный поставляемый
Просмотреть файл

@@ -7,6 +7,7 @@
package http2
import (
"crypto/tls"
"net/http"
"testing"
"time"
@@ -64,3 +65,15 @@ func TestConfigureServerIdleTimeout_Go18(t *testing.T) {
}
}
}
func TestCertClone(t *testing.T) {
c := &tls.Config{
GetClientCertificate: func(*tls.CertificateRequestInfo) (*tls.Certificate, error) {
panic("shouldn't be called")
},
}
c2 := cloneTLSConfig(c)
if c2.GetClientCertificate == nil {
t.Error("GetClientCertificate is nil")
}
}

29
vendor/golang.org/x/net/http2/hpack/encode.go сгенерированный поставляемый
Просмотреть файл

@@ -39,13 +39,14 @@ func NewEncoder(w io.Writer) *Encoder {
tableSizeUpdate: false,
w: w,
}
e.dynTab.table.init()
e.dynTab.setMaxSize(initialHeaderTableSize)
return e
}
// WriteField encodes f into a single Write to e's underlying Writer.
// This function may also produce bytes for "Header Table Size Update"
// if necessary. If produced, it is done before encoding f.
// if necessary. If produced, it is done before encoding f.
func (e *Encoder) WriteField(f HeaderField) error {
e.buf = e.buf[:0]
@@ -88,29 +89,17 @@ func (e *Encoder) WriteField(f HeaderField) error {
// only name matches, i points to that index and nameValueMatch
// becomes false.
func (e *Encoder) searchTable(f HeaderField) (i uint64, nameValueMatch bool) {
for idx, hf := range staticTable {
if !constantTimeStringCompare(hf.Name, f.Name) {
continue
}
if i == 0 {
i = uint64(idx + 1)
}
if f.Sensitive {
continue
}
if !constantTimeStringCompare(hf.Value, f.Value) {
continue
}
i = uint64(idx + 1)
nameValueMatch = true
return
i, nameValueMatch = staticTable.search(f)
if nameValueMatch {
return i, true
}
j, nameValueMatch := e.dynTab.search(f)
j, nameValueMatch := e.dynTab.table.search(f)
if nameValueMatch || (i == 0 && j != 0) {
i = j + uint64(len(staticTable))
return j + uint64(staticTable.len()), nameValueMatch
}
return
return i, false
}
// SetMaxDynamicTableSize changes the dynamic header table size to v.

70
vendor/golang.org/x/net/http2/hpack/encode_test.go сгенерированный поставляемый
Просмотреть файл

@@ -7,6 +7,8 @@ package hpack
import (
"bytes"
"encoding/hex"
"fmt"
"math/rand"
"reflect"
"strings"
"testing"
@@ -101,17 +103,20 @@ func TestEncoderSearchTable(t *testing.T) {
wantMatch bool
}{
// Name and Value match
{pair("foo", "bar"), uint64(len(staticTable) + 3), true},
{pair("blake", "miz"), uint64(len(staticTable) + 2), true},
{pair("foo", "bar"), uint64(staticTable.len()) + 3, true},
{pair("blake", "miz"), uint64(staticTable.len()) + 2, true},
{pair(":method", "GET"), 2, true},
// Only name match because Sensitive == true
{HeaderField{":method", "GET", true}, 2, false},
// Only name match because Sensitive == true. This is allowed to match
// any ":method" entry. The current implementation uses the last entry
// added in newStaticTable.
{HeaderField{":method", "GET", true}, 3, false},
// Only Name matches
{pair("foo", "..."), uint64(len(staticTable) + 3), false},
{pair("blake", "..."), uint64(len(staticTable) + 2), false},
{pair(":method", "..."), 2, false},
{pair("foo", "..."), uint64(staticTable.len()) + 3, false},
{pair("blake", "..."), uint64(staticTable.len()) + 2, false},
// As before, this is allowed to match any ":method" entry.
{pair(":method", "..."), 3, false},
// None match
{pair("foo-", "bar"), 0, false},
@@ -328,3 +333,54 @@ func TestEncoderSetMaxDynamicTableSizeLimit(t *testing.T) {
func removeSpace(s string) string {
return strings.Replace(s, " ", "", -1)
}
func BenchmarkEncoderSearchTable(b *testing.B) {
e := NewEncoder(nil)
// A sample of possible header fields.
// This is not based on any actual data from HTTP/2 traces.
var possible []HeaderField
for _, f := range staticTable.ents {
if f.Value == "" {
possible = append(possible, f)
continue
}
// Generate 5 random values, except for cookie and set-cookie,
// which we know can have many values in practice.
num := 5
if f.Name == "cookie" || f.Name == "set-cookie" {
num = 25
}
for i := 0; i < num; i++ {
f.Value = fmt.Sprintf("%s-%d", f.Name, i)
possible = append(possible, f)
}
}
for k := 0; k < 10; k++ {
f := HeaderField{
Name: fmt.Sprintf("x-header-%d", k),
Sensitive: rand.Int()%2 == 0,
}
for i := 0; i < 5; i++ {
f.Value = fmt.Sprintf("%s-%d", f.Name, i)
possible = append(possible, f)
}
}
// Add a random sample to the dynamic table. This very loosely simulates
// a history of 100 requests with 20 header fields per request.
for r := 0; r < 100*20; r++ {
f := possible[rand.Int31n(int32(len(possible)))]
// Skip if this is in the staticTable verbatim.
if _, has := staticTable.search(f); !has {
e.dynTab.add(f)
}
}
b.ResetTimer()
for n := 0; n < b.N; n++ {
for _, f := range possible {
e.searchTable(f)
}
}
}

104
vendor/golang.org/x/net/http2/hpack/hpack.go сгенерированный поставляемый
Просмотреть файл

@@ -61,7 +61,7 @@ func (hf HeaderField) String() string {
func (hf HeaderField) Size() uint32 {
// http://http2.github.io/http2-spec/compression.html#rfc.section.4.1
// "The size of the dynamic table is the sum of the size of
// its entries. The size of an entry is the sum of its name's
// its entries. The size of an entry is the sum of its name's
// length in octets (as defined in Section 5.2), its value's
// length in octets (see Section 5.2), plus 32. The size of
// an entry is calculated using the length of the name and
@@ -102,6 +102,7 @@ func NewDecoder(maxDynamicTableSize uint32, emitFunc func(f HeaderField)) *Decod
emit: emitFunc,
emitEnabled: true,
}
d.dynTab.table.init()
d.dynTab.allowedMaxSize = maxDynamicTableSize
d.dynTab.setMaxSize(maxDynamicTableSize)
return d
@@ -154,12 +155,9 @@ func (d *Decoder) SetAllowedMaxDynamicTableSize(v uint32) {
}
type dynamicTable struct {
// ents is the FIFO described at
// http://http2.github.io/http2-spec/compression.html#rfc.section.2.3.2
// The newest (low index) is append at the end, and items are
// evicted from the front.
ents []HeaderField
size uint32
table headerFieldTable
size uint32 // in bytes
maxSize uint32 // current maxSize
allowedMaxSize uint32 // maxSize may go up to this, inclusive
}
@@ -169,95 +167,45 @@ func (dt *dynamicTable) setMaxSize(v uint32) {
dt.evict()
}
// TODO: change dynamicTable to be a struct with a slice and a size int field,
// per http://http2.github.io/http2-spec/compression.html#rfc.section.4.1:
//
//
// Then make add increment the size. maybe the max size should move from Decoder to
// dynamicTable and add should return an ok bool if there was enough space.
//
// Later we'll need a remove operation on dynamicTable.
func (dt *dynamicTable) add(f HeaderField) {
dt.ents = append(dt.ents, f)
dt.table.addEntry(f)
dt.size += f.Size()
dt.evict()
}
// If we're too big, evict old stuff (front of the slice)
// If we're too big, evict old stuff.
func (dt *dynamicTable) evict() {
base := dt.ents // keep base pointer of slice
for dt.size > dt.maxSize {
dt.size -= dt.ents[0].Size()
dt.ents = dt.ents[1:]
var n int
for dt.size > dt.maxSize && n < dt.table.len() {
dt.size -= dt.table.ents[n].Size()
n++
}
// Shift slice contents down if we evicted things.
if len(dt.ents) != len(base) {
copy(base, dt.ents)
dt.ents = base[:len(dt.ents)]
}
}
// constantTimeStringCompare compares string a and b in a constant
// time manner.
func constantTimeStringCompare(a, b string) bool {
if len(a) != len(b) {
return false
}
c := byte(0)
for i := 0; i < len(a); i++ {
c |= a[i] ^ b[i]
}
return c == 0
}
// Search searches f in the table. The return value i is 0 if there is
// no name match. If there is name match or name/value match, i is the
// index of that entry (1-based). If both name and value match,
// nameValueMatch becomes true.
func (dt *dynamicTable) search(f HeaderField) (i uint64, nameValueMatch bool) {
l := len(dt.ents)
for j := l - 1; j >= 0; j-- {
ent := dt.ents[j]
if !constantTimeStringCompare(ent.Name, f.Name) {
continue
}
if i == 0 {
i = uint64(l - j)
}
if f.Sensitive {
continue
}
if !constantTimeStringCompare(ent.Value, f.Value) {
continue
}
i = uint64(l - j)
nameValueMatch = true
return
}
return
dt.table.evictOldest(n)
}
func (d *Decoder) maxTableIndex() int {
return len(d.dynTab.ents) + len(staticTable)
// This should never overflow. RFC 7540 Section 6.5.2 limits the size of
// the dynamic table to 2^32 bytes, where each entry will occupy more than
// one byte. Further, the staticTable has a fixed, small length.
return d.dynTab.table.len() + staticTable.len()
}
func (d *Decoder) at(i uint64) (hf HeaderField, ok bool) {
if i < 1 {
// See Section 2.3.3.
if i == 0 {
return
}
if i <= uint64(staticTable.len()) {
return staticTable.ents[i-1], true
}
if i > uint64(d.maxTableIndex()) {
return
}
if i <= uint64(len(staticTable)) {
return staticTable[i-1], true
}
dents := d.dynTab.ents
return dents[len(dents)-(int(i)-len(staticTable))], true
// In the dynamic table, newer entries have lower indices.
// However, dt.ents[0] is the oldest entry. Hence, dt.ents is
// the reversed dynamic table.
dt := d.dynTab.table
return dt.ents[dt.len()-(int(i)-staticTable.len())], true
}
// Decode decodes an entire block.
@@ -307,7 +255,7 @@ func (d *Decoder) Write(p []byte) (n int, err error) {
err = d.parseHeaderFieldRepr()
if err == errNeedMore {
// Extra paranoia, making sure saveBuf won't
// get too large. All the varint and string
// get too large. All the varint and string
// reading code earlier should already catch
// overlong things and return ErrStringLength,
// but keep this as a last resort.

146
vendor/golang.org/x/net/http2/hpack/hpack_test.go сгенерированный поставляемый
Просмотреть файл

@@ -5,117 +5,16 @@
package hpack
import (
"bufio"
"bytes"
"encoding/hex"
"fmt"
"math/rand"
"reflect"
"regexp"
"strconv"
"strings"
"testing"
"time"
)
func TestStaticTable(t *testing.T) {
fromSpec := `
+-------+-----------------------------+---------------+
| 1 | :authority | |
| 2 | :method | GET |
| 3 | :method | POST |
| 4 | :path | / |
| 5 | :path | /index.html |
| 6 | :scheme | http |
| 7 | :scheme | https |
| 8 | :status | 200 |
| 9 | :status | 204 |
| 10 | :status | 206 |
| 11 | :status | 304 |
| 12 | :status | 400 |
| 13 | :status | 404 |
| 14 | :status | 500 |
| 15 | accept-charset | |
| 16 | accept-encoding | gzip, deflate |
| 17 | accept-language | |
| 18 | accept-ranges | |
| 19 | accept | |
| 20 | access-control-allow-origin | |
| 21 | age | |
| 22 | allow | |
| 23 | authorization | |
| 24 | cache-control | |
| 25 | content-disposition | |
| 26 | content-encoding | |
| 27 | content-language | |
| 28 | content-length | |
| 29 | content-location | |
| 30 | content-range | |
| 31 | content-type | |
| 32 | cookie | |
| 33 | date | |
| 34 | etag | |
| 35 | expect | |
| 36 | expires | |
| 37 | from | |
| 38 | host | |
| 39 | if-match | |
| 40 | if-modified-since | |
| 41 | if-none-match | |
| 42 | if-range | |
| 43 | if-unmodified-since | |
| 44 | last-modified | |
| 45 | link | |
| 46 | location | |
| 47 | max-forwards | |
| 48 | proxy-authenticate | |
| 49 | proxy-authorization | |
| 50 | range | |
| 51 | referer | |
| 52 | refresh | |
| 53 | retry-after | |
| 54 | server | |
| 55 | set-cookie | |
| 56 | strict-transport-security | |
| 57 | transfer-encoding | |
| 58 | user-agent | |
| 59 | vary | |
| 60 | via | |
| 61 | www-authenticate | |
+-------+-----------------------------+---------------+
`
bs := bufio.NewScanner(strings.NewReader(fromSpec))
re := regexp.MustCompile(`\| (\d+)\s+\| (\S+)\s*\| (\S(.*\S)?)?\s+\|`)
for bs.Scan() {
l := bs.Text()
if !strings.Contains(l, "|") {
continue
}
m := re.FindStringSubmatch(l)
if m == nil {
continue
}
i, err := strconv.Atoi(m[1])
if err != nil {
t.Errorf("Bogus integer on line %q", l)
continue
}
if i < 1 || i > len(staticTable) {
t.Errorf("Bogus index %d on line %q", i, l)
continue
}
if got, want := staticTable[i-1].Name, m[2]; got != want {
t.Errorf("header index %d name = %q; want %q", i, got, want)
}
if got, want := staticTable[i-1].Value, m[3]; got != want {
t.Errorf("header index %d value = %q; want %q", i, got, want)
}
}
if err := bs.Err(); err != nil {
t.Error(err)
}
}
func (d *Decoder) mustAt(idx int) HeaderField {
if hf, ok := d.at(uint64(idx)); !ok {
panic(fmt.Sprintf("bogus index %d", idx))
@@ -132,10 +31,10 @@ func TestDynamicTableAt(t *testing.T) {
}
d.dynTab.add(pair("foo", "bar"))
d.dynTab.add(pair("blake", "miz"))
if got, want := at(len(staticTable)+1), (pair("blake", "miz")); got != want {
if got, want := at(staticTable.len()+1), (pair("blake", "miz")); got != want {
t.Errorf("at(dyn 1) = %v; want %v", got, want)
}
if got, want := at(len(staticTable)+2), (pair("foo", "bar")); got != want {
if got, want := at(staticTable.len()+2), (pair("foo", "bar")); got != want {
t.Errorf("at(dyn 2) = %v; want %v", got, want)
}
if got, want := at(3), (pair(":method", "POST")); got != want {
@@ -143,41 +42,6 @@ func TestDynamicTableAt(t *testing.T) {
}
}
func TestDynamicTableSearch(t *testing.T) {
dt := dynamicTable{}
dt.setMaxSize(4096)
dt.add(pair("foo", "bar"))
dt.add(pair("blake", "miz"))
dt.add(pair(":method", "GET"))
tests := []struct {
hf HeaderField
wantI uint64
wantMatch bool
}{
// Name and Value match
{pair("foo", "bar"), 3, true},
{pair(":method", "GET"), 1, true},
// Only name match because of Sensitive == true
{HeaderField{"blake", "miz", true}, 2, false},
// Only Name matches
{pair("foo", "..."), 3, false},
{pair("blake", "..."), 2, false},
{pair(":method", "..."), 1, false},
// None match
{pair("foo-", "bar"), 0, false},
}
for _, tt := range tests {
if gotI, gotMatch := dt.search(tt.hf); gotI != tt.wantI || gotMatch != tt.wantMatch {
t.Errorf("d.search(%+v) = %v, %v; want %v, %v", tt.hf, gotI, gotMatch, tt.wantI, tt.wantMatch)
}
}
}
func TestDynamicTableSizeEvict(t *testing.T) {
d := NewDecoder(4096, nil)
if want := uint32(0); d.dynTab.size != want {
@@ -196,7 +60,7 @@ func TestDynamicTableSizeEvict(t *testing.T) {
if want := uint32(6 + 32); d.dynTab.size != want {
t.Fatalf("after setMaxSize, size = %d; want %d", d.dynTab.size, want)
}
if got, want := d.mustAt(len(staticTable)+1), (pair("foo", "bar")); got != want {
if got, want := d.mustAt(staticTable.len()+1), (pair("foo", "bar")); got != want {
t.Errorf("at(dyn 1) = %v; want %v", got, want)
}
add(pair("long", strings.Repeat("x", 500)))
@@ -255,9 +119,9 @@ func TestDecoderDecode(t *testing.T) {
}
func (dt *dynamicTable) reverseCopy() (hf []HeaderField) {
hf = make([]HeaderField, len(dt.ents))
hf = make([]HeaderField, len(dt.table.ents))
for i := range hf {
hf[i] = dt.ents[len(dt.ents)-1-i]
hf[i] = dt.table.ents[len(dt.table.ents)-1-i]
}
return
}

250
vendor/golang.org/x/net/http2/hpack/tables.go сгенерированный поставляемый
Просмотреть файл

@@ -4,73 +4,199 @@
package hpack
import (
"fmt"
)
// headerFieldTable implements a list of HeaderFields.
// This is used to implement the static and dynamic tables.
type headerFieldTable struct {
// For static tables, entries are never evicted.
//
// For dynamic tables, entries are evicted from ents[0] and added to the end.
// Each entry has a unique id that starts at one and increments for each
// entry that is added. This unique id is stable across evictions, meaning
// it can be used as a pointer to a specific entry. As in hpack, unique ids
// are 1-based. The unique id for ents[k] is k + evictCount + 1.
//
// Zero is not a valid unique id.
//
// evictCount should not overflow in any remotely practical situation. In
// practice, we will have one dynamic table per HTTP/2 connection. If we
// assume a very powerful server that handles 1M QPS per connection and each
// request adds (then evicts) 100 entries from the table, it would still take
// 2M years for evictCount to overflow.
ents []HeaderField
evictCount uint64
// byName maps a HeaderField name to the unique id of the newest entry with
// the same name. See above for a definition of "unique id".
byName map[string]uint64
// byNameValue maps a HeaderField name/value pair to the unique id of the newest
// entry with the same name and value. See above for a definition of "unique id".
byNameValue map[pairNameValue]uint64
}
type pairNameValue struct {
name, value string
}
func (t *headerFieldTable) init() {
t.byName = make(map[string]uint64)
t.byNameValue = make(map[pairNameValue]uint64)
}
// len reports the number of entries in the table.
func (t *headerFieldTable) len() int {
return len(t.ents)
}
// addEntry adds a new entry.
func (t *headerFieldTable) addEntry(f HeaderField) {
id := uint64(t.len()) + t.evictCount + 1
t.byName[f.Name] = id
t.byNameValue[pairNameValue{f.Name, f.Value}] = id
t.ents = append(t.ents, f)
}
// evictOldest evicts the n oldest entries in the table.
func (t *headerFieldTable) evictOldest(n int) {
if n > t.len() {
panic(fmt.Sprintf("evictOldest(%v) on table with %v entries", n, t.len()))
}
for k := 0; k < n; k++ {
f := t.ents[k]
id := t.evictCount + uint64(k) + 1
if t.byName[f.Name] == id {
t.byName[f.Name] = 0
}
if p := (pairNameValue{f.Name, f.Value}); t.byNameValue[p] == id {
t.byNameValue[p] = 0
}
}
copy(t.ents, t.ents[n:])
for k := t.len() - n; k < t.len(); k++ {
t.ents[k] = HeaderField{} // so strings can be garbage collected
}
t.ents = t.ents[:t.len()-n]
if t.evictCount+uint64(n) < t.evictCount {
panic("evictCount overflow")
}
t.evictCount += uint64(n)
}
// search finds f in the table. If there is no match, i is 0.
// If both name and value match, i is the matched index and nameValueMatch
// becomes true. If only name matches, i points to that index and
// nameValueMatch becomes false.
//
// The returned index is a 1-based HPACK index. For dynamic tables, HPACK says
// that index 1 should be the newest entry, but t.ents[0] is the oldest entry,
// meaning t.ents is reversed for dynamic tables. Hence, when t is a dynamic
// table, the return value i actually refers to the entry t.ents[t.len()-i].
//
// All tables are assumed to be a dynamic tables except for the global
// staticTable pointer.
//
// See Section 2.3.3.
func (t *headerFieldTable) search(f HeaderField) (i uint64, nameValueMatch bool) {
if !f.Sensitive {
if id := t.byNameValue[pairNameValue{f.Name, f.Value}]; id != 0 {
return t.idToIndex(id), true
}
}
if id := t.byName[f.Name]; id != 0 {
return t.idToIndex(id), false
}
return 0, false
}
// idToIndex converts a unique id to an HPACK index.
// See Section 2.3.3.
func (t *headerFieldTable) idToIndex(id uint64) uint64 {
if id <= t.evictCount {
panic(fmt.Sprintf("id (%v) <= evictCount (%v)", id, t.evictCount))
}
k := id - t.evictCount - 1 // convert id to an index t.ents[k]
if t != staticTable {
return uint64(t.len()) - k // dynamic table
}
return k + 1
}
func pair(name, value string) HeaderField {
return HeaderField{Name: name, Value: value}
}
// http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B
var staticTable = [...]HeaderField{
pair(":authority", ""), // index 1 (1-based)
pair(":method", "GET"),
pair(":method", "POST"),
pair(":path", "/"),
pair(":path", "/index.html"),
pair(":scheme", "http"),
pair(":scheme", "https"),
pair(":status", "200"),
pair(":status", "204"),
pair(":status", "206"),
pair(":status", "304"),
pair(":status", "400"),
pair(":status", "404"),
pair(":status", "500"),
pair("accept-charset", ""),
pair("accept-encoding", "gzip, deflate"),
pair("accept-language", ""),
pair("accept-ranges", ""),
pair("accept", ""),
pair("access-control-allow-origin", ""),
pair("age", ""),
pair("allow", ""),
pair("authorization", ""),
pair("cache-control", ""),
pair("content-disposition", ""),
pair("content-encoding", ""),
pair("content-language", ""),
pair("content-length", ""),
pair("content-location", ""),
pair("content-range", ""),
pair("content-type", ""),
pair("cookie", ""),
pair("date", ""),
pair("etag", ""),
pair("expect", ""),
pair("expires", ""),
pair("from", ""),
pair("host", ""),
pair("if-match", ""),
pair("if-modified-since", ""),
pair("if-none-match", ""),
pair("if-range", ""),
pair("if-unmodified-since", ""),
pair("last-modified", ""),
pair("link", ""),
pair("location", ""),
pair("max-forwards", ""),
pair("proxy-authenticate", ""),
pair("proxy-authorization", ""),
pair("range", ""),
pair("referer", ""),
pair("refresh", ""),
pair("retry-after", ""),
pair("server", ""),
pair("set-cookie", ""),
pair("strict-transport-security", ""),
pair("transfer-encoding", ""),
pair("user-agent", ""),
pair("vary", ""),
pair("via", ""),
pair("www-authenticate", ""),
var staticTable = newStaticTable()
func newStaticTable() *headerFieldTable {
t := &headerFieldTable{}
t.init()
t.addEntry(pair(":authority", ""))
t.addEntry(pair(":method", "GET"))
t.addEntry(pair(":method", "POST"))
t.addEntry(pair(":path", "/"))
t.addEntry(pair(":path", "/index.html"))
t.addEntry(pair(":scheme", "http"))
t.addEntry(pair(":scheme", "https"))
t.addEntry(pair(":status", "200"))
t.addEntry(pair(":status", "204"))
t.addEntry(pair(":status", "206"))
t.addEntry(pair(":status", "304"))
t.addEntry(pair(":status", "400"))
t.addEntry(pair(":status", "404"))
t.addEntry(pair(":status", "500"))
t.addEntry(pair("accept-charset", ""))
t.addEntry(pair("accept-encoding", "gzip, deflate"))
t.addEntry(pair("accept-language", ""))
t.addEntry(pair("accept-ranges", ""))
t.addEntry(pair("accept", ""))
t.addEntry(pair("access-control-allow-origin", ""))
t.addEntry(pair("age", ""))
t.addEntry(pair("allow", ""))
t.addEntry(pair("authorization", ""))
t.addEntry(pair("cache-control", ""))
t.addEntry(pair("content-disposition", ""))
t.addEntry(pair("content-encoding", ""))
t.addEntry(pair("content-language", ""))
t.addEntry(pair("content-length", ""))
t.addEntry(pair("content-location", ""))
t.addEntry(pair("content-range", ""))
t.addEntry(pair("content-type", ""))
t.addEntry(pair("cookie", ""))
t.addEntry(pair("date", ""))
t.addEntry(pair("etag", ""))
t.addEntry(pair("expect", ""))
t.addEntry(pair("expires", ""))
t.addEntry(pair("from", ""))
t.addEntry(pair("host", ""))
t.addEntry(pair("if-match", ""))
t.addEntry(pair("if-modified-since", ""))
t.addEntry(pair("if-none-match", ""))
t.addEntry(pair("if-range", ""))
t.addEntry(pair("if-unmodified-since", ""))
t.addEntry(pair("last-modified", ""))
t.addEntry(pair("link", ""))
t.addEntry(pair("location", ""))
t.addEntry(pair("max-forwards", ""))
t.addEntry(pair("proxy-authenticate", ""))
t.addEntry(pair("proxy-authorization", ""))
t.addEntry(pair("range", ""))
t.addEntry(pair("referer", ""))
t.addEntry(pair("refresh", ""))
t.addEntry(pair("retry-after", ""))
t.addEntry(pair("server", ""))
t.addEntry(pair("set-cookie", ""))
t.addEntry(pair("strict-transport-security", ""))
t.addEntry(pair("transfer-encoding", ""))
t.addEntry(pair("user-agent", ""))
t.addEntry(pair("vary", ""))
t.addEntry(pair("via", ""))
t.addEntry(pair("www-authenticate", ""))
return t
}
var huffmanCodes = [256]uint32{

188
vendor/golang.org/x/net/http2/hpack/tables_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,188 @@
// 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 hpack
import (
"bufio"
"regexp"
"strconv"
"strings"
"testing"
)
func TestHeaderFieldTable(t *testing.T) {
table := &headerFieldTable{}
table.init()
table.addEntry(pair("key1", "value1-1"))
table.addEntry(pair("key2", "value2-1"))
table.addEntry(pair("key1", "value1-2"))
table.addEntry(pair("key3", "value3-1"))
table.addEntry(pair("key4", "value4-1"))
table.addEntry(pair("key2", "value2-2"))
// Tests will be run twice: once before evicting anything, and
// again after evicting the three oldest entries.
tests := []struct {
f HeaderField
beforeWantStaticI uint64
beforeWantMatch bool
afterWantStaticI uint64
afterWantMatch bool
}{
{HeaderField{"key1", "value1-1", false}, 1, true, 0, false},
{HeaderField{"key1", "value1-2", false}, 3, true, 0, false},
{HeaderField{"key1", "value1-3", false}, 3, false, 0, false},
{HeaderField{"key2", "value2-1", false}, 2, true, 3, false},
{HeaderField{"key2", "value2-2", false}, 6, true, 3, true},
{HeaderField{"key2", "value2-3", false}, 6, false, 3, false},
{HeaderField{"key4", "value4-1", false}, 5, true, 2, true},
// Name match only, because sensitive.
{HeaderField{"key4", "value4-1", true}, 5, false, 2, false},
// Key not found.
{HeaderField{"key5", "value5-x", false}, 0, false, 0, false},
}
staticToDynamic := func(i uint64) uint64 {
if i == 0 {
return 0
}
return uint64(table.len()) - i + 1 // dynamic is the reversed table
}
searchStatic := func(f HeaderField) (uint64, bool) {
old := staticTable
staticTable = table
defer func() { staticTable = old }()
return staticTable.search(f)
}
searchDynamic := func(f HeaderField) (uint64, bool) {
return table.search(f)
}
for _, test := range tests {
gotI, gotMatch := searchStatic(test.f)
if wantI, wantMatch := test.beforeWantStaticI, test.beforeWantMatch; gotI != wantI || gotMatch != wantMatch {
t.Errorf("before evictions: searchStatic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch)
}
gotI, gotMatch = searchDynamic(test.f)
wantDynamicI := staticToDynamic(test.beforeWantStaticI)
if wantI, wantMatch := wantDynamicI, test.beforeWantMatch; gotI != wantI || gotMatch != wantMatch {
t.Errorf("before evictions: searchDynamic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch)
}
}
table.evictOldest(3)
for _, test := range tests {
gotI, gotMatch := searchStatic(test.f)
if wantI, wantMatch := test.afterWantStaticI, test.afterWantMatch; gotI != wantI || gotMatch != wantMatch {
t.Errorf("after evictions: searchStatic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch)
}
gotI, gotMatch = searchDynamic(test.f)
wantDynamicI := staticToDynamic(test.afterWantStaticI)
if wantI, wantMatch := wantDynamicI, test.afterWantMatch; gotI != wantI || gotMatch != wantMatch {
t.Errorf("after evictions: searchDynamic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch)
}
}
}
func TestStaticTable(t *testing.T) {
fromSpec := `
+-------+-----------------------------+---------------+
| 1 | :authority | |
| 2 | :method | GET |
| 3 | :method | POST |
| 4 | :path | / |
| 5 | :path | /index.html |
| 6 | :scheme | http |
| 7 | :scheme | https |
| 8 | :status | 200 |
| 9 | :status | 204 |
| 10 | :status | 206 |
| 11 | :status | 304 |
| 12 | :status | 400 |
| 13 | :status | 404 |
| 14 | :status | 500 |
| 15 | accept-charset | |
| 16 | accept-encoding | gzip, deflate |
| 17 | accept-language | |
| 18 | accept-ranges | |
| 19 | accept | |
| 20 | access-control-allow-origin | |
| 21 | age | |
| 22 | allow | |
| 23 | authorization | |
| 24 | cache-control | |
| 25 | content-disposition | |
| 26 | content-encoding | |
| 27 | content-language | |
| 28 | content-length | |
| 29 | content-location | |
| 30 | content-range | |
| 31 | content-type | |
| 32 | cookie | |
| 33 | date | |
| 34 | etag | |
| 35 | expect | |
| 36 | expires | |
| 37 | from | |
| 38 | host | |
| 39 | if-match | |
| 40 | if-modified-since | |
| 41 | if-none-match | |
| 42 | if-range | |
| 43 | if-unmodified-since | |
| 44 | last-modified | |
| 45 | link | |
| 46 | location | |
| 47 | max-forwards | |
| 48 | proxy-authenticate | |
| 49 | proxy-authorization | |
| 50 | range | |
| 51 | referer | |
| 52 | refresh | |
| 53 | retry-after | |
| 54 | server | |
| 55 | set-cookie | |
| 56 | strict-transport-security | |
| 57 | transfer-encoding | |
| 58 | user-agent | |
| 59 | vary | |
| 60 | via | |
| 61 | www-authenticate | |
+-------+-----------------------------+---------------+
`
bs := bufio.NewScanner(strings.NewReader(fromSpec))
re := regexp.MustCompile(`\| (\d+)\s+\| (\S+)\s*\| (\S(.*\S)?)?\s+\|`)
for bs.Scan() {
l := bs.Text()
if !strings.Contains(l, "|") {
continue
}
m := re.FindStringSubmatch(l)
if m == nil {
continue
}
i, err := strconv.Atoi(m[1])
if err != nil {
t.Errorf("Bogus integer on line %q", l)
continue
}
if i < 1 || i > staticTable.len() {
t.Errorf("Bogus index %d on line %q", i, l)
continue
}
if got, want := staticTable.ents[i-1].Name, m[2]; got != want {
t.Errorf("header index %d name = %q; want %q", i, got, want)
}
if got, want := staticTable.ents[i-1].Value, m[3]; got != want {
t.Errorf("header index %d value = %q; want %q", i, got, want)
}
}
if err := bs.Err(); err != nil {
t.Error(err)
}
}

2
vendor/golang.org/x/net/http2/pipe.go сгенерированный поставляемый
Просмотреть файл

@@ -10,7 +10,7 @@ import (
"sync"
)
// pipe is a goroutine-safe io.Reader/io.Writer pair. It's like
// pipe is a goroutine-safe io.Reader/io.Writer pair. It's like
// io.Pipe except there are no PipeReader/PipeWriter halves, and the
// underlying buffer is an interface. (io.Pipe is always unbuffered)
type pipe struct {

199
vendor/golang.org/x/net/http2/server.go сгенерированный поставляемый
Просмотреть файл

@@ -110,11 +110,38 @@ type Server struct {
// activity for the purposes of IdleTimeout.
IdleTimeout time.Duration
// MaxUploadBufferPerConnection is the size of the initial flow
// control window for each connections. The HTTP/2 spec does not
// allow this to be smaller than 65535 or larger than 2^32-1.
// If the value is outside this range, a default value will be
// used instead.
MaxUploadBufferPerConnection int32
// MaxUploadBufferPerStream is the size of the initial flow control
// window for each stream. The HTTP/2 spec does not allow this to
// be larger than 2^32-1. If the value is zero or larger than the
// maximum, a default value will be used instead.
MaxUploadBufferPerStream int32
// NewWriteScheduler constructs a write scheduler for a connection.
// If nil, a default scheduler is chosen.
NewWriteScheduler func() WriteScheduler
}
func (s *Server) initialConnRecvWindowSize() int32 {
if s.MaxUploadBufferPerConnection > initialWindowSize {
return s.MaxUploadBufferPerConnection
}
return 1 << 20
}
func (s *Server) initialStreamRecvWindowSize() int32 {
if s.MaxUploadBufferPerStream > 0 {
return s.MaxUploadBufferPerStream
}
return 1 << 20
}
func (s *Server) maxReadFrameSize() uint32 {
if v := s.MaxReadFrameSize; v >= minMaxFrameSize && v <= maxFrameSize {
return v
@@ -255,27 +282,27 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
defer cancel()
sc := &serverConn{
srv: s,
hs: opts.baseConfig(),
conn: c,
baseCtx: baseCtx,
remoteAddrStr: c.RemoteAddr().String(),
bw: newBufferedWriter(c),
handler: opts.handler(),
streams: make(map[uint32]*stream),
readFrameCh: make(chan readFrameResult),
wantWriteFrameCh: make(chan FrameWriteRequest, 8),
wantStartPushCh: make(chan startPushRequest, 8),
wroteFrameCh: make(chan frameWriteResult, 1), // buffered; one send in writeFrameAsync
bodyReadCh: make(chan bodyReadMsg), // buffering doesn't matter either way
doneServing: make(chan struct{}),
clientMaxStreams: math.MaxUint32, // Section 6.5.2: "Initially, there is no limit to this value"
advMaxStreams: s.maxConcurrentStreams(),
initialWindowSize: initialWindowSize,
maxFrameSize: initialMaxFrameSize,
headerTableSize: initialHeaderTableSize,
serveG: newGoroutineLock(),
pushEnabled: true,
srv: s,
hs: opts.baseConfig(),
conn: c,
baseCtx: baseCtx,
remoteAddrStr: c.RemoteAddr().String(),
bw: newBufferedWriter(c),
handler: opts.handler(),
streams: make(map[uint32]*stream),
readFrameCh: make(chan readFrameResult),
wantWriteFrameCh: make(chan FrameWriteRequest, 8),
wantStartPushCh: make(chan startPushRequest, 8),
wroteFrameCh: make(chan frameWriteResult, 1), // buffered; one send in writeFrameAsync
bodyReadCh: make(chan bodyReadMsg), // buffering doesn't matter either way
doneServing: make(chan struct{}),
clientMaxStreams: math.MaxUint32, // Section 6.5.2: "Initially, there is no limit to this value"
advMaxStreams: s.maxConcurrentStreams(),
initialStreamSendWindowSize: initialWindowSize,
maxFrameSize: initialMaxFrameSize,
headerTableSize: initialHeaderTableSize,
serveG: newGoroutineLock(),
pushEnabled: true,
}
// The net/http package sets the write deadline from the
@@ -294,6 +321,9 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
sc.writeSched = NewRandomWriteScheduler()
}
// These start at the RFC-specified defaults. If there is a higher
// configured value for inflow, that will be updated when we send a
// WINDOW_UPDATE shortly after sending SETTINGS.
sc.flow.add(initialWindowSize)
sc.inflow.add(initialWindowSize)
sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
@@ -387,34 +417,34 @@ type serverConn struct {
writeSched WriteScheduler
// Everything following is owned by the serve loop; use serveG.check():
serveG goroutineLock // used to verify funcs are on serve()
pushEnabled bool
sawFirstSettings bool // got the initial SETTINGS frame after the preface
needToSendSettingsAck bool
unackedSettings int // how many SETTINGS have we sent without ACKs?
clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit)
advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client
curClientStreams uint32 // number of open streams initiated by the client
curPushedStreams uint32 // number of open streams initiated by server push
maxClientStreamID uint32 // max ever seen from client (odd), or 0 if there have been no client requests
maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes
streams map[uint32]*stream
initialWindowSize int32
maxFrameSize int32
headerTableSize uint32
peerMaxHeaderListSize uint32 // zero means unknown (default)
canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case
writingFrame bool // started writing a frame (on serve goroutine or separate)
writingFrameAsync bool // started a frame on its own goroutine but haven't heard back on wroteFrameCh
needsFrameFlush bool // last frame write wasn't a flush
inGoAway bool // we've started to or sent GOAWAY
inFrameScheduleLoop bool // whether we're in the scheduleFrameWrite loop
needToSendGoAway bool // we need to schedule a GOAWAY frame write
goAwayCode ErrCode
shutdownTimerCh <-chan time.Time // nil until used
shutdownTimer *time.Timer // nil until used
idleTimer *time.Timer // nil if unused
idleTimerCh <-chan time.Time // nil if unused
serveG goroutineLock // used to verify funcs are on serve()
pushEnabled bool
sawFirstSettings bool // got the initial SETTINGS frame after the preface
needToSendSettingsAck bool
unackedSettings int // how many SETTINGS have we sent without ACKs?
clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit)
advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client
curClientStreams uint32 // number of open streams initiated by the client
curPushedStreams uint32 // number of open streams initiated by server push
maxClientStreamID uint32 // max ever seen from client (odd), or 0 if there have been no client requests
maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes
streams map[uint32]*stream
initialStreamSendWindowSize int32
maxFrameSize int32
headerTableSize uint32
peerMaxHeaderListSize uint32 // zero means unknown (default)
canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case
writingFrame bool // started writing a frame (on serve goroutine or separate)
writingFrameAsync bool // started a frame on its own goroutine but haven't heard back on wroteFrameCh
needsFrameFlush bool // last frame write wasn't a flush
inGoAway bool // we've started to or sent GOAWAY
inFrameScheduleLoop bool // whether we're in the scheduleFrameWrite loop
needToSendGoAway bool // we need to schedule a GOAWAY frame write
goAwayCode ErrCode
shutdownTimerCh <-chan time.Time // nil until used
shutdownTimer *time.Timer // nil until used
idleTimer *time.Timer // nil if unused
idleTimerCh <-chan time.Time // nil if unused
// Owned by the writeFrameAsync goroutine:
headerWriteBuf bytes.Buffer
@@ -463,10 +493,9 @@ type stream struct {
numTrailerValues int64
weight uint8
state streamState
resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
gotTrailerHeader bool // HEADER frame for trailers was seen
wroteHeaders bool // whether we wrote headers (not status 100)
reqBuf []byte // if non-nil, body pipe buffer to return later at EOF
resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
gotTrailerHeader bool // HEADER frame for trailers was seen
wroteHeaders bool // whether we wrote headers (not status 100)
trailer http.Header // accumulated trailers
reqTrailer http.Header // handler's Request.Trailer
@@ -696,21 +725,23 @@ func (sc *serverConn) serve() {
{SettingMaxFrameSize, sc.srv.maxReadFrameSize()},
{SettingMaxConcurrentStreams, sc.advMaxStreams},
{SettingMaxHeaderListSize, sc.maxHeaderListSize()},
// TODO: more actual settings, notably
// SettingInitialWindowSize, but then we also
// want to bump up the conn window size the
// same amount here right after the settings
{SettingInitialWindowSize, uint32(sc.srv.initialStreamRecvWindowSize())},
},
})
sc.unackedSettings++
// Each connection starts with intialWindowSize inflow tokens.
// If a higher value is configured, we add more tokens.
if diff := sc.srv.initialConnRecvWindowSize() - initialWindowSize; diff > 0 {
sc.sendWindowUpdate(nil, int(diff))
}
if err := sc.readPreface(); err != nil {
sc.condlogf(err, "http2: server: error reading preface from client %v: %v", sc.conn.RemoteAddr(), err)
return
}
// Now that we've got the preface, get us out of the
// "StateNew" state. We can't go directly to idle, though.
// "StateNew" state. We can't go directly to idle, though.
// Active means we read some data and anticipate a request. We'll
// do another Active when we get a HEADERS frame.
sc.setConnState(http.StateActive)
@@ -1395,9 +1426,9 @@ func (sc *serverConn) processSettingInitialWindowSize(val uint32) error {
// adjust the size of all stream flow control windows that it
// maintains by the difference between the new value and the
// old value."
old := sc.initialWindowSize
sc.initialWindowSize = int32(val)
growth := sc.initialWindowSize - old // may be negative
old := sc.initialStreamSendWindowSize
sc.initialStreamSendWindowSize = int32(val)
growth := int32(val) - old // may be negative
for _, st := range sc.streams {
if !st.flow.add(growth) {
// 6.9.2 Initial Flow Control Window Size
@@ -1719,9 +1750,9 @@ func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream
}
st.cw.Init()
st.flow.conn = &sc.flow // link to conn-level counter
st.flow.add(sc.initialWindowSize)
st.inflow.conn = &sc.inflow // link to conn-level counter
st.inflow.add(initialWindowSize) // TODO: update this when we send a higher initial window size in the initial settings
st.flow.add(sc.initialStreamSendWindowSize)
st.inflow.conn = &sc.inflow // link to conn-level counter
st.inflow.add(sc.srv.initialStreamRecvWindowSize())
sc.streams[id] = st
sc.writeSched.OpenStream(st.id, OpenStreamOptions{PusherID: pusherID})
@@ -1785,16 +1816,14 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
return nil, nil, err
}
if bodyOpen {
st.reqBuf = getRequestBodyBuf()
req.Body.(*requestBody).pipe = &pipe{
b: &fixedBuffer{buf: st.reqBuf},
}
if vv, ok := rp.header["Content-Length"]; ok {
req.ContentLength, _ = strconv.ParseInt(vv[0], 10, 64)
} else {
req.ContentLength = -1
}
req.Body.(*requestBody).pipe = &pipe{
b: &dataBuffer{expected: req.ContentLength},
}
}
return rw, req, nil
}
@@ -1890,24 +1919,6 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r
return rw, req, nil
}
var reqBodyCache = make(chan []byte, 8)
func getRequestBodyBuf() []byte {
select {
case b := <-reqBodyCache:
return b
default:
return make([]byte, initialWindowSize)
}
}
func putRequestBodyBuf(b []byte) {
select {
case reqBodyCache <- b:
default:
}
}
// Run on its own goroutine.
func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) {
didPanic := true
@@ -2003,12 +2014,6 @@ func (sc *serverConn) noteBodyReadFromHandler(st *stream, n int, err error) {
case <-sc.doneServing:
}
}
if err == io.EOF {
if buf := st.reqBuf; buf != nil {
st.reqBuf = nil // shouldn't matter; field unused by other
putRequestBodyBuf(buf)
}
}
}
func (sc *serverConn) noteBodyRead(st *stream, n int) {
@@ -2103,8 +2108,8 @@ func (b *requestBody) Read(p []byte) (n int, err error) {
return
}
// responseWriter is the http.ResponseWriter implementation. It's
// intentionally small (1 pointer wide) to minimize garbage. The
// responseWriter is the http.ResponseWriter implementation. It's
// intentionally small (1 pointer wide) to minimize garbage. The
// responseWriterState pointer inside is zeroed at the end of a
// request (in handlerDone) and calls on the responseWriter thereafter
// simply crash (caller's mistake), but the much larger responseWriterState
@@ -2278,7 +2283,7 @@ const TrailerPrefix = "Trailer:"
// says you SHOULD (but not must) predeclare any trailers in the
// header, the official ResponseWriter rules said trailers in Go must
// be predeclared, and then we reuse the same ResponseWriter.Header()
// map to mean both Headers and Trailers. When it's time to write the
// map to mean both Headers and Trailers. When it's time to write the
// Trailers, we pick out the fields of Headers that were declared as
// trailers. That worked for a while, until we found the first major
// user of Trailers in the wild: gRPC (using them only over http2),

155
vendor/golang.org/x/net/http2/server_test.go сгенерированный поставляемый
Просмотреть файл

@@ -80,6 +80,7 @@ type serverTesterOpt string
var optOnlyServer = serverTesterOpt("only_server")
var optQuiet = serverTesterOpt("quiet_logging")
var optFramerReuseFrames = serverTesterOpt("frame_reuse_frames")
func newServerTester(t testing.TB, handler http.HandlerFunc, opts ...interface{}) *serverTester {
resetHooks()
@@ -91,7 +92,7 @@ func newServerTester(t testing.TB, handler http.HandlerFunc, opts ...interface{}
NextProtos: []string{NextProtoTLS},
}
var onlyServer, quiet bool
var onlyServer, quiet, framerReuseFrames bool
h2server := new(Server)
for _, opt := range opts {
switch v := opt.(type) {
@@ -107,6 +108,8 @@ func newServerTester(t testing.TB, handler http.HandlerFunc, opts ...interface{}
onlyServer = true
case optQuiet:
quiet = true
case optFramerReuseFrames:
framerReuseFrames = true
}
case func(net.Conn, http.ConnState):
ts.Config.ConnState = v
@@ -149,6 +152,9 @@ func newServerTester(t testing.TB, handler http.HandlerFunc, opts ...interface{}
}
st.cc = cc
st.fr = NewFramer(cc, cc)
if framerReuseFrames {
st.fr.SetReuseFrames()
}
if !logFrameReads && !logFrameWrites {
st.fr.debugReadLoggerf = func(m string, v ...interface{}) {
m = time.Now().Format("2006-01-02 15:04:05.999999999 ") + strings.TrimPrefix(m, "http2: ") + "\n"
@@ -254,11 +260,52 @@ func (st *serverTester) Close() {
// greet initiates the client's HTTP/2 connection into a state where
// frames may be sent.
func (st *serverTester) greet() {
st.greetAndCheckSettings(func(Setting) error { return nil })
}
func (st *serverTester) greetAndCheckSettings(checkSetting func(s Setting) error) {
st.writePreface()
st.writeInitialSettings()
st.wantSettings()
st.wantSettings().ForeachSetting(checkSetting)
st.writeSettingsAck()
st.wantSettingsAck()
// The initial WINDOW_UPDATE and SETTINGS ACK can come in any order.
var gotSettingsAck bool
var gotWindowUpdate bool
for i := 0; i < 2; i++ {
f, err := st.readFrame()
if err != nil {
st.t.Fatal(err)
}
switch f := f.(type) {
case *SettingsFrame:
if !f.Header().Flags.Has(FlagSettingsAck) {
st.t.Fatal("Settings Frame didn't have ACK set")
}
gotSettingsAck = true
case *WindowUpdateFrame:
if f.FrameHeader.StreamID != 0 {
st.t.Fatalf("WindowUpdate StreamID = %d; want 0", f.FrameHeader.StreamID, 0)
}
incr := uint32((&Server{}).initialConnRecvWindowSize() - initialWindowSize)
if f.Increment != incr {
st.t.Fatalf("WindowUpdate increment = %d; want %d", f.Increment, incr)
}
gotWindowUpdate = true
default:
st.t.Fatalf("Wanting a settings ACK or window update, received a %T", f)
}
}
if !gotSettingsAck {
st.t.Fatalf("Didn't get a settings ACK")
}
if !gotWindowUpdate {
st.t.Fatalf("Didn't get a window update")
}
}
func (st *serverTester) writePreface() {
@@ -318,7 +365,7 @@ func (st *serverTester) encodeHeaderRaw(headers ...string) []byte {
}
// encodeHeader encodes headers and returns their HPACK bytes. headers
// must contain an even number of key/value pairs. There may be
// must contain an even number of key/value pairs. There may be
// multiple pairs for keys (e.g. "cookie"). The :method, :path, and
// :scheme headers default to GET, / and https. The :authority header
// defaults to st.ts.Listener.Addr().
@@ -578,12 +625,7 @@ func TestServer(t *testing.T) {
server sends in the HTTP/2 connection.
`)
st.writePreface()
st.writeInitialSettings()
st.wantSettings()
st.writeSettingsAck()
st.wantSettingsAck()
st.greet()
st.writeHeaders(HeadersFrameParam{
StreamID: 1, // clients send odd numbers
BlockFragment: st.encodeHeader(),
@@ -656,7 +698,7 @@ func TestServer_Request_Get_PathSlashes(t *testing.T) {
}
// TODO: add a test with EndStream=true on the HEADERS but setting a
// Content-Length anyway. Should we just omit it and force it to
// Content-Length anyway. Should we just omit it and force it to
// zero?
func TestServer_Request_Post_NoContentLength_EndStream(t *testing.T) {
@@ -1192,7 +1234,7 @@ func TestServer_Handler_Sends_WindowUpdate_Padding(t *testing.T) {
EndStream: false,
EndHeaders: true,
})
st.writeDataPadded(1, false, []byte("abcdef"), []byte("1234"))
st.writeDataPadded(1, false, []byte("abcdef"), []byte{0, 0, 0, 0})
// Expect to immediately get our 5 bytes of padding back for
// both the connection and stream (4 bytes of padding + 1 byte of length)
@@ -2595,11 +2637,9 @@ func TestServerDoS_MaxHeaderListSize(t *testing.T) {
defer st.Close()
// shake hands
st.writePreface()
st.writeInitialSettings()
frameSize := defaultMaxReadFrameSize
var advHeaderListSize *uint32
st.wantSettings().ForeachSetting(func(s Setting) error {
st.greetAndCheckSettings(func(s Setting) error {
switch s.ID {
case SettingMaxFrameSize:
if s.Val < minMaxFrameSize {
@@ -2614,8 +2654,6 @@ func TestServerDoS_MaxHeaderListSize(t *testing.T) {
}
return nil
})
st.writeSettingsAck()
st.wantSettingsAck()
if advHeaderListSize == nil {
t.Errorf("server didn't advertise a max header list size")
@@ -2994,6 +3032,89 @@ func BenchmarkServerPosts(b *testing.B) {
}
}
// Send a stream of messages from server to client in separate data frames.
// Brings up performance issues seen in long streams.
// Created to show problem in go issue #18502
func BenchmarkServerToClientStreamDefaultOptions(b *testing.B) {
benchmarkServerToClientStream(b)
}
// Justification for Change-Id: Iad93420ef6c3918f54249d867098f1dadfa324d8
// Expect to see memory/alloc reduction by opting in to Frame reuse with the Framer.
func BenchmarkServerToClientStreamReuseFrames(b *testing.B) {
benchmarkServerToClientStream(b, optFramerReuseFrames)
}
func benchmarkServerToClientStream(b *testing.B, newServerOpts ...interface{}) {
defer disableGoroutineTracking()()
b.ReportAllocs()
const msgLen = 1
// default window size
const windowSize = 1<<16 - 1
// next message to send from the server and for the client to expect
nextMsg := func(i int) []byte {
msg := make([]byte, msgLen)
msg[0] = byte(i)
if len(msg) != msgLen {
panic("invalid test setup msg length")
}
return msg
}
st := newServerTester(b, func(w http.ResponseWriter, r *http.Request) {
// Consume the (empty) body from th peer before replying, otherwise
// the server will sometimes (depending on scheduling) send the peer a
// a RST_STREAM with the CANCEL error code.
if n, err := io.Copy(ioutil.Discard, r.Body); n != 0 || err != nil {
b.Errorf("Copy error; got %v, %v; want 0, nil", n, err)
}
for i := 0; i < b.N; i += 1 {
w.Write(nextMsg(i))
w.(http.Flusher).Flush()
}
}, newServerOpts...)
defer st.Close()
st.greet()
const id = uint32(1)
st.writeHeaders(HeadersFrameParam{
StreamID: id,
BlockFragment: st.encodeHeader(":method", "POST"),
EndStream: false,
EndHeaders: true,
})
st.writeData(id, true, nil)
st.wantHeaders()
var pendingWindowUpdate = uint32(0)
for i := 0; i < b.N; i += 1 {
expected := nextMsg(i)
df := st.wantData()
if bytes.Compare(expected, df.data) != 0 {
b.Fatalf("Bad message received; want %v; got %v", expected, df.data)
}
// try to send infrequent but large window updates so they don't overwhelm the test
pendingWindowUpdate += uint32(len(df.data))
if pendingWindowUpdate >= windowSize/2 {
if err := st.fr.WriteWindowUpdate(0, pendingWindowUpdate); err != nil {
b.Fatal(err)
}
if err := st.fr.WriteWindowUpdate(id, pendingWindowUpdate); err != nil {
b.Fatal(err)
}
pendingWindowUpdate = 0
}
}
df := st.wantData()
if !df.StreamEnded() {
b.Fatalf("DATA didn't have END_STREAM; got %v", df)
}
}
// go-fuzz bug, originally reported at https://github.com/bradfitz/http2/issues/53
// Verify we don't hang.
func TestIssue53(t *testing.T) {

9
vendor/golang.org/x/net/http2/transport.go сгенерированный поставляемый
Просмотреть файл

@@ -575,7 +575,7 @@ func (cc *ClientConn) canTakeNewRequestLocked() bool {
cc.nextStreamID < math.MaxInt32
}
// onIdleTimeout is called from a time.AfterFunc goroutine. It will
// onIdleTimeout is called from a time.AfterFunc goroutine. It will
// only be called when we're idle, but because we're coming from a new
// goroutine, there could be a new request coming in at the same time,
// so this simply calls the synchronized closeIfIdle to shut down this
@@ -809,8 +809,8 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
// 2xx, however, then assume the server DOES potentially
// want our body (e.g. full-duplex streaming:
// golang.org/issue/13444). If it turns out the server
// doesn't, they'll RST_STREAM us soon enough. This is a
// heuristic to avoid adding knobs to Transport. Hopefully
// doesn't, they'll RST_STREAM us soon enough. This is a
// heuristic to avoid adding knobs to Transport. Hopefully
// we can keep it.
bodyWriter.cancel()
cs.abortRequestBodyWrite(errStopReqBodyWrite)
@@ -1528,8 +1528,7 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
return res, nil
}
buf := new(bytes.Buffer) // TODO(bradfitz): recycle this garbage
cs.bufPipe = pipe{b: buf}
cs.bufPipe = pipe{b: &dataBuffer{expected: res.ContentLength}}
cs.bytesRemain = res.ContentLength
res.Body = transportResponseBody{cs}
go cs.awaitRequestCancel(cs.req)

2
vendor/golang.org/x/net/http2/transport_test.go сгенерированный поставляемый
Просмотреть файл

@@ -2406,7 +2406,7 @@ func TestTransportReturnsDataPaddingFlowControl(t *testing.T) {
EndStream: false,
BlockFragment: buf.Bytes(),
})
pad := []byte("12345")
pad := make([]byte, 5)
ct.fr.WriteDataPadded(hf.StreamID, false, make([]byte, 5000), pad) // without ending stream
f, err := ct.readNonSettingsFrame()

4
vendor/golang.org/x/net/internal/netreflect/socket.go сгенерированный поставляемый
Просмотреть файл

@@ -2,8 +2,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !go1.9
// Package netreflect implements run-time reflection for the
// facilities of net package.
//
// This package works only for Go 1.8 or below.
package netreflect
import (

37
vendor/golang.org/x/net/internal/netreflect/socket_19.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,37 @@
// 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.
// +build go1.9
package netreflect
import (
"errors"
"net"
)
var (
errInvalidType = errors.New("invalid type")
errOpNoSupport = errors.New("operation not supported")
)
// SocketOf returns the socket descriptor of c.
func SocketOf(c net.Conn) (uintptr, error) {
switch c.(type) {
case *net.TCPConn, *net.UDPConn, *net.IPConn, *net.UnixConn:
return 0, errOpNoSupport
default:
return 0, errInvalidType
}
}
// PacketSocketOf returns the socket descriptor of c.
func PacketSocketOf(c net.PacketConn) (uintptr, error) {
switch c.(type) {
case *net.UDPConn, *net.IPConn, *net.UnixConn:
return 0, errOpNoSupport
default:
return 0, errInvalidType
}
}

1
vendor/golang.org/x/net/internal/netreflect/socket_posix.go сгенерированный поставляемый
Просмотреть файл

@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !go1.9
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
package netreflect

1
vendor/golang.org/x/net/internal/netreflect/socket_stub.go сгенерированный поставляемый
Просмотреть файл

@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !go1.9
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
package netreflect

3
vendor/golang.org/x/net/internal/netreflect/socket_test.go сгенерированный поставляемый
Просмотреть файл

@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !go1.9
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
package netreflect_test
import (

2
vendor/golang.org/x/net/internal/timeseries/timeseries.go сгенерированный поставляемый
Просмотреть файл

@@ -371,7 +371,7 @@ func (ts *timeSeries) ComputeRange(start, finish time.Time, num int) []Observabl
}
}
// Failed to find a level that covers the desired range. So just
// Failed to find a level that covers the desired range. So just
// extract from the last level, even if it doesn't cover the entire
// desired range.
ts.extract(ts.levels[len(ts.levels)-1], start, finish, num, results)

12
vendor/golang.org/x/net/ipv4/doc.go сгенерированный поставляемый
Просмотреть файл

@@ -21,7 +21,7 @@
//
// The options for unicasting are available for net.TCPConn,
// net.UDPConn and net.IPConn which are created as network connections
// that use the IPv4 transport. When a single TCP connection carrying
// that use the IPv4 transport. When a single TCP connection carrying
// a data flow of multiple packets needs to indicate the flow is
// important, Conn is used to set the type-of-service field on the
// IPv4 header for each packet.
@@ -56,7 +56,7 @@
//
// The options for multicasting are available for net.UDPConn and
// net.IPconn which are created as network connections that use the
// IPv4 transport. A few network facilities must be prepared before
// IPv4 transport. A few network facilities must be prepared before
// you begin multicasting, at a minimum joining network interfaces and
// multicast groups.
//
@@ -80,7 +80,7 @@
// defer c.Close()
//
// Second, the application joins multicast groups, starts listening to
// the groups on the specified network interfaces. Note that the
// the groups on the specified network interfaces. Note that the
// service port for transport layer protocol does not matter with this
// operation as joining groups affects only network and link layer
// protocols, such as IPv4 and Ethernet.
@@ -94,7 +94,7 @@
// }
//
// The application might set per packet control message transmissions
// between the protocol stack within the kernel. When the application
// between the protocol stack within the kernel. When the application
// needs a destination address on an incoming packet,
// SetControlMessage of PacketConn is used to enable control message
// transmissions.
@@ -145,7 +145,7 @@
// More multicasting
//
// An application that uses PacketConn or RawConn may join multiple
// multicast groups. For example, a UDP listener with port 1024 might
// multicast groups. For example, a UDP listener with port 1024 might
// join two different groups across over two different network
// interfaces by using:
//
@@ -166,7 +166,7 @@
// }
//
// It is possible for multiple UDP listeners that listen on the same
// UDP port to join the same multicast group. The net package will
// UDP port to join the same multicast group. The net package will
// provide a socket that listens to a wildcard address with reusable
// UDP port when an appropriate multicast address prefix is passed to
// the net.ListenPacket or net.ListenUDP.

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше