Commit 967c19df authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #50531 from NVIDIA/gRPC-keep-alive-godeps

Automatic merge from submit-queue (batch tested with PRs 50531, 50853, 49976, 50939, 50607) Updated gRPC vendoring to support Keep Alive **What this PR does / why we need it**: This PR bumps the version of the vendored version of gRPC from v1.0.4 to v1.5.1 This is needed as part of the Device Plugin API where we expect client and server to use the Keep alive feature in order to detect an error. Unfortunately I had to also bump the version of `golang.org/x/text` and `golang.org/x/net`. - Design document: kubernetes/community#695 - PR tracking: [kubernetes/features#368](https://github.com/kubernetes/features/issues/368#issuecomment-321625420) **Special notes for your reviewer**: @vishh @jiayingz **Release note**: ``` Bumped gRPC from v1.0.4 to v1.5.1 ```
parents 5c03d375 faee6d6d
...@@ -2715,51 +2715,51 @@ ...@@ -2715,51 +2715,51 @@
}, },
{ {
"ImportPath": "golang.org/x/net/context", "ImportPath": "golang.org/x/net/context",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/context/ctxhttp", "ImportPath": "golang.org/x/net/context/ctxhttp",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/html", "ImportPath": "golang.org/x/net/html",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/html/atom", "ImportPath": "golang.org/x/net/html/atom",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/internal/timeseries", "ImportPath": "golang.org/x/net/internal/timeseries",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/lex/httplex", "ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/proxy", "ImportPath": "golang.org/x/net/proxy",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/trace", "ImportPath": "golang.org/x/net/trace",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/websocket", "ImportPath": "golang.org/x/net/websocket",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/oauth2", "ImportPath": "golang.org/x/oauth2",
...@@ -2791,63 +2791,67 @@ ...@@ -2791,63 +2791,67 @@
}, },
{ {
"ImportPath": "golang.org/x/text/cases", "ImportPath": "golang.org/x/text/cases",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/encoding", "ImportPath": "golang.org/x/text/encoding",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/encoding/internal", "ImportPath": "golang.org/x/text/encoding/internal",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/encoding/internal/identifier", "ImportPath": "golang.org/x/text/encoding/internal/identifier",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/encoding/unicode", "ImportPath": "golang.org/x/text/encoding/unicode",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/internal",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/internal/tag", "ImportPath": "golang.org/x/text/internal/tag",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/internal/utf8internal", "ImportPath": "golang.org/x/text/internal/utf8internal",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/language", "ImportPath": "golang.org/x/text/language",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/runes", "ImportPath": "golang.org/x/text/runes",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/bidirule", "ImportPath": "golang.org/x/text/secure/bidirule",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/precis", "ImportPath": "golang.org/x/text/secure/precis",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/transform", "ImportPath": "golang.org/x/text/transform",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/unicode/bidi", "ImportPath": "golang.org/x/text/unicode/bidi",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/unicode/norm", "ImportPath": "golang.org/x/text/unicode/norm",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/width", "ImportPath": "golang.org/x/text/width",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/time/rate", "ImportPath": "golang.org/x/time/rate",
...@@ -2910,49 +2914,78 @@ ...@@ -2910,49 +2914,78 @@
"Rev": "98825bb0065da4054e5da6db34f5fc598e50bc24" "Rev": "98825bb0065da4054e5da6db34f5fc598e50bc24"
}, },
{ {
"ImportPath": "google.golang.org/genproto/googleapis/rpc/status",
"Rev": "09f6ed296fc66555a25fe4ce95173148778dfa85"
},
{
"ImportPath": "google.golang.org/grpc", "ImportPath": "google.golang.org/grpc",
"Comment": "v1.0.4", "Comment": "v1.5.1",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/codes", "ImportPath": "google.golang.org/grpc/codes",
"Comment": "v1.0.4", "Comment": "v1.5.1",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/credentials", "ImportPath": "google.golang.org/grpc/credentials",
"Comment": "v1.0.4", "Comment": "v1.5.1",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/grpclb/grpc_lb_v1",
"Comment": "v1.5.1",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/grpclog", "ImportPath": "google.golang.org/grpc/grpclog",
"Comment": "v1.0.4", "Comment": "v1.5.1",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/internal", "ImportPath": "google.golang.org/grpc/internal",
"Comment": "v1.0.4", "Comment": "v1.5.1",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/keepalive",
"Comment": "v1.5.1",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/metadata", "ImportPath": "google.golang.org/grpc/metadata",
"Comment": "v1.0.4", "Comment": "v1.5.1",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/naming", "ImportPath": "google.golang.org/grpc/naming",
"Comment": "v1.0.4", "Comment": "v1.5.1",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/peer", "ImportPath": "google.golang.org/grpc/peer",
"Comment": "v1.0.4", "Comment": "v1.5.1",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/stats",
"Comment": "v1.5.1",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/status",
"Comment": "v1.5.1",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/tap",
"Comment": "v1.5.1",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/transport", "ImportPath": "google.golang.org/grpc/transport",
"Comment": "v1.0.4", "Comment": "v1.5.1",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "gopkg.in/gcfg.v1", "ImportPath": "gopkg.in/gcfg.v1",
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -84,59 +84,63 @@ ...@@ -84,59 +84,63 @@
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/lex/httplex", "ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/text/cases", "ImportPath": "golang.org/x/text/cases",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/internal",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/internal/tag", "ImportPath": "golang.org/x/text/internal/tag",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/language", "ImportPath": "golang.org/x/text/language",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/runes", "ImportPath": "golang.org/x/text/runes",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/bidirule", "ImportPath": "golang.org/x/text/secure/bidirule",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/precis", "ImportPath": "golang.org/x/text/secure/precis",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/transform", "ImportPath": "golang.org/x/text/transform",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/unicode/bidi", "ImportPath": "golang.org/x/text/unicode/bidi",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/unicode/norm", "ImportPath": "golang.org/x/text/unicode/norm",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/width", "ImportPath": "golang.org/x/text/width",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "gopkg.in/inf.v0", "ImportPath": "gopkg.in/inf.v0",
......
...@@ -304,43 +304,43 @@ ...@@ -304,43 +304,43 @@
}, },
{ {
"ImportPath": "golang.org/x/net/context", "ImportPath": "golang.org/x/net/context",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/html", "ImportPath": "golang.org/x/net/html",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/html/atom", "ImportPath": "golang.org/x/net/html/atom",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/internal/timeseries", "ImportPath": "golang.org/x/net/internal/timeseries",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/lex/httplex", "ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/trace", "ImportPath": "golang.org/x/net/trace",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/websocket", "ImportPath": "golang.org/x/net/websocket",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/sys/unix", "ImportPath": "golang.org/x/sys/unix",
...@@ -348,79 +348,107 @@ ...@@ -348,79 +348,107 @@
}, },
{ {
"ImportPath": "golang.org/x/text/cases", "ImportPath": "golang.org/x/text/cases",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/internal",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/internal/tag", "ImportPath": "golang.org/x/text/internal/tag",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/language", "ImportPath": "golang.org/x/text/language",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/runes", "ImportPath": "golang.org/x/text/runes",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/bidirule", "ImportPath": "golang.org/x/text/secure/bidirule",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/precis", "ImportPath": "golang.org/x/text/secure/precis",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/transform", "ImportPath": "golang.org/x/text/transform",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/unicode/bidi", "ImportPath": "golang.org/x/text/unicode/bidi",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/unicode/norm", "ImportPath": "golang.org/x/text/unicode/norm",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/width", "ImportPath": "golang.org/x/text/width",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "google.golang.org/genproto/googleapis/rpc/status",
"Rev": "09f6ed296fc66555a25fe4ce95173148778dfa85"
}, },
{ {
"ImportPath": "google.golang.org/grpc", "ImportPath": "google.golang.org/grpc",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/codes", "ImportPath": "google.golang.org/grpc/codes",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/credentials", "ImportPath": "google.golang.org/grpc/credentials",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/grpclb/grpc_lb_v1",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/grpclog", "ImportPath": "google.golang.org/grpc/grpclog",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/internal", "ImportPath": "google.golang.org/grpc/internal",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/keepalive",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/metadata", "ImportPath": "google.golang.org/grpc/metadata",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/naming", "ImportPath": "google.golang.org/grpc/naming",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/peer", "ImportPath": "google.golang.org/grpc/peer",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/stats",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/status",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/tap",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/transport", "ImportPath": "google.golang.org/grpc/transport",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "gopkg.in/inf.v0", "ImportPath": "gopkg.in/inf.v0",
......
...@@ -136,71 +136,75 @@ ...@@ -136,71 +136,75 @@
}, },
{ {
"ImportPath": "golang.org/x/net/html", "ImportPath": "golang.org/x/net/html",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/html/atom", "ImportPath": "golang.org/x/net/html/atom",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/lex/httplex", "ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/websocket", "ImportPath": "golang.org/x/net/websocket",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/text/cases", "ImportPath": "golang.org/x/text/cases",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/internal",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/internal/tag", "ImportPath": "golang.org/x/text/internal/tag",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/language", "ImportPath": "golang.org/x/text/language",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/runes", "ImportPath": "golang.org/x/text/runes",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/bidirule", "ImportPath": "golang.org/x/text/secure/bidirule",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/precis", "ImportPath": "golang.org/x/text/secure/precis",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/transform", "ImportPath": "golang.org/x/text/transform",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/unicode/bidi", "ImportPath": "golang.org/x/text/unicode/bidi",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/unicode/norm", "ImportPath": "golang.org/x/text/unicode/norm",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/width", "ImportPath": "golang.org/x/text/width",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "gopkg.in/inf.v0", "ImportPath": "gopkg.in/inf.v0",
......
...@@ -580,43 +580,43 @@ ...@@ -580,43 +580,43 @@
}, },
{ {
"ImportPath": "golang.org/x/net/context", "ImportPath": "golang.org/x/net/context",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/html", "ImportPath": "golang.org/x/net/html",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/html/atom", "ImportPath": "golang.org/x/net/html/atom",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/internal/timeseries", "ImportPath": "golang.org/x/net/internal/timeseries",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/lex/httplex", "ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/trace", "ImportPath": "golang.org/x/net/trace",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/websocket", "ImportPath": "golang.org/x/net/websocket",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/sys/unix", "ImportPath": "golang.org/x/sys/unix",
...@@ -624,83 +624,111 @@ ...@@ -624,83 +624,111 @@
}, },
{ {
"ImportPath": "golang.org/x/text/cases", "ImportPath": "golang.org/x/text/cases",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/internal",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/internal/tag", "ImportPath": "golang.org/x/text/internal/tag",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/language", "ImportPath": "golang.org/x/text/language",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/runes", "ImportPath": "golang.org/x/text/runes",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/bidirule", "ImportPath": "golang.org/x/text/secure/bidirule",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/precis", "ImportPath": "golang.org/x/text/secure/precis",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/transform", "ImportPath": "golang.org/x/text/transform",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/unicode/bidi", "ImportPath": "golang.org/x/text/unicode/bidi",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/unicode/norm", "ImportPath": "golang.org/x/text/unicode/norm",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/width", "ImportPath": "golang.org/x/text/width",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/time/rate", "ImportPath": "golang.org/x/time/rate",
"Rev": "f51c12702a4d776e4c1fa9b0fabab841babae631" "Rev": "f51c12702a4d776e4c1fa9b0fabab841babae631"
}, },
{ {
"ImportPath": "google.golang.org/genproto/googleapis/rpc/status",
"Rev": "09f6ed296fc66555a25fe4ce95173148778dfa85"
},
{
"ImportPath": "google.golang.org/grpc", "ImportPath": "google.golang.org/grpc",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/codes", "ImportPath": "google.golang.org/grpc/codes",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/credentials", "ImportPath": "google.golang.org/grpc/credentials",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/grpclb/grpc_lb_v1",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/grpclog", "ImportPath": "google.golang.org/grpc/grpclog",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/internal", "ImportPath": "google.golang.org/grpc/internal",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/keepalive",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/metadata", "ImportPath": "google.golang.org/grpc/metadata",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/naming", "ImportPath": "google.golang.org/grpc/naming",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/peer", "ImportPath": "google.golang.org/grpc/peer",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/stats",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/status",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/tap",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/transport", "ImportPath": "google.golang.org/grpc/transport",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "gopkg.in/inf.v0", "ImportPath": "gopkg.in/inf.v0",
......
...@@ -256,27 +256,27 @@ ...@@ -256,27 +256,27 @@
}, },
{ {
"ImportPath": "golang.org/x/net/context", "ImportPath": "golang.org/x/net/context",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/context/ctxhttp", "ImportPath": "golang.org/x/net/context/ctxhttp",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/lex/httplex", "ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/oauth2", "ImportPath": "golang.org/x/oauth2",
...@@ -304,43 +304,47 @@ ...@@ -304,43 +304,47 @@
}, },
{ {
"ImportPath": "golang.org/x/text/cases", "ImportPath": "golang.org/x/text/cases",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/internal",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/internal/tag", "ImportPath": "golang.org/x/text/internal/tag",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/language", "ImportPath": "golang.org/x/text/language",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/runes", "ImportPath": "golang.org/x/text/runes",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/bidirule", "ImportPath": "golang.org/x/text/secure/bidirule",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/precis", "ImportPath": "golang.org/x/text/secure/precis",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/transform", "ImportPath": "golang.org/x/text/transform",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/unicode/bidi", "ImportPath": "golang.org/x/text/unicode/bidi",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/unicode/norm", "ImportPath": "golang.org/x/text/unicode/norm",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/width", "ImportPath": "golang.org/x/text/width",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "gopkg.in/inf.v0", "ImportPath": "gopkg.in/inf.v0",
......
...@@ -224,59 +224,63 @@ ...@@ -224,59 +224,63 @@
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/lex/httplex", "ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/text/cases", "ImportPath": "golang.org/x/text/cases",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/internal",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/internal/tag", "ImportPath": "golang.org/x/text/internal/tag",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/language", "ImportPath": "golang.org/x/text/language",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/runes", "ImportPath": "golang.org/x/text/runes",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/bidirule", "ImportPath": "golang.org/x/text/secure/bidirule",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/precis", "ImportPath": "golang.org/x/text/secure/precis",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/transform", "ImportPath": "golang.org/x/text/transform",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/unicode/bidi", "ImportPath": "golang.org/x/text/unicode/bidi",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/unicode/norm", "ImportPath": "golang.org/x/text/unicode/norm",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/width", "ImportPath": "golang.org/x/text/width",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "gopkg.in/inf.v0", "ImportPath": "gopkg.in/inf.v0",
......
...@@ -300,43 +300,43 @@ ...@@ -300,43 +300,43 @@
}, },
{ {
"ImportPath": "golang.org/x/net/context", "ImportPath": "golang.org/x/net/context",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/html", "ImportPath": "golang.org/x/net/html",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/html/atom", "ImportPath": "golang.org/x/net/html/atom",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/internal/timeseries", "ImportPath": "golang.org/x/net/internal/timeseries",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/lex/httplex", "ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/trace", "ImportPath": "golang.org/x/net/trace",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/websocket", "ImportPath": "golang.org/x/net/websocket",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/sys/unix", "ImportPath": "golang.org/x/sys/unix",
...@@ -344,79 +344,107 @@ ...@@ -344,79 +344,107 @@
}, },
{ {
"ImportPath": "golang.org/x/text/cases", "ImportPath": "golang.org/x/text/cases",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/internal",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/internal/tag", "ImportPath": "golang.org/x/text/internal/tag",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/language", "ImportPath": "golang.org/x/text/language",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/runes", "ImportPath": "golang.org/x/text/runes",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/bidirule", "ImportPath": "golang.org/x/text/secure/bidirule",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/precis", "ImportPath": "golang.org/x/text/secure/precis",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/transform", "ImportPath": "golang.org/x/text/transform",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/unicode/bidi", "ImportPath": "golang.org/x/text/unicode/bidi",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/unicode/norm", "ImportPath": "golang.org/x/text/unicode/norm",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/width", "ImportPath": "golang.org/x/text/width",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "google.golang.org/genproto/googleapis/rpc/status",
"Rev": "09f6ed296fc66555a25fe4ce95173148778dfa85"
}, },
{ {
"ImportPath": "google.golang.org/grpc", "ImportPath": "google.golang.org/grpc",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/codes", "ImportPath": "google.golang.org/grpc/codes",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/credentials", "ImportPath": "google.golang.org/grpc/credentials",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/grpclb/grpc_lb_v1",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/grpclog", "ImportPath": "google.golang.org/grpc/grpclog",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/internal", "ImportPath": "google.golang.org/grpc/internal",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/keepalive",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/metadata", "ImportPath": "google.golang.org/grpc/metadata",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/naming", "ImportPath": "google.golang.org/grpc/naming",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/peer", "ImportPath": "google.golang.org/grpc/peer",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/stats",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/status",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/tap",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/transport", "ImportPath": "google.golang.org/grpc/transport",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "gopkg.in/inf.v0", "ImportPath": "gopkg.in/inf.v0",
......
...@@ -124,59 +124,63 @@ ...@@ -124,59 +124,63 @@
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/lex/httplex", "ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/text/cases", "ImportPath": "golang.org/x/text/cases",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/internal",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/internal/tag", "ImportPath": "golang.org/x/text/internal/tag",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/language", "ImportPath": "golang.org/x/text/language",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/runes", "ImportPath": "golang.org/x/text/runes",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/bidirule", "ImportPath": "golang.org/x/text/secure/bidirule",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/precis", "ImportPath": "golang.org/x/text/secure/precis",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/transform", "ImportPath": "golang.org/x/text/transform",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/unicode/bidi", "ImportPath": "golang.org/x/text/unicode/bidi",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/unicode/norm", "ImportPath": "golang.org/x/text/unicode/norm",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/width", "ImportPath": "golang.org/x/text/width",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "gopkg.in/inf.v0", "ImportPath": "gopkg.in/inf.v0",
......
...@@ -292,43 +292,43 @@ ...@@ -292,43 +292,43 @@
}, },
{ {
"ImportPath": "golang.org/x/net/context", "ImportPath": "golang.org/x/net/context",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/html", "ImportPath": "golang.org/x/net/html",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/html/atom", "ImportPath": "golang.org/x/net/html/atom",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/internal/timeseries", "ImportPath": "golang.org/x/net/internal/timeseries",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/lex/httplex", "ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/trace", "ImportPath": "golang.org/x/net/trace",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/net/websocket", "ImportPath": "golang.org/x/net/websocket",
"Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
}, },
{ {
"ImportPath": "golang.org/x/sys/unix", "ImportPath": "golang.org/x/sys/unix",
...@@ -336,79 +336,107 @@ ...@@ -336,79 +336,107 @@
}, },
{ {
"ImportPath": "golang.org/x/text/cases", "ImportPath": "golang.org/x/text/cases",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/internal",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/internal/tag", "ImportPath": "golang.org/x/text/internal/tag",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/language", "ImportPath": "golang.org/x/text/language",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/runes", "ImportPath": "golang.org/x/text/runes",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/bidirule", "ImportPath": "golang.org/x/text/secure/bidirule",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/precis", "ImportPath": "golang.org/x/text/secure/precis",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/transform", "ImportPath": "golang.org/x/text/transform",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/unicode/bidi", "ImportPath": "golang.org/x/text/unicode/bidi",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/unicode/norm", "ImportPath": "golang.org/x/text/unicode/norm",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/width", "ImportPath": "golang.org/x/text/width",
"Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "google.golang.org/genproto/googleapis/rpc/status",
"Rev": "09f6ed296fc66555a25fe4ce95173148778dfa85"
}, },
{ {
"ImportPath": "google.golang.org/grpc", "ImportPath": "google.golang.org/grpc",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/codes", "ImportPath": "google.golang.org/grpc/codes",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/credentials", "ImportPath": "google.golang.org/grpc/credentials",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/grpclb/grpc_lb_v1",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/grpclog", "ImportPath": "google.golang.org/grpc/grpclog",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/internal", "ImportPath": "google.golang.org/grpc/internal",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/keepalive",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/metadata", "ImportPath": "google.golang.org/grpc/metadata",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/naming", "ImportPath": "google.golang.org/grpc/naming",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/peer", "ImportPath": "google.golang.org/grpc/peer",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/stats",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/status",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
},
{
"ImportPath": "google.golang.org/grpc/tap",
"Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "google.golang.org/grpc/transport", "ImportPath": "google.golang.org/grpc/transport",
"Rev": "777daa17ff9b5daef1cfdf915088a2ada3332bf0" "Rev": "b8669c35455183da6d5c474ea6e72fbf55183274"
}, },
{ {
"ImportPath": "gopkg.in/inf.v0", "ImportPath": "gopkg.in/inf.v0",
......
...@@ -338,8 +338,7 @@ filegroup( ...@@ -338,8 +338,7 @@ filegroup(
"//vendor/golang.org/x/sys/windows:all-srcs", "//vendor/golang.org/x/sys/windows:all-srcs",
"//vendor/golang.org/x/text/cases:all-srcs", "//vendor/golang.org/x/text/cases:all-srcs",
"//vendor/golang.org/x/text/encoding:all-srcs", "//vendor/golang.org/x/text/encoding:all-srcs",
"//vendor/golang.org/x/text/internal/tag:all-srcs", "//vendor/golang.org/x/text/internal:all-srcs",
"//vendor/golang.org/x/text/internal/utf8internal:all-srcs",
"//vendor/golang.org/x/text/language:all-srcs", "//vendor/golang.org/x/text/language:all-srcs",
"//vendor/golang.org/x/text/runes:all-srcs", "//vendor/golang.org/x/text/runes:all-srcs",
"//vendor/golang.org/x/text/secure/bidirule:all-srcs", "//vendor/golang.org/x/text/secure/bidirule:all-srcs",
...@@ -362,6 +361,7 @@ filegroup( ...@@ -362,6 +361,7 @@ filegroup(
"//vendor/google.golang.org/api/logging/v2beta1:all-srcs", "//vendor/google.golang.org/api/logging/v2beta1:all-srcs",
"//vendor/google.golang.org/api/monitoring/v3:all-srcs", "//vendor/google.golang.org/api/monitoring/v3:all-srcs",
"//vendor/google.golang.org/api/pubsub/v1:all-srcs", "//vendor/google.golang.org/api/pubsub/v1:all-srcs",
"//vendor/google.golang.org/genproto/googleapis/rpc/status:all-srcs",
"//vendor/google.golang.org/grpc:all-srcs", "//vendor/google.golang.org/grpc:all-srcs",
"//vendor/gopkg.in/gcfg.v1:all-srcs", "//vendor/gopkg.in/gcfg.v1:all-srcs",
"//vendor/gopkg.in/inf.v0:all-srcs", "//vendor/gopkg.in/inf.v0:all-srcs",
......
...@@ -5,7 +5,9 @@ go_library( ...@@ -5,7 +5,9 @@ go_library(
srcs = [ srcs = [
"context.go", "context.go",
"go17.go", "go17.go",
"go19.go",
"pre_go17.go", "pre_go17.go",
"pre_go19.go",
], ],
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
) )
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
// and between processes. // and between processes.
// //
// Incoming requests to a server should create a Context, and outgoing calls to // 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 // propagate the Context, optionally replacing it with a modified copy created
// using WithDeadline, WithTimeout, WithCancel, or WithValue. // using WithDeadline, WithTimeout, WithCancel, or WithValue.
// //
...@@ -16,14 +16,14 @@ ...@@ -16,14 +16,14 @@
// propagation: // propagation:
// //
// Do not store Contexts inside a struct type; instead, pass a Context // 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: // parameter, typically named ctx:
// //
// func DoSomething(ctx context.Context, arg Arg) error { // func DoSomething(ctx context.Context, arg Arg) error {
// // ... use ctx ... // // ... 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. // if you are unsure about which Context to use.
// //
// Use context Values only for request-scoped data that transits processes and // Use context Values only for request-scoped data that transits processes and
...@@ -36,112 +36,15 @@ ...@@ -36,112 +36,15 @@
// Contexts. // Contexts.
package context package context
import "time"
// A Context carries a deadline, a cancelation signal, and other values across
// API boundaries.
//
// 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.
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.
//
// WithCancel arranges for Done to be closed when cancel is called;
// WithDeadline arranges for Done to be closed when the deadline
// expires; WithTimeout arranges for Done to be closed when the timeout
// elapses.
//
// Done is provided for use in select statements:
//
// // Stream generates values with DoSomething and sends them to out
// // until DoSomething returns an error or ctx.Done is closed.
// func Stream(ctx context.Context, out chan<- Value) error {
// for {
// v, err := DoSomething(ctx)
// if err != nil {
// return err
// }
// select {
// case <-ctx.Done():
// return ctx.Err()
// case out <- v:
// }
// }
// }
//
// See http://blog.golang.org/pipelines for more examples of how to use
// a Done channel for cancelation.
Done() <-chan struct{}
// 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.
// 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
// 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
// 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;
// packages should define keys as an unexported type to avoid
// collisions.
//
// Packages that define a Context key should provide type-safe accessors
// for the values stores using that key:
//
// // Package user defines a User type that's stored in Contexts.
// package user
//
// import "golang.org/x/net/context"
//
// // User is the type of value stored in the Contexts.
// type User struct {...}
//
// // key is an unexported type for keys defined in this package.
// // This prevents collisions with keys defined in other packages.
// type key int
//
// // 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
//
// // NewContext returns a new Context that carries value u.
// func NewContext(ctx context.Context, u *User) context.Context {
// return context.WithValue(ctx, userKey, u)
// }
//
// // FromContext returns the User value stored in ctx, if any.
// func FromContext(ctx context.Context) (*User, bool) {
// u, ok := ctx.Value(userKey).(*User)
// return u, ok
// }
Value(key interface{}) interface{}
}
// Background returns a non-nil, empty Context. It is never canceled, has no // 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 // initialization, and tests, and as the top-level Context for incoming
// requests. // requests.
func Background() Context { func Background() Context {
return background 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 // 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 // surrounding function has not yet been extended to accept a Context
// parameter). TODO is recognized by static analysis tools that determine // parameter). TODO is recognized by static analysis tools that determine
...@@ -149,8 +52,3 @@ func Background() Context { ...@@ -149,8 +52,3 @@ func Background() Context {
func TODO() Context { func TODO() Context {
return todo return todo
} }
// A CancelFunc tells an operation to abandon its work.
// A CancelFunc does not wait for the work to stop.
// After the first call, subsequent calls to a CancelFunc do nothing.
type CancelFunc func()
...@@ -35,8 +35,8 @@ func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { ...@@ -35,8 +35,8 @@ func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
} }
// WithDeadline returns a copy of the parent context with the deadline adjusted // 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, // 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 // WithDeadline(parent, d) is semantically equivalent to parent. The returned
// context's Done channel is closed when the deadline expires, when 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 // cancel function is called, or when the parent context's Done channel is
// closed, whichever happens first. // closed, whichever happens first.
......
// 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 context
import "context" // standard library's context, as of Go 1.7
// A Context carries a deadline, a cancelation signal, and other values across
// API boundaries.
//
// Context's methods may be called by multiple goroutines simultaneously.
type Context = context.Context
// A CancelFunc tells an operation to abandon its work.
// A CancelFunc does not wait for the work to stop.
// After the first call, subsequent calls to a CancelFunc do nothing.
type CancelFunc = context.CancelFunc
...@@ -13,7 +13,7 @@ import ( ...@@ -13,7 +13,7 @@ import (
"time" "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. // struct{}, since vars of this type must have distinct addresses.
type emptyCtx int type emptyCtx int
...@@ -104,7 +104,7 @@ func propagateCancel(parent Context, child canceler) { ...@@ -104,7 +104,7 @@ func propagateCancel(parent Context, child canceler) {
} }
// parentCancelCtx follows a chain of parent references until it finds a // 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. // package represents its parent.
func parentCancelCtx(parent Context) (*cancelCtx, bool) { func parentCancelCtx(parent Context) (*cancelCtx, bool) {
for { for {
...@@ -134,14 +134,14 @@ func removeChild(parent Context, child canceler) { ...@@ -134,14 +134,14 @@ func removeChild(parent Context, child canceler) {
p.mu.Unlock() 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. // implementations are *cancelCtx and *timerCtx.
type canceler interface { type canceler interface {
cancel(removeFromParent bool, err error) cancel(removeFromParent bool, err error)
Done() <-chan struct{} 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. // that implement canceler.
type cancelCtx struct { type cancelCtx struct {
Context Context
...@@ -193,8 +193,8 @@ func (c *cancelCtx) cancel(removeFromParent bool, err error) { ...@@ -193,8 +193,8 @@ func (c *cancelCtx) cancel(removeFromParent bool, err error) {
} }
// WithDeadline returns a copy of the parent context with the deadline adjusted // 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, // 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 // WithDeadline(parent, d) is semantically equivalent to parent. The returned
// context's Done channel is closed when the deadline expires, when 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 // cancel function is called, or when the parent context's Done channel is
// closed, whichever happens first. // closed, whichever happens first.
...@@ -226,8 +226,8 @@ func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) { ...@@ -226,8 +226,8 @@ func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
return c, func() { c.cancel(true, Canceled) } return c, func() { c.cancel(true, Canceled) }
} }
// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to // 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 // implement Done and Err. It implements cancel by stopping its timer then
// delegating to cancelCtx.cancel. // delegating to cancelCtx.cancel.
type timerCtx struct { type timerCtx struct {
*cancelCtx *cancelCtx
...@@ -281,7 +281,7 @@ func WithValue(parent Context, key interface{}, val interface{}) Context { ...@@ -281,7 +281,7 @@ func WithValue(parent Context, key interface{}, val interface{}) Context {
return &valueCtx{parent, key, val} 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. // delegates all other calls to the embedded Context.
type valueCtx struct { type valueCtx struct {
Context Context
......
// 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.
// +build !go1.9
package context
import "time"
// A Context carries a deadline, a cancelation signal, and other values across
// API boundaries.
//
// 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.
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.
//
// WithCancel arranges for Done to be closed when cancel is called;
// WithDeadline arranges for Done to be closed when the deadline
// expires; WithTimeout arranges for Done to be closed when the timeout
// elapses.
//
// Done is provided for use in select statements:
//
// // Stream generates values with DoSomething and sends them to out
// // until DoSomething returns an error or ctx.Done is closed.
// func Stream(ctx context.Context, out chan<- Value) error {
// for {
// v, err := DoSomething(ctx)
// if err != nil {
// return err
// }
// select {
// case <-ctx.Done():
// return ctx.Err()
// case out <- v:
// }
// }
// }
//
// See http://blog.golang.org/pipelines for more examples of how to use
// a Done channel for cancelation.
Done() <-chan struct{}
// 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.
// 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
// 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
// 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;
// packages should define keys as an unexported type to avoid
// collisions.
//
// Packages that define a Context key should provide type-safe accessors
// for the values stores using that key:
//
// // Package user defines a User type that's stored in Contexts.
// package user
//
// import "golang.org/x/net/context"
//
// // User is the type of value stored in the Contexts.
// type User struct {...}
//
// // key is an unexported type for keys defined in this package.
// // This prevents collisions with keys defined in other packages.
// type key int
//
// // 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
//
// // NewContext returns a new Context that carries value u.
// func NewContext(ctx context.Context, u *User) context.Context {
// return context.WithValue(ctx, userKey, u)
// }
//
// // FromContext returns the User value stored in ctx, if any.
// func FromContext(ctx context.Context) (*User, bool) {
// u, ok := ctx.Value(userKey).(*User)
// return u, ok
// }
Value(key interface{}) interface{}
}
// A CancelFunc tells an operation to abandon its work.
// A CancelFunc does not wait for the work to stop.
// After the first call, subsequent calls to a CancelFunc do nothing.
type CancelFunc func()
...@@ -3,22 +3,25 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") ...@@ -3,22 +3,25 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = [ srcs = [
"ciphers.go",
"client_conn_pool.go", "client_conn_pool.go",
"configure_transport.go", "configure_transport.go",
"databuffer.go",
"errors.go", "errors.go",
"fixed_buffer.go",
"flow.go", "flow.go",
"frame.go", "frame.go",
"go16.go", "go16.go",
"go17.go", "go17.go",
"go17_not18.go", "go17_not18.go",
"go18.go", "go18.go",
"go19.go",
"gotrack.go", "gotrack.go",
"headermap.go", "headermap.go",
"http2.go", "http2.go",
"not_go16.go", "not_go16.go",
"not_go17.go", "not_go17.go",
"not_go18.go", "not_go18.go",
"not_go19.go",
"pipe.go", "pipe.go",
"server.go", "server.go",
"transport.go", "transport.go",
......
...@@ -247,7 +247,7 @@ func filterOutClientConn(in []*ClientConn, exclude *ClientConn) []*ClientConn { ...@@ -247,7 +247,7 @@ func filterOutClientConn(in []*ClientConn, exclude *ClientConn) []*ClientConn {
} }
// noDialClientConnPool is an implementation of http2.ClientConnPool // 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. // connection instead.
type noDialClientConnPool struct{ *clientConnPool } type noDialClientConnPool struct{ *clientConnPool }
......
...@@ -56,7 +56,7 @@ func configureTransport(t1 *http.Transport) (*Transport, error) { ...@@ -56,7 +56,7 @@ func configureTransport(t1 *http.Transport) (*Transport, error) {
} }
// registerHTTPSProtocol calls Transport.RegisterProtocol but // registerHTTPSProtocol calls Transport.RegisterProtocol but
// convering panics into errors. // converting panics into errors.
func registerHTTPSProtocol(t *http.Transport, rt http.RoundTripper) (err error) { func registerHTTPSProtocol(t *http.Transport, rt http.RoundTripper) (err error) {
defer func() { defer func() {
if e := recover(); e != nil { if e := recover(); e != nil {
......
// 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
}
...@@ -87,13 +87,16 @@ type goAwayFlowError struct{} ...@@ -87,13 +87,16 @@ type goAwayFlowError struct{}
func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" } func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" }
// connErrorReason wraps a ConnectionError with an informative error about why it occurs. // connError represents an HTTP/2 ConnectionError error code, along
// with a string (for debugging) explaining why.
//
// Errors of this type are only returned by the frame parser functions // Errors of this type are only returned by the frame parser functions
// and converted into ConnectionError(ErrCodeProtocol). // and converted into ConnectionError(Code), after stashing away
// the Reason into the Framer's errDetail field, accessible via
// the (*Framer).ErrorDetail method.
type connError struct { type connError struct {
Code ErrCode Code ErrCode // the ConnectionError error code
Reason string Reason string // additional reason
} }
func (e connError) Error() string { func (e connError) Error() string {
......
// 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
}
...@@ -122,7 +122,7 @@ var flagName = map[FrameType]map[Flags]string{ ...@@ -122,7 +122,7 @@ var flagName = map[FrameType]map[Flags]string{
// a frameParser parses a frame given its FrameHeader and payload // a frameParser parses a frame given its FrameHeader and payload
// bytes. The length of payload will always equal fh.Length (which // bytes. The length of payload will always equal fh.Length (which
// might be 0). // 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{ var frameParsers = map[FrameType]frameParser{
FrameData: parseDataFrame, FrameData: parseDataFrame,
...@@ -312,7 +312,7 @@ type Framer struct { ...@@ -312,7 +312,7 @@ type Framer struct {
MaxHeaderListSize uint32 MaxHeaderListSize uint32
// TODO: track which type of frame & with which flags was sent // 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 // we're in the middle of a header block and a
// non-Continuation or Continuation on a different stream is // non-Continuation or Continuation on a different stream is
// attempted to be written. // attempted to be written.
...@@ -323,6 +323,8 @@ type Framer struct { ...@@ -323,6 +323,8 @@ type Framer struct {
debugFramerBuf *bytes.Buffer debugFramerBuf *bytes.Buffer
debugReadLoggerf func(string, ...interface{}) debugReadLoggerf func(string, ...interface{})
debugWriteLoggerf func(string, ...interface{}) debugWriteLoggerf func(string, ...interface{})
frameCache *frameCache // nil if frames aren't reused (default)
} }
func (fr *Framer) maxHeaderListSize() uint32 { func (fr *Framer) maxHeaderListSize() uint32 {
...@@ -398,6 +400,27 @@ const ( ...@@ -398,6 +400,27 @@ const (
maxFrameSize = 1<<24 - 1 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. // NewFramer returns a Framer that writes frames to w and reads them from r.
func NewFramer(w io.Writer, r io.Reader) *Framer { func NewFramer(w io.Writer, r io.Reader) *Framer {
fr := &Framer{ fr := &Framer{
...@@ -477,7 +500,7 @@ func (fr *Framer) ReadFrame() (Frame, error) { ...@@ -477,7 +500,7 @@ func (fr *Framer) ReadFrame() (Frame, error) {
if _, err := io.ReadFull(fr.r, payload); err != nil { if _, err := io.ReadFull(fr.r, payload); err != nil {
return nil, err return nil, err
} }
f, err := typeFrameParser(fh.Type)(fh, payload) f, err := typeFrameParser(fh.Type)(fr.frameCache, fh, payload)
if err != nil { if err != nil {
if ce, ok := err.(connError); ok { if ce, ok := err.(connError); ok {
return nil, fr.connError(ce.Code, ce.Reason) return nil, fr.connError(ce.Code, ce.Reason)
...@@ -565,7 +588,7 @@ func (f *DataFrame) Data() []byte { ...@@ -565,7 +588,7 @@ func (f *DataFrame) Data() []byte {
return f.data 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 { if fh.StreamID == 0 {
// DATA frames MUST be associated with a stream. If a // DATA frames MUST be associated with a stream. If a
// DATA frame is received whose stream identifier // DATA frame is received whose stream identifier
...@@ -574,9 +597,9 @@ func parseDataFrame(fh FrameHeader, payload []byte) (Frame, error) { ...@@ -574,9 +597,9 @@ func parseDataFrame(fh FrameHeader, payload []byte) (Frame, error) {
// PROTOCOL_ERROR. // PROTOCOL_ERROR.
return nil, connError{ErrCodeProtocol, "DATA frame with stream ID 0"} return nil, connError{ErrCodeProtocol, "DATA frame with stream ID 0"}
} }
f := &DataFrame{ f := fc.getDataFrame()
FrameHeader: fh, f.FrameHeader = fh
}
var padSize byte var padSize byte
if fh.Flags.Has(FlagDataPadded) { if fh.Flags.Has(FlagDataPadded) {
var err error var err error
...@@ -600,6 +623,7 @@ var ( ...@@ -600,6 +623,7 @@ var (
errStreamID = errors.New("invalid stream ID") errStreamID = errors.New("invalid stream ID")
errDepStreamID = errors.New("invalid dependent stream ID") errDepStreamID = errors.New("invalid dependent stream ID")
errPadLength = errors.New("pad length too large") 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 { func validStreamIDOrZero(streamID uint32) bool {
...@@ -623,6 +647,7 @@ func (f *Framer) WriteData(streamID uint32, endStream bool, data []byte) error { ...@@ -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. // If pad is nil, the padding bit is not sent.
// The length of pad must not exceed 255 bytes. // 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 will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility not to violate the maximum frame size // 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 ...@@ -631,8 +656,18 @@ func (f *Framer) WriteDataPadded(streamID uint32, endStream bool, data, pad []by
if !validStreamID(streamID) && !f.AllowIllegalWrites { if !validStreamID(streamID) && !f.AllowIllegalWrites {
return errStreamID return errStreamID
} }
if len(pad) > 255 { if len(pad) > 0 {
return errPadLength 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 var flags Flags
if endStream { if endStream {
...@@ -660,10 +695,10 @@ type SettingsFrame struct { ...@@ -660,10 +695,10 @@ type SettingsFrame struct {
p []byte 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 { if fh.Flags.Has(FlagSettingsAck) && fh.Length > 0 {
// When this (ACK 0x1) bit is set, the payload of the // 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 // SETTINGS frame with the ACK flag set and a length
// field value other than 0 MUST be treated as a // field value other than 0 MUST be treated as a
// connection error (Section 5.4.1) of type // connection error (Section 5.4.1) of type
...@@ -672,7 +707,7 @@ func parseSettingsFrame(fh FrameHeader, p []byte) (Frame, error) { ...@@ -672,7 +707,7 @@ func parseSettingsFrame(fh FrameHeader, p []byte) (Frame, error) {
} }
if fh.StreamID != 0 { if fh.StreamID != 0 {
// SETTINGS frames always apply to a connection, // 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 // SETTINGS frame MUST be zero (0x0). If an endpoint
// receives a SETTINGS frame whose stream identifier // receives a SETTINGS frame whose stream identifier
// field is anything other than 0x0, the endpoint MUST // field is anything other than 0x0, the endpoint MUST
...@@ -762,7 +797,7 @@ type PingFrame struct { ...@@ -762,7 +797,7 @@ type PingFrame struct {
func (f *PingFrame) IsAck() bool { return f.Flags.Has(FlagPingAck) } 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 { if len(payload) != 8 {
return nil, ConnectionError(ErrCodeFrameSize) return nil, ConnectionError(ErrCodeFrameSize)
} }
...@@ -802,7 +837,7 @@ func (f *GoAwayFrame) DebugData() []byte { ...@@ -802,7 +837,7 @@ func (f *GoAwayFrame) DebugData() []byte {
return f.debugData return f.debugData
} }
func parseGoAwayFrame(fh FrameHeader, p []byte) (Frame, error) { func parseGoAwayFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
if fh.StreamID != 0 { if fh.StreamID != 0 {
return nil, ConnectionError(ErrCodeProtocol) return nil, ConnectionError(ErrCodeProtocol)
} }
...@@ -842,7 +877,7 @@ func (f *UnknownFrame) Payload() []byte { ...@@ -842,7 +877,7 @@ func (f *UnknownFrame) Payload() []byte {
return f.p 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 return &UnknownFrame{fh, p}, nil
} }
...@@ -853,7 +888,7 @@ type WindowUpdateFrame struct { ...@@ -853,7 +888,7 @@ type WindowUpdateFrame struct {
Increment uint32 // never read with high bit set 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 { if len(p) != 4 {
return nil, ConnectionError(ErrCodeFrameSize) return nil, ConnectionError(ErrCodeFrameSize)
} }
...@@ -918,12 +953,12 @@ func (f *HeadersFrame) HasPriority() bool { ...@@ -918,12 +953,12 @@ func (f *HeadersFrame) HasPriority() bool {
return f.FrameHeader.Flags.Has(FlagHeadersPriority) 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{ hf := &HeadersFrame{
FrameHeader: fh, FrameHeader: fh,
} }
if fh.StreamID == 0 { 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 // is received whose stream identifier field is 0x0, the recipient MUST
// respond with a connection error (Section 5.4.1) of type // respond with a connection error (Section 5.4.1) of type
// PROTOCOL_ERROR. // PROTOCOL_ERROR.
...@@ -1045,7 +1080,7 @@ type PriorityParam struct { ...@@ -1045,7 +1080,7 @@ type PriorityParam struct {
Exclusive bool Exclusive bool
// Weight is the stream's zero-indexed weight. It should be // 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 // the spec, "Add one to the value to obtain a weight between
// 1 and 256." // 1 and 256."
Weight uint8 Weight uint8
...@@ -1055,7 +1090,7 @@ func (p PriorityParam) IsZero() bool { ...@@ -1055,7 +1090,7 @@ func (p PriorityParam) IsZero() bool {
return p == PriorityParam{} return p == PriorityParam{}
} }
func parsePriorityFrame(fh FrameHeader, payload []byte) (Frame, error) { func parsePriorityFrame(_ *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
if fh.StreamID == 0 { if fh.StreamID == 0 {
return nil, connError{ErrCodeProtocol, "PRIORITY frame with stream ID 0"} return nil, connError{ErrCodeProtocol, "PRIORITY frame with stream ID 0"}
} }
...@@ -1102,7 +1137,7 @@ type RSTStreamFrame struct { ...@@ -1102,7 +1137,7 @@ type RSTStreamFrame struct {
ErrCode ErrCode ErrCode ErrCode
} }
func parseRSTStreamFrame(fh FrameHeader, p []byte) (Frame, error) { func parseRSTStreamFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
if len(p) != 4 { if len(p) != 4 {
return nil, ConnectionError(ErrCodeFrameSize) return nil, ConnectionError(ErrCodeFrameSize)
} }
...@@ -1132,7 +1167,7 @@ type ContinuationFrame struct { ...@@ -1132,7 +1167,7 @@ type ContinuationFrame struct {
headerFragBuf []byte headerFragBuf []byte
} }
func parseContinuationFrame(fh FrameHeader, p []byte) (Frame, error) { func parseContinuationFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
if fh.StreamID == 0 { if fh.StreamID == 0 {
return nil, connError{ErrCodeProtocol, "CONTINUATION frame with stream ID 0"} return nil, connError{ErrCodeProtocol, "CONTINUATION frame with stream ID 0"}
} }
...@@ -1182,7 +1217,7 @@ func (f *PushPromiseFrame) HeadersEnded() bool { ...@@ -1182,7 +1217,7 @@ func (f *PushPromiseFrame) HeadersEnded() bool {
return f.FrameHeader.Flags.Has(FlagPushPromiseEndHeaders) 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{ pp := &PushPromiseFrame{
FrameHeader: fh, FrameHeader: fh,
} }
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
package http2 package http2
import ( import (
"crypto/tls"
"net/http" "net/http"
"time" "time"
) )
...@@ -15,29 +14,3 @@ import ( ...@@ -15,29 +14,3 @@ import (
func transportExpectContinueTimeout(t1 *http.Transport) time.Duration { func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
return t1.ExpectContinueTimeout return t1.ExpectContinueTimeout
} }
// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
func isBadCipher(cipher uint16) bool {
switch cipher {
case tls.TLS_RSA_WITH_RC4_128_SHA,
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
// Reject cipher suites from Appendix A.
// "This list includes those cipher suites that do not
// offer an ephemeral key exchange and those that are
// based on the TLS null, stream or block cipher type"
return true
default:
return false
}
}
...@@ -12,7 +12,11 @@ import ( ...@@ -12,7 +12,11 @@ import (
"net/http" "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) var _ http.Pusher = (*responseWriter)(nil)
...@@ -48,3 +52,5 @@ func reqGetBody(req *http.Request) func() (io.ReadCloser, error) { ...@@ -48,3 +52,5 @@ func reqGetBody(req *http.Request) func() (io.ReadCloser, error) {
func reqBodyIsNoBody(body io.ReadCloser) bool { func reqBodyIsNoBody(body io.ReadCloser) bool {
return body == http.NoBody return body == http.NoBody
} }
func go18httpNoBody() io.ReadCloser { return http.NoBody } // for tests only
// 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
package http2
import (
"net/http"
)
func configureServer19(s *http.Server, conf *Server) error {
s.RegisterOnShutdown(conf.state.startGracefulShutdown)
return nil
}
...@@ -39,13 +39,14 @@ func NewEncoder(w io.Writer) *Encoder { ...@@ -39,13 +39,14 @@ func NewEncoder(w io.Writer) *Encoder {
tableSizeUpdate: false, tableSizeUpdate: false,
w: w, w: w,
} }
e.dynTab.table.init()
e.dynTab.setMaxSize(initialHeaderTableSize) e.dynTab.setMaxSize(initialHeaderTableSize)
return e return e
} }
// WriteField encodes f into a single Write to e's underlying Writer. // WriteField encodes f into a single Write to e's underlying Writer.
// This function may also produce bytes for "Header Table Size Update" // 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 { func (e *Encoder) WriteField(f HeaderField) error {
e.buf = e.buf[:0] e.buf = e.buf[:0]
...@@ -88,29 +89,17 @@ func (e *Encoder) WriteField(f HeaderField) error { ...@@ -88,29 +89,17 @@ func (e *Encoder) WriteField(f HeaderField) error {
// only name matches, i points to that index and nameValueMatch // only name matches, i points to that index and nameValueMatch
// becomes false. // becomes false.
func (e *Encoder) searchTable(f HeaderField) (i uint64, nameValueMatch bool) { func (e *Encoder) searchTable(f HeaderField) (i uint64, nameValueMatch bool) {
for idx, hf := range staticTable { i, nameValueMatch = staticTable.search(f)
if !constantTimeStringCompare(hf.Name, f.Name) { if nameValueMatch {
continue return i, true
}
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
} }
j, nameValueMatch := e.dynTab.search(f) j, nameValueMatch := e.dynTab.table.search(f)
if nameValueMatch || (i == 0 && j != 0) { 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. // SetMaxDynamicTableSize changes the dynamic header table size to v.
......
...@@ -61,7 +61,7 @@ func (hf HeaderField) String() string { ...@@ -61,7 +61,7 @@ func (hf HeaderField) String() string {
func (hf HeaderField) Size() uint32 { func (hf HeaderField) Size() uint32 {
// http://http2.github.io/http2-spec/compression.html#rfc.section.4.1 // 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 // "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 (as defined in Section 5.2), its value's
// length in octets (see Section 5.2), plus 32. The size of // length in octets (see Section 5.2), plus 32. The size of
// an entry is calculated using the length of the name and // an entry is calculated using the length of the name and
...@@ -102,6 +102,7 @@ func NewDecoder(maxDynamicTableSize uint32, emitFunc func(f HeaderField)) *Decod ...@@ -102,6 +102,7 @@ func NewDecoder(maxDynamicTableSize uint32, emitFunc func(f HeaderField)) *Decod
emit: emitFunc, emit: emitFunc,
emitEnabled: true, emitEnabled: true,
} }
d.dynTab.table.init()
d.dynTab.allowedMaxSize = maxDynamicTableSize d.dynTab.allowedMaxSize = maxDynamicTableSize
d.dynTab.setMaxSize(maxDynamicTableSize) d.dynTab.setMaxSize(maxDynamicTableSize)
return d return d
...@@ -154,12 +155,9 @@ func (d *Decoder) SetAllowedMaxDynamicTableSize(v uint32) { ...@@ -154,12 +155,9 @@ func (d *Decoder) SetAllowedMaxDynamicTableSize(v uint32) {
} }
type dynamicTable struct { type dynamicTable struct {
// ents is the FIFO described at
// http://http2.github.io/http2-spec/compression.html#rfc.section.2.3.2 // 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 table headerFieldTable
// evicted from the front. size uint32 // in bytes
ents []HeaderField
size uint32
maxSize uint32 // current maxSize maxSize uint32 // current maxSize
allowedMaxSize uint32 // maxSize may go up to this, inclusive allowedMaxSize uint32 // maxSize may go up to this, inclusive
} }
...@@ -169,95 +167,45 @@ func (dt *dynamicTable) setMaxSize(v uint32) { ...@@ -169,95 +167,45 @@ func (dt *dynamicTable) setMaxSize(v uint32) {
dt.evict() 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) { func (dt *dynamicTable) add(f HeaderField) {
dt.ents = append(dt.ents, f) dt.table.addEntry(f)
dt.size += f.Size() dt.size += f.Size()
dt.evict() 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() { func (dt *dynamicTable) evict() {
base := dt.ents // keep base pointer of slice var n int
for dt.size > dt.maxSize { for dt.size > dt.maxSize && n < dt.table.len() {
dt.size -= dt.ents[0].Size() dt.size -= dt.table.ents[n].Size()
dt.ents = dt.ents[1:] 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)]
} }
} dt.table.evictOldest(n)
// 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
} }
func (d *Decoder) maxTableIndex() int { 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) { func (d *Decoder) at(i uint64) (hf HeaderField, ok bool) {
if i < 1 { // See Section 2.3.3.
if i == 0 {
return return
} }
if i <= uint64(staticTable.len()) {
return staticTable.ents[i-1], true
}
if i > uint64(d.maxTableIndex()) { if i > uint64(d.maxTableIndex()) {
return return
} }
if i <= uint64(len(staticTable)) { // In the dynamic table, newer entries have lower indices.
return staticTable[i-1], true // However, dt.ents[0] is the oldest entry. Hence, dt.ents is
} // the reversed dynamic table.
dents := d.dynTab.ents dt := d.dynTab.table
return dents[len(dents)-(int(i)-len(staticTable))], true return dt.ents[dt.len()-(int(i)-staticTable.len())], true
} }
// Decode decodes an entire block. // Decode decodes an entire block.
...@@ -307,7 +255,7 @@ func (d *Decoder) Write(p []byte) (n int, err error) { ...@@ -307,7 +255,7 @@ func (d *Decoder) Write(p []byte) (n int, err error) {
err = d.parseHeaderFieldRepr() err = d.parseHeaderFieldRepr()
if err == errNeedMore { if err == errNeedMore {
// Extra paranoia, making sure saveBuf won't // 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 // reading code earlier should already catch
// overlong things and return ErrStringLength, // overlong things and return ErrStringLength,
// but keep this as a last resort. // but keep this as a last resort.
......
...@@ -4,73 +4,200 @@ ...@@ -4,73 +4,200 @@
package hpack package hpack
func pair(name, value string) HeaderField { import (
return HeaderField{Name: name, Value: value} "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 {
delete(t.byName, f.Name)
}
if p := (pairNameValue{f.Name, f.Value}); t.byNameValue[p] == id {
delete(t.byNameValue, p)
}
}
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
} }
// http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B // http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B
var staticTable = [...]HeaderField{ var staticTable = newStaticTable()
pair(":authority", ""), // index 1 (1-based) var staticTableEntries = [...]HeaderField{
pair(":method", "GET"), {Name: ":authority"},
pair(":method", "POST"), {Name: ":method", Value: "GET"},
pair(":path", "/"), {Name: ":method", Value: "POST"},
pair(":path", "/index.html"), {Name: ":path", Value: "/"},
pair(":scheme", "http"), {Name: ":path", Value: "/index.html"},
pair(":scheme", "https"), {Name: ":scheme", Value: "http"},
pair(":status", "200"), {Name: ":scheme", Value: "https"},
pair(":status", "204"), {Name: ":status", Value: "200"},
pair(":status", "206"), {Name: ":status", Value: "204"},
pair(":status", "304"), {Name: ":status", Value: "206"},
pair(":status", "400"), {Name: ":status", Value: "304"},
pair(":status", "404"), {Name: ":status", Value: "400"},
pair(":status", "500"), {Name: ":status", Value: "404"},
pair("accept-charset", ""), {Name: ":status", Value: "500"},
pair("accept-encoding", "gzip, deflate"), {Name: "accept-charset"},
pair("accept-language", ""), {Name: "accept-encoding", Value: "gzip, deflate"},
pair("accept-ranges", ""), {Name: "accept-language"},
pair("accept", ""), {Name: "accept-ranges"},
pair("access-control-allow-origin", ""), {Name: "accept"},
pair("age", ""), {Name: "access-control-allow-origin"},
pair("allow", ""), {Name: "age"},
pair("authorization", ""), {Name: "allow"},
pair("cache-control", ""), {Name: "authorization"},
pair("content-disposition", ""), {Name: "cache-control"},
pair("content-encoding", ""), {Name: "content-disposition"},
pair("content-language", ""), {Name: "content-encoding"},
pair("content-length", ""), {Name: "content-language"},
pair("content-location", ""), {Name: "content-length"},
pair("content-range", ""), {Name: "content-location"},
pair("content-type", ""), {Name: "content-range"},
pair("cookie", ""), {Name: "content-type"},
pair("date", ""), {Name: "cookie"},
pair("etag", ""), {Name: "date"},
pair("expect", ""), {Name: "etag"},
pair("expires", ""), {Name: "expect"},
pair("from", ""), {Name: "expires"},
pair("host", ""), {Name: "from"},
pair("if-match", ""), {Name: "host"},
pair("if-modified-since", ""), {Name: "if-match"},
pair("if-none-match", ""), {Name: "if-modified-since"},
pair("if-range", ""), {Name: "if-none-match"},
pair("if-unmodified-since", ""), {Name: "if-range"},
pair("last-modified", ""), {Name: "if-unmodified-since"},
pair("link", ""), {Name: "last-modified"},
pair("location", ""), {Name: "link"},
pair("max-forwards", ""), {Name: "location"},
pair("proxy-authenticate", ""), {Name: "max-forwards"},
pair("proxy-authorization", ""), {Name: "proxy-authenticate"},
pair("range", ""), {Name: "proxy-authorization"},
pair("referer", ""), {Name: "range"},
pair("refresh", ""), {Name: "referer"},
pair("retry-after", ""), {Name: "refresh"},
pair("server", ""), {Name: "retry-after"},
pair("set-cookie", ""), {Name: "server"},
pair("strict-transport-security", ""), {Name: "set-cookie"},
pair("transfer-encoding", ""), {Name: "strict-transport-security"},
pair("user-agent", ""), {Name: "transfer-encoding"},
pair("vary", ""), {Name: "user-agent"},
pair("via", ""), {Name: "vary"},
pair("www-authenticate", ""), {Name: "via"},
{Name: "www-authenticate"},
}
func newStaticTable() *headerFieldTable {
t := &headerFieldTable{}
t.init()
for _, e := range staticTableEntries[:] {
t.addEntry(e)
}
return t
} }
var huffmanCodes = [256]uint32{ var huffmanCodes = [256]uint32{
......
...@@ -376,12 +376,16 @@ func (s *sorter) SortStrings(ss []string) { ...@@ -376,12 +376,16 @@ func (s *sorter) SortStrings(ss []string) {
// validPseudoPath reports whether v is a valid :path pseudo-header // validPseudoPath reports whether v is a valid :path pseudo-header
// value. It must be either: // value. It must be either:
// //
// *) a non-empty string starting with '/', but not with with "//", // *) a non-empty string starting with '/'
// *) the string '*', for OPTIONS requests. // *) the string '*', for OPTIONS requests.
// //
// For now this is only used a quick check for deciding when to clean // For now this is only used a quick check for deciding when to clean
// up Opaque URLs before sending requests from the Transport. // up Opaque URLs before sending requests from the Transport.
// See golang.org/issue/16847 // See golang.org/issue/16847
//
// We used to enforce that the path also didn't start with "//", but
// Google's GFE accepts such paths and Chrome sends them, so ignore
// that part of the spec. See golang.org/issue/19103.
func validPseudoPath(v string) bool { func validPseudoPath(v string) bool {
return (len(v) > 0 && v[0] == '/' && (len(v) == 1 || v[1] != '/')) || v == "*" return (len(v) > 0 && v[0] == '/') || v == "*"
} }
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
package http2 package http2
import ( import (
"crypto/tls"
"net/http" "net/http"
"time" "time"
) )
...@@ -20,27 +19,3 @@ func transportExpectContinueTimeout(t1 *http.Transport) time.Duration { ...@@ -20,27 +19,3 @@ func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
return 0 return 0
} }
// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
func isBadCipher(cipher uint16) bool {
switch cipher {
case tls.TLS_RSA_WITH_RC4_128_SHA,
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
// Reject cipher suites from Appendix A.
// "This list includes those cipher suites that do not
// offer an ephemeral key exchange and those that are
// based on the TLS null, stream or block cipher type"
return true
default:
return false
}
}
...@@ -25,3 +25,5 @@ func reqGetBody(req *http.Request) func() (io.ReadCloser, error) { ...@@ -25,3 +25,5 @@ func reqGetBody(req *http.Request) func() (io.ReadCloser, error) {
} }
func reqBodyIsNoBody(io.ReadCloser) bool { return false } func reqBodyIsNoBody(io.ReadCloser) bool { return false }
func go18httpNoBody() io.ReadCloser { return nil } // for tests only
// 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
package http2
import (
"net/http"
)
func configureServer19(s *http.Server, conf *Server) error {
// not supported prior to go1.9
return nil
}
...@@ -10,13 +10,13 @@ import ( ...@@ -10,13 +10,13 @@ import (
"sync" "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 // io.Pipe except there are no PipeReader/PipeWriter halves, and the
// underlying buffer is an interface. (io.Pipe is always unbuffered) // underlying buffer is an interface. (io.Pipe is always unbuffered)
type pipe struct { type pipe struct {
mu sync.Mutex mu sync.Mutex
c sync.Cond // c.L lazily initialized to &p.mu c sync.Cond // c.L lazily initialized to &p.mu
b pipeBuffer b pipeBuffer // nil when done reading
err error // read error once empty. non-nil means closed. err error // read error once empty. non-nil means closed.
breakErr error // immediate read error (caller doesn't see rest of b) breakErr error // immediate read error (caller doesn't see rest of b)
donec chan struct{} // closed on error donec chan struct{} // closed on error
...@@ -32,6 +32,9 @@ type pipeBuffer interface { ...@@ -32,6 +32,9 @@ type pipeBuffer interface {
func (p *pipe) Len() int { func (p *pipe) Len() int {
p.mu.Lock() p.mu.Lock()
defer p.mu.Unlock() defer p.mu.Unlock()
if p.b == nil {
return 0
}
return p.b.Len() return p.b.Len()
} }
...@@ -47,7 +50,7 @@ func (p *pipe) Read(d []byte) (n int, err error) { ...@@ -47,7 +50,7 @@ func (p *pipe) Read(d []byte) (n int, err error) {
if p.breakErr != nil { if p.breakErr != nil {
return 0, p.breakErr return 0, p.breakErr
} }
if p.b.Len() > 0 { if p.b != nil && p.b.Len() > 0 {
return p.b.Read(d) return p.b.Read(d)
} }
if p.err != nil { if p.err != nil {
...@@ -55,6 +58,7 @@ func (p *pipe) Read(d []byte) (n int, err error) { ...@@ -55,6 +58,7 @@ func (p *pipe) Read(d []byte) (n int, err error) {
p.readFn() // e.g. copy trailers p.readFn() // e.g. copy trailers
p.readFn = nil // not sticky like p.err p.readFn = nil // not sticky like p.err
} }
p.b = nil
return 0, p.err return 0, p.err
} }
p.c.Wait() p.c.Wait()
...@@ -75,6 +79,9 @@ func (p *pipe) Write(d []byte) (n int, err error) { ...@@ -75,6 +79,9 @@ func (p *pipe) Write(d []byte) (n int, err error) {
if p.err != nil { if p.err != nil {
return 0, errClosedPipeWrite return 0, errClosedPipeWrite
} }
if p.breakErr != nil {
return len(d), nil // discard when there is no reader
}
return p.b.Write(d) return p.b.Write(d)
} }
...@@ -109,6 +116,9 @@ func (p *pipe) closeWithError(dst *error, err error, fn func()) { ...@@ -109,6 +116,9 @@ func (p *pipe) closeWithError(dst *error, err error, fn func()) {
return return
} }
p.readFn = fn p.readFn = fn
if dst == &p.breakErr {
p.b = nil
}
*dst = err *dst = err
p.closeDoneLocked() p.closeDoneLocked()
} }
......
...@@ -53,7 +53,7 @@ type PriorityWriteSchedulerConfig struct { ...@@ -53,7 +53,7 @@ type PriorityWriteSchedulerConfig struct {
} }
// NewPriorityWriteScheduler constructs a WriteScheduler that schedules // NewPriorityWriteScheduler constructs a WriteScheduler that schedules
// frames by following HTTP/2 priorities as described in RFC 7340 Section 5.3. // frames by following HTTP/2 priorities as described in RFC 7540 Section 5.3.
// If cfg is nil, default options are used. // If cfg is nil, default options are used.
func NewPriorityWriteScheduler(cfg *PriorityWriteSchedulerConfig) WriteScheduler { func NewPriorityWriteScheduler(cfg *PriorityWriteSchedulerConfig) WriteScheduler {
if cfg == nil { if cfg == nil {
......
...@@ -5,8 +5,15 @@ go_library( ...@@ -5,8 +5,15 @@ go_library(
srcs = [ srcs = [
"idna.go", "idna.go",
"punycode.go", "punycode.go",
"tables.go",
"trie.go",
"trieval.go",
], ],
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [
"//vendor/golang.org/x/text/secure/bidirule:go_default_library",
"//vendor/golang.org/x/text/unicode/norm:go_default_library",
],
) )
filegroup( filegroup(
......
// Copyright 2012 The Go Authors. All rights reserved. // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
...@@ -7,7 +9,6 @@ package idna ...@@ -7,7 +9,6 @@ package idna
// This file implements the Punycode algorithm from RFC 3492. // This file implements the Punycode algorithm from RFC 3492.
import ( import (
"fmt"
"math" "math"
"strings" "strings"
"unicode/utf8" "unicode/utf8"
...@@ -27,6 +28,8 @@ const ( ...@@ -27,6 +28,8 @@ const (
tmin int32 = 1 tmin int32 = 1
) )
func punyError(s string) error { return &labelError{s, "A3"} }
// decode decodes a string as specified in section 6.2. // decode decodes a string as specified in section 6.2.
func decode(encoded string) (string, error) { func decode(encoded string) (string, error) {
if encoded == "" { if encoded == "" {
...@@ -34,7 +37,7 @@ func decode(encoded string) (string, error) { ...@@ -34,7 +37,7 @@ func decode(encoded string) (string, error) {
} }
pos := 1 + strings.LastIndex(encoded, "-") pos := 1 + strings.LastIndex(encoded, "-")
if pos == 1 { if pos == 1 {
return "", fmt.Errorf("idna: invalid label %q", encoded) return "", punyError(encoded)
} }
if pos == len(encoded) { if pos == len(encoded) {
return encoded[:len(encoded)-1], nil return encoded[:len(encoded)-1], nil
...@@ -50,16 +53,16 @@ func decode(encoded string) (string, error) { ...@@ -50,16 +53,16 @@ func decode(encoded string) (string, error) {
oldI, w := i, int32(1) oldI, w := i, int32(1)
for k := base; ; k += base { for k := base; ; k += base {
if pos == len(encoded) { if pos == len(encoded) {
return "", fmt.Errorf("idna: invalid label %q", encoded) return "", punyError(encoded)
} }
digit, ok := decodeDigit(encoded[pos]) digit, ok := decodeDigit(encoded[pos])
if !ok { if !ok {
return "", fmt.Errorf("idna: invalid label %q", encoded) return "", punyError(encoded)
} }
pos++ pos++
i += digit * w i += digit * w
if i < 0 { if i < 0 {
return "", fmt.Errorf("idna: invalid label %q", encoded) return "", punyError(encoded)
} }
t := k - bias t := k - bias
if t < tmin { if t < tmin {
...@@ -72,7 +75,7 @@ func decode(encoded string) (string, error) { ...@@ -72,7 +75,7 @@ func decode(encoded string) (string, error) {
} }
w *= base - t w *= base - t
if w >= math.MaxInt32/base { if w >= math.MaxInt32/base {
return "", fmt.Errorf("idna: invalid label %q", encoded) return "", punyError(encoded)
} }
} }
x := int32(len(output) + 1) x := int32(len(output) + 1)
...@@ -80,7 +83,7 @@ func decode(encoded string) (string, error) { ...@@ -80,7 +83,7 @@ func decode(encoded string) (string, error) {
n += i / x n += i / x
i %= x i %= x
if n > utf8.MaxRune || len(output) >= 1024 { if n > utf8.MaxRune || len(output) >= 1024 {
return "", fmt.Errorf("idna: invalid label %q", encoded) return "", punyError(encoded)
} }
output = append(output, 0) output = append(output, 0)
copy(output[i+1:], output[i:]) copy(output[i+1:], output[i:])
...@@ -121,14 +124,14 @@ func encode(prefix, s string) (string, error) { ...@@ -121,14 +124,14 @@ func encode(prefix, s string) (string, error) {
} }
delta += (m - n) * (h + 1) delta += (m - n) * (h + 1)
if delta < 0 { if delta < 0 {
return "", fmt.Errorf("idna: invalid label %q", s) return "", punyError(s)
} }
n = m n = m
for _, r := range s { for _, r := range s {
if r < n { if r < n {
delta++ delta++
if delta < 0 { if delta < 0 {
return "", fmt.Errorf("idna: invalid label %q", s) return "", punyError(s)
} }
continue continue
} }
......
This source diff could not be displayed because it is too large. You can view the blob instead.
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
// 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.
package idna
// appendMapping appends the mapping for the respective rune. isMapped must be
// true. A mapping is a categorization of a rune as defined in UTS #46.
func (c info) appendMapping(b []byte, s string) []byte {
index := int(c >> indexShift)
if c&xorBit == 0 {
s := mappings[index:]
return append(b, s[1:s[0]+1]...)
}
b = append(b, s...)
if c&inlineXOR == inlineXOR {
// TODO: support and handle two-byte inline masks
b[len(b)-1] ^= byte(index)
} else {
for p := len(b) - int(xorData[index]); p < len(b); p++ {
index++
b[p] ^= xorData[index]
}
}
return b
}
// Sparse block handling code.
type valueRange struct {
value uint16 // header: value:stride
lo, hi byte // header: lo:n
}
type sparseBlocks struct {
values []valueRange
offset []uint16
}
var idnaSparse = sparseBlocks{
values: idnaSparseValues[:],
offset: idnaSparseOffset[:],
}
// Don't use newIdnaTrie to avoid unconditional linking in of the table.
var trie = &idnaTrie{}
// lookup determines the type of block n and looks up the value for b.
// For n < t.cutoff, the block is a simple lookup table. Otherwise, the block
// is a list of ranges with an accompanying value. Given a matching range r,
// the value for b is by r.value + (b - r.lo) * stride.
func (t *sparseBlocks) lookup(n uint32, b byte) uint16 {
offset := t.offset[n]
header := t.values[offset]
lo := offset + 1
hi := lo + uint16(header.lo)
for lo < hi {
m := lo + (hi-lo)/2
r := t.values[m]
if r.lo <= b && b <= r.hi {
return r.value + uint16(b-r.lo)*header.value
}
if b < r.lo {
hi = m
} else {
lo = m + 1
}
}
return 0
}
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
package idna
// This file contains definitions for interpreting the trie value of the idna
// trie generated by "go run gen*.go". It is shared by both the generator
// program and the resultant package. Sharing is achieved by the generator
// copying gen_trieval.go to trieval.go and changing what's above this comment.
// info holds information from the IDNA mapping table for a single rune. It is
// the value returned by a trie lookup. In most cases, all information fits in
// a 16-bit value. For mappings, this value may contain an index into a slice
// with the mapped string. Such mappings can consist of the actual mapped value
// or an XOR pattern to be applied to the bytes of the UTF8 encoding of the
// input rune. This technique is used by the cases packages and reduces the
// table size significantly.
//
// The per-rune values have the following format:
//
// if mapped {
// if inlinedXOR {
// 15..13 inline XOR marker
// 12..11 unused
// 10..3 inline XOR mask
// } else {
// 15..3 index into xor or mapping table
// }
// } else {
// 15..13 unused
// 12 modifier (including virama)
// 11 virama modifier
// 10..8 joining type
// 7..3 category type
// }
// 2 use xor pattern
// 1..0 mapped category
//
// See the definitions below for a more detailed description of the various
// bits.
type info uint16
const (
catSmallMask = 0x3
catBigMask = 0xF8
indexShift = 3
xorBit = 0x4 // interpret the index as an xor pattern
inlineXOR = 0xE000 // These bits are set if the XOR pattern is inlined.
joinShift = 8
joinMask = 0x07
viramaModifier = 0x0800
modifier = 0x1000
)
// A category corresponds to a category defined in the IDNA mapping table.
type category uint16
const (
unknown category = 0 // not defined currently in unicode.
mapped category = 1
disallowedSTD3Mapped category = 2
deviation category = 3
)
const (
valid category = 0x08
validNV8 category = 0x18
validXV8 category = 0x28
disallowed category = 0x40
disallowedSTD3Valid category = 0x80
ignored category = 0xC0
)
// join types and additional rune information
const (
joiningL = (iota + 1)
joiningD
joiningT
joiningR
//the following types are derived during processing
joinZWJ
joinZWNJ
joinVirama
numJoinTypes
)
func (c info) isMapped() bool {
return c&0x3 != 0
}
func (c info) category() category {
small := c & catSmallMask
if small != 0 {
return category(small)
}
return category(c & catBigMask)
}
func (c info) joinType() info {
if c.isMapped() {
return 0
}
return (c >> joinShift) & joinMask
}
func (c info) isModifier() bool {
return c&(modifier|catSmallMask) == modifier
}
func (c info) isViramaModifier() bool {
return c&(viramaModifier|catSmallMask) == viramaModifier
}
...@@ -371,7 +371,7 @@ func (ts *timeSeries) ComputeRange(start, finish time.Time, num int) []Observabl ...@@ -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 // extract from the last level, even if it doesn't cover the entire
// desired range. // desired range.
ts.extract(ts.levels[len(ts.levels)-1], start, finish, num, results) ts.extract(ts.levels[len(ts.levels)-1], start, finish, num, results)
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"strings" "strings"
) )
// A PerHost directs connections to a default Dialer unless the hostname // A PerHost directs connections to a default Dialer unless the host name
// requested matches one of a number of exceptions. // requested matches one of a number of exceptions.
type PerHost struct { type PerHost struct {
def, bypass Dialer def, bypass Dialer
...@@ -76,7 +76,7 @@ func (p *PerHost) dialerForRequest(host string) Dialer { ...@@ -76,7 +76,7 @@ func (p *PerHost) dialerForRequest(host string) Dialer {
// AddFromString parses a string that contains comma-separated values // AddFromString parses a string that contains comma-separated values
// specifying hosts that should use the bypass proxy. Each value is either an // specifying hosts that should use the bypass proxy. Each value is either an
// IP address, a CIDR range, a zone (*.example.com) or a hostname // IP address, a CIDR range, a zone (*.example.com) or a host name
// (localhost). A best effort is made to parse the string and errors are // (localhost). A best effort is made to parse the string and errors are
// ignored. // ignored.
func (p *PerHost) AddFromString(s string) { func (p *PerHost) AddFromString(s string) {
...@@ -131,7 +131,7 @@ func (p *PerHost) AddZone(zone string) { ...@@ -131,7 +131,7 @@ func (p *PerHost) AddZone(zone string) {
p.bypassZones = append(p.bypassZones, zone) p.bypassZones = append(p.bypassZones, zone)
} }
// AddHost specifies a hostname that will use the bypass proxy. // AddHost specifies a host name that will use the bypass proxy.
func (p *PerHost) AddHost(host string) { func (p *PerHost) AddHost(host string) {
if strings.HasSuffix(host, ".") { if strings.HasSuffix(host, ".") {
host = host[:len(host)-1] host = host[:len(host)-1]
......
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
"net" "net"
"net/url" "net/url"
"os" "os"
"sync"
) )
// A Dialer is a means to establish a connection. // A Dialer is a means to establish a connection.
...@@ -27,7 +28,7 @@ type Auth struct { ...@@ -27,7 +28,7 @@ type Auth struct {
// FromEnvironment returns the dialer specified by the proxy related variables in // FromEnvironment returns the dialer specified by the proxy related variables in
// the environment. // the environment.
func FromEnvironment() Dialer { func FromEnvironment() Dialer {
allProxy := os.Getenv("all_proxy") allProxy := allProxyEnv.Get()
if len(allProxy) == 0 { if len(allProxy) == 0 {
return Direct return Direct
} }
...@@ -41,7 +42,7 @@ func FromEnvironment() Dialer { ...@@ -41,7 +42,7 @@ func FromEnvironment() Dialer {
return Direct return Direct
} }
noProxy := os.Getenv("no_proxy") noProxy := noProxyEnv.Get()
if len(noProxy) == 0 { if len(noProxy) == 0 {
return proxy return proxy
} }
...@@ -92,3 +93,42 @@ func FromURL(u *url.URL, forward Dialer) (Dialer, error) { ...@@ -92,3 +93,42 @@ func FromURL(u *url.URL, forward Dialer) (Dialer, error) {
return nil, errors.New("proxy: unknown scheme: " + u.Scheme) return nil, errors.New("proxy: unknown scheme: " + u.Scheme)
} }
var (
allProxyEnv = &envOnce{
names: []string{"ALL_PROXY", "all_proxy"},
}
noProxyEnv = &envOnce{
names: []string{"NO_PROXY", "no_proxy"},
}
)
// envOnce looks up an environment variable (optionally by multiple
// names) once. It mitigates expensive lookups on some platforms
// (e.g. Windows).
// (Borrowed from net/http/transport.go)
type envOnce struct {
names []string
once sync.Once
val string
}
func (e *envOnce) Get() string {
e.once.Do(e.init)
return e.val
}
func (e *envOnce) init() {
for _, n := range e.names {
e.val = os.Getenv(n)
if e.val != "" {
return
}
}
}
// reset is used by tests
func (e *envOnce) reset() {
e.once = sync.Once{}
e.val = ""
}
...@@ -72,24 +72,28 @@ func (s *socks5) Dial(network, addr string) (net.Conn, error) { ...@@ -72,24 +72,28 @@ func (s *socks5) Dial(network, addr string) (net.Conn, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
closeConn := &conn if err := s.connect(conn, addr); err != nil {
defer func() { conn.Close()
if closeConn != nil { return nil, err
(*closeConn).Close() }
} return conn, nil
}() }
host, portStr, err := net.SplitHostPort(addr) // connect takes an existing connection to a socks5 proxy server,
// and commands the server to extend that connection to target,
// which must be a canonical address with a host and port.
func (s *socks5) connect(conn net.Conn, target string) error {
host, portStr, err := net.SplitHostPort(target)
if err != nil { if err != nil {
return nil, err return err
} }
port, err := strconv.Atoi(portStr) port, err := strconv.Atoi(portStr)
if err != nil { if err != nil {
return nil, errors.New("proxy: failed to parse port number: " + portStr) return errors.New("proxy: failed to parse port number: " + portStr)
} }
if port < 1 || port > 0xffff { if port < 1 || port > 0xffff {
return nil, errors.New("proxy: port number out of range: " + portStr) return errors.New("proxy: port number out of range: " + portStr)
} }
// the size here is just an estimate // the size here is just an estimate
...@@ -103,17 +107,17 @@ func (s *socks5) Dial(network, addr string) (net.Conn, error) { ...@@ -103,17 +107,17 @@ func (s *socks5) Dial(network, addr string) (net.Conn, error) {
} }
if _, err := conn.Write(buf); err != nil { if _, err := conn.Write(buf); err != nil {
return nil, errors.New("proxy: failed to write greeting to SOCKS5 proxy at " + s.addr + ": " + err.Error()) return errors.New("proxy: failed to write greeting to SOCKS5 proxy at " + s.addr + ": " + err.Error())
} }
if _, err := io.ReadFull(conn, buf[:2]); err != nil { if _, err := io.ReadFull(conn, buf[:2]); err != nil {
return nil, errors.New("proxy: failed to read greeting from SOCKS5 proxy at " + s.addr + ": " + err.Error()) return errors.New("proxy: failed to read greeting from SOCKS5 proxy at " + s.addr + ": " + err.Error())
} }
if buf[0] != 5 { if buf[0] != 5 {
return nil, errors.New("proxy: SOCKS5 proxy at " + s.addr + " has unexpected version " + strconv.Itoa(int(buf[0]))) return errors.New("proxy: SOCKS5 proxy at " + s.addr + " has unexpected version " + strconv.Itoa(int(buf[0])))
} }
if buf[1] == 0xff { if buf[1] == 0xff {
return nil, errors.New("proxy: SOCKS5 proxy at " + s.addr + " requires authentication") return errors.New("proxy: SOCKS5 proxy at " + s.addr + " requires authentication")
} }
if buf[1] == socks5AuthPassword { if buf[1] == socks5AuthPassword {
...@@ -125,15 +129,15 @@ func (s *socks5) Dial(network, addr string) (net.Conn, error) { ...@@ -125,15 +129,15 @@ func (s *socks5) Dial(network, addr string) (net.Conn, error) {
buf = append(buf, s.password...) buf = append(buf, s.password...)
if _, err := conn.Write(buf); err != nil { if _, err := conn.Write(buf); err != nil {
return nil, errors.New("proxy: failed to write authentication request to SOCKS5 proxy at " + s.addr + ": " + err.Error()) return errors.New("proxy: failed to write authentication request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
} }
if _, err := io.ReadFull(conn, buf[:2]); err != nil { if _, err := io.ReadFull(conn, buf[:2]); err != nil {
return nil, errors.New("proxy: failed to read authentication reply from SOCKS5 proxy at " + s.addr + ": " + err.Error()) return errors.New("proxy: failed to read authentication reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
} }
if buf[1] != 0 { if buf[1] != 0 {
return nil, errors.New("proxy: SOCKS5 proxy at " + s.addr + " rejected username/password") return errors.New("proxy: SOCKS5 proxy at " + s.addr + " rejected username/password")
} }
} }
...@@ -150,7 +154,7 @@ func (s *socks5) Dial(network, addr string) (net.Conn, error) { ...@@ -150,7 +154,7 @@ func (s *socks5) Dial(network, addr string) (net.Conn, error) {
buf = append(buf, ip...) buf = append(buf, ip...)
} else { } else {
if len(host) > 255 { if len(host) > 255 {
return nil, errors.New("proxy: destination hostname too long: " + host) return errors.New("proxy: destination host name too long: " + host)
} }
buf = append(buf, socks5Domain) buf = append(buf, socks5Domain)
buf = append(buf, byte(len(host))) buf = append(buf, byte(len(host)))
...@@ -159,11 +163,11 @@ func (s *socks5) Dial(network, addr string) (net.Conn, error) { ...@@ -159,11 +163,11 @@ func (s *socks5) Dial(network, addr string) (net.Conn, error) {
buf = append(buf, byte(port>>8), byte(port)) buf = append(buf, byte(port>>8), byte(port))
if _, err := conn.Write(buf); err != nil { if _, err := conn.Write(buf); err != nil {
return nil, errors.New("proxy: failed to write connect request to SOCKS5 proxy at " + s.addr + ": " + err.Error()) return errors.New("proxy: failed to write connect request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
} }
if _, err := io.ReadFull(conn, buf[:4]); err != nil { if _, err := io.ReadFull(conn, buf[:4]); err != nil {
return nil, errors.New("proxy: failed to read connect reply from SOCKS5 proxy at " + s.addr + ": " + err.Error()) return errors.New("proxy: failed to read connect reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
} }
failure := "unknown error" failure := "unknown error"
...@@ -172,7 +176,7 @@ func (s *socks5) Dial(network, addr string) (net.Conn, error) { ...@@ -172,7 +176,7 @@ func (s *socks5) Dial(network, addr string) (net.Conn, error) {
} }
if len(failure) > 0 { if len(failure) > 0 {
return nil, errors.New("proxy: SOCKS5 proxy at " + s.addr + " failed to connect: " + failure) return errors.New("proxy: SOCKS5 proxy at " + s.addr + " failed to connect: " + failure)
} }
bytesToDiscard := 0 bytesToDiscard := 0
...@@ -184,11 +188,11 @@ func (s *socks5) Dial(network, addr string) (net.Conn, error) { ...@@ -184,11 +188,11 @@ func (s *socks5) Dial(network, addr string) (net.Conn, error) {
case socks5Domain: case socks5Domain:
_, err := io.ReadFull(conn, buf[:1]) _, err := io.ReadFull(conn, buf[:1])
if err != nil { if err != nil {
return nil, errors.New("proxy: failed to read domain length from SOCKS5 proxy at " + s.addr + ": " + err.Error()) return errors.New("proxy: failed to read domain length from SOCKS5 proxy at " + s.addr + ": " + err.Error())
} }
bytesToDiscard = int(buf[0]) bytesToDiscard = int(buf[0])
default: default:
return nil, errors.New("proxy: got unknown address type " + strconv.Itoa(int(buf[3])) + " from SOCKS5 proxy at " + s.addr) return errors.New("proxy: got unknown address type " + strconv.Itoa(int(buf[3])) + " from SOCKS5 proxy at " + s.addr)
} }
if cap(buf) < bytesToDiscard { if cap(buf) < bytesToDiscard {
...@@ -197,14 +201,13 @@ func (s *socks5) Dial(network, addr string) (net.Conn, error) { ...@@ -197,14 +201,13 @@ func (s *socks5) Dial(network, addr string) (net.Conn, error) {
buf = buf[:bytesToDiscard] buf = buf[:bytesToDiscard]
} }
if _, err := io.ReadFull(conn, buf); err != nil { if _, err := io.ReadFull(conn, buf); err != nil {
return nil, errors.New("proxy: failed to read address from SOCKS5 proxy at " + s.addr + ": " + err.Error()) return errors.New("proxy: failed to read address from SOCKS5 proxy at " + s.addr + ": " + err.Error())
} }
// Also need to discard the port number // Also need to discard the port number
if _, err := io.ReadFull(conn, buf[:2]); err != nil { if _, err := io.ReadFull(conn, buf[:2]); err != nil {
return nil, errors.New("proxy: failed to read port from SOCKS5 proxy at " + s.addr + ": " + err.Error()) return errors.New("proxy: failed to read port from SOCKS5 proxy at " + s.addr + ": " + err.Error())
} }
closeConn = nil return nil
return conn, nil
} }
...@@ -6,6 +6,8 @@ go_library( ...@@ -6,6 +6,8 @@ go_library(
"events.go", "events.go",
"histogram.go", "histogram.go",
"trace.go", "trace.go",
"trace_go16.go",
"trace_go17.go",
], ],
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
......
...@@ -39,9 +39,9 @@ var buckets = []bucket{ ...@@ -39,9 +39,9 @@ var buckets = []bucket{
} }
// RenderEvents renders the HTML page typically served at /debug/events. // RenderEvents renders the HTML page typically served at /debug/events.
// It does not do any auth checking; see AuthRequest for the default auth check // It does not do any auth checking. The request may be nil.
// used by the handler registered on http.DefaultServeMux. //
// req may be nil. // Most users will use the Events handler.
func RenderEvents(w http.ResponseWriter, req *http.Request, sensitive bool) { func RenderEvents(w http.ResponseWriter, req *http.Request, sensitive bool) {
now := time.Now() now := time.Now()
data := &struct { data := &struct {
......
...@@ -77,7 +77,6 @@ import ( ...@@ -77,7 +77,6 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"golang.org/x/net/context"
"golang.org/x/net/internal/timeseries" "golang.org/x/net/internal/timeseries"
) )
...@@ -111,30 +110,46 @@ var AuthRequest = func(req *http.Request) (any, sensitive bool) { ...@@ -111,30 +110,46 @@ var AuthRequest = func(req *http.Request) (any, sensitive bool) {
} }
func init() { func init() {
http.HandleFunc("/debug/requests", func(w http.ResponseWriter, req *http.Request) { // TODO(jbd): Serve Traces from /debug/traces in the future?
any, sensitive := AuthRequest(req) // There is no requirement for a request to be present to have traces.
if !any { http.HandleFunc("/debug/requests", Traces)
http.Error(w, "not allowed", http.StatusUnauthorized) http.HandleFunc("/debug/events", Events)
return }
}
w.Header().Set("Content-Type", "text/html; charset=utf-8") // Traces responds with traces from the program.
Render(w, req, sensitive) // The package initialization registers it in http.DefaultServeMux
}) // at /debug/requests.
http.HandleFunc("/debug/events", func(w http.ResponseWriter, req *http.Request) { //
any, sensitive := AuthRequest(req) // It performs authorization by running AuthRequest.
if !any { func Traces(w http.ResponseWriter, req *http.Request) {
http.Error(w, "not allowed", http.StatusUnauthorized) any, sensitive := AuthRequest(req)
return if !any {
} http.Error(w, "not allowed", http.StatusUnauthorized)
w.Header().Set("Content-Type", "text/html; charset=utf-8") return
RenderEvents(w, req, sensitive) }
}) w.Header().Set("Content-Type", "text/html; charset=utf-8")
Render(w, req, sensitive)
}
// Events responds with a page of events collected by EventLogs.
// The package initialization registers it in http.DefaultServeMux
// at /debug/events.
//
// It performs authorization by running AuthRequest.
func Events(w http.ResponseWriter, req *http.Request) {
any, sensitive := AuthRequest(req)
if !any {
http.Error(w, "not allowed", http.StatusUnauthorized)
return
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
RenderEvents(w, req, sensitive)
} }
// Render renders the HTML page typically served at /debug/requests. // Render renders the HTML page typically served at /debug/requests.
// It does not do any auth checking; see AuthRequest for the default auth check // It does not do any auth checking. The request may be nil.
// used by the handler registered on http.DefaultServeMux. //
// req may be nil. // Most users will use the Traces handler.
func Render(w io.Writer, req *http.Request, sensitive bool) { func Render(w io.Writer, req *http.Request, sensitive bool) {
data := &struct { data := &struct {
Families []string Families []string
...@@ -271,18 +286,6 @@ type contextKeyT string ...@@ -271,18 +286,6 @@ type contextKeyT string
var contextKey = contextKeyT("golang.org/x/net/trace.Trace") var contextKey = contextKeyT("golang.org/x/net/trace.Trace")
// NewContext returns a copy of the parent context
// and associates it with a Trace.
func NewContext(ctx context.Context, tr Trace) context.Context {
return context.WithValue(ctx, contextKey, tr)
}
// FromContext returns the Trace bound to the context, if any.
func FromContext(ctx context.Context) (tr Trace, ok bool) {
tr, ok = ctx.Value(contextKey).(Trace)
return
}
// Trace represents an active request. // Trace represents an active request.
type Trace interface { type Trace interface {
// LazyLog adds x to the event log. It will be evaluated each time the // LazyLog adds x to the event log. It will be evaluated each time the
......
// 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.7
package trace
import "golang.org/x/net/context"
// NewContext returns a copy of the parent context
// and associates it with a Trace.
func NewContext(ctx context.Context, tr Trace) context.Context {
return context.WithValue(ctx, contextKey, tr)
}
// FromContext returns the Trace bound to the context, if any.
func FromContext(ctx context.Context) (tr Trace, ok bool) {
tr, ok = ctx.Value(contextKey).(Trace)
return
}
// 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.7
package trace
import "context"
// NewContext returns a copy of the parent context
// and associates it with a Trace.
func NewContext(ctx context.Context, tr Trace) context.Context {
return context.WithValue(ctx, contextKey, tr)
}
// FromContext returns the Trace bound to the context, if any.
func FromContext(ctx context.Context) (tr Trace, ok bool) {
tr, ok = ctx.Value(contextKey).(Trace)
return
}
...@@ -11,8 +11,10 @@ go_library( ...@@ -11,8 +11,10 @@ go_library(
"tables.go", "tables.go",
"trieval.go", "trieval.go",
], ],
cgo = True,
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
"//vendor/golang.org/x/text/internal:go_default_library",
"//vendor/golang.org/x/text/language:go_default_library", "//vendor/golang.org/x/text/language:go_default_library",
"//vendor/golang.org/x/text/transform:go_default_library", "//vendor/golang.org/x/text/transform:go_default_library",
"//vendor/golang.org/x/text/unicode/norm:go_default_library", "//vendor/golang.org/x/text/unicode/norm:go_default_library",
......
...@@ -35,7 +35,7 @@ import ( ...@@ -35,7 +35,7 @@ import (
// A Caser may be stateful and should therefore not be shared between // A Caser may be stateful and should therefore not be shared between
// goroutines. // goroutines.
type Caser struct { type Caser struct {
t transform.Transformer t transform.SpanningTransformer
} }
// Bytes returns a new byte slice with the result of converting b to the case // Bytes returns a new byte slice with the result of converting b to the case
...@@ -56,12 +56,17 @@ func (c Caser) String(s string) string { ...@@ -56,12 +56,17 @@ func (c Caser) String(s string) string {
// Transform. // Transform.
func (c Caser) Reset() { c.t.Reset() } func (c Caser) Reset() { c.t.Reset() }
// Transform implements the Transformer interface and transforms the given input // Transform implements the transform.Transformer interface and transforms the
// to the case form implemented by c. // given input to the case form implemented by c.
func (c Caser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { func (c Caser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
return c.t.Transform(dst, src, atEOF) return c.t.Transform(dst, src, atEOF)
} }
// Span implements the transform.SpanningTransformer interface.
func (c Caser) Span(src []byte, atEOF bool) (n int, err error) {
return c.t.Span(src, atEOF)
}
// Upper returns a Caser for language-specific uppercasing. // Upper returns a Caser for language-specific uppercasing.
func Upper(t language.Tag, opts ...Option) Caser { func Upper(t language.Tag, opts ...Option) Caser {
return Caser{makeUpper(t, getOpts(opts...))} return Caser{makeUpper(t, getOpts(opts...))}
...@@ -83,14 +88,20 @@ func Title(t language.Tag, opts ...Option) Caser { ...@@ -83,14 +88,20 @@ func Title(t language.Tag, opts ...Option) Caser {
// //
// Case folding does not normalize the input and may not preserve a normal form. // Case folding does not normalize the input and may not preserve a normal form.
// Use the collate or search package for more convenient and linguistically // Use the collate or search package for more convenient and linguistically
// sound comparisons. Use unicode/precis for string comparisons where security // sound comparisons. Use golang.org/x/text/secure/precis for string comparisons
// aspects are a concern. // where security aspects are a concern.
func Fold(opts ...Option) Caser { func Fold(opts ...Option) Caser {
return Caser{makeFold(getOpts(opts...))} return Caser{makeFold(getOpts(opts...))}
} }
// An Option is used to modify the behavior of a Caser. // An Option is used to modify the behavior of a Caser.
type Option func(o *options) type Option func(o options) options
// TODO: consider these options to take a boolean as well, like FinalSigma.
// The advantage of using this approach is that other providers of a lower-case
// algorithm could set different defaults by prefixing a user-provided slice
// of options with their own. This is handy, for instance, for the precis
// package which would override the default to not handle the Greek final sigma.
var ( var (
// NoLower disables the lowercasing of non-leading letters for a title // NoLower disables the lowercasing of non-leading letters for a title
...@@ -110,20 +121,42 @@ type options struct { ...@@ -110,20 +121,42 @@ type options struct {
// TODO: segmenter, max ignorable, alternative versions, etc. // TODO: segmenter, max ignorable, alternative versions, etc.
noFinalSigma bool // Only used for testing. ignoreFinalSigma bool
} }
func getOpts(o ...Option) (res options) { func getOpts(o ...Option) (res options) {
for _, f := range o { for _, f := range o {
f(&res) res = f(res)
} }
return return
} }
func noLower(o *options) { func noLower(o options) options {
o.noLower = true o.noLower = true
return o
} }
func compact(o *options) { func compact(o options) options {
o.simple = true o.simple = true
return o
}
// HandleFinalSigma specifies whether the special handling of Greek final sigma
// should be enabled. Unicode prescribes handling the Greek final sigma for all
// locales, but standards like IDNA and PRECIS override this default.
func HandleFinalSigma(enable bool) Option {
if enable {
return handleFinalSigma
}
return ignoreFinalSigma
}
func ignoreFinalSigma(o options) options {
o.ignoreFinalSigma = true
return o
}
func handleFinalSigma(o options) options {
o.ignoreFinalSigma = false
return o
} }
...@@ -4,9 +4,7 @@ ...@@ -4,9 +4,7 @@
package cases package cases
import ( import "golang.org/x/text/transform"
"golang.org/x/text/transform"
)
// A context is used for iterating over source bytes, fetching case info and // A context is used for iterating over source bytes, fetching case info and
// writing to a destination buffer. // writing to a destination buffer.
...@@ -56,6 +54,14 @@ func (c *context) ret() (nDst, nSrc int, err error) { ...@@ -56,6 +54,14 @@ func (c *context) ret() (nDst, nSrc int, err error) {
return c.nDst, c.nSrc, transform.ErrShortSrc return c.nDst, c.nSrc, transform.ErrShortSrc
} }
// retSpan returns the return values for the Span method. It checks whether
// there were insufficient bytes in src to complete and introduces an error
// accordingly, if necessary.
func (c *context) retSpan() (n int, err error) {
_, nSrc, err := c.ret()
return nSrc, err
}
// checkpoint sets the return value buffer points for Transform to the current // checkpoint sets the return value buffer points for Transform to the current
// positions. // positions.
func (c *context) checkpoint() { func (c *context) checkpoint() {
...@@ -200,6 +206,23 @@ func lower(c *context) bool { ...@@ -200,6 +206,23 @@ func lower(c *context) bool {
return c.copy() return c.copy()
} }
func isLower(c *context) bool {
ct := c.caseType()
if c.info&hasMappingMask == 0 || ct == cLower {
return true
}
if c.info&exceptionBit == 0 {
c.err = transform.ErrEndOfSpan
return false
}
e := exceptions[c.info>>exceptionShift:]
if nLower := (e[1] >> lengthBits) & lengthMask; nLower != noChange {
c.err = transform.ErrEndOfSpan
return false
}
return true
}
// upper writes the uppercase version of the current rune to dst. // upper writes the uppercase version of the current rune to dst.
func upper(c *context) bool { func upper(c *context) bool {
ct := c.caseType() ct := c.caseType()
...@@ -226,6 +249,29 @@ func upper(c *context) bool { ...@@ -226,6 +249,29 @@ func upper(c *context) bool {
return c.copy() return c.copy()
} }
// isUpper writes the isUppercase version of the current rune to dst.
func isUpper(c *context) bool {
ct := c.caseType()
if c.info&hasMappingMask == 0 || ct == cUpper {
return true
}
if c.info&exceptionBit == 0 {
c.err = transform.ErrEndOfSpan
return false
}
e := exceptions[c.info>>exceptionShift:]
// Get length of first special case mapping.
n := (e[1] >> lengthBits) & lengthMask
if ct == cTitle {
n = e[1] & lengthMask
}
if n != noChange {
c.err = transform.ErrEndOfSpan
return false
}
return true
}
// title writes the title case version of the current rune to dst. // title writes the title case version of the current rune to dst.
func title(c *context) bool { func title(c *context) bool {
ct := c.caseType() ct := c.caseType()
...@@ -257,6 +303,33 @@ func title(c *context) bool { ...@@ -257,6 +303,33 @@ func title(c *context) bool {
return c.copy() return c.copy()
} }
// isTitle reports whether the current rune is in title case.
func isTitle(c *context) bool {
ct := c.caseType()
if c.info&hasMappingMask == 0 || ct == cTitle {
return true
}
if c.info&exceptionBit == 0 {
if ct == cLower {
c.err = transform.ErrEndOfSpan
return false
}
return true
}
// Get the exception data.
e := exceptions[c.info>>exceptionShift:]
if nTitle := e[1] & lengthMask; nTitle != noChange {
c.err = transform.ErrEndOfSpan
return false
}
nFirst := (e[1] >> lengthBits) & lengthMask
if ct == cLower && nFirst != noChange {
c.err = transform.ErrEndOfSpan
return false
}
return true
}
// foldFull writes the foldFull version of the current rune to dst. // foldFull writes the foldFull version of the current rune to dst.
func foldFull(c *context) bool { func foldFull(c *context) bool {
if c.info&hasMappingMask == 0 { if c.info&hasMappingMask == 0 {
...@@ -279,3 +352,25 @@ func foldFull(c *context) bool { ...@@ -279,3 +352,25 @@ func foldFull(c *context) bool {
} }
return c.writeString(e[2 : 2+n]) return c.writeString(e[2 : 2+n])
} }
// isFoldFull reports whether the current run is mapped to foldFull
func isFoldFull(c *context) bool {
if c.info&hasMappingMask == 0 {
return true
}
ct := c.caseType()
if c.info&exceptionBit == 0 {
if ct != cLower || c.info&inverseFoldBit != 0 {
c.err = transform.ErrEndOfSpan
return false
}
return true
}
e := exceptions[c.info>>exceptionShift:]
n := e[0] & lengthMask
if n == 0 && ct == cLower {
return true
}
c.err = transform.ErrEndOfSpan
return false
}
...@@ -18,7 +18,15 @@ func (t *caseFolder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err ...@@ -18,7 +18,15 @@ func (t *caseFolder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err
return c.ret() return c.ret()
} }
func makeFold(o options) transform.Transformer { func (t *caseFolder) Span(src []byte, atEOF bool) (n int, err error) {
c := context{src: src, atEOF: atEOF}
for c.next() && isFoldFull(&c) {
c.checkpoint()
}
return c.retSpan()
}
func makeFold(o options) transform.SpanningTransformer {
// TODO: Special case folding, through option Language, Special/Turkic, or // TODO: Special case folding, through option Language, Special/Turkic, or
// both. // both.
// TODO: Implement Compact options. // TODO: Implement Compact options.
......
...@@ -76,7 +76,7 @@ type breakCategory int ...@@ -76,7 +76,7 @@ type breakCategory int
const ( const (
breakBreak breakCategory = iota breakBreak breakCategory = iota
breakLetter breakLetter
breakIgnored breakMid
) )
// mapping returns the case mapping for the given case type. // mapping returns the case mapping for the given case type.
...@@ -162,9 +162,14 @@ func parseUCD() []runeInfo { ...@@ -162,9 +162,14 @@ func parseUCD() []runeInfo {
// We collapse the word breaking properties onto the categories we need. // We collapse the word breaking properties onto the categories we need.
switch p.String(1) { // TODO: officially we need to canonicalize. switch p.String(1) { // TODO: officially we need to canonicalize.
case "Format", "MidLetter", "MidNumLet", "Single_Quote": case "MidLetter", "MidNumLet", "Single_Quote":
ri.BreakCat = breakIgnored ri.BreakCat = breakMid
case "ALetter", "Hebrew_Letter", "Numeric", "Extend", "ExtendNumLet": if !ri.CaseIgnorable {
// finalSigma relies on the fact that all breakMid runes are
// also a Case_Ignorable. Revisit this code when this changes.
log.Fatalf("Rune %U, which has a break category mid, is not a case ignorable", ri)
}
case "ALetter", "Hebrew_Letter", "Numeric", "Extend", "ExtendNumLet", "Format", "ZWJ":
ri.BreakCat = breakLetter ri.BreakCat = breakLetter
} }
}) })
...@@ -240,8 +245,11 @@ func makeEntry(ri *runeInfo) { ...@@ -240,8 +245,11 @@ func makeEntry(ri *runeInfo) {
case above: // Above case above: // Above
ccc = cccAbove ccc = cccAbove
} }
if ri.BreakCat == breakBreak { switch ri.BreakCat {
case breakBreak:
ccc = cccBreak ccc = cccBreak
case breakMid:
ri.entry |= isMidBit
} }
ri.entry |= ccc ri.entry |= ccc
...@@ -588,7 +596,7 @@ func verifyProperties(chars []runeInfo) { ...@@ -588,7 +596,7 @@ func verifyProperties(chars []runeInfo) {
// decomposition is greater than U+00FF, the rune is always // decomposition is greater than U+00FF, the rune is always
// great and not a modifier. // great and not a modifier.
if f := runes[0]; unicode.IsMark(f) || f > 0xFF && !unicode.Is(unicode.Greek, f) { if f := runes[0]; unicode.IsMark(f) || f > 0xFF && !unicode.Is(unicode.Greek, f) {
log.Fatalf("%U: expeced first rune of Greek decomposition to be letter, found %U", r, f) log.Fatalf("%U: expected first rune of Greek decomposition to be letter, found %U", r, f)
} }
// A.6.2: Any follow-up rune in a Greek decomposition is a // A.6.2: Any follow-up rune in a Greek decomposition is a
// modifier of which the first should be gobbled in // modifier of which the first should be gobbled in
...@@ -597,7 +605,7 @@ func verifyProperties(chars []runeInfo) { ...@@ -597,7 +605,7 @@ func verifyProperties(chars []runeInfo) {
switch m { switch m {
case 0x0313, 0x0314, 0x0301, 0x0300, 0x0306, 0x0342, 0x0308, 0x0304, 0x345: case 0x0313, 0x0314, 0x0301, 0x0300, 0x0306, 0x0342, 0x0308, 0x0304, 0x345:
default: default:
log.Fatalf("%U: modifier %U is outside of expeced Greek modifier set", r, m) log.Fatalf("%U: modifier %U is outside of expected Greek modifier set", r, m)
} }
} }
} }
...@@ -690,7 +698,7 @@ func genTablesTest() { ...@@ -690,7 +698,7 @@ func genTablesTest() {
parse("auxiliary/WordBreakProperty.txt", func(p *ucd.Parser) { parse("auxiliary/WordBreakProperty.txt", func(p *ucd.Parser) {
switch p.String(1) { switch p.String(1) {
case "Extend", "Format", "MidLetter", "MidNumLet", "Single_Quote", case "Extend", "Format", "MidLetter", "MidNumLet", "Single_Quote",
"ALetter", "Hebrew_Letter", "Numeric", "ExtendNumLet": "ALetter", "Hebrew_Letter", "Numeric", "ExtendNumLet", "ZWJ":
notBreak[p.Rune(0)] = true notBreak[p.Rune(0)] = true
} }
}) })
......
...@@ -26,6 +26,7 @@ package main ...@@ -26,6 +26,7 @@ package main
// Only 13..8 are used for XOR patterns. // Only 13..8 are used for XOR patterns.
// 7 inverseFold (fold to upper, not to lower) // 7 inverseFold (fold to upper, not to lower)
// 6 index: interpret the XOR pattern as an index // 6 index: interpret the XOR pattern as an index
// or isMid if case mode is cIgnorableUncased.
// 5..4 CCC: zero (normal or break), above or other // 5..4 CCC: zero (normal or break), above or other
// } // }
// 3 exception: interpret this value as an exception index // 3 exception: interpret this value as an exception index
...@@ -48,6 +49,7 @@ const ( ...@@ -48,6 +49,7 @@ const (
ignorableValue = 0x0004 ignorableValue = 0x0004
inverseFoldBit = 1 << 7 inverseFoldBit = 1 << 7
isMidBit = 1 << 6
exceptionBit = 1 << 3 exceptionBit = 1 << 3
exceptionShift = 5 exceptionShift = 5
...@@ -57,7 +59,7 @@ const ( ...@@ -57,7 +59,7 @@ const (
xorShift = 8 xorShift = 8
// There is no mapping if all xor bits and the exception bit are zero. // There is no mapping if all xor bits and the exception bit are zero.
hasMappingMask = 0xffc0 | exceptionBit hasMappingMask = 0xff80 | exceptionBit
) )
// The case mode bits encodes the case type of a rune. This includes uncased, // The case mode bits encodes the case type of a rune. This includes uncased,
...@@ -95,10 +97,6 @@ func (c info) isCaseIgnorable() bool { ...@@ -95,10 +97,6 @@ func (c info) isCaseIgnorable() bool {
return c&ignorableMask == ignorableValue return c&ignorableMask == ignorableValue
} }
func (c info) isCaseIgnorableAndNonBreakStarter() bool {
return c&(fullCasedMask|cccMask) == (ignorableValue | cccZero)
}
func (c info) isNotCasedAndNotCaseIgnorable() bool { func (c info) isNotCasedAndNotCaseIgnorable() bool {
return c&fullCasedMask == 0 return c&fullCasedMask == 0
} }
...@@ -107,6 +105,10 @@ func (c info) isCaseIgnorableAndNotCased() bool { ...@@ -107,6 +105,10 @@ func (c info) isCaseIgnorableAndNotCased() bool {
return c&fullCasedMask == cIgnorableUncased return c&fullCasedMask == cIgnorableUncased
} }
func (c info) isMid() bool {
return c&(fullCasedMask|isMidBit) == isMidBit|cIgnorableUncased
}
// The case mapping implementation will need to know about various Canonical // The case mapping implementation will need to know about various Canonical
// Combining Class (CCC) values. We encode two of these in the trie value: // Combining Class (CCC) values. We encode two of these in the trie value:
// cccZero (0) and cccAbove (230). If the value is cccOther, it means that // cccZero (0) and cccAbove (230). If the value is cccOther, it means that
......
// 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 icu
package cases
// Ideally these functions would be defined in a test file, but go test doesn't
// allow CGO in tests. The build tag should ensure either way that these
// functions will not end up in the package.
// TODO: Ensure that the correct ICU version is set.
/*
#cgo LDFLAGS: -licui18n.57 -licuuc.57
#include <stdlib.h>
#include <unicode/ustring.h>
#include <unicode/utypes.h>
#include <unicode/localpointer.h>
#include <unicode/ucasemap.h>
*/
import "C"
import "unsafe"
func doICU(tag, caser, input string) string {
err := C.UErrorCode(0)
loc := C.CString(tag)
cm := C.ucasemap_open(loc, C.uint32_t(0), &err)
buf := make([]byte, len(input)*4)
dst := (*C.char)(unsafe.Pointer(&buf[0]))
src := C.CString(input)
cn := C.int32_t(0)
switch caser {
case "fold":
cn = C.ucasemap_utf8FoldCase(cm,
dst, C.int32_t(len(buf)),
src, C.int32_t(len(input)),
&err)
case "lower":
cn = C.ucasemap_utf8ToLower(cm,
dst, C.int32_t(len(buf)),
src, C.int32_t(len(input)),
&err)
case "upper":
cn = C.ucasemap_utf8ToUpper(cm,
dst, C.int32_t(len(buf)),
src, C.int32_t(len(input)),
&err)
case "title":
cn = C.ucasemap_utf8ToTitle(cm,
dst, C.int32_t(len(buf)),
src, C.int32_t(len(input)),
&err)
}
return string(buf[:cn])
}
...@@ -28,9 +28,6 @@ func (c info) cccType() info { ...@@ -28,9 +28,6 @@ func (c info) cccType() info {
// only makes sense, though, if the performance and/or space penalty of using // only makes sense, though, if the performance and/or space penalty of using
// the generic breaker is big. Extra data will only be needed for non-cased // the generic breaker is big. Extra data will only be needed for non-cased
// runes, which means there are sufficient bits left in the caseType. // runes, which means there are sufficient bits left in the caseType.
// Also note that the standard breaking algorithm doesn't always make sense
// for title casing. For example, a4a -> A4a, but a"4a -> A"4A (where " stands
// for modifier \u0308).
// ICU prohibits breaking in such cases as well. // ICU prohibits breaking in such cases as well.
// For the purpose of title casing we use an approximation of the Unicode Word // For the purpose of title casing we use an approximation of the Unicode Word
...@@ -41,17 +38,19 @@ func (c info) cccType() info { ...@@ -41,17 +38,19 @@ func (c info) cccType() info {
// categories, with associated rules: // categories, with associated rules:
// //
// 1) Letter: // 1) Letter:
// ALetter, Hebrew_Letter, Numeric, ExtendNumLet, Extend. // ALetter, Hebrew_Letter, Numeric, ExtendNumLet, Extend, Format_FE, ZWJ.
// Rule: Never break between consecutive runes of this category. // Rule: Never break between consecutive runes of this category.
// //
// 2) Mid: // 2) Mid:
// Format, MidLetter, MidNumLet, Single_Quote. // MidLetter, MidNumLet, Single_Quote.
// (Cf. case-ignorable: MidLetter, MidNumLet or cat is Mn, Me, Cf, Lm or Sk). // (Cf. case-ignorable: MidLetter, MidNumLet, Single_Quote or cat is Mn,
// Me, Cf, Lm or Sk).
// Rule: Don't break between Letter and Mid, but break between two Mids. // Rule: Don't break between Letter and Mid, but break between two Mids.
// //
// 3) Break: // 3) Break:
// Any other category, including NewLine, CR, LF and Double_Quote. These // Any other category: NewLine, MidNum, CR, LF, Double_Quote, Katakana, and
// categories should always result in a break between two cased letters. // Other.
// These categories should always result in a break between two cased letters.
// Rule: Always break. // Rule: Always break.
// //
// Note 1: the Katakana and MidNum categories can, in esoteric cases, result in // Note 1: the Katakana and MidNum categories can, in esoteric cases, result in
......
// This file was generated by go generate; DO NOT EDIT // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
package cases package cases
...@@ -22,6 +22,7 @@ package cases ...@@ -22,6 +22,7 @@ package cases
// Only 13..8 are used for XOR patterns. // Only 13..8 are used for XOR patterns.
// 7 inverseFold (fold to upper, not to lower) // 7 inverseFold (fold to upper, not to lower)
// 6 index: interpret the XOR pattern as an index // 6 index: interpret the XOR pattern as an index
// or isMid if case mode is cIgnorableUncased.
// 5..4 CCC: zero (normal or break), above or other // 5..4 CCC: zero (normal or break), above or other
// } // }
// 3 exception: interpret this value as an exception index // 3 exception: interpret this value as an exception index
...@@ -44,6 +45,7 @@ const ( ...@@ -44,6 +45,7 @@ const (
ignorableValue = 0x0004 ignorableValue = 0x0004
inverseFoldBit = 1 << 7 inverseFoldBit = 1 << 7
isMidBit = 1 << 6
exceptionBit = 1 << 3 exceptionBit = 1 << 3
exceptionShift = 5 exceptionShift = 5
...@@ -53,7 +55,7 @@ const ( ...@@ -53,7 +55,7 @@ const (
xorShift = 8 xorShift = 8
// There is no mapping if all xor bits and the exception bit are zero. // There is no mapping if all xor bits and the exception bit are zero.
hasMappingMask = 0xffc0 | exceptionBit hasMappingMask = 0xff80 | exceptionBit
) )
// The case mode bits encodes the case type of a rune. This includes uncased, // The case mode bits encodes the case type of a rune. This includes uncased,
...@@ -91,10 +93,6 @@ func (c info) isCaseIgnorable() bool { ...@@ -91,10 +93,6 @@ func (c info) isCaseIgnorable() bool {
return c&ignorableMask == ignorableValue return c&ignorableMask == ignorableValue
} }
func (c info) isCaseIgnorableAndNonBreakStarter() bool {
return c&(fullCasedMask|cccMask) == (ignorableValue | cccZero)
}
func (c info) isNotCasedAndNotCaseIgnorable() bool { func (c info) isNotCasedAndNotCaseIgnorable() bool {
return c&fullCasedMask == 0 return c&fullCasedMask == 0
} }
...@@ -103,6 +101,10 @@ func (c info) isCaseIgnorableAndNotCased() bool { ...@@ -103,6 +101,10 @@ func (c info) isCaseIgnorableAndNotCased() bool {
return c&fullCasedMask == cIgnorableUncased return c&fullCasedMask == cIgnorableUncased
} }
func (c info) isMid() bool {
return c&(fullCasedMask|isMidBit) == isMidBit|cIgnorableUncased
}
// The case mapping implementation will need to know about various Canonical // The case mapping implementation will need to know about various Canonical
// Combining Class (CCC) values. We encode two of these in the trie value: // Combining Class (CCC) values. We encode two of these in the trie value:
// cccZero (0) and cccAbove (230). If the value is cccOther, it means that // cccZero (0) and cccAbove (230). If the value is cccOther, it means that
......
...@@ -52,7 +52,7 @@ type Decoder struct { ...@@ -52,7 +52,7 @@ type Decoder struct {
} }
// Bytes converts the given encoded bytes to UTF-8. It returns the converted // Bytes converts the given encoded bytes to UTF-8. It returns the converted
// bytes or 0, err if any error occurred. // bytes or nil, err if any error occurred.
func (d *Decoder) Bytes(b []byte) ([]byte, error) { func (d *Decoder) Bytes(b []byte) ([]byte, error) {
b, _, err := transform.Bytes(d, b) b, _, err := transform.Bytes(d, b)
if err != nil { if err != nil {
...@@ -62,7 +62,7 @@ func (d *Decoder) Bytes(b []byte) ([]byte, error) { ...@@ -62,7 +62,7 @@ func (d *Decoder) Bytes(b []byte) ([]byte, error) {
} }
// String converts the given encoded string to UTF-8. It returns the converted // String converts the given encoded string to UTF-8. It returns the converted
// string or 0, err if any error occurred. // string or "", err if any error occurred.
func (d *Decoder) String(s string) (string, error) { func (d *Decoder) String(s string) (string, error) {
s, _, err := transform.String(d, s) s, _, err := transform.String(d, s)
if err != nil { if err != nil {
...@@ -95,7 +95,7 @@ type Encoder struct { ...@@ -95,7 +95,7 @@ type Encoder struct {
_ struct{} _ struct{}
} }
// Bytes converts bytes from UTF-8. It returns the converted bytes or 0, err if // Bytes converts bytes from UTF-8. It returns the converted bytes or nil, err if
// any error occurred. // any error occurred.
func (e *Encoder) Bytes(b []byte) ([]byte, error) { func (e *Encoder) Bytes(b []byte) ([]byte, error) {
b, _, err := transform.Bytes(e, b) b, _, err := transform.Bytes(e, b)
...@@ -106,7 +106,7 @@ func (e *Encoder) Bytes(b []byte) ([]byte, error) { ...@@ -106,7 +106,7 @@ func (e *Encoder) Bytes(b []byte) ([]byte, error) {
} }
// String converts a string from UTF-8. It returns the converted string or // String converts a string from UTF-8. It returns the converted string or
// 0, err if any error occurred. // "", err if any error occurred.
func (e *Encoder) String(s string) (string, error) { func (e *Encoder) String(s string) (string, error) {
s, _, err := transform.String(e, s) s, _, err := transform.String(e, s)
if err != nil { if err != nil {
......
...@@ -36,8 +36,8 @@ package identifier ...@@ -36,8 +36,8 @@ package identifier
// - http://www.ietf.org/rfc/rfc2978.txt // - http://www.ietf.org/rfc/rfc2978.txt
// - http://www.unicode.org/reports/tr22/ // - http://www.unicode.org/reports/tr22/
// - http://www.w3.org/TR/encoding/ // - http://www.w3.org/TR/encoding/
// - http://www.w3.org/TR/encoding/indexes/encodings.json
// - https://encoding.spec.whatwg.org/ // - https://encoding.spec.whatwg.org/
// - https://encoding.spec.whatwg.org/encodings.json
// - https://tools.ietf.org/html/rfc6657#section-5 // - https://tools.ietf.org/html/rfc6657#section-5
// Interface can be implemented by Encodings to define the CCS or CES for which // Interface can be implemented by Encodings to define the CCS or CES for which
......
// This file was generated by go generate; DO NOT EDIT // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
package identifier package identifier
......
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"internal.go",
"match.go",
"tables.go",
],
tags = ["automanaged"],
deps = ["//vendor/golang.org/x/text/language:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//vendor/golang.org/x/text/internal/tag:all-srcs",
"//vendor/golang.org/x/text/internal/utf8internal:all-srcs",
],
tags = ["automanaged"],
)
// 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 ignore
package main
import (
"log"
"golang.org/x/text/internal/gen"
"golang.org/x/text/language"
"golang.org/x/text/unicode/cldr"
)
func main() {
r := gen.OpenCLDRCoreZip()
defer r.Close()
d := &cldr.Decoder{}
data, err := d.DecodeZip(r)
if err != nil {
log.Fatalf("DecodeZip: %v", err)
}
w := gen.NewCodeWriter()
defer w.WriteGoFile("tables.go", "internal")
// Create parents table.
parents := make([]uint16, language.NumCompactTags)
for _, loc := range data.Locales() {
tag := language.MustParse(loc)
index, ok := language.CompactIndex(tag)
if !ok {
continue
}
parentIndex := 0 // und
for p := tag.Parent(); p != language.Und; p = p.Parent() {
if x, ok := language.CompactIndex(p); ok {
parentIndex = x
break
}
}
parents[index] = uint16(parentIndex)
}
w.WriteComment(`
Parent maps a compact index of a tag to the compact index of the parent of
this tag.`)
w.WriteVar("Parent", parents)
}
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:generate go run gen.go
// Package internal contains non-exported functionality that are used by
// packages in the text repository.
package internal
import (
"sort"
"golang.org/x/text/language"
)
// SortTags sorts tags in place.
func SortTags(tags []language.Tag) {
sort.Sort(sorter(tags))
}
type sorter []language.Tag
func (s sorter) Len() int {
return len(s)
}
func (s sorter) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s sorter) Less(i, j int) bool {
return s[i].String() < s[j].String()
}
// UniqueTags sorts and filters duplicate tags in place and returns a slice with
// only unique tags.
func UniqueTags(tags []language.Tag) []language.Tag {
if len(tags) <= 1 {
return tags
}
SortTags(tags)
k := 0
for i := 1; i < len(tags); i++ {
if tags[k].String() < tags[i].String() {
k++
tags[k] = tags[i]
}
}
return tags[:k+1]
}
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package internal
// This file contains matchers that implement CLDR inheritance.
//
// See http://unicode.org/reports/tr35/#Locale_Inheritance.
//
// Some of the inheritance described in this document is already handled by
// the cldr package.
import (
"golang.org/x/text/language"
)
// TODO: consider if (some of the) matching algorithm needs to be public after
// getting some feel about what is generic and what is specific.
// NewInheritanceMatcher returns a matcher that matches based on the inheritance
// chain.
//
// The matcher uses canonicalization and the parent relationship to find a
// match. The resulting match will always be either Und or a language with the
// same language and script as the requested language. It will not match
// languages for which there is understood to be mutual or one-directional
// intelligibility.
//
// A Match will indicate an Exact match if the language matches after
// canonicalization and High if the matched tag is a parent.
func NewInheritanceMatcher(t []language.Tag) *InheritanceMatcher {
tags := &InheritanceMatcher{make(map[language.Tag]int)}
for i, tag := range t {
ct, err := language.All.Canonicalize(tag)
if err != nil {
ct = tag
}
tags.index[ct] = i
}
return tags
}
type InheritanceMatcher struct {
index map[language.Tag]int
}
func (m InheritanceMatcher) Match(want ...language.Tag) (language.Tag, int, language.Confidence) {
for _, t := range want {
ct, err := language.All.Canonicalize(t)
if err != nil {
ct = t
}
conf := language.Exact
for {
if index, ok := m.index[ct]; ok {
return ct, index, conf
}
if ct == language.Und {
break
}
ct = ct.Parent()
conf = language.High
}
}
return language.Und, 0, language.No
}
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
package internal
// Parent maps a compact index of a tag to the compact index of the parent of
// this tag.
var Parent = []uint16{ // 754 elements
// Entry 0 - 3F
0x0000, 0x0053, 0x00e5, 0x0000, 0x0003, 0x0003, 0x0000, 0x0006,
0x0000, 0x0008, 0x0000, 0x000a, 0x0000, 0x000c, 0x000c, 0x000c,
0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c,
0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c,
0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c,
0x000c, 0x0000, 0x0000, 0x002a, 0x0000, 0x002c, 0x0000, 0x002e,
0x0000, 0x0000, 0x0031, 0x0030, 0x0030, 0x0000, 0x0035, 0x0000,
0x0037, 0x0000, 0x0039, 0x0000, 0x003b, 0x0000, 0x003d, 0x0000,
// Entry 40 - 7F
0x0000, 0x0040, 0x0000, 0x0042, 0x0042, 0x0000, 0x0045, 0x0045,
0x0000, 0x0048, 0x0000, 0x004a, 0x0000, 0x0000, 0x004d, 0x004c,
0x004c, 0x0000, 0x0051, 0x0051, 0x0051, 0x0051, 0x0000, 0x0056,
0x0000, 0x0058, 0x0000, 0x005a, 0x0000, 0x005c, 0x005c, 0x0000,
0x005f, 0x0000, 0x0061, 0x0000, 0x0063, 0x0000, 0x0065, 0x0065,
0x0000, 0x0068, 0x0000, 0x006a, 0x006a, 0x006a, 0x006a, 0x006a,
0x006a, 0x006a, 0x0000, 0x0072, 0x0000, 0x0074, 0x0000, 0x0076,
0x0000, 0x0000, 0x0079, 0x0000, 0x007b, 0x0000, 0x007d, 0x0000,
// Entry 80 - BF
0x007f, 0x007f, 0x0000, 0x0082, 0x0082, 0x0000, 0x0085, 0x0086,
0x0086, 0x0086, 0x0085, 0x0087, 0x0086, 0x0086, 0x0086, 0x0085,
0x0086, 0x0086, 0x0086, 0x0086, 0x0086, 0x0086, 0x0087, 0x0086,
0x0086, 0x0086, 0x0086, 0x0087, 0x0086, 0x0087, 0x0086, 0x0086,
0x0087, 0x0086, 0x0086, 0x0086, 0x0086, 0x0086, 0x0086, 0x0086,
0x0086, 0x0086, 0x0085, 0x0086, 0x0086, 0x0086, 0x0086, 0x0086,
0x0086, 0x0086, 0x0086, 0x0086, 0x0086, 0x0086, 0x0086, 0x0086,
0x0086, 0x0086, 0x0086, 0x0086, 0x0085, 0x0086, 0x0085, 0x0086,
// Entry C0 - FF
0x0086, 0x0086, 0x0086, 0x0086, 0x0086, 0x0086, 0x0086, 0x0087,
0x0086, 0x0086, 0x0086, 0x0086, 0x0086, 0x0086, 0x0086, 0x0085,
0x0086, 0x0086, 0x0086, 0x0086, 0x0086, 0x0087, 0x0086, 0x0086,
0x0087, 0x0086, 0x0086, 0x0086, 0x0086, 0x0086, 0x0086, 0x0086,
0x0086, 0x0086, 0x0086, 0x0086, 0x0085, 0x0085, 0x0086, 0x0086,
0x0085, 0x0086, 0x0086, 0x0086, 0x0086, 0x0086, 0x0000, 0x00ee,
0x0000, 0x00f0, 0x00f1, 0x00f1, 0x00f1, 0x00f1, 0x00f1, 0x00f1,
0x00f1, 0x00f1, 0x00f1, 0x00f0, 0x00f1, 0x00f0, 0x00f0, 0x00f1,
// Entry 100 - 13F
0x00f1, 0x00f0, 0x00f1, 0x00f1, 0x00f1, 0x00f1, 0x00f0, 0x00f1,
0x00f1, 0x00f1, 0x00f1, 0x00f1, 0x00f1, 0x0000, 0x010d, 0x0000,
0x010f, 0x0000, 0x0111, 0x0000, 0x0113, 0x0113, 0x0000, 0x0116,
0x0116, 0x0116, 0x0116, 0x0000, 0x011b, 0x0000, 0x011d, 0x0000,
0x011f, 0x011f, 0x0000, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122,
0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122,
0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122,
0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122,
// Entry 140 - 17F
0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122,
0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122,
0x0122, 0x0000, 0x0151, 0x0000, 0x0153, 0x0000, 0x0155, 0x0000,
0x0157, 0x0000, 0x0159, 0x0000, 0x015b, 0x015b, 0x015b, 0x0000,
0x015f, 0x0000, 0x0000, 0x0162, 0x0000, 0x0164, 0x0000, 0x0166,
0x0166, 0x0166, 0x0000, 0x016a, 0x0000, 0x016c, 0x0000, 0x016e,
0x0000, 0x0170, 0x0170, 0x0000, 0x0173, 0x0000, 0x0175, 0x0000,
0x0177, 0x0000, 0x0179, 0x0000, 0x017b, 0x0000, 0x017d, 0x0000,
// Entry 180 - 1BF
0x017f, 0x0000, 0x0181, 0x0181, 0x0181, 0x0181, 0x0000, 0x0000,
0x0187, 0x0000, 0x0000, 0x018a, 0x0000, 0x018c, 0x0000, 0x0000,
0x018f, 0x0000, 0x0191, 0x0000, 0x0000, 0x0194, 0x0000, 0x0000,
0x0197, 0x0000, 0x0199, 0x0000, 0x019b, 0x0000, 0x019d, 0x0000,
0x019f, 0x0000, 0x01a1, 0x0000, 0x01a3, 0x0000, 0x01a5, 0x0000,
0x01a7, 0x0000, 0x01a9, 0x0000, 0x01ab, 0x01ab, 0x0000, 0x01ae,
0x0000, 0x01b0, 0x0000, 0x01b2, 0x0000, 0x01b4, 0x0000, 0x01b6,
0x0000, 0x0000, 0x01b9, 0x0000, 0x01bb, 0x0000, 0x01bd, 0x0000,
// Entry 1C0 - 1FF
0x01bf, 0x0000, 0x01c1, 0x0000, 0x01c3, 0x0000, 0x01c5, 0x01c5,
0x01c5, 0x01c5, 0x0000, 0x01ca, 0x0000, 0x01cc, 0x01cc, 0x0000,
0x01cf, 0x0000, 0x01d1, 0x0000, 0x01d3, 0x0000, 0x01d5, 0x0000,
0x01d7, 0x0000, 0x01d9, 0x01d9, 0x0000, 0x01dc, 0x0000, 0x01de,
0x0000, 0x01e0, 0x0000, 0x01e2, 0x0000, 0x01e4, 0x0000, 0x01e6,
0x0000, 0x01e8, 0x0000, 0x01ea, 0x0000, 0x01ec, 0x0000, 0x01ee,
0x01ee, 0x01ee, 0x0000, 0x01f2, 0x0000, 0x01f4, 0x0000, 0x01f6,
0x0000, 0x01f8, 0x0000, 0x0000, 0x01fb, 0x0000, 0x01fd, 0x01fd,
// Entry 200 - 23F
0x0000, 0x0200, 0x0000, 0x0202, 0x0202, 0x0000, 0x0205, 0x0205,
0x0000, 0x0208, 0x0208, 0x0208, 0x0208, 0x0208, 0x0208, 0x0208,
0x0000, 0x0210, 0x0000, 0x0212, 0x0000, 0x0214, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x021a, 0x0000, 0x0000, 0x021d, 0x0000,
0x021f, 0x021f, 0x0000, 0x0222, 0x0000, 0x0224, 0x0224, 0x0000,
0x0000, 0x0228, 0x0227, 0x0227, 0x0000, 0x0000, 0x022d, 0x0000,
0x022f, 0x0000, 0x0231, 0x0000, 0x023d, 0x0233, 0x023d, 0x023d,
0x023d, 0x023d, 0x023d, 0x023d, 0x023d, 0x0233, 0x023d, 0x023d,
// Entry 240 - 27F
0x0000, 0x0240, 0x0240, 0x0240, 0x0000, 0x0244, 0x0000, 0x0246,
0x0000, 0x0248, 0x0248, 0x0000, 0x024b, 0x0000, 0x024d, 0x024d,
0x024d, 0x024d, 0x024d, 0x024d, 0x0000, 0x0254, 0x0000, 0x0256,
0x0000, 0x0258, 0x0000, 0x025a, 0x0000, 0x025c, 0x0000, 0x0000,
0x025f, 0x025f, 0x025f, 0x0000, 0x0263, 0x0000, 0x0265, 0x0000,
0x0267, 0x0000, 0x0000, 0x026a, 0x0269, 0x0269, 0x0000, 0x026e,
0x0000, 0x0270, 0x0000, 0x0272, 0x0000, 0x0000, 0x0000, 0x0000,
0x0277, 0x0000, 0x0000, 0x027a, 0x0000, 0x027c, 0x027c, 0x027c,
// Entry 280 - 2BF
0x027c, 0x0000, 0x0281, 0x0281, 0x0281, 0x0000, 0x0285, 0x0285,
0x0285, 0x0285, 0x0285, 0x0000, 0x028b, 0x028b, 0x028b, 0x028b,
0x0000, 0x0000, 0x0000, 0x0000, 0x0293, 0x0293, 0x0293, 0x0000,
0x0297, 0x0297, 0x0297, 0x0297, 0x0000, 0x0000, 0x029d, 0x029d,
0x029d, 0x029d, 0x0000, 0x02a2, 0x0000, 0x02a4, 0x02a4, 0x0000,
0x02a7, 0x0000, 0x02a9, 0x02a9, 0x0000, 0x0000, 0x02ad, 0x0000,
0x0000, 0x02b0, 0x0000, 0x02b2, 0x02b2, 0x0000, 0x0000, 0x02b6,
0x0000, 0x02b8, 0x0000, 0x02ba, 0x0000, 0x02bc, 0x0000, 0x02be,
// Entry 2C0 - 2FF
0x02be, 0x0000, 0x0000, 0x02c2, 0x0000, 0x02c4, 0x02c1, 0x02c1,
0x0000, 0x0000, 0x02c9, 0x02c8, 0x02c8, 0x0000, 0x0000, 0x02ce,
0x0000, 0x02d0, 0x0000, 0x02d2, 0x0000, 0x0000, 0x02d5, 0x0000,
0x0000, 0x0000, 0x02d9, 0x0000, 0x02db, 0x0000, 0x02dd, 0x0000,
0x02df, 0x02df, 0x0000, 0x02e2, 0x0000, 0x02e4, 0x0000, 0x02e6,
0x02e6, 0x02e6, 0x02e6, 0x02e6, 0x0000, 0x02ec, 0x02ed, 0x02ec,
0x0000, 0x02f0,
} // Size: 1532 bytes
// Total table size 1532 bytes (1KiB); checksum: 90718A2
// This file was generated by go generate; DO NOT EDIT // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
package language package language
......
...@@ -678,6 +678,8 @@ func (b *builder) parseIndices() { ...@@ -678,6 +678,8 @@ func (b *builder) parseIndices() {
b.locale.parse(meta.DefaultContent.Locales) b.locale.parse(meta.DefaultContent.Locales)
} }
// TODO: region inclusion data will probably not be use used in future matchers.
func (b *builder) computeRegionGroups() { func (b *builder) computeRegionGroups() {
b.groups = make(map[int]index) b.groups = make(map[int]index)
...@@ -686,6 +688,11 @@ func (b *builder) computeRegionGroups() { ...@@ -686,6 +688,11 @@ func (b *builder) computeRegionGroups() {
b.groups[i] = index(len(b.groups)) b.groups[i] = index(len(b.groups))
} }
for _, g := range b.supp.TerritoryContainment.Group { for _, g := range b.supp.TerritoryContainment.Group {
// Skip UN and EURO zone as they are flattening the containment
// relationship.
if g.Type == "EZ" || g.Type == "UN" {
continue
}
group := b.region.index(g.Type) group := b.region.index(g.Type)
if _, ok := b.groups[group]; !ok { if _, ok := b.groups[group]; !ok {
b.groups[group] = index(len(b.groups)) b.groups[group] = index(len(b.groups))
...@@ -782,6 +789,7 @@ func (b *builder) writeLanguage() { ...@@ -782,6 +789,7 @@ func (b *builder) writeLanguage() {
lang.updateLater("tw", "twi") lang.updateLater("tw", "twi")
lang.updateLater("nb", "nob") lang.updateLater("nb", "nob")
lang.updateLater("ak", "aka") lang.updateLater("ak", "aka")
lang.updateLater("bh", "bih")
// Ensure that each 2-letter code is matched with a 3-letter code. // Ensure that each 2-letter code is matched with a 3-letter code.
for _, v := range lang.s[1:] { for _, v := range lang.s[1:] {
...@@ -798,10 +806,10 @@ func (b *builder) writeLanguage() { ...@@ -798,10 +806,10 @@ func (b *builder) writeLanguage() {
} }
} }
// Complete canonialized language tags. // Complete canonicalized language tags.
lang.freeze() lang.freeze()
for i, v := range lang.s { for i, v := range lang.s {
// We can avoid these manual entries by using the IANI registry directly. // We can avoid these manual entries by using the IANA registry directly.
// Seems easier to update the list manually, as changes are rare. // Seems easier to update the list manually, as changes are rare.
// The panic in this loop will trigger if we miss an entry. // The panic in this loop will trigger if we miss an entry.
add := "" add := ""
...@@ -908,7 +916,7 @@ func (b *builder) writeRegion() { ...@@ -908,7 +916,7 @@ func (b *builder) writeRegion() {
i := b.region.index(s) i := b.region.index(s)
for _, d := range e.description { for _, d := range e.description {
if strings.Contains(d, "Private use") { if strings.Contains(d, "Private use") {
regionTypes[i] = iso3166UserAssgined regionTypes[i] = iso3166UserAssigned
} }
} }
regionTypes[i] |= bcp47Region regionTypes[i] |= bcp47Region
...@@ -1065,7 +1073,7 @@ const ( ...@@ -1065,7 +1073,7 @@ const (
) )
const ( const (
iso3166UserAssgined = 1 << iota iso3166UserAssigned = 1 << iota
ccTLD ccTLD
bcp47Region bcp47Region
) )
...@@ -1355,42 +1363,23 @@ func (b *builder) writeLikelyData() { ...@@ -1355,42 +1363,23 @@ func (b *builder) writeLikelyData() {
type mutualIntelligibility struct { type mutualIntelligibility struct {
want, have uint16 want, have uint16
conf uint8 distance uint8
oneway bool oneway bool
} }
type scriptIntelligibility struct { type scriptIntelligibility struct {
lang uint16 // langID or 0 if * wantLang, haveLang uint16
want, have uint8 wantScript, haveScript uint8
conf uint8 distance uint8
} // Always oneway
type sortByConf []mutualIntelligibility
func (l sortByConf) Less(a, b int) bool {
return l[a].conf > l[b].conf
} }
func (l sortByConf) Swap(a, b int) { type regionIntelligibility struct {
l[a], l[b] = l[b], l[a] lang uint16 // compact language id
} script uint8 // 0 means any
group uint8 // 0 means any; if bit 7 is set it means inverse
func (l sortByConf) Len() int { distance uint8
return len(l) // Always twoway.
}
// toConf converts a percentage value [0, 100] to a confidence class.
func toConf(pct uint8) uint8 {
switch {
case pct == 100:
return 3 // Exact
case pct >= 90:
return 2 // High
case pct > 50:
return 1 // Low
default:
return 0 // No
}
} }
// writeMatchData writes tables with languages and scripts for which there is // writeMatchData writes tables with languages and scripts for which there is
...@@ -1400,13 +1389,50 @@ func toConf(pct uint8) uint8 { ...@@ -1400,13 +1389,50 @@ func toConf(pct uint8) uint8 {
// We also drop all region-related data as we use a different algorithm to // We also drop all region-related data as we use a different algorithm to
// determine region equivalence. // determine region equivalence.
func (b *builder) writeMatchData() { func (b *builder) writeMatchData() {
b.writeType(mutualIntelligibility{})
b.writeType(scriptIntelligibility{})
lm := b.supp.LanguageMatching.LanguageMatches lm := b.supp.LanguageMatching.LanguageMatches
cldr.MakeSlice(&lm).SelectAnyOf("type", "written") cldr.MakeSlice(&lm).SelectAnyOf("type", "written_new")
regionHierarchy := map[string][]string{}
for _, g := range b.supp.TerritoryContainment.Group {
regions := strings.Split(g.Contains, " ")
regionHierarchy[g.Type] = append(regionHierarchy[g.Type], regions...)
}
regionToGroups := make([]uint8, len(b.region.s))
matchLang := []mutualIntelligibility{} idToIndex := map[string]uint8{}
for i, mv := range lm[0].MatchVariable {
if i > 6 {
log.Fatalf("Too many groups: %d", i)
}
idToIndex[mv.Id] = uint8(i + 1)
// TODO: also handle '-'
for _, r := range strings.Split(mv.Value, "+") {
todo := []string{r}
for k := 0; k < len(todo); k++ {
r := todo[k]
regionToGroups[b.region.index(r)] |= 1 << uint8(i)
todo = append(todo, regionHierarchy[r]...)
}
}
}
b.writeSlice("regionToGroups", regionToGroups)
b.writeType(mutualIntelligibility{})
b.writeType(scriptIntelligibility{})
b.writeType(regionIntelligibility{})
matchLang := []mutualIntelligibility{{
// TODO: remove once CLDR is fixed.
want: uint16(b.langIndex("sr")),
have: uint16(b.langIndex("hr")),
distance: uint8(5),
}, {
want: uint16(b.langIndex("sr")),
have: uint16(b.langIndex("bs")),
distance: uint8(5),
}}
matchScript := []scriptIntelligibility{} matchScript := []scriptIntelligibility{}
matchRegion := []regionIntelligibility{}
// Convert the languageMatch entries in lists keyed by desired language. // Convert the languageMatch entries in lists keyed by desired language.
for _, m := range lm[0].LanguageMatch { for _, m := range lm[0].LanguageMatch {
// Different versions of CLDR use different separators. // Different versions of CLDR use different separators.
...@@ -1414,33 +1440,38 @@ func (b *builder) writeMatchData() { ...@@ -1414,33 +1440,38 @@ func (b *builder) writeMatchData() {
supported := strings.Replace(m.Supported, "-", "_", -1) supported := strings.Replace(m.Supported, "-", "_", -1)
d := strings.Split(desired, "_") d := strings.Split(desired, "_")
s := strings.Split(supported, "_") s := strings.Split(supported, "_")
if len(d) != len(s) || len(d) > 2 { if len(d) != len(s) {
// Skip all entries with regions and work around CLDR bug. log.Fatalf("not supported: desired=%q; supported=%q", desired, supported)
continue continue
} }
pct, _ := strconv.ParseInt(m.Percent, 10, 8) distance, _ := strconv.ParseInt(m.Distance, 10, 8)
if len(d) == 2 && d[0] == s[0] && len(d[1]) == 4 { switch len(d) {
// language-script pair. case 2:
lang := uint16(0) if desired == supported && desired == "*_*" {
if d[0] != "*" { continue
lang = uint16(b.langIndex(d[0]))
} }
// language-script pair.
matchScript = append(matchScript, scriptIntelligibility{ matchScript = append(matchScript, scriptIntelligibility{
lang: lang, wantLang: uint16(b.langIndex(d[0])),
want: uint8(b.script.index(d[1])), haveLang: uint16(b.langIndex(s[0])),
have: uint8(b.script.index(s[1])), wantScript: uint8(b.script.index(d[1])),
conf: toConf(uint8(pct)), haveScript: uint8(b.script.index(s[1])),
distance: uint8(distance),
}) })
if m.Oneway != "true" { if m.Oneway != "true" {
matchScript = append(matchScript, scriptIntelligibility{ matchScript = append(matchScript, scriptIntelligibility{
lang: lang, wantLang: uint16(b.langIndex(s[0])),
want: uint8(b.script.index(s[1])), haveLang: uint16(b.langIndex(d[0])),
have: uint8(b.script.index(d[1])), wantScript: uint8(b.script.index(s[1])),
conf: toConf(uint8(pct)), haveScript: uint8(b.script.index(d[1])),
distance: uint8(distance),
}) })
} }
} else if len(d) == 1 && d[0] != "*" { case 1:
if pct == 100 { if desired == supported && desired == "*" {
continue
}
if distance == 1 {
// nb == no is already handled by macro mapping. Check there // nb == no is already handled by macro mapping. Check there
// really is only this case. // really is only this case.
if d[0] != "no" || s[0] != "nb" { if d[0] != "no" || s[0] != "nb" {
...@@ -1448,28 +1479,57 @@ func (b *builder) writeMatchData() { ...@@ -1448,28 +1479,57 @@ func (b *builder) writeMatchData() {
} }
continue continue
} }
// TODO: consider dropping oneway field and just doubling the entry.
matchLang = append(matchLang, mutualIntelligibility{ matchLang = append(matchLang, mutualIntelligibility{
want: uint16(b.langIndex(d[0])), want: uint16(b.langIndex(d[0])),
have: uint16(b.langIndex(s[0])), have: uint16(b.langIndex(s[0])),
conf: uint8(pct), distance: uint8(distance),
oneway: m.Oneway == "true", oneway: m.Oneway == "true",
}) })
} else { case 3:
// TODO: Handle other mappings. if desired == supported && desired == "*_*_*" {
a := []string{"*;*", "*_*;*_*", "es_MX;es_419"} continue
s := strings.Join([]string{desired, supported}, ";") }
if i := sort.SearchStrings(a, s); i == len(a) || a[i] != s { if desired != supported { // (Weird but correct.)
log.Printf("%q not handled", s) log.Fatalf("not supported: desired=%q; supported=%q", desired, supported)
continue
}
ri := regionIntelligibility{
lang: b.langIndex(d[0]),
distance: uint8(distance),
} }
if d[1] != "*" {
ri.script = uint8(b.script.index(d[1]))
}
switch {
case d[2] == "*":
ri.group = 0x80 // not contained in anything
case strings.HasPrefix(d[2], "$!"):
ri.group = 0x80
d[2] = "$" + d[2][len("$!"):]
fallthrough
case strings.HasPrefix(d[2], "$"):
ri.group |= idToIndex[d[2]]
}
matchRegion = append(matchRegion, ri)
default:
log.Fatalf("not supported: desired=%q; supported=%q", desired, supported)
} }
} }
sort.Stable(sortByConf(matchLang)) sort.SliceStable(matchLang, func(i, j int) bool {
// collapse percentage into confidence classes return matchLang[i].distance < matchLang[j].distance
for i, m := range matchLang { })
matchLang[i].conf = toConf(m.conf)
}
b.writeSlice("matchLang", matchLang) b.writeSlice("matchLang", matchLang)
sort.SliceStable(matchScript, func(i, j int) bool {
return matchScript[i].distance < matchScript[j].distance
})
b.writeSlice("matchScript", matchScript) b.writeSlice("matchScript", matchScript)
sort.SliceStable(matchRegion, func(i, j int) bool {
return matchRegion[i].distance < matchRegion[j].distance
})
b.writeSlice("matchRegion", matchRegion)
} }
func (b *builder) writeRegionInclusionData() { func (b *builder) writeRegionInclusionData() {
...@@ -1482,6 +1542,11 @@ func (b *builder) writeRegionInclusionData() { ...@@ -1482,6 +1542,11 @@ func (b *builder) writeRegionInclusionData() {
containment = make(map[index][]index) containment = make(map[index][]index)
) )
for _, g := range b.supp.TerritoryContainment.Group { for _, g := range b.supp.TerritoryContainment.Group {
// Skip UN and EURO zone as they are flattening the containment
// relationship.
if g.Type == "EZ" || g.Type == "UN" {
continue
}
group := b.region.index(g.Type) group := b.region.index(g.Type)
groupIdx := b.groups[group] groupIdx := b.groups[group]
for _, mem := range strings.Split(g.Contains, " ") { for _, mem := range strings.Split(g.Contains, " ") {
...@@ -1508,7 +1573,6 @@ func (b *builder) writeRegionInclusionData() { ...@@ -1508,7 +1573,6 @@ func (b *builder) writeRegionInclusionData() {
for _, v := range l { for _, v := range l {
regionContainment[g] |= 1 << v regionContainment[g] |= 1 << v
} }
// log.Printf("%d: %X", g, regionContainment[g])
} }
b.writeSlice("regionContainment", regionContainment) b.writeSlice("regionContainment", regionContainment)
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment