updated ipbl
All checks were successful
continuous-integration/drone Build is passing

This commit is contained in:
Paul 2021-12-12 17:33:40 +01:00
parent 7cff022c29
commit bc35e6ad67
190 changed files with 10255 additions and 9163 deletions

View File

@ -8,6 +8,7 @@ import (
"git.paulbsd.com/paulbsd/ipbl/src/ipbl" "git.paulbsd.com/paulbsd/ipbl/src/ipbl"
"git.paulbsd.com/paulbsd/ipbl/src/ipblws" "git.paulbsd.com/paulbsd/ipbl/src/ipblws"
_ "github.com/lib/pq" _ "github.com/lib/pq"
"github.com/robfig/cron"
) )
//var version string //var version string
@ -24,8 +25,16 @@ func main() {
} }
defer cfg.Db.Close() defer cfg.Db.Close()
// Handles IP with no reverse DNS
go ipbl.ScanIP(&cfg) go ipbl.ScanIP(&cfg)
// Add cron task to handle them
cr := cron.New()
cr.AddFunc("0 * * * * *", func() {
ipbl.ScanIP(&cfg)
})
cr.Start()
// Run the ipbl web service // Run the ipbl web service
err = ipblws.RunServer(&cfg) err = ipblws.RunServer(&cfg)
if err != nil { if err != nil {

22
go.mod
View File

@ -4,28 +4,30 @@ go 1.17
require ( require (
github.com/labstack/echo/v4 v4.6.1 github.com/labstack/echo/v4 v4.6.1
github.com/lib/pq v1.10.3 github.com/lib/pq v1.10.4
gopkg.in/ini.v1 v1.63.2 github.com/robfig/cron v1.2.0
gopkg.in/ini.v1 v1.66.2
xorm.io/xorm v1.2.5 xorm.io/xorm v1.2.5
) )
require ( require (
github.com/goccy/go-json v0.7.8 // indirect github.com/goccy/go-json v0.8.1 // indirect
github.com/golang/snappy v0.0.4 // indirect github.com/golang/snappy v0.0.4 // indirect
github.com/json-iterator/go v1.1.11 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/labstack/gommon v0.3.0 // indirect github.com/labstack/gommon v0.3.1 // indirect
github.com/mattn/go-colorable v0.1.8 // indirect github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-isatty v0.0.14 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/onsi/ginkgo v1.16.4 // indirect github.com/onsi/ginkgo v1.16.4 // indirect
github.com/onsi/gomega v1.14.0 // indirect github.com/onsi/gomega v1.14.0 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/syndtr/goleveldb v1.0.0 // indirect github.com/syndtr/goleveldb v1.0.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.1 // indirect github.com/valyala/fasttemplate v1.2.1 // indirect
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b // indirect
golang.org/x/net v0.0.0-20210913180222-943fd674d43e // indirect golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect
golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0 // indirect golang.org/x/sys v0.0.0-20211210111614-af8b64212486 // indirect
golang.org/x/text v0.3.7 // indirect golang.org/x/text v0.3.7 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
xorm.io/builder v0.3.9 // indirect xorm.io/builder v0.3.9 // indirect

27
go.sum
View File

@ -77,6 +77,8 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg78
github.com/goccy/go-json v0.7.4/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.7.4/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.7.8 h1:CvMH7LotYymYuLGEohBM1lTZWX4g6jzWUUl2aLFuBoE= github.com/goccy/go-json v0.7.8 h1:CvMH7LotYymYuLGEohBM1lTZWX4g6jzWUUl2aLFuBoE=
github.com/goccy/go-json v0.7.8/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.7.8/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.8.1 h1:4/Wjm0JIJaTDm8K1KcGrLHJoa8EsJ13YWeX+6Kfq6uI=
github.com/goccy/go-json v0.8.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
@ -200,6 +202,8 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
@ -217,6 +221,8 @@ github.com/labstack/echo/v4 v4.6.1 h1:OMVsrnNFzYlGSdaiYGHbgWQnr+JM7NG+B9suCPie14
github.com/labstack/echo/v4 v4.6.1/go.mod h1:RnjgMWNDB9g/HucVWhQYNQP9PvbYf6adqftqryo7s9k= github.com/labstack/echo/v4 v4.6.1/go.mod h1:RnjgMWNDB9g/HucVWhQYNQP9PvbYf6adqftqryo7s9k=
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0= github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o=
github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
@ -224,6 +230,8 @@ github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.3 h1:v9QZf2Sn6AmjXtQeFpdoq/eaNtYP6IN+7lcrygsIAtg= github.com/lib/pq v1.10.3 h1:v9QZf2Sn6AmjXtQeFpdoq/eaNtYP6IN+7lcrygsIAtg=
github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
@ -233,6 +241,9 @@ github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
@ -261,6 +272,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
@ -325,6 +338,10 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
@ -407,6 +424,8 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b h1:QAqMVf3pSa6eeTsuklijukjXBlj7Es2QQplab+/RbQ4=
golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@ -439,6 +458,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210913180222-943fd674d43e h1:+b/22bPvDYt4NPDcy4xAGCmON713ONAWFeY3Z7I3tR8= golang.org/x/net v0.0.0-20210913180222-943fd674d43e h1:+b/22bPvDYt4NPDcy4xAGCmON713ONAWFeY3Z7I3tR8=
golang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY=
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -483,6 +504,10 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0 h1:xrCZDmdtoloIiooiA9q0OQb9r8HejIHYoHGhGCe1pGg= golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0 h1:xrCZDmdtoloIiooiA9q0OQb9r8HejIHYoHGhGCe1pGg=
golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486 h1:5hpz5aRr+W1erYCL5JRhSUBJRph7l9XkNveoExlrKYk=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -557,6 +582,8 @@ gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
gopkg.in/ini.v1 v1.63.2 h1:tGK/CyBg7SMzb60vP1M03vNZ3VDu3wGQJwn7Sxi9r3c= gopkg.in/ini.v1 v1.63.2 h1:tGK/CyBg7SMzb60vP1M03vNZ3VDu3wGQJwn7Sxi9r3c=
gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI=
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=

View File

@ -15,7 +15,7 @@ import (
// Init creates connection to database and exec Schema // Init creates connection to database and exec Schema
func Init(cfg *config.Config) (err error) { func Init(cfg *config.Config) (err error) {
databaseEngine := "postgres" databaseEngine := "postgres"
tables := []interface{}{ipbl.IP{}} tables := []interface{}{ipbl.IP{}, ipbl.Cfg{}, ipbl.Src{}}
cfg.Db, err = xorm.NewEngine(databaseEngine, cfg.Db, err = xorm.NewEngine(databaseEngine,
fmt.Sprintf("%s://%s:%s@%s/%s", fmt.Sprintf("%s://%s:%s@%s/%s",

8
src/ipbl/cfg.go Normal file
View File

@ -0,0 +1,8 @@
package ipbl
// Cfg is ipbl config
type Cfg struct {
ID int `xorm:"pk autoincr" json:"-"`
Key string `xorm:"text notnull unique" json:"key"`
Value string `xorm:"text default" json:"value"`
}

View File

@ -1,7 +1,9 @@
package ipbl package ipbl
import ( import (
"database/sql"
"fmt" "fmt"
"log"
"net" "net"
"time" "time"
@ -16,7 +18,25 @@ func (i *IP) UpdateRDNS() (result string) {
return res[0] return res[0]
} }
func ScanIP(cfg *config.Config) { func (i *IP) InsertIP(cfg *config.Config) (num int64, err error) {
num, err = cfg.Db.Insert(i)
return
}
func InsertIPBulk(cfg *config.Config, ips *[]IP) (numinserts int64, numfail int64, err error) {
for _, ip := range *ips {
num, err := cfg.Db.Insert(ip)
if err != nil {
numfail++
continue
}
numinserts += num
}
return
}
func ScanIP(cfg *config.Config) (err error) {
log.Println("Starting set of rdns")
for { for {
var orphans = []IP{} var orphans = []IP{}
cfg.Db.Where("rdns IS NULL").Asc("ip").Find(&orphans) cfg.Db.Where("rdns IS NULL").Asc("ip").Find(&orphans)
@ -25,36 +45,30 @@ func ScanIP(cfg *config.Config) {
reverse := i.UpdateRDNS() reverse := i.UpdateRDNS()
if reverse == "" { if reverse == "" {
fmt.Printf("Set \"none\" rdns to IP %s\n", i.IP) fmt.Printf("Set \"none\" rdns to IP %s\n", i.IP)
i.Rdns = "none" i.Rdns.String = "none"
cfg.Db.ID(i.ID).Cols("rdns").Update(&i)
} else { } else {
fmt.Printf("%s %s\n", i.IP, reverse) fmt.Printf("%s %s\n", i.IP, reverse)
i.Rdns = reverse i.Rdns.String = reverse
cfg.Db.ID(i.ID).Cols("rdns").Update(&i) }
i.Rdns.Valid = true
_, err = cfg.Db.ID(i.ID).Cols("rdns").Update(&i)
if err != nil {
log.Println(err)
} }
} }
} else { } else {
fmt.Println("end")
break break
} }
} }
log.Println("End set of rdns")
return
} }
// User describe accounts // IP describe IP objects
type IP struct { type IP struct {
ID int `xorm:"pk autoincr" json:"-"` ID int `xorm:"pk autoincr" json:"-"`
IP string `xorm:"text notnull unique(ipsrc)" json:"ip"` IP string `xorm:"text notnull unique(ipsrc)" json:"ip"`
Rdns string `xorm:"text default" json:"rdns"` Rdns sql.NullString `xorm:"text default" json:"rdns"`
Src string `xorm:"text notnull unique(ipsrc)" json:"src"`
Created time.Time `xorm:"created notnull" json:"-"`
Updated time.Time `xorm:"updated notnull" json:"-"`
}
// User describe accounts
type IPBLCfg struct {
ID int `xorm:"pk autoincr" json:"-"`
IP string `xorm:"text notnull unique(ipsrc)" json:"ip"`
Rdns string `xorm:"text default" json:"rdns"`
Src string `xorm:"text notnull unique(ipsrc)" json:"src"` Src string `xorm:"text notnull unique(ipsrc)" json:"src"`
Created time.Time `xorm:"created notnull" json:"-"` Created time.Time `xorm:"created notnull" json:"-"`
Updated time.Time `xorm:"updated notnull" json:"-"` Updated time.Time `xorm:"updated notnull" json:"-"`

7
src/ipbl/src.go Normal file
View File

@ -0,0 +1,7 @@
package ipbl
// Src is src types
type Src struct {
ID int `xorm:"pk autoincr" json:"-"`
Src string `xorm:"text notnull unique" json:"src"`
}

View File

@ -18,7 +18,11 @@ func RunServer(cfg *config.Config) (err error) {
e.HideBanner = cfg.Options.HideBanner e.HideBanner = cfg.Options.HideBanner
e.GET("/", func(c echo.Context) error { e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Welcome to ipbl software (https://git.paulbsd.com/paulbsd/ipbl)") return c.HTML(http.StatusOK, `<html>
<body style="background-color: black">
<p style="color:white">Welcome to ipbl software (https://git.paulbsd.com/paulbsd/ipbl)</p>
</body>
</html>`)
}) })
e.GET("/ip/:ip", func(c echo.Context) (err error) { e.GET("/ip/:ip", func(c echo.Context) (err error) {
var ip = ipbl.IP{IP: c.Param("ip")} var ip = ipbl.IP{IP: c.Param("ip")}
@ -26,10 +30,19 @@ func RunServer(cfg *config.Config) (err error) {
if res { if res {
return c.JSON(http.StatusOK, ip) return c.JSON(http.StatusOK, ip)
} }
return c.String(http.StatusNotFound, "IP not found") return c.JSON(http.StatusNotFound, "IP not found")
}) })
e.POST("/ip", func(c echo.Context) (err error) { e.POST("/ip", func(c echo.Context) (err error) {
return c.String(http.StatusNotImplemented, "") var ip = new(ipbl.IP)
err = c.Bind(ip)
if err != nil {
return c.JSON(http.StatusInternalServerError, "Error when parsing body")
}
num, err := ip.InsertIP(cfg)
if err != nil {
return c.JSON(http.StatusInternalServerError, "Error inserting data")
}
return c.JSON(http.StatusOK, fmt.Sprintf("Inserted %d IP", num))
}) })
e.GET("/ips", func(c echo.Context) (err error) { e.GET("/ips", func(c echo.Context) (err error) {
var ips = []ipbl.IP{} var ips = []ipbl.IP{}
@ -45,7 +58,12 @@ func RunServer(cfg *config.Config) (err error) {
}) })
e.POST("/ips", func(c echo.Context) (err error) { e.POST("/ips", func(c echo.Context) (err error) {
var ips = []ipbl.IP{} var ips = []ipbl.IP{}
return c.JSON(http.StatusOK, ips) err = c.Bind(&ips)
if err != nil {
return c.JSON(http.StatusInternalServerError, "Error when parsing body")
}
numinsert, numfail, _ := ipbl.InsertIPBulk(cfg, &ips)
return c.JSON(http.StatusOK, fmt.Sprintf("Inserted %d IP, %d errors", numinsert, numfail))
}) })
e.Logger.Fatal( e.Logger.Fatal(

View File

@ -1,3 +1,20 @@
# v0.8.1 - 2021/12/05
* Fix operation conversion from PtrHead to Head in Recursive type ( #305 )
# v0.8.0 - 2021/12/02
* Fix embedded field conflict behavior ( #300 )
* Refactor compiler for encoder ( #301 #302 )
# v0.7.10 - 2021/10/16
* Fix conversion from pointer to uint64 ( #294 )
# v0.7.9 - 2021/09/28
* Fix encoding of nil value about interface type that has method ( #291 )
# v0.7.8 - 2021/09/01 # v0.7.8 - 2021/09/01
* Fix mapassign_faststr for indirect struct type ( #283 ) * Fix mapassign_faststr for indirect struct type ( #283 )

View File

@ -13,7 +13,7 @@ Fast JSON encoder/decoder compatible with encoding/json for Go
``` ```
* version ( expected release date ) * version ( expected release date )
* v0.7.0 * v0.8.0
| |
| while maintaining compatibility with encoding/json, we will add convenient APIs | while maintaining compatibility with encoding/json, we will add convenient APIs
| |
@ -21,7 +21,7 @@ Fast JSON encoder/decoder compatible with encoding/json for Go
* v1.0.0 * v1.0.0
``` ```
We are accepting requests for features that will be implemented between v0.7.0 and v.1.0.0. We are accepting requests for features that will be implemented between v0.8.0 and v.1.0.0.
If you have the API you need, please submit your issue [here](https://github.com/goccy/go-json/issues). If you have the API you need, please submit your issue [here](https://github.com/goccy/go-json/issues).
For example, I'm thinking of supporting `context.Context` of `json.Marshaler` and decoding using JSON Path. For example, I'm thinking of supporting `context.Context` of `json.Marshaler` and decoding using JSON Path.

View File

@ -1,7 +1,7 @@
version: '2' version: '2'
services: services:
go-json: go-json:
image: golang:1.16 image: golang:1.17
volumes: volumes:
- '.:/go/src/go-json' - '.:/go/src/go-json'
deploy: deploy:

View File

@ -0,0 +1,875 @@
package encoder
import (
"fmt"
"unsafe"
"github.com/goccy/go-json/internal/runtime"
)
type Code interface {
Kind() CodeKind
ToOpcode(*compileContext) Opcodes
}
type AnonymousCode interface {
ToAnonymousOpcode(*compileContext) Opcodes
}
type Opcodes []*Opcode
func (o Opcodes) First() *Opcode {
if len(o) == 0 {
return nil
}
return o[0]
}
func (o Opcodes) Last() *Opcode {
if len(o) == 0 {
return nil
}
return o[len(o)-1]
}
func (o Opcodes) Add(codes ...*Opcode) Opcodes {
return append(o, codes...)
}
type CodeKind int
const (
CodeKindInterface CodeKind = iota
CodeKindPtr
CodeKindInt
CodeKindUint
CodeKindFloat
CodeKindString
CodeKindBool
CodeKindStruct
CodeKindMap
CodeKindSlice
CodeKindArray
CodeKindBytes
CodeKindMarshalJSON
CodeKindMarshalText
CodeKindRecursive
)
type IntCode struct {
typ *runtime.Type
bitSize uint8
isString bool
isPtr bool
}
func (c *IntCode) Kind() CodeKind {
return CodeKindInt
}
func (c *IntCode) ToOpcode(ctx *compileContext) Opcodes {
var code *Opcode
switch {
case c.isPtr:
code = newOpCode(ctx, c.typ, OpIntPtr)
case c.isString:
code = newOpCode(ctx, c.typ, OpIntString)
default:
code = newOpCode(ctx, c.typ, OpInt)
}
code.NumBitSize = c.bitSize
ctx.incIndex()
return Opcodes{code}
}
type UintCode struct {
typ *runtime.Type
bitSize uint8
isString bool
isPtr bool
}
func (c *UintCode) Kind() CodeKind {
return CodeKindUint
}
func (c *UintCode) ToOpcode(ctx *compileContext) Opcodes {
var code *Opcode
switch {
case c.isPtr:
code = newOpCode(ctx, c.typ, OpUintPtr)
case c.isString:
code = newOpCode(ctx, c.typ, OpUintString)
default:
code = newOpCode(ctx, c.typ, OpUint)
}
code.NumBitSize = c.bitSize
ctx.incIndex()
return Opcodes{code}
}
type FloatCode struct {
typ *runtime.Type
bitSize uint8
isPtr bool
}
func (c *FloatCode) Kind() CodeKind {
return CodeKindFloat
}
func (c *FloatCode) ToOpcode(ctx *compileContext) Opcodes {
var code *Opcode
switch {
case c.isPtr:
switch c.bitSize {
case 32:
code = newOpCode(ctx, c.typ, OpFloat32Ptr)
default:
code = newOpCode(ctx, c.typ, OpFloat64Ptr)
}
default:
switch c.bitSize {
case 32:
code = newOpCode(ctx, c.typ, OpFloat32)
default:
code = newOpCode(ctx, c.typ, OpFloat64)
}
}
ctx.incIndex()
return Opcodes{code}
}
type StringCode struct {
typ *runtime.Type
isPtr bool
}
func (c *StringCode) Kind() CodeKind {
return CodeKindString
}
func (c *StringCode) ToOpcode(ctx *compileContext) Opcodes {
isJSONNumberType := c.typ == runtime.Type2RType(jsonNumberType)
var code *Opcode
if c.isPtr {
if isJSONNumberType {
code = newOpCode(ctx, c.typ, OpNumberPtr)
} else {
code = newOpCode(ctx, c.typ, OpStringPtr)
}
} else {
if isJSONNumberType {
code = newOpCode(ctx, c.typ, OpNumber)
} else {
code = newOpCode(ctx, c.typ, OpString)
}
}
ctx.incIndex()
return Opcodes{code}
}
type BoolCode struct {
typ *runtime.Type
isPtr bool
}
func (c *BoolCode) Kind() CodeKind {
return CodeKindBool
}
func (c *BoolCode) ToOpcode(ctx *compileContext) Opcodes {
var code *Opcode
switch {
case c.isPtr:
code = newOpCode(ctx, c.typ, OpBoolPtr)
default:
code = newOpCode(ctx, c.typ, OpBool)
}
ctx.incIndex()
return Opcodes{code}
}
type BytesCode struct {
typ *runtime.Type
isPtr bool
}
func (c *BytesCode) Kind() CodeKind {
return CodeKindBytes
}
func (c *BytesCode) ToOpcode(ctx *compileContext) Opcodes {
var code *Opcode
switch {
case c.isPtr:
code = newOpCode(ctx, c.typ, OpBytesPtr)
default:
code = newOpCode(ctx, c.typ, OpBytes)
}
ctx.incIndex()
return Opcodes{code}
}
type SliceCode struct {
typ *runtime.Type
value Code
}
func (c *SliceCode) Kind() CodeKind {
return CodeKindSlice
}
func (c *SliceCode) ToOpcode(ctx *compileContext) Opcodes {
// header => opcode => elem => end
// ^ |
// |________|
size := c.typ.Elem().Size()
header := newSliceHeaderCode(ctx, c.typ)
ctx.incIndex()
ctx.incIndent()
codes := c.value.ToOpcode(ctx)
ctx.decIndent()
codes.First().Flags |= IndirectFlags
elemCode := newSliceElemCode(ctx, c.typ.Elem(), header, size)
ctx.incIndex()
end := newOpCode(ctx, c.typ, OpSliceEnd)
ctx.incIndex()
header.End = end
header.Next = codes.First()
codes.Last().Next = elemCode
elemCode.Next = codes.First()
elemCode.End = end
return Opcodes{header}.Add(codes...).Add(elemCode).Add(end)
}
type ArrayCode struct {
typ *runtime.Type
value Code
}
func (c *ArrayCode) Kind() CodeKind {
return CodeKindArray
}
func (c *ArrayCode) ToOpcode(ctx *compileContext) Opcodes {
// header => opcode => elem => end
// ^ |
// |________|
elem := c.typ.Elem()
alen := c.typ.Len()
size := elem.Size()
header := newArrayHeaderCode(ctx, c.typ, alen)
ctx.incIndex()
ctx.incIndent()
codes := c.value.ToOpcode(ctx)
ctx.decIndent()
codes.First().Flags |= IndirectFlags
elemCode := newArrayElemCode(ctx, elem, header, alen, size)
ctx.incIndex()
end := newOpCode(ctx, c.typ, OpArrayEnd)
ctx.incIndex()
header.End = end
header.Next = codes.First()
codes.Last().Next = elemCode
elemCode.Next = codes.First()
elemCode.End = end
return Opcodes{header}.Add(codes...).Add(elemCode).Add(end)
}
type MapCode struct {
typ *runtime.Type
key Code
value Code
}
func (c *MapCode) Kind() CodeKind {
return CodeKindMap
}
func (c *MapCode) ToOpcode(ctx *compileContext) Opcodes {
// header => code => value => code => key => code => value => code => end
// ^ |
// |_______________________|
header := newMapHeaderCode(ctx, c.typ)
ctx.incIndex()
keyCodes := c.key.ToOpcode(ctx)
value := newMapValueCode(ctx, c.typ.Elem(), header)
ctx.incIndex()
ctx.incIndent()
valueCodes := c.value.ToOpcode(ctx)
ctx.decIndent()
valueCodes.First().Flags |= IndirectFlags
key := newMapKeyCode(ctx, c.typ.Key(), header)
ctx.incIndex()
end := newMapEndCode(ctx, c.typ, header)
ctx.incIndex()
header.Next = keyCodes.First()
keyCodes.Last().Next = value
value.Next = valueCodes.First()
valueCodes.Last().Next = key
key.Next = keyCodes.First()
header.End = end
key.End = end
value.End = end
return Opcodes{header}.Add(keyCodes...).Add(value).Add(valueCodes...).Add(key).Add(end)
}
type StructCode struct {
typ *runtime.Type
fields []*StructFieldCode
isPtr bool
disableIndirectConversion bool
isIndirect bool
isRecursive bool
}
func (c *StructCode) Kind() CodeKind {
return CodeKindStruct
}
func (c *StructCode) lastFieldCode(field *StructFieldCode, firstField *Opcode) *Opcode {
if field.isAnonymous {
return c.lastAnonymousFieldCode(firstField)
}
lastField := firstField
for lastField.NextField != nil {
lastField = lastField.NextField
}
return lastField
}
func (c *StructCode) lastAnonymousFieldCode(firstField *Opcode) *Opcode {
// firstField is special StructHead operation for anonymous structure.
// So, StructHead's next operation is truly struct head operation.
lastField := firstField.Next
for lastField.NextField != nil {
lastField = lastField.NextField
}
return lastField
}
func (c *StructCode) ToOpcode(ctx *compileContext) Opcodes {
// header => code => structField => code => end
// ^ |
// |__________|
if c.isRecursive {
recursive := newRecursiveCode(ctx, c.typ, &CompiledCode{})
recursive.Type = c.typ
ctx.incIndex()
*ctx.recursiveCodes = append(*ctx.recursiveCodes, recursive)
return Opcodes{recursive}
}
codes := Opcodes{}
var prevField *Opcode
ctx.incIndent()
for idx, field := range c.fields {
isFirstField := idx == 0
isEndField := idx == len(c.fields)-1
fieldCodes := field.ToOpcode(ctx, isFirstField, isEndField)
for _, code := range fieldCodes {
if c.isIndirect {
code.Flags |= IndirectFlags
}
}
firstField := fieldCodes.First()
if len(codes) > 0 {
codes.Last().Next = firstField
firstField.Idx = codes.First().Idx
}
if prevField != nil {
prevField.NextField = firstField
}
if isEndField {
endField := fieldCodes.Last()
if len(codes) > 0 {
codes.First().End = endField
} else if field.isAnonymous {
firstField.End = endField
lastField := c.lastAnonymousFieldCode(firstField)
lastField.NextField = endField
} else {
firstField.End = endField
}
codes = codes.Add(fieldCodes...)
break
}
prevField = c.lastFieldCode(field, firstField)
codes = codes.Add(fieldCodes...)
}
if len(codes) == 0 {
head := &Opcode{
Op: OpStructHead,
Idx: opcodeOffset(ctx.ptrIndex),
Type: c.typ,
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
}
ctx.incOpcodeIndex()
end := &Opcode{
Op: OpStructEnd,
Idx: opcodeOffset(ctx.ptrIndex),
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
}
head.NextField = end
head.Next = end
head.End = end
codes = codes.Add(head, end)
ctx.incIndex()
}
ctx.decIndent()
ctx.structTypeToCodes[uintptr(unsafe.Pointer(c.typ))] = codes
return codes
}
func (c *StructCode) ToAnonymousOpcode(ctx *compileContext) Opcodes {
// header => code => structField => code => end
// ^ |
// |__________|
if c.isRecursive {
recursive := newRecursiveCode(ctx, c.typ, &CompiledCode{})
recursive.Type = c.typ
ctx.incIndex()
*ctx.recursiveCodes = append(*ctx.recursiveCodes, recursive)
return Opcodes{recursive}
}
codes := Opcodes{}
var prevField *Opcode
for idx, field := range c.fields {
isFirstField := idx == 0
isEndField := idx == len(c.fields)-1
fieldCodes := field.ToAnonymousOpcode(ctx, isFirstField, isEndField)
for _, code := range fieldCodes {
if c.isIndirect {
code.Flags |= IndirectFlags
}
}
firstField := fieldCodes.First()
if len(codes) > 0 {
codes.Last().Next = firstField
firstField.Idx = codes.First().Idx
}
if prevField != nil {
prevField.NextField = firstField
}
if isEndField {
lastField := fieldCodes.Last()
if len(codes) > 0 {
codes.First().End = lastField
} else {
firstField.End = lastField
}
}
prevField = firstField
codes = codes.Add(fieldCodes...)
}
return codes
}
func (c *StructCode) removeFieldsByTags(tags runtime.StructTags) {
fields := make([]*StructFieldCode, 0, len(c.fields))
for _, field := range c.fields {
if field.isAnonymous {
structCode := field.getAnonymousStruct()
if structCode != nil && !structCode.isRecursive {
structCode.removeFieldsByTags(tags)
if len(structCode.fields) > 0 {
fields = append(fields, field)
}
continue
}
}
if tags.ExistsKey(field.key) {
continue
}
fields = append(fields, field)
}
c.fields = fields
}
func (c *StructCode) enableIndirect() {
if c.isIndirect {
return
}
c.isIndirect = true
if len(c.fields) == 0 {
return
}
structCode := c.fields[0].getStruct()
if structCode == nil {
return
}
structCode.enableIndirect()
}
type StructFieldCode struct {
typ *runtime.Type
key string
tag *runtime.StructTag
value Code
offset uintptr
isAnonymous bool
isTaggedKey bool
isNilableType bool
isNilCheck bool
isAddrForMarshaler bool
isNextOpPtrType bool
}
func (c *StructFieldCode) getStruct() *StructCode {
value := c.value
ptr, ok := value.(*PtrCode)
if ok {
value = ptr.value
}
structCode, ok := value.(*StructCode)
if ok {
return structCode
}
return nil
}
func (c *StructFieldCode) getAnonymousStruct() *StructCode {
if !c.isAnonymous {
return nil
}
return c.getStruct()
}
func optimizeStructHeader(code *Opcode, tag *runtime.StructTag) OpType {
headType := code.ToHeaderType(tag.IsString)
if tag.IsOmitEmpty {
headType = headType.HeadToOmitEmptyHead()
}
return headType
}
func optimizeStructField(code *Opcode, tag *runtime.StructTag) OpType {
fieldType := code.ToFieldType(tag.IsString)
if tag.IsOmitEmpty {
fieldType = fieldType.FieldToOmitEmptyField()
}
return fieldType
}
func (c *StructFieldCode) headerOpcodes(ctx *compileContext, field *Opcode, valueCodes Opcodes) Opcodes {
value := valueCodes.First()
op := optimizeStructHeader(value, c.tag)
field.Op = op
field.NumBitSize = value.NumBitSize
field.PtrNum = value.PtrNum
fieldCodes := Opcodes{field}
if op.IsMultipleOpHead() {
field.Next = value
fieldCodes = fieldCodes.Add(valueCodes...)
} else {
ctx.decIndex()
}
return fieldCodes
}
func (c *StructFieldCode) fieldOpcodes(ctx *compileContext, field *Opcode, valueCodes Opcodes) Opcodes {
value := valueCodes.First()
op := optimizeStructField(value, c.tag)
field.Op = op
field.NumBitSize = value.NumBitSize
field.PtrNum = value.PtrNum
fieldCodes := Opcodes{field}
if op.IsMultipleOpField() {
field.Next = value
fieldCodes = fieldCodes.Add(valueCodes...)
} else {
ctx.decIndex()
}
return fieldCodes
}
func (c *StructFieldCode) addStructEndCode(ctx *compileContext, codes Opcodes) Opcodes {
end := &Opcode{
Op: OpStructEnd,
Idx: opcodeOffset(ctx.ptrIndex),
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
}
codes.Last().Next = end
codes.First().NextField = end
codes = codes.Add(end)
ctx.incOpcodeIndex()
return codes
}
func (c *StructFieldCode) structKey(ctx *compileContext) string {
if ctx.escapeKey {
rctx := &RuntimeContext{Option: &Option{Flag: HTMLEscapeOption}}
return fmt.Sprintf(`%s:`, string(AppendString(rctx, []byte{}, c.key)))
}
return fmt.Sprintf(`"%s":`, c.key)
}
func (c *StructFieldCode) flags() OpFlags {
var flags OpFlags
if c.isTaggedKey {
flags |= IsTaggedKeyFlags
}
if c.isNilableType {
flags |= IsNilableTypeFlags
}
if c.isNilCheck {
flags |= NilCheckFlags
}
if c.isAddrForMarshaler {
flags |= AddrForMarshalerFlags
}
if c.isNextOpPtrType {
flags |= IsNextOpPtrTypeFlags
}
if c.isAnonymous {
flags |= AnonymousKeyFlags
}
return flags
}
func (c *StructFieldCode) toValueOpcodes(ctx *compileContext) Opcodes {
if c.isAnonymous {
anonymCode, ok := c.value.(AnonymousCode)
if ok {
return anonymCode.ToAnonymousOpcode(ctx)
}
}
return c.value.ToOpcode(ctx)
}
func (c *StructFieldCode) ToOpcode(ctx *compileContext, isFirstField, isEndField bool) Opcodes {
field := &Opcode{
Idx: opcodeOffset(ctx.ptrIndex),
Flags: c.flags(),
Key: c.structKey(ctx),
Offset: uint32(c.offset),
Type: c.typ,
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
DisplayKey: c.key,
}
ctx.incIndex()
valueCodes := c.toValueOpcodes(ctx)
if isFirstField {
codes := c.headerOpcodes(ctx, field, valueCodes)
if isEndField {
codes = c.addStructEndCode(ctx, codes)
}
return codes
}
codes := c.fieldOpcodes(ctx, field, valueCodes)
if isEndField {
if isEnableStructEndOptimization(c.value) {
field.Op = field.Op.FieldToEnd()
} else {
codes = c.addStructEndCode(ctx, codes)
}
}
return codes
}
func (c *StructFieldCode) ToAnonymousOpcode(ctx *compileContext, isFirstField, isEndField bool) Opcodes {
field := &Opcode{
Idx: opcodeOffset(ctx.ptrIndex),
Flags: c.flags() | AnonymousHeadFlags,
Key: c.structKey(ctx),
Offset: uint32(c.offset),
Type: c.typ,
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
DisplayKey: c.key,
}
ctx.incIndex()
valueCodes := c.toValueOpcodes(ctx)
if isFirstField {
return c.headerOpcodes(ctx, field, valueCodes)
}
return c.fieldOpcodes(ctx, field, valueCodes)
}
func isEnableStructEndOptimization(value Code) bool {
switch value.Kind() {
case CodeKindInt,
CodeKindUint,
CodeKindFloat,
CodeKindString,
CodeKindBool,
CodeKindBytes:
return true
case CodeKindPtr:
return isEnableStructEndOptimization(value.(*PtrCode).value)
default:
return false
}
}
type InterfaceCode struct {
typ *runtime.Type
isPtr bool
}
func (c *InterfaceCode) Kind() CodeKind {
return CodeKindInterface
}
func (c *InterfaceCode) ToOpcode(ctx *compileContext) Opcodes {
var code *Opcode
switch {
case c.isPtr:
code = newOpCode(ctx, c.typ, OpInterfacePtr)
default:
code = newOpCode(ctx, c.typ, OpInterface)
}
if c.typ.NumMethod() > 0 {
code.Flags |= NonEmptyInterfaceFlags
}
ctx.incIndex()
return Opcodes{code}
}
type MarshalJSONCode struct {
typ *runtime.Type
isAddrForMarshaler bool
isNilableType bool
isMarshalerContext bool
}
func (c *MarshalJSONCode) Kind() CodeKind {
return CodeKindMarshalJSON
}
func (c *MarshalJSONCode) ToOpcode(ctx *compileContext) Opcodes {
code := newOpCode(ctx, c.typ, OpMarshalJSON)
if c.isAddrForMarshaler {
code.Flags |= AddrForMarshalerFlags
}
if c.isMarshalerContext {
code.Flags |= MarshalerContextFlags
}
if c.isNilableType {
code.Flags |= IsNilableTypeFlags
} else {
code.Flags &= ^IsNilableTypeFlags
}
ctx.incIndex()
return Opcodes{code}
}
type MarshalTextCode struct {
typ *runtime.Type
isAddrForMarshaler bool
isNilableType bool
}
func (c *MarshalTextCode) Kind() CodeKind {
return CodeKindMarshalText
}
func (c *MarshalTextCode) ToOpcode(ctx *compileContext) Opcodes {
code := newOpCode(ctx, c.typ, OpMarshalText)
if c.isAddrForMarshaler {
code.Flags |= AddrForMarshalerFlags
}
if c.isNilableType {
code.Flags |= IsNilableTypeFlags
} else {
code.Flags &= ^IsNilableTypeFlags
}
ctx.incIndex()
return Opcodes{code}
}
type PtrCode struct {
typ *runtime.Type
value Code
ptrNum uint8
}
func (c *PtrCode) Kind() CodeKind {
return CodeKindPtr
}
func (c *PtrCode) ToOpcode(ctx *compileContext) Opcodes {
codes := c.value.ToOpcode(ctx)
codes.First().Op = convertPtrOp(codes.First())
codes.First().PtrNum = c.ptrNum
return codes
}
func (c *PtrCode) ToAnonymousOpcode(ctx *compileContext) Opcodes {
var codes Opcodes
anonymCode, ok := c.value.(AnonymousCode)
if ok {
codes = anonymCode.ToAnonymousOpcode(ctx)
} else {
codes = c.value.ToOpcode(ctx)
}
codes.First().Op = convertPtrOp(codes.First())
codes.First().PtrNum = c.ptrNum
return codes
}
func convertPtrOp(code *Opcode) OpType {
ptrHeadOp := code.Op.HeadToPtrHead()
if code.Op != ptrHeadOp {
if code.PtrNum > 0 {
// ptr field and ptr head
code.PtrNum--
}
return ptrHeadOp
}
switch code.Op {
case OpInt:
return OpIntPtr
case OpUint:
return OpUintPtr
case OpFloat32:
return OpFloat32Ptr
case OpFloat64:
return OpFloat64Ptr
case OpString:
return OpStringPtr
case OpBool:
return OpBoolPtr
case OpBytes:
return OpBytesPtr
case OpNumber:
return OpNumberPtr
case OpArray:
return OpArrayPtr
case OpSlice:
return OpSlicePtr
case OpMap:
return OpMapPtr
case OpMarshalJSON:
return OpMarshalJSONPtr
case OpMarshalText:
return OpMarshalTextPtr
case OpInterface:
return OpInterfacePtr
case OpRecursive:
return OpRecursivePtr
}
return code.Op
}

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,8 @@
//go:build !race
// +build !race // +build !race
package encoder package encoder
import (
"unsafe"
"github.com/goccy/go-json/internal/runtime"
)
func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) { func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) {
if typeptr > typeAddr.MaxTypeAddr { if typeptr > typeAddr.MaxTypeAddr {
return compileToGetCodeSetSlowPath(typeptr) return compileToGetCodeSetSlowPath(typeptr)
@ -16,41 +11,10 @@ func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) {
if codeSet := cachedOpcodeSets[index]; codeSet != nil { if codeSet := cachedOpcodeSets[index]; codeSet != nil {
return codeSet, nil return codeSet, nil
} }
codeSet, err := newCompiler().compile(typeptr)
// noescape trick for header.typ ( reflect.*rtype )
copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr))
noescapeKeyCode, err := compileHead(&compileContext{
typ: copiedType,
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
})
if err != nil { if err != nil {
return nil, err return nil, err
} }
escapeKeyCode, err := compileHead(&compileContext{
typ: copiedType,
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
escapeKey: true,
})
if err != nil {
return nil, err
}
noescapeKeyCode = copyOpcode(noescapeKeyCode)
escapeKeyCode = copyOpcode(escapeKeyCode)
setTotalLengthToInterfaceOp(noescapeKeyCode)
setTotalLengthToInterfaceOp(escapeKeyCode)
interfaceNoescapeKeyCode := copyToInterfaceOpcode(noescapeKeyCode)
interfaceEscapeKeyCode := copyToInterfaceOpcode(escapeKeyCode)
codeLength := noescapeKeyCode.TotalLength()
codeSet := &OpcodeSet{
Type: copiedType,
NoescapeKeyCode: noescapeKeyCode,
EscapeKeyCode: escapeKeyCode,
InterfaceNoescapeKeyCode: interfaceNoescapeKeyCode,
InterfaceEscapeKeyCode: interfaceEscapeKeyCode,
CodeLength: codeLength,
EndCode: ToEndCode(interfaceNoescapeKeyCode),
}
cachedOpcodeSets[index] = codeSet cachedOpcodeSets[index] = codeSet
return codeSet, nil return codeSet, nil
} }

View File

@ -1,12 +1,10 @@
//go:build race
// +build race // +build race
package encoder package encoder
import ( import (
"sync" "sync"
"unsafe"
"github.com/goccy/go-json/internal/runtime"
) )
var setsMu sync.RWMutex var setsMu sync.RWMutex
@ -23,41 +21,10 @@ func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) {
} }
setsMu.RUnlock() setsMu.RUnlock()
// noescape trick for header.typ ( reflect.*rtype ) codeSet, err := newCompiler().compile(typeptr)
copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr))
noescapeKeyCode, err := compileHead(&compileContext{
typ: copiedType,
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
})
if err != nil { if err != nil {
return nil, err return nil, err
} }
escapeKeyCode, err := compileHead(&compileContext{
typ: copiedType,
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
escapeKey: true,
})
if err != nil {
return nil, err
}
noescapeKeyCode = copyOpcode(noescapeKeyCode)
escapeKeyCode = copyOpcode(escapeKeyCode)
setTotalLengthToInterfaceOp(noescapeKeyCode)
setTotalLengthToInterfaceOp(escapeKeyCode)
interfaceNoescapeKeyCode := copyToInterfaceOpcode(noescapeKeyCode)
interfaceEscapeKeyCode := copyToInterfaceOpcode(escapeKeyCode)
codeLength := noescapeKeyCode.TotalLength()
codeSet := &OpcodeSet{
Type: copiedType,
NoescapeKeyCode: noescapeKeyCode,
EscapeKeyCode: escapeKeyCode,
InterfaceNoescapeKeyCode: interfaceNoescapeKeyCode,
InterfaceEscapeKeyCode: interfaceEscapeKeyCode,
CodeLength: codeLength,
EndCode: ToEndCode(interfaceNoescapeKeyCode),
}
setsMu.Lock() setsMu.Lock()
cachedOpcodeSets[index] = codeSet cachedOpcodeSets[index] = codeSet
setsMu.Unlock() setsMu.Unlock()

View File

@ -9,44 +9,20 @@ import (
) )
type compileContext struct { type compileContext struct {
typ *runtime.Type
opcodeIndex uint32 opcodeIndex uint32
ptrIndex int ptrIndex int
indent uint32 indent uint32
escapeKey bool escapeKey bool
structTypeToCompiledCode map[uintptr]*CompiledCode structTypeToCodes map[uintptr]Opcodes
recursiveCodes *Opcodes
parent *compileContext
} }
func (c *compileContext) context() *compileContext { func (c *compileContext) incIndent() {
return &compileContext{ c.indent++
typ: c.typ,
opcodeIndex: c.opcodeIndex,
ptrIndex: c.ptrIndex,
indent: c.indent,
escapeKey: c.escapeKey,
structTypeToCompiledCode: c.structTypeToCompiledCode,
parent: c,
}
} }
func (c *compileContext) withType(typ *runtime.Type) *compileContext { func (c *compileContext) decIndent() {
ctx := c.context() c.indent--
ctx.typ = typ
return ctx
}
func (c *compileContext) incIndent() *compileContext {
ctx := c.context()
ctx.indent++
return ctx
}
func (c *compileContext) decIndent() *compileContext {
ctx := c.context()
ctx.indent--
return ctx
} }
func (c *compileContext) incIndex() { func (c *compileContext) incIndex() {
@ -61,30 +37,18 @@ func (c *compileContext) decIndex() {
func (c *compileContext) incOpcodeIndex() { func (c *compileContext) incOpcodeIndex() {
c.opcodeIndex++ c.opcodeIndex++
if c.parent != nil {
c.parent.incOpcodeIndex()
}
} }
func (c *compileContext) decOpcodeIndex() { func (c *compileContext) decOpcodeIndex() {
c.opcodeIndex-- c.opcodeIndex--
if c.parent != nil {
c.parent.decOpcodeIndex()
}
} }
func (c *compileContext) incPtrIndex() { func (c *compileContext) incPtrIndex() {
c.ptrIndex++ c.ptrIndex++
if c.parent != nil {
c.parent.incPtrIndex()
}
} }
func (c *compileContext) decPtrIndex() { func (c *compileContext) decPtrIndex() {
c.ptrIndex-- c.ptrIndex--
if c.parent != nil {
c.parent.decPtrIndex()
}
} }
const ( const (

View File

@ -53,7 +53,18 @@ func numMask(numBitSize uint8) uint64 {
return 1<<numBitSize - 1 return 1<<numBitSize - 1
} }
func AppendInt(_ *RuntimeContext, out []byte, u64 uint64, code *Opcode) []byte { func AppendInt(_ *RuntimeContext, out []byte, p uintptr, code *Opcode) []byte {
var u64 uint64
switch code.NumBitSize {
case 8:
u64 = (uint64)(**(**uint8)(unsafe.Pointer(&p)))
case 16:
u64 = (uint64)(**(**uint16)(unsafe.Pointer(&p)))
case 32:
u64 = (uint64)(**(**uint32)(unsafe.Pointer(&p)))
case 64:
u64 = **(**uint64)(unsafe.Pointer(&p))
}
mask := numMask(code.NumBitSize) mask := numMask(code.NumBitSize)
n := u64 & mask n := u64 & mask
negative := (u64>>(code.NumBitSize-1))&1 == 1 negative := (u64>>(code.NumBitSize-1))&1 == 1
@ -96,7 +107,18 @@ func AppendInt(_ *RuntimeContext, out []byte, u64 uint64, code *Opcode) []byte {
return append(out, b[i:]...) return append(out, b[i:]...)
} }
func AppendUint(_ *RuntimeContext, out []byte, u64 uint64, code *Opcode) []byte { func AppendUint(_ *RuntimeContext, out []byte, p uintptr, code *Opcode) []byte {
var u64 uint64
switch code.NumBitSize {
case 8:
u64 = (uint64)(**(**uint8)(unsafe.Pointer(&p)))
case 16:
u64 = (uint64)(**(**uint16)(unsafe.Pointer(&p)))
case 32:
u64 = (uint64)(**(**uint32)(unsafe.Pointer(&p)))
case 64:
u64 = **(**uint64)(unsafe.Pointer(&p))
}
mask := numMask(code.NumBitSize) mask := numMask(code.NumBitSize)
n := u64 & mask n := u64 & mask
if n < 10 { if n < 10 {

View File

@ -38,7 +38,6 @@ type Opcode struct {
Flags OpFlags Flags OpFlags
Type *runtime.Type // go type Type *runtime.Type // go type
PrevField *Opcode // prev struct field
Jmp *CompiledCode // for recursive call Jmp *CompiledCode // for recursive call
ElemIdx uint32 // offset to access array/slice/map elem ElemIdx uint32 // offset to access array/slice/map elem
Length uint32 // offset to access slice/map length or array length Length uint32 // offset to access slice/map length or array length
@ -50,6 +49,42 @@ type Opcode struct {
DisplayKey string // key text to display DisplayKey string // key text to display
} }
func (c *Opcode) Validate() error {
var prevIdx uint32
for code := c; !code.IsEnd(); {
if prevIdx != 0 {
if code.DisplayIdx != prevIdx+1 {
return fmt.Errorf(
"invalid index. previous display index is %d but next is %d. dump = %s",
prevIdx, code.DisplayIdx, c.Dump(),
)
}
}
prevIdx = code.DisplayIdx
code = code.IterNext()
}
return nil
}
func (c *Opcode) IterNext() *Opcode {
if c == nil {
return nil
}
switch c.Op.CodeType() {
case CodeArrayElem, CodeSliceElem, CodeMapKey:
return c.End
default:
return c.Next
}
}
func (c *Opcode) IsEnd() bool {
if c == nil {
return true
}
return c.Op == OpEnd || c.Op == OpInterfaceEnd || c.Op == OpRecursiveEnd
}
func (c *Opcode) MaxIdx() uint32 { func (c *Opcode) MaxIdx() uint32 {
max := uint32(0) max := uint32(0)
for _, value := range []uint32{ for _, value := range []uint32{
@ -273,82 +308,27 @@ func (c *Opcode) ToFieldType(isString bool) OpType {
return OpStructField return OpStructField
} }
func newOpCode(ctx *compileContext, op OpType) *Opcode { func newOpCode(ctx *compileContext, typ *runtime.Type, op OpType) *Opcode {
return newOpCodeWithNext(ctx, op, newEndOp(ctx)) return newOpCodeWithNext(ctx, typ, op, newEndOp(ctx, typ))
} }
func opcodeOffset(idx int) uint32 { func opcodeOffset(idx int) uint32 {
return uint32(idx) * uintptrSize return uint32(idx) * uintptrSize
} }
func getCodeAddrByIdx(head *Opcode, idx uint32) *Opcode {
addr := uintptr(unsafe.Pointer(head)) + uintptr(idx)*unsafe.Sizeof(Opcode{})
return *(**Opcode)(unsafe.Pointer(&addr))
}
func copyOpcode(code *Opcode) *Opcode { func copyOpcode(code *Opcode) *Opcode {
codeMap := map[uintptr]*Opcode{} codeNum := ToEndCode(code).DisplayIdx + 1
return code.copy(codeMap) codeSlice := make([]Opcode, codeNum)
} head := (*Opcode)((*runtime.SliceHeader)(unsafe.Pointer(&codeSlice)).Data)
ptr := head
func setTotalLengthToInterfaceOp(code *Opcode) {
c := code c := code
for c.Op != OpEnd && c.Op != OpInterfaceEnd { for {
if c.Op == OpInterface { *ptr = Opcode{
c.Length = uint32(code.TotalLength())
}
switch c.Op.CodeType() {
case CodeArrayElem, CodeSliceElem, CodeMapKey:
c = c.End
default:
c = c.Next
}
}
}
func ToEndCode(code *Opcode) *Opcode {
c := code
for c.Op != OpEnd && c.Op != OpInterfaceEnd {
switch c.Op.CodeType() {
case CodeArrayElem, CodeSliceElem, CodeMapKey:
c = c.End
default:
c = c.Next
}
}
return c
}
func copyToInterfaceOpcode(code *Opcode) *Opcode {
copied := copyOpcode(code)
c := copied
c = ToEndCode(c)
c.Idx += uintptrSize
c.ElemIdx = c.Idx + uintptrSize
c.Length = c.Idx + 2*uintptrSize
c.Op = OpInterfaceEnd
return copied
}
func newOpCodeWithNext(ctx *compileContext, op OpType, next *Opcode) *Opcode {
return &Opcode{
Op: op,
Idx: opcodeOffset(ctx.ptrIndex),
Next: next,
Type: ctx.typ,
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
}
}
func newEndOp(ctx *compileContext) *Opcode {
return newOpCodeWithNext(ctx, OpEnd, nil)
}
func (c *Opcode) copy(codeMap map[uintptr]*Opcode) *Opcode {
if c == nil {
return nil
}
addr := uintptr(unsafe.Pointer(c))
if code, exists := codeMap[addr]; exists {
return code
}
copied := &Opcode{
Op: c.Op, Op: c.Op,
Key: c.Key, Key: c.Key,
PtrNum: c.PtrNum, PtrNum: c.PtrNum,
@ -365,37 +345,73 @@ func (c *Opcode) copy(codeMap map[uintptr]*Opcode) *Opcode {
MapPos: c.MapPos, MapPos: c.MapPos,
Size: c.Size, Size: c.Size,
Indent: c.Indent, Indent: c.Indent,
Jmp: c.Jmp,
} }
codeMap[addr] = copied if c.End != nil {
copied.End = c.End.copy(codeMap) ptr.End = getCodeAddrByIdx(head, c.End.DisplayIdx)
copied.PrevField = c.PrevField.copy(codeMap) }
copied.NextField = c.NextField.copy(codeMap) if c.NextField != nil {
copied.Next = c.Next.copy(codeMap) ptr.NextField = getCodeAddrByIdx(head, c.NextField.DisplayIdx)
copied.Jmp = c.Jmp }
if c.Next != nil {
ptr.Next = getCodeAddrByIdx(head, c.Next.DisplayIdx)
}
if c.IsEnd() {
break
}
ptr = getCodeAddrByIdx(head, c.DisplayIdx+1)
c = c.IterNext()
}
return head
}
func setTotalLengthToInterfaceOp(code *Opcode) {
for c := code; !c.IsEnd(); {
if c.Op == OpInterface {
c.Length = uint32(code.TotalLength())
}
c = c.IterNext()
}
}
func ToEndCode(code *Opcode) *Opcode {
c := code
for !c.IsEnd() {
c = c.IterNext()
}
return c
}
func copyToInterfaceOpcode(code *Opcode) *Opcode {
copied := copyOpcode(code)
c := copied
c = ToEndCode(c)
c.Idx += uintptrSize
c.ElemIdx = c.Idx + uintptrSize
c.Length = c.Idx + 2*uintptrSize
c.Op = OpInterfaceEnd
return copied return copied
} }
func (c *Opcode) BeforeLastCode() *Opcode { func newOpCodeWithNext(ctx *compileContext, typ *runtime.Type, op OpType, next *Opcode) *Opcode {
code := c return &Opcode{
for { Op: op,
var nextCode *Opcode Idx: opcodeOffset(ctx.ptrIndex),
switch code.Op.CodeType() { Next: next,
case CodeArrayElem, CodeSliceElem, CodeMapKey: Type: typ,
nextCode = code.End DisplayIdx: ctx.opcodeIndex,
default: Indent: ctx.indent,
nextCode = code.Next
}
if nextCode.Op == OpEnd {
return code
}
code = nextCode
} }
} }
func newEndOp(ctx *compileContext, typ *runtime.Type) *Opcode {
return newOpCodeWithNext(ctx, typ, OpEnd, nil)
}
func (c *Opcode) TotalLength() int { func (c *Opcode) TotalLength() int {
var idx int var idx int
code := c code := c
for code.Op != OpEnd && code.Op != OpInterfaceEnd { for !code.IsEnd() {
maxIdx := int(code.MaxIdx() / uintptrSize) maxIdx := int(code.MaxIdx() / uintptrSize)
if idx < maxIdx { if idx < maxIdx {
idx = maxIdx idx = maxIdx
@ -403,12 +419,7 @@ func (c *Opcode) TotalLength() int {
if code.Op == OpRecursiveEnd { if code.Op == OpRecursiveEnd {
break break
} }
switch code.Op.CodeType() { code = code.IterNext()
case CodeArrayElem, CodeSliceElem, CodeMapKey:
code = code.End
default:
code = code.Next
}
} }
maxIdx := int(code.MaxIdx() / uintptrSize) maxIdx := int(code.MaxIdx() / uintptrSize)
if idx < maxIdx { if idx < maxIdx {
@ -417,42 +428,6 @@ func (c *Opcode) TotalLength() int {
return idx + 1 return idx + 1
} }
func (c *Opcode) decOpcodeIndex() {
for code := c; code.Op != OpEnd; {
code.DisplayIdx--
if code.Idx > 0 {
code.Idx -= uintptrSize
}
if code.ElemIdx > 0 {
code.ElemIdx -= uintptrSize
}
if code.MapIter > 0 {
code.MapIter -= uintptrSize
}
if code.Length > 0 && code.Op.CodeType() != CodeArrayHead && code.Op.CodeType() != CodeArrayElem {
code.Length -= uintptrSize
}
switch code.Op.CodeType() {
case CodeArrayElem, CodeSliceElem, CodeMapKey:
code = code.End
default:
code = code.Next
}
}
}
func (c *Opcode) decIndent() {
for code := c; code.Op != OpEnd; {
code.Indent--
switch code.Op.CodeType() {
case CodeArrayElem, CodeSliceElem, CodeMapKey:
code = code.End
default:
code = code.Next
}
}
}
func (c *Opcode) dumpHead(code *Opcode) string { func (c *Opcode) dumpHead(code *Opcode) string {
var length uint32 var length uint32
if code.Op.CodeType() == CodeArrayHead { if code.Op.CodeType() == CodeArrayHead {
@ -461,7 +436,7 @@ func (c *Opcode) dumpHead(code *Opcode) string {
length = code.Length / uintptrSize length = code.Length / uintptrSize
} }
return fmt.Sprintf( return fmt.Sprintf(
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d])`, `[%03d]%s%s ([idx:%d][elemIdx:%d][length:%d])`,
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", int(code.Indent)), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
@ -473,7 +448,7 @@ func (c *Opcode) dumpHead(code *Opcode) string {
func (c *Opcode) dumpMapHead(code *Opcode) string { func (c *Opcode) dumpMapHead(code *Opcode) string {
return fmt.Sprintf( return fmt.Sprintf(
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`, `[%03d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`,
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", int(code.Indent)), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
@ -486,7 +461,7 @@ func (c *Opcode) dumpMapHead(code *Opcode) string {
func (c *Opcode) dumpMapEnd(code *Opcode) string { func (c *Opcode) dumpMapEnd(code *Opcode) string {
return fmt.Sprintf( return fmt.Sprintf(
`[%d]%s%s ([idx:%d][mapPos:%d][length:%d])`, `[%03d]%s%s ([idx:%d][mapPos:%d][length:%d])`,
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", int(code.Indent)), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
@ -504,7 +479,7 @@ func (c *Opcode) dumpElem(code *Opcode) string {
length = code.Length / uintptrSize length = code.Length / uintptrSize
} }
return fmt.Sprintf( return fmt.Sprintf(
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][size:%d])`, `[%03d]%s%s ([idx:%d][elemIdx:%d][length:%d][size:%d])`,
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", int(code.Indent)), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
@ -517,7 +492,7 @@ func (c *Opcode) dumpElem(code *Opcode) string {
func (c *Opcode) dumpField(code *Opcode) string { func (c *Opcode) dumpField(code *Opcode) string {
return fmt.Sprintf( return fmt.Sprintf(
`[%d]%s%s ([idx:%d][key:%s][offset:%d])`, `[%03d]%s%s ([idx:%d][key:%s][offset:%d])`,
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", int(code.Indent)), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
@ -529,7 +504,7 @@ func (c *Opcode) dumpField(code *Opcode) string {
func (c *Opcode) dumpKey(code *Opcode) string { func (c *Opcode) dumpKey(code *Opcode) string {
return fmt.Sprintf( return fmt.Sprintf(
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`, `[%03d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`,
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", int(code.Indent)), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
@ -542,7 +517,7 @@ func (c *Opcode) dumpKey(code *Opcode) string {
func (c *Opcode) dumpValue(code *Opcode) string { func (c *Opcode) dumpValue(code *Opcode) string {
return fmt.Sprintf( return fmt.Sprintf(
`[%d]%s%s ([idx:%d][mapIter:%d])`, `[%03d]%s%s ([idx:%d][mapIter:%d])`,
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", int(code.Indent)), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
@ -553,7 +528,7 @@ func (c *Opcode) dumpValue(code *Opcode) string {
func (c *Opcode) Dump() string { func (c *Opcode) Dump() string {
codes := []string{} codes := []string{}
for code := c; code.Op != OpEnd && code.Op != OpInterfaceEnd; { for code := c; !code.IsEnd(); {
switch code.Op.CodeType() { switch code.Op.CodeType() {
case CodeSliceHead: case CodeSliceHead:
codes = append(codes, c.dumpHead(code)) codes = append(codes, c.dumpHead(code))
@ -581,7 +556,7 @@ func (c *Opcode) Dump() string {
code = code.Next code = code.Next
default: default:
codes = append(codes, fmt.Sprintf( codes = append(codes, fmt.Sprintf(
"[%d]%s%s ([idx:%d])", "[%03d]%s%s ([idx:%d])",
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", int(code.Indent)), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
@ -593,44 +568,7 @@ func (c *Opcode) Dump() string {
return strings.Join(codes, "\n") return strings.Join(codes, "\n")
} }
func prevField(code *Opcode, removedFields map[*Opcode]struct{}) *Opcode { func newSliceHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode {
if _, exists := removedFields[code]; exists {
return prevField(code.PrevField, removedFields)
}
return code
}
func nextField(code *Opcode, removedFields map[*Opcode]struct{}) *Opcode {
if _, exists := removedFields[code]; exists {
return nextField(code.NextField, removedFields)
}
return code
}
func linkPrevToNextField(cur *Opcode, removedFields map[*Opcode]struct{}) {
prev := prevField(cur.PrevField, removedFields)
prev.NextField = nextField(cur.NextField, removedFields)
code := prev
fcode := cur
for {
var nextCode *Opcode
switch code.Op.CodeType() {
case CodeArrayElem, CodeSliceElem, CodeMapKey:
nextCode = code.End
default:
nextCode = code.Next
}
if nextCode == fcode {
code.Next = fcode.Next
break
} else if nextCode.Op == OpEnd {
break
}
code = nextCode
}
}
func newSliceHeaderCode(ctx *compileContext) *Opcode {
idx := opcodeOffset(ctx.ptrIndex) idx := opcodeOffset(ctx.ptrIndex)
ctx.incPtrIndex() ctx.incPtrIndex()
elemIdx := opcodeOffset(ctx.ptrIndex) elemIdx := opcodeOffset(ctx.ptrIndex)
@ -638,6 +576,7 @@ func newSliceHeaderCode(ctx *compileContext) *Opcode {
length := opcodeOffset(ctx.ptrIndex) length := opcodeOffset(ctx.ptrIndex)
return &Opcode{ return &Opcode{
Op: OpSlice, Op: OpSlice,
Type: typ,
Idx: idx, Idx: idx,
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
ElemIdx: elemIdx, ElemIdx: elemIdx,
@ -646,9 +585,10 @@ func newSliceHeaderCode(ctx *compileContext) *Opcode {
} }
} }
func newSliceElemCode(ctx *compileContext, head *Opcode, size uintptr) *Opcode { func newSliceElemCode(ctx *compileContext, typ *runtime.Type, head *Opcode, size uintptr) *Opcode {
return &Opcode{ return &Opcode{
Op: OpSliceElem, Op: OpSliceElem,
Type: typ,
Idx: head.Idx, Idx: head.Idx,
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
ElemIdx: head.ElemIdx, ElemIdx: head.ElemIdx,
@ -658,12 +598,13 @@ func newSliceElemCode(ctx *compileContext, head *Opcode, size uintptr) *Opcode {
} }
} }
func newArrayHeaderCode(ctx *compileContext, alen int) *Opcode { func newArrayHeaderCode(ctx *compileContext, typ *runtime.Type, alen int) *Opcode {
idx := opcodeOffset(ctx.ptrIndex) idx := opcodeOffset(ctx.ptrIndex)
ctx.incPtrIndex() ctx.incPtrIndex()
elemIdx := opcodeOffset(ctx.ptrIndex) elemIdx := opcodeOffset(ctx.ptrIndex)
return &Opcode{ return &Opcode{
Op: OpArray, Op: OpArray,
Type: typ,
Idx: idx, Idx: idx,
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
ElemIdx: elemIdx, ElemIdx: elemIdx,
@ -672,9 +613,10 @@ func newArrayHeaderCode(ctx *compileContext, alen int) *Opcode {
} }
} }
func newArrayElemCode(ctx *compileContext, head *Opcode, length int, size uintptr) *Opcode { func newArrayElemCode(ctx *compileContext, typ *runtime.Type, head *Opcode, length int, size uintptr) *Opcode {
return &Opcode{ return &Opcode{
Op: OpArrayElem, Op: OpArrayElem,
Type: typ,
Idx: head.Idx, Idx: head.Idx,
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
ElemIdx: head.ElemIdx, ElemIdx: head.ElemIdx,
@ -684,7 +626,7 @@ func newArrayElemCode(ctx *compileContext, head *Opcode, length int, size uintpt
} }
} }
func newMapHeaderCode(ctx *compileContext) *Opcode { func newMapHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode {
idx := opcodeOffset(ctx.ptrIndex) idx := opcodeOffset(ctx.ptrIndex)
ctx.incPtrIndex() ctx.incPtrIndex()
elemIdx := opcodeOffset(ctx.ptrIndex) elemIdx := opcodeOffset(ctx.ptrIndex)
@ -694,8 +636,8 @@ func newMapHeaderCode(ctx *compileContext) *Opcode {
mapIter := opcodeOffset(ctx.ptrIndex) mapIter := opcodeOffset(ctx.ptrIndex)
return &Opcode{ return &Opcode{
Op: OpMap, Op: OpMap,
Type: typ,
Idx: idx, Idx: idx,
Type: ctx.typ,
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
ElemIdx: elemIdx, ElemIdx: elemIdx,
Length: length, Length: length,
@ -704,9 +646,10 @@ func newMapHeaderCode(ctx *compileContext) *Opcode {
} }
} }
func newMapKeyCode(ctx *compileContext, head *Opcode) *Opcode { func newMapKeyCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode {
return &Opcode{ return &Opcode{
Op: OpMapKey, Op: OpMapKey,
Type: typ,
Idx: opcodeOffset(ctx.ptrIndex), Idx: opcodeOffset(ctx.ptrIndex),
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
ElemIdx: head.ElemIdx, ElemIdx: head.ElemIdx,
@ -716,9 +659,10 @@ func newMapKeyCode(ctx *compileContext, head *Opcode) *Opcode {
} }
} }
func newMapValueCode(ctx *compileContext, head *Opcode) *Opcode { func newMapValueCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode {
return &Opcode{ return &Opcode{
Op: OpMapValue, Op: OpMapValue,
Type: typ,
Idx: opcodeOffset(ctx.ptrIndex), Idx: opcodeOffset(ctx.ptrIndex),
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
ElemIdx: head.ElemIdx, ElemIdx: head.ElemIdx,
@ -728,14 +672,15 @@ func newMapValueCode(ctx *compileContext, head *Opcode) *Opcode {
} }
} }
func newMapEndCode(ctx *compileContext, head *Opcode) *Opcode { func newMapEndCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode {
mapPos := opcodeOffset(ctx.ptrIndex) mapPos := opcodeOffset(ctx.ptrIndex)
ctx.incPtrIndex() ctx.incPtrIndex()
idx := opcodeOffset(ctx.ptrIndex) idx := opcodeOffset(ctx.ptrIndex)
return &Opcode{ return &Opcode{
Op: OpMapEnd, Op: OpMapEnd,
Type: typ,
Idx: idx, Idx: idx,
Next: newEndOp(ctx), Next: newEndOp(ctx, typ),
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
Length: head.Length, Length: head.Length,
MapPos: mapPos, MapPos: mapPos,
@ -743,28 +688,12 @@ func newMapEndCode(ctx *compileContext, head *Opcode) *Opcode {
} }
} }
func newInterfaceCode(ctx *compileContext) *Opcode { func newRecursiveCode(ctx *compileContext, typ *runtime.Type, jmp *CompiledCode) *Opcode {
var flag OpFlags
if ctx.typ.NumMethod() > 0 {
flag |= NonEmptyInterfaceFlags
}
return &Opcode{
Op: OpInterface,
Idx: opcodeOffset(ctx.ptrIndex),
Next: newEndOp(ctx),
Type: ctx.typ,
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
Flags: flag,
}
}
func newRecursiveCode(ctx *compileContext, jmp *CompiledCode) *Opcode {
return &Opcode{ return &Opcode{
Op: OpRecursive, Op: OpRecursive,
Type: typ,
Idx: opcodeOffset(ctx.ptrIndex), Idx: opcodeOffset(ctx.ptrIndex),
Next: newEndOp(ctx), Next: newEndOp(ctx, typ),
Type: ctx.typ,
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent, Indent: ctx.indent,
Jmp: jmp, Jmp: jmp,

View File

@ -22,7 +22,7 @@ const (
CodeStructEnd CodeType = 11 CodeStructEnd CodeType = 11
) )
var opTypeStrings = [401]string{ var opTypeStrings = [400]string{
"End", "End",
"Interface", "Interface",
"Ptr", "Ptr",
@ -37,7 +37,6 @@ var opTypeStrings = [401]string{
"RecursivePtr", "RecursivePtr",
"RecursiveEnd", "RecursiveEnd",
"InterfaceEnd", "InterfaceEnd",
"StructAnonymousEnd",
"Int", "Int",
"Uint", "Uint",
"Float32", "Float32",
@ -443,397 +442,396 @@ const (
OpRecursivePtr OpType = 11 OpRecursivePtr OpType = 11
OpRecursiveEnd OpType = 12 OpRecursiveEnd OpType = 12
OpInterfaceEnd OpType = 13 OpInterfaceEnd OpType = 13
OpStructAnonymousEnd OpType = 14 OpInt OpType = 14
OpInt OpType = 15 OpUint OpType = 15
OpUint OpType = 16 OpFloat32 OpType = 16
OpFloat32 OpType = 17 OpFloat64 OpType = 17
OpFloat64 OpType = 18 OpBool OpType = 18
OpBool OpType = 19 OpString OpType = 19
OpString OpType = 20 OpBytes OpType = 20
OpBytes OpType = 21 OpNumber OpType = 21
OpNumber OpType = 22 OpArray OpType = 22
OpArray OpType = 23 OpMap OpType = 23
OpMap OpType = 24 OpSlice OpType = 24
OpSlice OpType = 25 OpStruct OpType = 25
OpStruct OpType = 26 OpMarshalJSON OpType = 26
OpMarshalJSON OpType = 27 OpMarshalText OpType = 27
OpMarshalText OpType = 28 OpIntString OpType = 28
OpIntString OpType = 29 OpUintString OpType = 29
OpUintString OpType = 30 OpFloat32String OpType = 30
OpFloat32String OpType = 31 OpFloat64String OpType = 31
OpFloat64String OpType = 32 OpBoolString OpType = 32
OpBoolString OpType = 33 OpStringString OpType = 33
OpStringString OpType = 34 OpNumberString OpType = 34
OpNumberString OpType = 35 OpIntPtr OpType = 35
OpIntPtr OpType = 36 OpUintPtr OpType = 36
OpUintPtr OpType = 37 OpFloat32Ptr OpType = 37
OpFloat32Ptr OpType = 38 OpFloat64Ptr OpType = 38
OpFloat64Ptr OpType = 39 OpBoolPtr OpType = 39
OpBoolPtr OpType = 40 OpStringPtr OpType = 40
OpStringPtr OpType = 41 OpBytesPtr OpType = 41
OpBytesPtr OpType = 42 OpNumberPtr OpType = 42
OpNumberPtr OpType = 43 OpArrayPtr OpType = 43
OpArrayPtr OpType = 44 OpMapPtr OpType = 44
OpMapPtr OpType = 45 OpSlicePtr OpType = 45
OpSlicePtr OpType = 46 OpMarshalJSONPtr OpType = 46
OpMarshalJSONPtr OpType = 47 OpMarshalTextPtr OpType = 47
OpMarshalTextPtr OpType = 48 OpInterfacePtr OpType = 48
OpInterfacePtr OpType = 49 OpIntPtrString OpType = 49
OpIntPtrString OpType = 50 OpUintPtrString OpType = 50
OpUintPtrString OpType = 51 OpFloat32PtrString OpType = 51
OpFloat32PtrString OpType = 52 OpFloat64PtrString OpType = 52
OpFloat64PtrString OpType = 53 OpBoolPtrString OpType = 53
OpBoolPtrString OpType = 54 OpStringPtrString OpType = 54
OpStringPtrString OpType = 55 OpNumberPtrString OpType = 55
OpNumberPtrString OpType = 56 OpStructHeadInt OpType = 56
OpStructHeadInt OpType = 57 OpStructHeadOmitEmptyInt OpType = 57
OpStructHeadOmitEmptyInt OpType = 58 OpStructPtrHeadInt OpType = 58
OpStructPtrHeadInt OpType = 59 OpStructPtrHeadOmitEmptyInt OpType = 59
OpStructPtrHeadOmitEmptyInt OpType = 60 OpStructHeadUint OpType = 60
OpStructHeadUint OpType = 61 OpStructHeadOmitEmptyUint OpType = 61
OpStructHeadOmitEmptyUint OpType = 62 OpStructPtrHeadUint OpType = 62
OpStructPtrHeadUint OpType = 63 OpStructPtrHeadOmitEmptyUint OpType = 63
OpStructPtrHeadOmitEmptyUint OpType = 64 OpStructHeadFloat32 OpType = 64
OpStructHeadFloat32 OpType = 65 OpStructHeadOmitEmptyFloat32 OpType = 65
OpStructHeadOmitEmptyFloat32 OpType = 66 OpStructPtrHeadFloat32 OpType = 66
OpStructPtrHeadFloat32 OpType = 67 OpStructPtrHeadOmitEmptyFloat32 OpType = 67
OpStructPtrHeadOmitEmptyFloat32 OpType = 68 OpStructHeadFloat64 OpType = 68
OpStructHeadFloat64 OpType = 69 OpStructHeadOmitEmptyFloat64 OpType = 69
OpStructHeadOmitEmptyFloat64 OpType = 70 OpStructPtrHeadFloat64 OpType = 70
OpStructPtrHeadFloat64 OpType = 71 OpStructPtrHeadOmitEmptyFloat64 OpType = 71
OpStructPtrHeadOmitEmptyFloat64 OpType = 72 OpStructHeadBool OpType = 72
OpStructHeadBool OpType = 73 OpStructHeadOmitEmptyBool OpType = 73
OpStructHeadOmitEmptyBool OpType = 74 OpStructPtrHeadBool OpType = 74
OpStructPtrHeadBool OpType = 75 OpStructPtrHeadOmitEmptyBool OpType = 75
OpStructPtrHeadOmitEmptyBool OpType = 76 OpStructHeadString OpType = 76
OpStructHeadString OpType = 77 OpStructHeadOmitEmptyString OpType = 77
OpStructHeadOmitEmptyString OpType = 78 OpStructPtrHeadString OpType = 78
OpStructPtrHeadString OpType = 79 OpStructPtrHeadOmitEmptyString OpType = 79
OpStructPtrHeadOmitEmptyString OpType = 80 OpStructHeadBytes OpType = 80
OpStructHeadBytes OpType = 81 OpStructHeadOmitEmptyBytes OpType = 81
OpStructHeadOmitEmptyBytes OpType = 82 OpStructPtrHeadBytes OpType = 82
OpStructPtrHeadBytes OpType = 83 OpStructPtrHeadOmitEmptyBytes OpType = 83
OpStructPtrHeadOmitEmptyBytes OpType = 84 OpStructHeadNumber OpType = 84
OpStructHeadNumber OpType = 85 OpStructHeadOmitEmptyNumber OpType = 85
OpStructHeadOmitEmptyNumber OpType = 86 OpStructPtrHeadNumber OpType = 86
OpStructPtrHeadNumber OpType = 87 OpStructPtrHeadOmitEmptyNumber OpType = 87
OpStructPtrHeadOmitEmptyNumber OpType = 88 OpStructHeadArray OpType = 88
OpStructHeadArray OpType = 89 OpStructHeadOmitEmptyArray OpType = 89
OpStructHeadOmitEmptyArray OpType = 90 OpStructPtrHeadArray OpType = 90
OpStructPtrHeadArray OpType = 91 OpStructPtrHeadOmitEmptyArray OpType = 91
OpStructPtrHeadOmitEmptyArray OpType = 92 OpStructHeadMap OpType = 92
OpStructHeadMap OpType = 93 OpStructHeadOmitEmptyMap OpType = 93
OpStructHeadOmitEmptyMap OpType = 94 OpStructPtrHeadMap OpType = 94
OpStructPtrHeadMap OpType = 95 OpStructPtrHeadOmitEmptyMap OpType = 95
OpStructPtrHeadOmitEmptyMap OpType = 96 OpStructHeadSlice OpType = 96
OpStructHeadSlice OpType = 97 OpStructHeadOmitEmptySlice OpType = 97
OpStructHeadOmitEmptySlice OpType = 98 OpStructPtrHeadSlice OpType = 98
OpStructPtrHeadSlice OpType = 99 OpStructPtrHeadOmitEmptySlice OpType = 99
OpStructPtrHeadOmitEmptySlice OpType = 100 OpStructHeadStruct OpType = 100
OpStructHeadStruct OpType = 101 OpStructHeadOmitEmptyStruct OpType = 101
OpStructHeadOmitEmptyStruct OpType = 102 OpStructPtrHeadStruct OpType = 102
OpStructPtrHeadStruct OpType = 103 OpStructPtrHeadOmitEmptyStruct OpType = 103
OpStructPtrHeadOmitEmptyStruct OpType = 104 OpStructHeadMarshalJSON OpType = 104
OpStructHeadMarshalJSON OpType = 105 OpStructHeadOmitEmptyMarshalJSON OpType = 105
OpStructHeadOmitEmptyMarshalJSON OpType = 106 OpStructPtrHeadMarshalJSON OpType = 106
OpStructPtrHeadMarshalJSON OpType = 107 OpStructPtrHeadOmitEmptyMarshalJSON OpType = 107
OpStructPtrHeadOmitEmptyMarshalJSON OpType = 108 OpStructHeadMarshalText OpType = 108
OpStructHeadMarshalText OpType = 109 OpStructHeadOmitEmptyMarshalText OpType = 109
OpStructHeadOmitEmptyMarshalText OpType = 110 OpStructPtrHeadMarshalText OpType = 110
OpStructPtrHeadMarshalText OpType = 111 OpStructPtrHeadOmitEmptyMarshalText OpType = 111
OpStructPtrHeadOmitEmptyMarshalText OpType = 112 OpStructHeadIntString OpType = 112
OpStructHeadIntString OpType = 113 OpStructHeadOmitEmptyIntString OpType = 113
OpStructHeadOmitEmptyIntString OpType = 114 OpStructPtrHeadIntString OpType = 114
OpStructPtrHeadIntString OpType = 115 OpStructPtrHeadOmitEmptyIntString OpType = 115
OpStructPtrHeadOmitEmptyIntString OpType = 116 OpStructHeadUintString OpType = 116
OpStructHeadUintString OpType = 117 OpStructHeadOmitEmptyUintString OpType = 117
OpStructHeadOmitEmptyUintString OpType = 118 OpStructPtrHeadUintString OpType = 118
OpStructPtrHeadUintString OpType = 119 OpStructPtrHeadOmitEmptyUintString OpType = 119
OpStructPtrHeadOmitEmptyUintString OpType = 120 OpStructHeadFloat32String OpType = 120
OpStructHeadFloat32String OpType = 121 OpStructHeadOmitEmptyFloat32String OpType = 121
OpStructHeadOmitEmptyFloat32String OpType = 122 OpStructPtrHeadFloat32String OpType = 122
OpStructPtrHeadFloat32String OpType = 123 OpStructPtrHeadOmitEmptyFloat32String OpType = 123
OpStructPtrHeadOmitEmptyFloat32String OpType = 124 OpStructHeadFloat64String OpType = 124
OpStructHeadFloat64String OpType = 125 OpStructHeadOmitEmptyFloat64String OpType = 125
OpStructHeadOmitEmptyFloat64String OpType = 126 OpStructPtrHeadFloat64String OpType = 126
OpStructPtrHeadFloat64String OpType = 127 OpStructPtrHeadOmitEmptyFloat64String OpType = 127
OpStructPtrHeadOmitEmptyFloat64String OpType = 128 OpStructHeadBoolString OpType = 128
OpStructHeadBoolString OpType = 129 OpStructHeadOmitEmptyBoolString OpType = 129
OpStructHeadOmitEmptyBoolString OpType = 130 OpStructPtrHeadBoolString OpType = 130
OpStructPtrHeadBoolString OpType = 131 OpStructPtrHeadOmitEmptyBoolString OpType = 131
OpStructPtrHeadOmitEmptyBoolString OpType = 132 OpStructHeadStringString OpType = 132
OpStructHeadStringString OpType = 133 OpStructHeadOmitEmptyStringString OpType = 133
OpStructHeadOmitEmptyStringString OpType = 134 OpStructPtrHeadStringString OpType = 134
OpStructPtrHeadStringString OpType = 135 OpStructPtrHeadOmitEmptyStringString OpType = 135
OpStructPtrHeadOmitEmptyStringString OpType = 136 OpStructHeadNumberString OpType = 136
OpStructHeadNumberString OpType = 137 OpStructHeadOmitEmptyNumberString OpType = 137
OpStructHeadOmitEmptyNumberString OpType = 138 OpStructPtrHeadNumberString OpType = 138
OpStructPtrHeadNumberString OpType = 139 OpStructPtrHeadOmitEmptyNumberString OpType = 139
OpStructPtrHeadOmitEmptyNumberString OpType = 140 OpStructHeadIntPtr OpType = 140
OpStructHeadIntPtr OpType = 141 OpStructHeadOmitEmptyIntPtr OpType = 141
OpStructHeadOmitEmptyIntPtr OpType = 142 OpStructPtrHeadIntPtr OpType = 142
OpStructPtrHeadIntPtr OpType = 143 OpStructPtrHeadOmitEmptyIntPtr OpType = 143
OpStructPtrHeadOmitEmptyIntPtr OpType = 144 OpStructHeadUintPtr OpType = 144
OpStructHeadUintPtr OpType = 145 OpStructHeadOmitEmptyUintPtr OpType = 145
OpStructHeadOmitEmptyUintPtr OpType = 146 OpStructPtrHeadUintPtr OpType = 146
OpStructPtrHeadUintPtr OpType = 147 OpStructPtrHeadOmitEmptyUintPtr OpType = 147
OpStructPtrHeadOmitEmptyUintPtr OpType = 148 OpStructHeadFloat32Ptr OpType = 148
OpStructHeadFloat32Ptr OpType = 149 OpStructHeadOmitEmptyFloat32Ptr OpType = 149
OpStructHeadOmitEmptyFloat32Ptr OpType = 150 OpStructPtrHeadFloat32Ptr OpType = 150
OpStructPtrHeadFloat32Ptr OpType = 151 OpStructPtrHeadOmitEmptyFloat32Ptr OpType = 151
OpStructPtrHeadOmitEmptyFloat32Ptr OpType = 152 OpStructHeadFloat64Ptr OpType = 152
OpStructHeadFloat64Ptr OpType = 153 OpStructHeadOmitEmptyFloat64Ptr OpType = 153
OpStructHeadOmitEmptyFloat64Ptr OpType = 154 OpStructPtrHeadFloat64Ptr OpType = 154
OpStructPtrHeadFloat64Ptr OpType = 155 OpStructPtrHeadOmitEmptyFloat64Ptr OpType = 155
OpStructPtrHeadOmitEmptyFloat64Ptr OpType = 156 OpStructHeadBoolPtr OpType = 156
OpStructHeadBoolPtr OpType = 157 OpStructHeadOmitEmptyBoolPtr OpType = 157
OpStructHeadOmitEmptyBoolPtr OpType = 158 OpStructPtrHeadBoolPtr OpType = 158
OpStructPtrHeadBoolPtr OpType = 159 OpStructPtrHeadOmitEmptyBoolPtr OpType = 159
OpStructPtrHeadOmitEmptyBoolPtr OpType = 160 OpStructHeadStringPtr OpType = 160
OpStructHeadStringPtr OpType = 161 OpStructHeadOmitEmptyStringPtr OpType = 161
OpStructHeadOmitEmptyStringPtr OpType = 162 OpStructPtrHeadStringPtr OpType = 162
OpStructPtrHeadStringPtr OpType = 163 OpStructPtrHeadOmitEmptyStringPtr OpType = 163
OpStructPtrHeadOmitEmptyStringPtr OpType = 164 OpStructHeadBytesPtr OpType = 164
OpStructHeadBytesPtr OpType = 165 OpStructHeadOmitEmptyBytesPtr OpType = 165
OpStructHeadOmitEmptyBytesPtr OpType = 166 OpStructPtrHeadBytesPtr OpType = 166
OpStructPtrHeadBytesPtr OpType = 167 OpStructPtrHeadOmitEmptyBytesPtr OpType = 167
OpStructPtrHeadOmitEmptyBytesPtr OpType = 168 OpStructHeadNumberPtr OpType = 168
OpStructHeadNumberPtr OpType = 169 OpStructHeadOmitEmptyNumberPtr OpType = 169
OpStructHeadOmitEmptyNumberPtr OpType = 170 OpStructPtrHeadNumberPtr OpType = 170
OpStructPtrHeadNumberPtr OpType = 171 OpStructPtrHeadOmitEmptyNumberPtr OpType = 171
OpStructPtrHeadOmitEmptyNumberPtr OpType = 172 OpStructHeadArrayPtr OpType = 172
OpStructHeadArrayPtr OpType = 173 OpStructHeadOmitEmptyArrayPtr OpType = 173
OpStructHeadOmitEmptyArrayPtr OpType = 174 OpStructPtrHeadArrayPtr OpType = 174
OpStructPtrHeadArrayPtr OpType = 175 OpStructPtrHeadOmitEmptyArrayPtr OpType = 175
OpStructPtrHeadOmitEmptyArrayPtr OpType = 176 OpStructHeadMapPtr OpType = 176
OpStructHeadMapPtr OpType = 177 OpStructHeadOmitEmptyMapPtr OpType = 177
OpStructHeadOmitEmptyMapPtr OpType = 178 OpStructPtrHeadMapPtr OpType = 178
OpStructPtrHeadMapPtr OpType = 179 OpStructPtrHeadOmitEmptyMapPtr OpType = 179
OpStructPtrHeadOmitEmptyMapPtr OpType = 180 OpStructHeadSlicePtr OpType = 180
OpStructHeadSlicePtr OpType = 181 OpStructHeadOmitEmptySlicePtr OpType = 181
OpStructHeadOmitEmptySlicePtr OpType = 182 OpStructPtrHeadSlicePtr OpType = 182
OpStructPtrHeadSlicePtr OpType = 183 OpStructPtrHeadOmitEmptySlicePtr OpType = 183
OpStructPtrHeadOmitEmptySlicePtr OpType = 184 OpStructHeadMarshalJSONPtr OpType = 184
OpStructHeadMarshalJSONPtr OpType = 185 OpStructHeadOmitEmptyMarshalJSONPtr OpType = 185
OpStructHeadOmitEmptyMarshalJSONPtr OpType = 186 OpStructPtrHeadMarshalJSONPtr OpType = 186
OpStructPtrHeadMarshalJSONPtr OpType = 187 OpStructPtrHeadOmitEmptyMarshalJSONPtr OpType = 187
OpStructPtrHeadOmitEmptyMarshalJSONPtr OpType = 188 OpStructHeadMarshalTextPtr OpType = 188
OpStructHeadMarshalTextPtr OpType = 189 OpStructHeadOmitEmptyMarshalTextPtr OpType = 189
OpStructHeadOmitEmptyMarshalTextPtr OpType = 190 OpStructPtrHeadMarshalTextPtr OpType = 190
OpStructPtrHeadMarshalTextPtr OpType = 191 OpStructPtrHeadOmitEmptyMarshalTextPtr OpType = 191
OpStructPtrHeadOmitEmptyMarshalTextPtr OpType = 192 OpStructHeadInterfacePtr OpType = 192
OpStructHeadInterfacePtr OpType = 193 OpStructHeadOmitEmptyInterfacePtr OpType = 193
OpStructHeadOmitEmptyInterfacePtr OpType = 194 OpStructPtrHeadInterfacePtr OpType = 194
OpStructPtrHeadInterfacePtr OpType = 195 OpStructPtrHeadOmitEmptyInterfacePtr OpType = 195
OpStructPtrHeadOmitEmptyInterfacePtr OpType = 196 OpStructHeadIntPtrString OpType = 196
OpStructHeadIntPtrString OpType = 197 OpStructHeadOmitEmptyIntPtrString OpType = 197
OpStructHeadOmitEmptyIntPtrString OpType = 198 OpStructPtrHeadIntPtrString OpType = 198
OpStructPtrHeadIntPtrString OpType = 199 OpStructPtrHeadOmitEmptyIntPtrString OpType = 199
OpStructPtrHeadOmitEmptyIntPtrString OpType = 200 OpStructHeadUintPtrString OpType = 200
OpStructHeadUintPtrString OpType = 201 OpStructHeadOmitEmptyUintPtrString OpType = 201
OpStructHeadOmitEmptyUintPtrString OpType = 202 OpStructPtrHeadUintPtrString OpType = 202
OpStructPtrHeadUintPtrString OpType = 203 OpStructPtrHeadOmitEmptyUintPtrString OpType = 203
OpStructPtrHeadOmitEmptyUintPtrString OpType = 204 OpStructHeadFloat32PtrString OpType = 204
OpStructHeadFloat32PtrString OpType = 205 OpStructHeadOmitEmptyFloat32PtrString OpType = 205
OpStructHeadOmitEmptyFloat32PtrString OpType = 206 OpStructPtrHeadFloat32PtrString OpType = 206
OpStructPtrHeadFloat32PtrString OpType = 207 OpStructPtrHeadOmitEmptyFloat32PtrString OpType = 207
OpStructPtrHeadOmitEmptyFloat32PtrString OpType = 208 OpStructHeadFloat64PtrString OpType = 208
OpStructHeadFloat64PtrString OpType = 209 OpStructHeadOmitEmptyFloat64PtrString OpType = 209
OpStructHeadOmitEmptyFloat64PtrString OpType = 210 OpStructPtrHeadFloat64PtrString OpType = 210
OpStructPtrHeadFloat64PtrString OpType = 211 OpStructPtrHeadOmitEmptyFloat64PtrString OpType = 211
OpStructPtrHeadOmitEmptyFloat64PtrString OpType = 212 OpStructHeadBoolPtrString OpType = 212
OpStructHeadBoolPtrString OpType = 213 OpStructHeadOmitEmptyBoolPtrString OpType = 213
OpStructHeadOmitEmptyBoolPtrString OpType = 214 OpStructPtrHeadBoolPtrString OpType = 214
OpStructPtrHeadBoolPtrString OpType = 215 OpStructPtrHeadOmitEmptyBoolPtrString OpType = 215
OpStructPtrHeadOmitEmptyBoolPtrString OpType = 216 OpStructHeadStringPtrString OpType = 216
OpStructHeadStringPtrString OpType = 217 OpStructHeadOmitEmptyStringPtrString OpType = 217
OpStructHeadOmitEmptyStringPtrString OpType = 218 OpStructPtrHeadStringPtrString OpType = 218
OpStructPtrHeadStringPtrString OpType = 219 OpStructPtrHeadOmitEmptyStringPtrString OpType = 219
OpStructPtrHeadOmitEmptyStringPtrString OpType = 220 OpStructHeadNumberPtrString OpType = 220
OpStructHeadNumberPtrString OpType = 221 OpStructHeadOmitEmptyNumberPtrString OpType = 221
OpStructHeadOmitEmptyNumberPtrString OpType = 222 OpStructPtrHeadNumberPtrString OpType = 222
OpStructPtrHeadNumberPtrString OpType = 223 OpStructPtrHeadOmitEmptyNumberPtrString OpType = 223
OpStructPtrHeadOmitEmptyNumberPtrString OpType = 224 OpStructHead OpType = 224
OpStructHead OpType = 225 OpStructHeadOmitEmpty OpType = 225
OpStructHeadOmitEmpty OpType = 226 OpStructPtrHead OpType = 226
OpStructPtrHead OpType = 227 OpStructPtrHeadOmitEmpty OpType = 227
OpStructPtrHeadOmitEmpty OpType = 228 OpStructFieldInt OpType = 228
OpStructFieldInt OpType = 229 OpStructFieldOmitEmptyInt OpType = 229
OpStructFieldOmitEmptyInt OpType = 230 OpStructEndInt OpType = 230
OpStructEndInt OpType = 231 OpStructEndOmitEmptyInt OpType = 231
OpStructEndOmitEmptyInt OpType = 232 OpStructFieldUint OpType = 232
OpStructFieldUint OpType = 233 OpStructFieldOmitEmptyUint OpType = 233
OpStructFieldOmitEmptyUint OpType = 234 OpStructEndUint OpType = 234
OpStructEndUint OpType = 235 OpStructEndOmitEmptyUint OpType = 235
OpStructEndOmitEmptyUint OpType = 236 OpStructFieldFloat32 OpType = 236
OpStructFieldFloat32 OpType = 237 OpStructFieldOmitEmptyFloat32 OpType = 237
OpStructFieldOmitEmptyFloat32 OpType = 238 OpStructEndFloat32 OpType = 238
OpStructEndFloat32 OpType = 239 OpStructEndOmitEmptyFloat32 OpType = 239
OpStructEndOmitEmptyFloat32 OpType = 240 OpStructFieldFloat64 OpType = 240
OpStructFieldFloat64 OpType = 241 OpStructFieldOmitEmptyFloat64 OpType = 241
OpStructFieldOmitEmptyFloat64 OpType = 242 OpStructEndFloat64 OpType = 242
OpStructEndFloat64 OpType = 243 OpStructEndOmitEmptyFloat64 OpType = 243
OpStructEndOmitEmptyFloat64 OpType = 244 OpStructFieldBool OpType = 244
OpStructFieldBool OpType = 245 OpStructFieldOmitEmptyBool OpType = 245
OpStructFieldOmitEmptyBool OpType = 246 OpStructEndBool OpType = 246
OpStructEndBool OpType = 247 OpStructEndOmitEmptyBool OpType = 247
OpStructEndOmitEmptyBool OpType = 248 OpStructFieldString OpType = 248
OpStructFieldString OpType = 249 OpStructFieldOmitEmptyString OpType = 249
OpStructFieldOmitEmptyString OpType = 250 OpStructEndString OpType = 250
OpStructEndString OpType = 251 OpStructEndOmitEmptyString OpType = 251
OpStructEndOmitEmptyString OpType = 252 OpStructFieldBytes OpType = 252
OpStructFieldBytes OpType = 253 OpStructFieldOmitEmptyBytes OpType = 253
OpStructFieldOmitEmptyBytes OpType = 254 OpStructEndBytes OpType = 254
OpStructEndBytes OpType = 255 OpStructEndOmitEmptyBytes OpType = 255
OpStructEndOmitEmptyBytes OpType = 256 OpStructFieldNumber OpType = 256
OpStructFieldNumber OpType = 257 OpStructFieldOmitEmptyNumber OpType = 257
OpStructFieldOmitEmptyNumber OpType = 258 OpStructEndNumber OpType = 258
OpStructEndNumber OpType = 259 OpStructEndOmitEmptyNumber OpType = 259
OpStructEndOmitEmptyNumber OpType = 260 OpStructFieldArray OpType = 260
OpStructFieldArray OpType = 261 OpStructFieldOmitEmptyArray OpType = 261
OpStructFieldOmitEmptyArray OpType = 262 OpStructEndArray OpType = 262
OpStructEndArray OpType = 263 OpStructEndOmitEmptyArray OpType = 263
OpStructEndOmitEmptyArray OpType = 264 OpStructFieldMap OpType = 264
OpStructFieldMap OpType = 265 OpStructFieldOmitEmptyMap OpType = 265
OpStructFieldOmitEmptyMap OpType = 266 OpStructEndMap OpType = 266
OpStructEndMap OpType = 267 OpStructEndOmitEmptyMap OpType = 267
OpStructEndOmitEmptyMap OpType = 268 OpStructFieldSlice OpType = 268
OpStructFieldSlice OpType = 269 OpStructFieldOmitEmptySlice OpType = 269
OpStructFieldOmitEmptySlice OpType = 270 OpStructEndSlice OpType = 270
OpStructEndSlice OpType = 271 OpStructEndOmitEmptySlice OpType = 271
OpStructEndOmitEmptySlice OpType = 272 OpStructFieldStruct OpType = 272
OpStructFieldStruct OpType = 273 OpStructFieldOmitEmptyStruct OpType = 273
OpStructFieldOmitEmptyStruct OpType = 274 OpStructEndStruct OpType = 274
OpStructEndStruct OpType = 275 OpStructEndOmitEmptyStruct OpType = 275
OpStructEndOmitEmptyStruct OpType = 276 OpStructFieldMarshalJSON OpType = 276
OpStructFieldMarshalJSON OpType = 277 OpStructFieldOmitEmptyMarshalJSON OpType = 277
OpStructFieldOmitEmptyMarshalJSON OpType = 278 OpStructEndMarshalJSON OpType = 278
OpStructEndMarshalJSON OpType = 279 OpStructEndOmitEmptyMarshalJSON OpType = 279
OpStructEndOmitEmptyMarshalJSON OpType = 280 OpStructFieldMarshalText OpType = 280
OpStructFieldMarshalText OpType = 281 OpStructFieldOmitEmptyMarshalText OpType = 281
OpStructFieldOmitEmptyMarshalText OpType = 282 OpStructEndMarshalText OpType = 282
OpStructEndMarshalText OpType = 283 OpStructEndOmitEmptyMarshalText OpType = 283
OpStructEndOmitEmptyMarshalText OpType = 284 OpStructFieldIntString OpType = 284
OpStructFieldIntString OpType = 285 OpStructFieldOmitEmptyIntString OpType = 285
OpStructFieldOmitEmptyIntString OpType = 286 OpStructEndIntString OpType = 286
OpStructEndIntString OpType = 287 OpStructEndOmitEmptyIntString OpType = 287
OpStructEndOmitEmptyIntString OpType = 288 OpStructFieldUintString OpType = 288
OpStructFieldUintString OpType = 289 OpStructFieldOmitEmptyUintString OpType = 289
OpStructFieldOmitEmptyUintString OpType = 290 OpStructEndUintString OpType = 290
OpStructEndUintString OpType = 291 OpStructEndOmitEmptyUintString OpType = 291
OpStructEndOmitEmptyUintString OpType = 292 OpStructFieldFloat32String OpType = 292
OpStructFieldFloat32String OpType = 293 OpStructFieldOmitEmptyFloat32String OpType = 293
OpStructFieldOmitEmptyFloat32String OpType = 294 OpStructEndFloat32String OpType = 294
OpStructEndFloat32String OpType = 295 OpStructEndOmitEmptyFloat32String OpType = 295
OpStructEndOmitEmptyFloat32String OpType = 296 OpStructFieldFloat64String OpType = 296
OpStructFieldFloat64String OpType = 297 OpStructFieldOmitEmptyFloat64String OpType = 297
OpStructFieldOmitEmptyFloat64String OpType = 298 OpStructEndFloat64String OpType = 298
OpStructEndFloat64String OpType = 299 OpStructEndOmitEmptyFloat64String OpType = 299
OpStructEndOmitEmptyFloat64String OpType = 300 OpStructFieldBoolString OpType = 300
OpStructFieldBoolString OpType = 301 OpStructFieldOmitEmptyBoolString OpType = 301
OpStructFieldOmitEmptyBoolString OpType = 302 OpStructEndBoolString OpType = 302
OpStructEndBoolString OpType = 303 OpStructEndOmitEmptyBoolString OpType = 303
OpStructEndOmitEmptyBoolString OpType = 304 OpStructFieldStringString OpType = 304
OpStructFieldStringString OpType = 305 OpStructFieldOmitEmptyStringString OpType = 305
OpStructFieldOmitEmptyStringString OpType = 306 OpStructEndStringString OpType = 306
OpStructEndStringString OpType = 307 OpStructEndOmitEmptyStringString OpType = 307
OpStructEndOmitEmptyStringString OpType = 308 OpStructFieldNumberString OpType = 308
OpStructFieldNumberString OpType = 309 OpStructFieldOmitEmptyNumberString OpType = 309
OpStructFieldOmitEmptyNumberString OpType = 310 OpStructEndNumberString OpType = 310
OpStructEndNumberString OpType = 311 OpStructEndOmitEmptyNumberString OpType = 311
OpStructEndOmitEmptyNumberString OpType = 312 OpStructFieldIntPtr OpType = 312
OpStructFieldIntPtr OpType = 313 OpStructFieldOmitEmptyIntPtr OpType = 313
OpStructFieldOmitEmptyIntPtr OpType = 314 OpStructEndIntPtr OpType = 314
OpStructEndIntPtr OpType = 315 OpStructEndOmitEmptyIntPtr OpType = 315
OpStructEndOmitEmptyIntPtr OpType = 316 OpStructFieldUintPtr OpType = 316
OpStructFieldUintPtr OpType = 317 OpStructFieldOmitEmptyUintPtr OpType = 317
OpStructFieldOmitEmptyUintPtr OpType = 318 OpStructEndUintPtr OpType = 318
OpStructEndUintPtr OpType = 319 OpStructEndOmitEmptyUintPtr OpType = 319
OpStructEndOmitEmptyUintPtr OpType = 320 OpStructFieldFloat32Ptr OpType = 320
OpStructFieldFloat32Ptr OpType = 321 OpStructFieldOmitEmptyFloat32Ptr OpType = 321
OpStructFieldOmitEmptyFloat32Ptr OpType = 322 OpStructEndFloat32Ptr OpType = 322
OpStructEndFloat32Ptr OpType = 323 OpStructEndOmitEmptyFloat32Ptr OpType = 323
OpStructEndOmitEmptyFloat32Ptr OpType = 324 OpStructFieldFloat64Ptr OpType = 324
OpStructFieldFloat64Ptr OpType = 325 OpStructFieldOmitEmptyFloat64Ptr OpType = 325
OpStructFieldOmitEmptyFloat64Ptr OpType = 326 OpStructEndFloat64Ptr OpType = 326
OpStructEndFloat64Ptr OpType = 327 OpStructEndOmitEmptyFloat64Ptr OpType = 327
OpStructEndOmitEmptyFloat64Ptr OpType = 328 OpStructFieldBoolPtr OpType = 328
OpStructFieldBoolPtr OpType = 329 OpStructFieldOmitEmptyBoolPtr OpType = 329
OpStructFieldOmitEmptyBoolPtr OpType = 330 OpStructEndBoolPtr OpType = 330
OpStructEndBoolPtr OpType = 331 OpStructEndOmitEmptyBoolPtr OpType = 331
OpStructEndOmitEmptyBoolPtr OpType = 332 OpStructFieldStringPtr OpType = 332
OpStructFieldStringPtr OpType = 333 OpStructFieldOmitEmptyStringPtr OpType = 333
OpStructFieldOmitEmptyStringPtr OpType = 334 OpStructEndStringPtr OpType = 334
OpStructEndStringPtr OpType = 335 OpStructEndOmitEmptyStringPtr OpType = 335
OpStructEndOmitEmptyStringPtr OpType = 336 OpStructFieldBytesPtr OpType = 336
OpStructFieldBytesPtr OpType = 337 OpStructFieldOmitEmptyBytesPtr OpType = 337
OpStructFieldOmitEmptyBytesPtr OpType = 338 OpStructEndBytesPtr OpType = 338
OpStructEndBytesPtr OpType = 339 OpStructEndOmitEmptyBytesPtr OpType = 339
OpStructEndOmitEmptyBytesPtr OpType = 340 OpStructFieldNumberPtr OpType = 340
OpStructFieldNumberPtr OpType = 341 OpStructFieldOmitEmptyNumberPtr OpType = 341
OpStructFieldOmitEmptyNumberPtr OpType = 342 OpStructEndNumberPtr OpType = 342
OpStructEndNumberPtr OpType = 343 OpStructEndOmitEmptyNumberPtr OpType = 343
OpStructEndOmitEmptyNumberPtr OpType = 344 OpStructFieldArrayPtr OpType = 344
OpStructFieldArrayPtr OpType = 345 OpStructFieldOmitEmptyArrayPtr OpType = 345
OpStructFieldOmitEmptyArrayPtr OpType = 346 OpStructEndArrayPtr OpType = 346
OpStructEndArrayPtr OpType = 347 OpStructEndOmitEmptyArrayPtr OpType = 347
OpStructEndOmitEmptyArrayPtr OpType = 348 OpStructFieldMapPtr OpType = 348
OpStructFieldMapPtr OpType = 349 OpStructFieldOmitEmptyMapPtr OpType = 349
OpStructFieldOmitEmptyMapPtr OpType = 350 OpStructEndMapPtr OpType = 350
OpStructEndMapPtr OpType = 351 OpStructEndOmitEmptyMapPtr OpType = 351
OpStructEndOmitEmptyMapPtr OpType = 352 OpStructFieldSlicePtr OpType = 352
OpStructFieldSlicePtr OpType = 353 OpStructFieldOmitEmptySlicePtr OpType = 353
OpStructFieldOmitEmptySlicePtr OpType = 354 OpStructEndSlicePtr OpType = 354
OpStructEndSlicePtr OpType = 355 OpStructEndOmitEmptySlicePtr OpType = 355
OpStructEndOmitEmptySlicePtr OpType = 356 OpStructFieldMarshalJSONPtr OpType = 356
OpStructFieldMarshalJSONPtr OpType = 357 OpStructFieldOmitEmptyMarshalJSONPtr OpType = 357
OpStructFieldOmitEmptyMarshalJSONPtr OpType = 358 OpStructEndMarshalJSONPtr OpType = 358
OpStructEndMarshalJSONPtr OpType = 359 OpStructEndOmitEmptyMarshalJSONPtr OpType = 359
OpStructEndOmitEmptyMarshalJSONPtr OpType = 360 OpStructFieldMarshalTextPtr OpType = 360
OpStructFieldMarshalTextPtr OpType = 361 OpStructFieldOmitEmptyMarshalTextPtr OpType = 361
OpStructFieldOmitEmptyMarshalTextPtr OpType = 362 OpStructEndMarshalTextPtr OpType = 362
OpStructEndMarshalTextPtr OpType = 363 OpStructEndOmitEmptyMarshalTextPtr OpType = 363
OpStructEndOmitEmptyMarshalTextPtr OpType = 364 OpStructFieldInterfacePtr OpType = 364
OpStructFieldInterfacePtr OpType = 365 OpStructFieldOmitEmptyInterfacePtr OpType = 365
OpStructFieldOmitEmptyInterfacePtr OpType = 366 OpStructEndInterfacePtr OpType = 366
OpStructEndInterfacePtr OpType = 367 OpStructEndOmitEmptyInterfacePtr OpType = 367
OpStructEndOmitEmptyInterfacePtr OpType = 368 OpStructFieldIntPtrString OpType = 368
OpStructFieldIntPtrString OpType = 369 OpStructFieldOmitEmptyIntPtrString OpType = 369
OpStructFieldOmitEmptyIntPtrString OpType = 370 OpStructEndIntPtrString OpType = 370
OpStructEndIntPtrString OpType = 371 OpStructEndOmitEmptyIntPtrString OpType = 371
OpStructEndOmitEmptyIntPtrString OpType = 372 OpStructFieldUintPtrString OpType = 372
OpStructFieldUintPtrString OpType = 373 OpStructFieldOmitEmptyUintPtrString OpType = 373
OpStructFieldOmitEmptyUintPtrString OpType = 374 OpStructEndUintPtrString OpType = 374
OpStructEndUintPtrString OpType = 375 OpStructEndOmitEmptyUintPtrString OpType = 375
OpStructEndOmitEmptyUintPtrString OpType = 376 OpStructFieldFloat32PtrString OpType = 376
OpStructFieldFloat32PtrString OpType = 377 OpStructFieldOmitEmptyFloat32PtrString OpType = 377
OpStructFieldOmitEmptyFloat32PtrString OpType = 378 OpStructEndFloat32PtrString OpType = 378
OpStructEndFloat32PtrString OpType = 379 OpStructEndOmitEmptyFloat32PtrString OpType = 379
OpStructEndOmitEmptyFloat32PtrString OpType = 380 OpStructFieldFloat64PtrString OpType = 380
OpStructFieldFloat64PtrString OpType = 381 OpStructFieldOmitEmptyFloat64PtrString OpType = 381
OpStructFieldOmitEmptyFloat64PtrString OpType = 382 OpStructEndFloat64PtrString OpType = 382
OpStructEndFloat64PtrString OpType = 383 OpStructEndOmitEmptyFloat64PtrString OpType = 383
OpStructEndOmitEmptyFloat64PtrString OpType = 384 OpStructFieldBoolPtrString OpType = 384
OpStructFieldBoolPtrString OpType = 385 OpStructFieldOmitEmptyBoolPtrString OpType = 385
OpStructFieldOmitEmptyBoolPtrString OpType = 386 OpStructEndBoolPtrString OpType = 386
OpStructEndBoolPtrString OpType = 387 OpStructEndOmitEmptyBoolPtrString OpType = 387
OpStructEndOmitEmptyBoolPtrString OpType = 388 OpStructFieldStringPtrString OpType = 388
OpStructFieldStringPtrString OpType = 389 OpStructFieldOmitEmptyStringPtrString OpType = 389
OpStructFieldOmitEmptyStringPtrString OpType = 390 OpStructEndStringPtrString OpType = 390
OpStructEndStringPtrString OpType = 391 OpStructEndOmitEmptyStringPtrString OpType = 391
OpStructEndOmitEmptyStringPtrString OpType = 392 OpStructFieldNumberPtrString OpType = 392
OpStructFieldNumberPtrString OpType = 393 OpStructFieldOmitEmptyNumberPtrString OpType = 393
OpStructFieldOmitEmptyNumberPtrString OpType = 394 OpStructEndNumberPtrString OpType = 394
OpStructEndNumberPtrString OpType = 395 OpStructEndOmitEmptyNumberPtrString OpType = 395
OpStructEndOmitEmptyNumberPtrString OpType = 396 OpStructField OpType = 396
OpStructField OpType = 397 OpStructFieldOmitEmpty OpType = 397
OpStructFieldOmitEmpty OpType = 398 OpStructEnd OpType = 398
OpStructEnd OpType = 399 OpStructEndOmitEmpty OpType = 399
OpStructEndOmitEmpty OpType = 400
) )
func (t OpType) String() string { func (t OpType) String() string {
if int(t) >= 401 { if int(t) >= 400 {
return "" return ""
} }
return opTypeStrings[int(t)] return opTypeStrings[int(t)]
@ -896,7 +894,7 @@ func (t OpType) HeadToOmitEmptyHead() OpType {
} }
func (t OpType) PtrHeadToHead() OpType { func (t OpType) PtrHeadToHead() OpType {
idx := strings.Index(t.String(), "Ptr") idx := strings.Index(t.String(), "PtrHead")
if idx == -1 { if idx == -1 {
return t return t
} }

View File

@ -68,7 +68,19 @@ func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
return p return p
} }
func ptrToUint64(p uintptr) uint64 { return **(**uint64)(unsafe.Pointer(&p)) } func ptrToUint64(p uintptr, bitSize uint8) uint64 {
switch bitSize {
case 8:
return (uint64)(**(**uint8)(unsafe.Pointer(&p)))
case 16:
return (uint64)(**(**uint16)(unsafe.Pointer(&p)))
case 32:
return (uint64)(**(**uint32)(unsafe.Pointer(&p)))
case 64:
return **(**uint64)(unsafe.Pointer(&p))
}
return 0
}
func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) } func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) }
func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) } func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) }
func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) } func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) }
@ -114,6 +126,10 @@ func appendComma(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, ',') return append(b, ',')
} }
func appendNullComma(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, "null,"...)
}
func appendColon(_ *encoder.RuntimeContext, b []byte) []byte { func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
last := len(b) - 1 last := len(b) - 1
b[last] = ':' b[last] = ':'

File diff suppressed because it is too large Load Diff

View File

@ -61,7 +61,19 @@ func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
return p return p
} }
func ptrToUint64(p uintptr) uint64 { return **(**uint64)(unsafe.Pointer(&p)) } func ptrToUint64(p uintptr, bitSize uint8) uint64 {
switch bitSize {
case 8:
return (uint64)(**(**uint8)(unsafe.Pointer(&p)))
case 16:
return (uint64)(**(**uint16)(unsafe.Pointer(&p)))
case 32:
return (uint64)(**(**uint32)(unsafe.Pointer(&p)))
case 64:
return **(**uint64)(unsafe.Pointer(&p))
}
return 0
}
func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) } func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) }
func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) } func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) }
func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) } func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) }
@ -92,17 +104,17 @@ func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} {
})) }))
} }
func appendInt(ctx *encoder.RuntimeContext, b []byte, v uint64, code *encoder.Opcode) []byte { func appendInt(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte {
format := ctx.Option.ColorScheme.Int format := ctx.Option.ColorScheme.Int
b = append(b, format.Header...) b = append(b, format.Header...)
b = encoder.AppendInt(ctx, b, v, code) b = encoder.AppendInt(ctx, b, p, code)
return append(b, format.Footer...) return append(b, format.Footer...)
} }
func appendUint(ctx *encoder.RuntimeContext, b []byte, v uint64, code *encoder.Opcode) []byte { func appendUint(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte {
format := ctx.Option.ColorScheme.Uint format := ctx.Option.ColorScheme.Uint
b = append(b, format.Header...) b = append(b, format.Header...)
b = encoder.AppendUint(ctx, b, v, code) b = encoder.AppendUint(ctx, b, p, code)
return append(b, format.Footer...) return append(b, format.Footer...)
} }
@ -166,6 +178,13 @@ func appendComma(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, ',') return append(b, ',')
} }
func appendNullComma(ctx *encoder.RuntimeContext, b []byte) []byte {
format := ctx.Option.ColorScheme.Null
b = append(b, format.Header...)
b = append(b, "null"...)
return append(append(b, format.Footer...), ',')
}
func appendColon(_ *encoder.RuntimeContext, b []byte) []byte { func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
last := len(b) - 1 last := len(b) - 1
b[last] = ':' b[last] = ':'

File diff suppressed because it is too large Load Diff

View File

@ -63,7 +63,20 @@ func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
return p return p
} }
func ptrToUint64(p uintptr) uint64 { return **(**uint64)(unsafe.Pointer(&p)) } func ptrToUint64(p uintptr, bitSize uint8) uint64 {
switch bitSize {
case 8:
return (uint64)(**(**uint8)(unsafe.Pointer(&p)))
case 16:
return (uint64)(**(**uint16)(unsafe.Pointer(&p)))
case 32:
return (uint64)(**(**uint32)(unsafe.Pointer(&p)))
case 64:
return **(**uint64)(unsafe.Pointer(&p))
}
return 0
}
func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) } func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) }
func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) } func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) }
func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) } func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) }
@ -94,17 +107,17 @@ func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} {
})) }))
} }
func appendInt(ctx *encoder.RuntimeContext, b []byte, v uint64, code *encoder.Opcode) []byte { func appendInt(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte {
format := ctx.Option.ColorScheme.Int format := ctx.Option.ColorScheme.Int
b = append(b, format.Header...) b = append(b, format.Header...)
b = encoder.AppendInt(ctx, b, v, code) b = encoder.AppendInt(ctx, b, p, code)
return append(b, format.Footer...) return append(b, format.Footer...)
} }
func appendUint(ctx *encoder.RuntimeContext, b []byte, v uint64, code *encoder.Opcode) []byte { func appendUint(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte {
format := ctx.Option.ColorScheme.Uint format := ctx.Option.ColorScheme.Uint
b = append(b, format.Header...) b = append(b, format.Header...)
b = encoder.AppendUint(ctx, b, v, code) b = encoder.AppendUint(ctx, b, p, code)
return append(b, format.Footer...) return append(b, format.Footer...)
} }
@ -168,6 +181,13 @@ func appendComma(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, ',', '\n') return append(b, ',', '\n')
} }
func appendNullComma(ctx *encoder.RuntimeContext, b []byte) []byte {
format := ctx.Option.ColorScheme.Null
b = append(b, format.Header...)
b = append(b, "null"...)
return append(append(b, format.Footer...), ',', '\n')
}
func appendColon(_ *encoder.RuntimeContext, b []byte) []byte { func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, ':', ' ') return append(b, ':', ' ')
} }

File diff suppressed because it is too large Load Diff

View File

@ -70,7 +70,19 @@ func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
return p return p
} }
func ptrToUint64(p uintptr) uint64 { return **(**uint64)(unsafe.Pointer(&p)) } func ptrToUint64(p uintptr, bitSize uint8) uint64 {
switch bitSize {
case 8:
return (uint64)(**(**uint8)(unsafe.Pointer(&p)))
case 16:
return (uint64)(**(**uint16)(unsafe.Pointer(&p)))
case 32:
return (uint64)(**(**uint32)(unsafe.Pointer(&p)))
case 64:
return **(**uint64)(unsafe.Pointer(&p))
}
return 0
}
func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) } func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) }
func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) } func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) }
func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) } func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) }
@ -116,6 +128,10 @@ func appendComma(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, ',', '\n') return append(b, ',', '\n')
} }
func appendNullComma(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, "null,\n"...)
}
func appendColon(_ *encoder.RuntimeContext, b []byte) []byte { func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, ':', ' ') return append(b, ':', ' ')
} }

File diff suppressed because it is too large Load Diff

View File

@ -8,8 +8,6 @@
A high-performance 100% compatible drop-in replacement of "encoding/json" A high-performance 100% compatible drop-in replacement of "encoding/json"
You can also use thrift like JSON using [thrift-iterator](https://github.com/thrift-iterator/go)
# Benchmark # Benchmark
![benchmark](http://jsoniter.com/benchmarks/go-benchmark.png) ![benchmark](http://jsoniter.com/benchmarks/go-benchmark.png)

4
vendor/github.com/lib/pq/array.go generated vendored
View File

@ -587,8 +587,8 @@ func (a *Int32Array) scanBytes(src []byte) error {
} else { } else {
b := make(Int32Array, len(elems)) b := make(Int32Array, len(elems))
for i, v := range elems { for i, v := range elems {
var x int x, err := strconv.ParseInt(string(v), 10, 32)
if x, err = strconv.Atoi(string(v)); err != nil { if err != nil {
return fmt.Errorf("pq: parsing array element index %d: %v", i, err) return fmt.Errorf("pq: parsing array element index %d: %v", i, err)
} }
b[i] = int32(x) b[i] = int32(x)

149
vendor/github.com/lib/pq/conn.go generated vendored
View File

@ -18,7 +18,7 @@ import (
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
"sync/atomic" "sync"
"time" "time"
"unicode" "unicode"
@ -140,9 +140,10 @@ type conn struct {
saveMessageType byte saveMessageType byte
saveMessageBuffer []byte saveMessageBuffer []byte
// If true, this connection is bad and all public-facing functions should // If an error is set, this connection is bad and all public-facing
// return ErrBadConn. // functions should return the appropriate error by calling get()
bad *atomic.Value // (ErrBadConn) or getForNext().
err syncErr
// If set, this connection should never use the binary format when // If set, this connection should never use the binary format when
// receiving query results from prepared statements. Only provided for // receiving query results from prepared statements. Only provided for
@ -166,6 +167,40 @@ type conn struct {
gss GSS gss GSS
} }
type syncErr struct {
err error
sync.Mutex
}
// Return ErrBadConn if connection is bad.
func (e *syncErr) get() error {
e.Lock()
defer e.Unlock()
if e.err != nil {
return driver.ErrBadConn
}
return nil
}
// Return the error set on the connection. Currently only used by rows.Next.
func (e *syncErr) getForNext() error {
e.Lock()
defer e.Unlock()
return e.err
}
// Set error, only if it isn't set yet.
func (e *syncErr) set(err error) {
if err == nil {
panic("attempt to set nil err")
}
e.Lock()
defer e.Unlock()
if e.err == nil {
e.err = err
}
}
// Handle driver-side settings in parsed connection string. // Handle driver-side settings in parsed connection string.
func (cn *conn) handleDriverSettings(o values) (err error) { func (cn *conn) handleDriverSettings(o values) (err error) {
boolSetting := func(key string, val *bool) error { boolSetting := func(key string, val *bool) error {
@ -306,12 +341,9 @@ func (c *Connector) open(ctx context.Context) (cn *conn, err error) {
o[k] = v o[k] = v
} }
bad := &atomic.Value{}
bad.Store(false)
cn = &conn{ cn = &conn{
opts: o, opts: o,
dialer: c.dialer, dialer: c.dialer,
bad: bad,
} }
err = cn.handleDriverSettings(o) err = cn.handleDriverSettings(o)
if err != nil { if err != nil {
@ -516,22 +548,9 @@ func (cn *conn) isInTransaction() bool {
cn.txnStatus == txnStatusInFailedTransaction cn.txnStatus == txnStatusInFailedTransaction
} }
func (cn *conn) setBad() {
if cn.bad != nil {
cn.bad.Store(true)
}
}
func (cn *conn) getBad() bool {
if cn.bad != nil {
return cn.bad.Load().(bool)
}
return false
}
func (cn *conn) checkIsInTransaction(intxn bool) { func (cn *conn) checkIsInTransaction(intxn bool) {
if cn.isInTransaction() != intxn { if cn.isInTransaction() != intxn {
cn.setBad() cn.err.set(driver.ErrBadConn)
errorf("unexpected transaction status %v", cn.txnStatus) errorf("unexpected transaction status %v", cn.txnStatus)
} }
} }
@ -541,8 +560,8 @@ func (cn *conn) Begin() (_ driver.Tx, err error) {
} }
func (cn *conn) begin(mode string) (_ driver.Tx, err error) { func (cn *conn) begin(mode string) (_ driver.Tx, err error) {
if cn.getBad() { if err := cn.err.get(); err != nil {
return nil, driver.ErrBadConn return nil, err
} }
defer cn.errRecover(&err) defer cn.errRecover(&err)
@ -552,11 +571,11 @@ func (cn *conn) begin(mode string) (_ driver.Tx, err error) {
return nil, err return nil, err
} }
if commandTag != "BEGIN" { if commandTag != "BEGIN" {
cn.setBad() cn.err.set(driver.ErrBadConn)
return nil, fmt.Errorf("unexpected command tag %s", commandTag) return nil, fmt.Errorf("unexpected command tag %s", commandTag)
} }
if cn.txnStatus != txnStatusIdleInTransaction { if cn.txnStatus != txnStatusIdleInTransaction {
cn.setBad() cn.err.set(driver.ErrBadConn)
return nil, fmt.Errorf("unexpected transaction status %v", cn.txnStatus) return nil, fmt.Errorf("unexpected transaction status %v", cn.txnStatus)
} }
return cn, nil return cn, nil
@ -570,8 +589,8 @@ func (cn *conn) closeTxn() {
func (cn *conn) Commit() (err error) { func (cn *conn) Commit() (err error) {
defer cn.closeTxn() defer cn.closeTxn()
if cn.getBad() { if err := cn.err.get(); err != nil {
return driver.ErrBadConn return err
} }
defer cn.errRecover(&err) defer cn.errRecover(&err)
@ -592,12 +611,12 @@ func (cn *conn) Commit() (err error) {
_, commandTag, err := cn.simpleExec("COMMIT") _, commandTag, err := cn.simpleExec("COMMIT")
if err != nil { if err != nil {
if cn.isInTransaction() { if cn.isInTransaction() {
cn.setBad() cn.err.set(driver.ErrBadConn)
} }
return err return err
} }
if commandTag != "COMMIT" { if commandTag != "COMMIT" {
cn.setBad() cn.err.set(driver.ErrBadConn)
return fmt.Errorf("unexpected command tag %s", commandTag) return fmt.Errorf("unexpected command tag %s", commandTag)
} }
cn.checkIsInTransaction(false) cn.checkIsInTransaction(false)
@ -606,8 +625,8 @@ func (cn *conn) Commit() (err error) {
func (cn *conn) Rollback() (err error) { func (cn *conn) Rollback() (err error) {
defer cn.closeTxn() defer cn.closeTxn()
if cn.getBad() { if err := cn.err.get(); err != nil {
return driver.ErrBadConn return err
} }
defer cn.errRecover(&err) defer cn.errRecover(&err)
return cn.rollback() return cn.rollback()
@ -618,7 +637,7 @@ func (cn *conn) rollback() (err error) {
_, commandTag, err := cn.simpleExec("ROLLBACK") _, commandTag, err := cn.simpleExec("ROLLBACK")
if err != nil { if err != nil {
if cn.isInTransaction() { if cn.isInTransaction() {
cn.setBad() cn.err.set(driver.ErrBadConn)
} }
return err return err
} }
@ -658,7 +677,7 @@ func (cn *conn) simpleExec(q string) (res driver.Result, commandTag string, err
case 'T', 'D': case 'T', 'D':
// ignore any results // ignore any results
default: default:
cn.setBad() cn.err.set(driver.ErrBadConn)
errorf("unknown response for simple query: %q", t) errorf("unknown response for simple query: %q", t)
} }
} }
@ -680,7 +699,7 @@ func (cn *conn) simpleQuery(q string) (res *rows, err error) {
// the user can close, though, to avoid connections from being // the user can close, though, to avoid connections from being
// leaked. A "rows" with done=true works fine for that purpose. // leaked. A "rows" with done=true works fine for that purpose.
if err != nil { if err != nil {
cn.setBad() cn.err.set(driver.ErrBadConn)
errorf("unexpected message %q in simple query execution", t) errorf("unexpected message %q in simple query execution", t)
} }
if res == nil { if res == nil {
@ -707,7 +726,7 @@ func (cn *conn) simpleQuery(q string) (res *rows, err error) {
err = parseError(r) err = parseError(r)
case 'D': case 'D':
if res == nil { if res == nil {
cn.setBad() cn.err.set(driver.ErrBadConn)
errorf("unexpected DataRow in simple query execution") errorf("unexpected DataRow in simple query execution")
} }
// the query didn't fail; kick off to Next // the query didn't fail; kick off to Next
@ -722,7 +741,7 @@ func (cn *conn) simpleQuery(q string) (res *rows, err error) {
// To work around a bug in QueryRow in Go 1.2 and earlier, wait // To work around a bug in QueryRow in Go 1.2 and earlier, wait
// until the first DataRow has been received. // until the first DataRow has been received.
default: default:
cn.setBad() cn.err.set(driver.ErrBadConn)
errorf("unknown response for simple query: %q", t) errorf("unknown response for simple query: %q", t)
} }
} }
@ -815,8 +834,8 @@ func (cn *conn) prepareTo(q, stmtName string) *stmt {
} }
func (cn *conn) Prepare(q string) (_ driver.Stmt, err error) { func (cn *conn) Prepare(q string) (_ driver.Stmt, err error) {
if cn.getBad() { if err := cn.err.get(); err != nil {
return nil, driver.ErrBadConn return nil, err
} }
defer cn.errRecover(&err) defer cn.errRecover(&err)
@ -854,8 +873,8 @@ func (cn *conn) Query(query string, args []driver.Value) (driver.Rows, error) {
} }
func (cn *conn) query(query string, args []driver.Value) (_ *rows, err error) { func (cn *conn) query(query string, args []driver.Value) (_ *rows, err error) {
if cn.getBad() { if err := cn.err.get(); err != nil {
return nil, driver.ErrBadConn return nil, err
} }
if cn.inCopy { if cn.inCopy {
return nil, errCopyInProgress return nil, errCopyInProgress
@ -888,8 +907,8 @@ func (cn *conn) query(query string, args []driver.Value) (_ *rows, err error) {
// Implement the optional "Execer" interface for one-shot queries // Implement the optional "Execer" interface for one-shot queries
func (cn *conn) Exec(query string, args []driver.Value) (res driver.Result, err error) { func (cn *conn) Exec(query string, args []driver.Value) (res driver.Result, err error) {
if cn.getBad() { if err := cn.err.get(); err != nil {
return nil, driver.ErrBadConn return nil, err
} }
defer cn.errRecover(&err) defer cn.errRecover(&err)
@ -960,7 +979,7 @@ func (cn *conn) sendSimpleMessage(typ byte) (err error) {
// the message yourself. // the message yourself.
func (cn *conn) saveMessage(typ byte, buf *readBuf) { func (cn *conn) saveMessage(typ byte, buf *readBuf) {
if cn.saveMessageType != 0 { if cn.saveMessageType != 0 {
cn.setBad() cn.err.set(driver.ErrBadConn)
errorf("unexpected saveMessageType %d", cn.saveMessageType) errorf("unexpected saveMessageType %d", cn.saveMessageType)
} }
cn.saveMessageType = typ cn.saveMessageType = typ
@ -1330,8 +1349,8 @@ func (st *stmt) Close() (err error) {
if st.closed { if st.closed {
return nil return nil
} }
if st.cn.getBad() { if err := st.cn.err.get(); err != nil {
return driver.ErrBadConn return err
} }
defer st.cn.errRecover(&err) defer st.cn.errRecover(&err)
@ -1344,14 +1363,14 @@ func (st *stmt) Close() (err error) {
t, _ := st.cn.recv1() t, _ := st.cn.recv1()
if t != '3' { if t != '3' {
st.cn.setBad() st.cn.err.set(driver.ErrBadConn)
errorf("unexpected close response: %q", t) errorf("unexpected close response: %q", t)
} }
st.closed = true st.closed = true
t, r := st.cn.recv1() t, r := st.cn.recv1()
if t != 'Z' { if t != 'Z' {
st.cn.setBad() st.cn.err.set(driver.ErrBadConn)
errorf("expected ready for query, but got: %q", t) errorf("expected ready for query, but got: %q", t)
} }
st.cn.processReadyForQuery(r) st.cn.processReadyForQuery(r)
@ -1364,8 +1383,8 @@ func (st *stmt) Query(v []driver.Value) (r driver.Rows, err error) {
} }
func (st *stmt) query(v []driver.Value) (r *rows, err error) { func (st *stmt) query(v []driver.Value) (r *rows, err error) {
if st.cn.getBad() { if err := st.cn.err.get(); err != nil {
return nil, driver.ErrBadConn return nil, err
} }
defer st.cn.errRecover(&err) defer st.cn.errRecover(&err)
@ -1377,8 +1396,8 @@ func (st *stmt) query(v []driver.Value) (r *rows, err error) {
} }
func (st *stmt) Exec(v []driver.Value) (res driver.Result, err error) { func (st *stmt) Exec(v []driver.Value) (res driver.Result, err error) {
if st.cn.getBad() { if err := st.cn.err.get(); err != nil {
return nil, driver.ErrBadConn return nil, err
} }
defer st.cn.errRecover(&err) defer st.cn.errRecover(&err)
@ -1464,7 +1483,7 @@ func (cn *conn) parseComplete(commandTag string) (driver.Result, string) {
if affectedRows == nil && strings.HasPrefix(commandTag, "INSERT ") { if affectedRows == nil && strings.HasPrefix(commandTag, "INSERT ") {
parts := strings.Split(commandTag, " ") parts := strings.Split(commandTag, " ")
if len(parts) != 3 { if len(parts) != 3 {
cn.setBad() cn.err.set(driver.ErrBadConn)
errorf("unexpected INSERT command tag %s", commandTag) errorf("unexpected INSERT command tag %s", commandTag)
} }
affectedRows = &parts[len(parts)-1] affectedRows = &parts[len(parts)-1]
@ -1476,7 +1495,7 @@ func (cn *conn) parseComplete(commandTag string) (driver.Result, string) {
} }
n, err := strconv.ParseInt(*affectedRows, 10, 64) n, err := strconv.ParseInt(*affectedRows, 10, 64)
if err != nil { if err != nil {
cn.setBad() cn.err.set(driver.ErrBadConn)
errorf("could not parse commandTag: %s", err) errorf("could not parse commandTag: %s", err)
} }
return driver.RowsAffected(n), commandTag return driver.RowsAffected(n), commandTag
@ -1543,8 +1562,8 @@ func (rs *rows) Next(dest []driver.Value) (err error) {
} }
conn := rs.cn conn := rs.cn
if conn.getBad() { if err := conn.err.getForNext(); err != nil {
return driver.ErrBadConn return err
} }
defer conn.errRecover(&err) defer conn.errRecover(&err)
@ -1568,7 +1587,7 @@ func (rs *rows) Next(dest []driver.Value) (err error) {
case 'D': case 'D':
n := rs.rb.int16() n := rs.rb.int16()
if err != nil { if err != nil {
conn.setBad() conn.err.set(driver.ErrBadConn)
errorf("unexpected DataRow after error %s", err) errorf("unexpected DataRow after error %s", err)
} }
if n < len(dest) { if n < len(dest) {
@ -1762,7 +1781,7 @@ func (cn *conn) readReadyForQuery() {
cn.processReadyForQuery(r) cn.processReadyForQuery(r)
return return
default: default:
cn.setBad() cn.err.set(driver.ErrBadConn)
errorf("unexpected message %q; expected ReadyForQuery", t) errorf("unexpected message %q; expected ReadyForQuery", t)
} }
} }
@ -1782,7 +1801,7 @@ func (cn *conn) readParseResponse() {
cn.readReadyForQuery() cn.readReadyForQuery()
panic(err) panic(err)
default: default:
cn.setBad() cn.err.set(driver.ErrBadConn)
errorf("unexpected Parse response %q", t) errorf("unexpected Parse response %q", t)
} }
} }
@ -1807,7 +1826,7 @@ func (cn *conn) readStatementDescribeResponse() (paramTyps []oid.Oid, colNames [
cn.readReadyForQuery() cn.readReadyForQuery()
panic(err) panic(err)
default: default:
cn.setBad() cn.err.set(driver.ErrBadConn)
errorf("unexpected Describe statement response %q", t) errorf("unexpected Describe statement response %q", t)
} }
} }
@ -1825,7 +1844,7 @@ func (cn *conn) readPortalDescribeResponse() rowsHeader {
cn.readReadyForQuery() cn.readReadyForQuery()
panic(err) panic(err)
default: default:
cn.setBad() cn.err.set(driver.ErrBadConn)
errorf("unexpected Describe response %q", t) errorf("unexpected Describe response %q", t)
} }
panic("not reached") panic("not reached")
@ -1841,7 +1860,7 @@ func (cn *conn) readBindResponse() {
cn.readReadyForQuery() cn.readReadyForQuery()
panic(err) panic(err)
default: default:
cn.setBad() cn.err.set(driver.ErrBadConn)
errorf("unexpected Bind response %q", t) errorf("unexpected Bind response %q", t)
} }
} }
@ -1868,7 +1887,7 @@ func (cn *conn) postExecuteWorkaround() {
cn.saveMessage(t, r) cn.saveMessage(t, r)
return return
default: default:
cn.setBad() cn.err.set(driver.ErrBadConn)
errorf("unexpected message during extended query execution: %q", t) errorf("unexpected message during extended query execution: %q", t)
} }
} }
@ -1881,7 +1900,7 @@ func (cn *conn) readExecuteResponse(protocolState string) (res driver.Result, co
switch t { switch t {
case 'C': case 'C':
if err != nil { if err != nil {
cn.setBad() cn.err.set(driver.ErrBadConn)
errorf("unexpected CommandComplete after error %s", err) errorf("unexpected CommandComplete after error %s", err)
} }
res, commandTag = cn.parseComplete(r.string()) res, commandTag = cn.parseComplete(r.string())
@ -1895,7 +1914,7 @@ func (cn *conn) readExecuteResponse(protocolState string) (res driver.Result, co
err = parseError(r) err = parseError(r)
case 'T', 'D', 'I': case 'T', 'D', 'I':
if err != nil { if err != nil {
cn.setBad() cn.err.set(driver.ErrBadConn)
errorf("unexpected %q after error %s", t, err) errorf("unexpected %q after error %s", t, err)
} }
if t == 'I' { if t == 'I' {
@ -1903,7 +1922,7 @@ func (cn *conn) readExecuteResponse(protocolState string) (res driver.Result, co
} }
// ignore any results // ignore any results
default: default:
cn.setBad() cn.err.set(driver.ErrBadConn)
errorf("unknown %s response: %q", protocolState, t) errorf("unknown %s response: %q", protocolState, t)
} }
} }

View File

@ -7,7 +7,6 @@ import (
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"sync/atomic"
"time" "time"
) )
@ -115,7 +114,7 @@ func (cn *conn) watchCancel(ctx context.Context) func() {
} }
// Set the connection state to bad so it does not get reused. // Set the connection state to bad so it does not get reused.
cn.setBad() cn.err.set(ctx.Err())
// At this point the function level context is canceled, // At this point the function level context is canceled,
// so it must not be used for the additional network // so it must not be used for the additional network
@ -131,7 +130,7 @@ func (cn *conn) watchCancel(ctx context.Context) func() {
return func() { return func() {
select { select {
case <-finished: case <-finished:
cn.setBad() cn.err.set(ctx.Err())
cn.Close() cn.Close()
case finished <- struct{}{}: case finished <- struct{}{}:
} }
@ -157,11 +156,8 @@ func (cn *conn) cancel(ctx context.Context) error {
defer c.Close() defer c.Close()
{ {
bad := &atomic.Value{}
bad.Store(false)
can := conn{ can := conn{
c: c, c: c,
bad: bad,
} }
err = can.ssl(o) err = can.ssl(o)
if err != nil { if err != nil {

74
vendor/github.com/lib/pq/copy.go generated vendored
View File

@ -49,12 +49,14 @@ type copyin struct {
buffer []byte buffer []byte
rowData chan []byte rowData chan []byte
done chan bool done chan bool
driver.Result
closed bool closed bool
sync.Mutex // guards err mu struct {
sync.Mutex
err error err error
driver.Result
}
} }
const ciBufferSize = 64 * 1024 const ciBufferSize = 64 * 1024
@ -98,13 +100,13 @@ awaitCopyInResponse:
err = parseError(r) err = parseError(r)
case 'Z': case 'Z':
if err == nil { if err == nil {
ci.setBad() ci.setBad(driver.ErrBadConn)
errorf("unexpected ReadyForQuery in response to COPY") errorf("unexpected ReadyForQuery in response to COPY")
} }
cn.processReadyForQuery(r) cn.processReadyForQuery(r)
return nil, err return nil, err
default: default:
ci.setBad() ci.setBad(driver.ErrBadConn)
errorf("unknown response for copy query: %q", t) errorf("unknown response for copy query: %q", t)
} }
} }
@ -123,7 +125,7 @@ awaitCopyInResponse:
cn.processReadyForQuery(r) cn.processReadyForQuery(r)
return nil, err return nil, err
default: default:
ci.setBad() ci.setBad(driver.ErrBadConn)
errorf("unknown response for CopyFail: %q", t) errorf("unknown response for CopyFail: %q", t)
} }
} }
@ -144,7 +146,7 @@ func (ci *copyin) resploop() {
var r readBuf var r readBuf
t, err := ci.cn.recvMessage(&r) t, err := ci.cn.recvMessage(&r)
if err != nil { if err != nil {
ci.setBad() ci.setBad(driver.ErrBadConn)
ci.setError(err) ci.setError(err)
ci.done <- true ci.done <- true
return return
@ -166,7 +168,7 @@ func (ci *copyin) resploop() {
err := parseError(&r) err := parseError(&r)
ci.setError(err) ci.setError(err)
default: default:
ci.setBad() ci.setBad(driver.ErrBadConn)
ci.setError(fmt.Errorf("unknown response during CopyIn: %q", t)) ci.setError(fmt.Errorf("unknown response during CopyIn: %q", t))
ci.done <- true ci.done <- true
return return
@ -174,46 +176,41 @@ func (ci *copyin) resploop() {
} }
} }
func (ci *copyin) setBad() { func (ci *copyin) setBad(err error) {
ci.Lock() ci.cn.err.set(err)
ci.cn.setBad()
ci.Unlock()
} }
func (ci *copyin) isBad() bool { func (ci *copyin) getBad() error {
ci.Lock() return ci.cn.err.get()
b := ci.cn.getBad()
ci.Unlock()
return b
} }
func (ci *copyin) isErrorSet() bool { func (ci *copyin) err() error {
ci.Lock() ci.mu.Lock()
isSet := (ci.err != nil) err := ci.mu.err
ci.Unlock() ci.mu.Unlock()
return isSet return err
} }
// setError() sets ci.err if one has not been set already. Caller must not be // setError() sets ci.err if one has not been set already. Caller must not be
// holding ci.Mutex. // holding ci.Mutex.
func (ci *copyin) setError(err error) { func (ci *copyin) setError(err error) {
ci.Lock() ci.mu.Lock()
if ci.err == nil { if ci.mu.err == nil {
ci.err = err ci.mu.err = err
} }
ci.Unlock() ci.mu.Unlock()
} }
func (ci *copyin) setResult(result driver.Result) { func (ci *copyin) setResult(result driver.Result) {
ci.Lock() ci.mu.Lock()
ci.Result = result ci.mu.Result = result
ci.Unlock() ci.mu.Unlock()
} }
func (ci *copyin) getResult() driver.Result { func (ci *copyin) getResult() driver.Result {
ci.Lock() ci.mu.Lock()
result := ci.Result result := ci.mu.Result
ci.Unlock() ci.mu.Unlock()
if result == nil { if result == nil {
return driver.RowsAffected(0) return driver.RowsAffected(0)
} }
@ -240,13 +237,13 @@ func (ci *copyin) Exec(v []driver.Value) (r driver.Result, err error) {
return nil, errCopyInClosed return nil, errCopyInClosed
} }
if ci.isBad() { if err := ci.getBad(); err != nil {
return nil, driver.ErrBadConn return nil, err
} }
defer ci.cn.errRecover(&err) defer ci.cn.errRecover(&err)
if ci.isErrorSet() { if err := ci.err(); err != nil {
return nil, ci.err return nil, err
} }
if len(v) == 0 { if len(v) == 0 {
@ -282,8 +279,8 @@ func (ci *copyin) Close() (err error) {
} }
ci.closed = true ci.closed = true
if ci.isBad() { if err := ci.getBad(); err != nil {
return driver.ErrBadConn return err
} }
defer ci.cn.errRecover(&err) defer ci.cn.errRecover(&err)
@ -299,8 +296,7 @@ func (ci *copyin) Close() (err error) {
<-ci.done <-ci.done
ci.cn.inCopy = false ci.cn.inCopy = false
if ci.isErrorSet() { if err := ci.err(); err != nil {
err = ci.err
return err return err
} }
return nil return nil

2
vendor/github.com/lib/pq/encode.go generated vendored
View File

@ -559,7 +559,7 @@ func parseBytea(s []byte) (result []byte, err error) {
if len(s) < 4 { if len(s) < 4 {
return nil, fmt.Errorf("invalid bytea sequence %v", s) return nil, fmt.Errorf("invalid bytea sequence %v", s)
} }
r, err := strconv.ParseInt(string(s[1:4]), 8, 9) r, err := strconv.ParseUint(string(s[1:4]), 8, 8)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not parse bytea value: %s", err.Error()) return nil, fmt.Errorf("could not parse bytea value: %s", err.Error())
} }

10
vendor/github.com/lib/pq/error.go generated vendored
View File

@ -484,7 +484,7 @@ func (cn *conn) errRecover(err *error) {
case nil: case nil:
// Do nothing // Do nothing
case runtime.Error: case runtime.Error:
cn.setBad() cn.err.set(driver.ErrBadConn)
panic(v) panic(v)
case *Error: case *Error:
if v.Fatal() { if v.Fatal() {
@ -493,10 +493,10 @@ func (cn *conn) errRecover(err *error) {
*err = v *err = v
} }
case *net.OpError: case *net.OpError:
cn.setBad() cn.err.set(driver.ErrBadConn)
*err = v *err = v
case *safeRetryError: case *safeRetryError:
cn.setBad() cn.err.set(driver.ErrBadConn)
*err = driver.ErrBadConn *err = driver.ErrBadConn
case error: case error:
if v == io.EOF || v.Error() == "remote error: handshake failure" { if v == io.EOF || v.Error() == "remote error: handshake failure" {
@ -506,13 +506,13 @@ func (cn *conn) errRecover(err *error) {
} }
default: default:
cn.setBad() cn.err.set(driver.ErrBadConn)
panic(fmt.Sprintf("unknown error: %#v", e)) panic(fmt.Sprintf("unknown error: %#v", e))
} }
// Any time we return ErrBadConn, we need to remember it since *Tx doesn't // Any time we return ErrBadConn, we need to remember it since *Tx doesn't
// mark the connection bad in database/sql. // mark the connection bad in database/sql.
if *err == driver.ErrBadConn { if *err == driver.ErrBadConn {
cn.setBad() cn.err.set(driver.ErrBadConn)
} }
} }

View File

@ -1,7 +1,7 @@
// Package pq is a pure Go Postgres driver for the database/sql package. // Package pq is a pure Go Postgres driver for the database/sql package.
//go:build aix || darwin || dragonfly || freebsd || linux || nacl || netbsd || openbsd || plan9 || solaris || rumprun || illumos //go:build aix || darwin || dragonfly || freebsd || (linux && !android) || nacl || netbsd || openbsd || plan9 || solaris || rumprun || illumos
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris rumprun illumos // +build aix darwin dragonfly freebsd linux,!android nacl netbsd openbsd plan9 solaris rumprun illumos
package pq package pq

View File

@ -1,15 +0,0 @@
language: go
sudo: false
go:
- 1.13.x
- tip
before_install:
- go get -t -v ./...
script:
- ./go.test.sh
after_success:
- bash <(curl -s https://codecov.io/bash)

View File

@ -1,6 +1,6 @@
# go-colorable # go-colorable
[![Build Status](https://travis-ci.org/mattn/go-colorable.svg?branch=master)](https://travis-ci.org/mattn/go-colorable) [![Build Status](https://github.com/mattn/go-colorable/workflows/test/badge.svg)](https://github.com/mattn/go-colorable/actions?query=workflow%3Atest)
[![Codecov](https://codecov.io/gh/mattn/go-colorable/branch/master/graph/badge.svg)](https://codecov.io/gh/mattn/go-colorable) [![Codecov](https://codecov.io/gh/mattn/go-colorable/branch/master/graph/badge.svg)](https://codecov.io/gh/mattn/go-colorable)
[![GoDoc](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable) [![GoDoc](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable)
[![Go Report Card](https://goreportcard.com/badge/mattn/go-colorable)](https://goreportcard.com/report/mattn/go-colorable) [![Go Report Card](https://goreportcard.com/badge/mattn/go-colorable)](https://goreportcard.com/report/mattn/go-colorable)

View File

@ -1,3 +1,4 @@
//go:build appengine
// +build appengine // +build appengine
package colorable package colorable

View File

@ -1,5 +1,5 @@
// +build !windows //go:build !windows && !appengine
// +build !appengine // +build !windows,!appengine
package colorable package colorable

View File

@ -1,5 +1,5 @@
// +build windows //go:build windows && !appengine
// +build !appengine // +build windows,!appengine
package colorable package colorable
@ -452,18 +452,22 @@ func (w *Writer) Write(data []byte) (n int, err error) {
} else { } else {
er = bytes.NewReader(data) er = bytes.NewReader(data)
} }
var bw [1]byte var plaintext bytes.Buffer
loop: loop:
for { for {
c1, err := er.ReadByte() c1, err := er.ReadByte()
if err != nil { if err != nil {
plaintext.WriteTo(w.out)
break loop break loop
} }
if c1 != 0x1b { if c1 != 0x1b {
bw[0] = c1 plaintext.WriteByte(c1)
w.out.Write(bw[:])
continue continue
} }
_, err = plaintext.WriteTo(w.out)
if err != nil {
break loop
}
c2, err := er.ReadByte() c2, err := er.ReadByte()
if err != nil { if err != nil {
break loop break loop

View File

@ -18,18 +18,22 @@ func NewNonColorable(w io.Writer) io.Writer {
// Write writes data on console // Write writes data on console
func (w *NonColorable) Write(data []byte) (n int, err error) { func (w *NonColorable) Write(data []byte) (n int, err error) {
er := bytes.NewReader(data) er := bytes.NewReader(data)
var bw [1]byte var plaintext bytes.Buffer
loop: loop:
for { for {
c1, err := er.ReadByte() c1, err := er.ReadByte()
if err != nil { if err != nil {
plaintext.WriteTo(w.out)
break loop break loop
} }
if c1 != 0x1b { if c1 != 0x1b {
bw[0] = c1 plaintext.WriteByte(c1)
w.out.Write(bw[:])
continue continue
} }
_, err = plaintext.WriteTo(w.out)
if err != nil {
break loop
}
c2, err := er.ReadByte() c2, err := er.ReadByte()
if err != nil { if err != nil {
break loop break loop
@ -38,7 +42,6 @@ loop:
continue continue
} }
var buf bytes.Buffer
for { for {
c, err := er.ReadByte() c, err := er.ReadByte()
if err != nil { if err != nil {
@ -47,7 +50,6 @@ loop:
if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' { if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
break break
} }
buf.Write([]byte(string(c)))
} }
} }

View File

@ -1,7 +1,7 @@
language: go language: go
go: go:
- 1.8.x - 1.9.x
- 1.x - 1.x
before_install: before_install:

View File

@ -1,15 +1,9 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
name = "github.com/modern-go/concurrent"
packages = ["."]
revision = "e0a39a4cb4216ea8db28e22a69f4ec25610d513a"
version = "1.0.0"
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "daee8a88b3498b61c5640056665b8b9eea062006f5e596bbb6a3ed9119a11ec7" input-imports = []
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

View File

@ -26,10 +26,6 @@
ignored = [] ignored = []
[[constraint]]
name = "github.com/modern-go/concurrent"
version = "1.0.0"
[prune] [prune]
go-tests = true go-tests = true
unused-packages = true unused-packages = true

23
vendor/github.com/modern-go/reflect2/go_above_118.go generated vendored Normal file
View File

@ -0,0 +1,23 @@
//+build go1.18
package reflect2
import (
"unsafe"
)
// m escapes into the return value, but the caller of mapiterinit
// doesn't let the return value escape.
//go:noescape
//go:linkname mapiterinit reflect.mapiterinit
func mapiterinit(rtype unsafe.Pointer, m unsafe.Pointer, it *hiter)
func (type2 *UnsafeMapType) UnsafeIterate(obj unsafe.Pointer) MapIterator {
var it hiter
mapiterinit(type2.rtype, *(*unsafe.Pointer)(obj), &it)
return &UnsafeMapIterator{
hiter: &it,
pKeyRType: type2.pKeyRType,
pElemRType: type2.pElemRType,
}
}

View File

@ -1,8 +0,0 @@
//+build go1.7
package reflect2
import "unsafe"
//go:linkname resolveTypeOff reflect.resolveTypeOff
func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer

View File

@ -6,6 +6,9 @@ import (
"unsafe" "unsafe"
) )
//go:linkname resolveTypeOff reflect.resolveTypeOff
func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
//go:linkname makemap reflect.makemap //go:linkname makemap reflect.makemap
func makemap(rtype unsafe.Pointer, cap int) (m unsafe.Pointer) func makemap(rtype unsafe.Pointer, cap int) (m unsafe.Pointer)

21
vendor/github.com/modern-go/reflect2/go_below_118.go generated vendored Normal file
View File

@ -0,0 +1,21 @@
//+build !go1.18
package reflect2
import (
"unsafe"
)
// m escapes into the return value, but the caller of mapiterinit
// doesn't let the return value escape.
//go:noescape
//go:linkname mapiterinit reflect.mapiterinit
func mapiterinit(rtype unsafe.Pointer, m unsafe.Pointer) (val *hiter)
func (type2 *UnsafeMapType) UnsafeIterate(obj unsafe.Pointer) MapIterator {
return &UnsafeMapIterator{
hiter: mapiterinit(type2.rtype, *(*unsafe.Pointer)(obj)),
pKeyRType: type2.pKeyRType,
pElemRType: type2.pElemRType,
}
}

View File

@ -1,9 +0,0 @@
//+build !go1.7
package reflect2
import "unsafe"
func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
return nil
}

View File

@ -1,14 +0,0 @@
//+build !go1.9
package reflect2
import (
"unsafe"
)
//go:linkname makemap reflect.makemap
func makemap(rtype unsafe.Pointer) (m unsafe.Pointer)
func makeMapWithSize(rtype unsafe.Pointer, cap int) unsafe.Pointer {
return makemap(rtype)
}

View File

@ -1,8 +1,9 @@
package reflect2 package reflect2
import ( import (
"github.com/modern-go/concurrent"
"reflect" "reflect"
"runtime"
"sync"
"unsafe" "unsafe"
) )
@ -130,13 +131,13 @@ var ConfigSafe = Config{UseSafeImplementation: true}.Froze()
type frozenConfig struct { type frozenConfig struct {
useSafeImplementation bool useSafeImplementation bool
cache *concurrent.Map cache *sync.Map
} }
func (cfg Config) Froze() *frozenConfig { func (cfg Config) Froze() *frozenConfig {
return &frozenConfig{ return &frozenConfig{
useSafeImplementation: cfg.UseSafeImplementation, useSafeImplementation: cfg.UseSafeImplementation,
cache: concurrent.NewMap(), cache: new(sync.Map),
} }
} }
@ -288,11 +289,12 @@ func NoEscape(p unsafe.Pointer) unsafe.Pointer {
} }
func UnsafeCastString(str string) []byte { func UnsafeCastString(str string) []byte {
bytes := make([]byte, 0)
stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&str)) stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&str))
sliceHeader := &reflect.SliceHeader{ sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&bytes))
Data: stringHeader.Data, sliceHeader.Data = stringHeader.Data
Cap: stringHeader.Len, sliceHeader.Cap = stringHeader.Len
Len: stringHeader.Len, sliceHeader.Len = stringHeader.Len
} runtime.KeepAlive(str)
return *(*[]byte)(unsafe.Pointer(sliceHeader)) return bytes
} }

View File

@ -1,12 +0,0 @@
#!/usr/bin/env bash
set -e
echo "" > coverage.txt
for d in $(go list github.com/modern-go/reflect2-tests/... | grep -v vendor); do
go test -coverprofile=profile.out -coverpkg=github.com/modern-go/reflect2 $d
if [ -f profile.out ]; then
cat profile.out >> coverage.txt
rm profile.out
fi
done

View File

@ -1,17 +1,13 @@
// +build !gccgo
package reflect2 package reflect2
import ( import (
"reflect" "reflect"
"runtime"
"strings"
"sync" "sync"
"unsafe" "unsafe"
) )
// typelinks1 for 1.5 ~ 1.6
//go:linkname typelinks1 reflect.typelinks
func typelinks1() [][]unsafe.Pointer
// typelinks2 for 1.7 ~ // typelinks2 for 1.7 ~
//go:linkname typelinks2 reflect.typelinks //go:linkname typelinks2 reflect.typelinks
func typelinks2() (sections []unsafe.Pointer, offset [][]int32) func typelinks2() (sections []unsafe.Pointer, offset [][]int32)
@ -27,49 +23,10 @@ func discoverTypes() {
types = make(map[string]reflect.Type) types = make(map[string]reflect.Type)
packages = make(map[string]map[string]reflect.Type) packages = make(map[string]map[string]reflect.Type)
ver := runtime.Version() loadGoTypes()
if ver == "go1.5" || strings.HasPrefix(ver, "go1.5.") {
loadGo15Types()
} else if ver == "go1.6" || strings.HasPrefix(ver, "go1.6.") {
loadGo15Types()
} else {
loadGo17Types()
}
} }
func loadGo15Types() { func loadGoTypes() {
var obj interface{} = reflect.TypeOf(0)
typePtrss := typelinks1()
for _, typePtrs := range typePtrss {
for _, typePtr := range typePtrs {
(*emptyInterface)(unsafe.Pointer(&obj)).word = typePtr
typ := obj.(reflect.Type)
if typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct {
loadedType := typ.Elem()
pkgTypes := packages[loadedType.PkgPath()]
if pkgTypes == nil {
pkgTypes = map[string]reflect.Type{}
packages[loadedType.PkgPath()] = pkgTypes
}
types[loadedType.String()] = loadedType
pkgTypes[loadedType.Name()] = loadedType
}
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Ptr &&
typ.Elem().Elem().Kind() == reflect.Struct {
loadedType := typ.Elem().Elem()
pkgTypes := packages[loadedType.PkgPath()]
if pkgTypes == nil {
pkgTypes = map[string]reflect.Type{}
packages[loadedType.PkgPath()] = pkgTypes
}
types[loadedType.String()] = loadedType
pkgTypes[loadedType.Name()] = loadedType
}
}
}
}
func loadGo17Types() {
var obj interface{} = reflect.TypeOf(0) var obj interface{} = reflect.TypeOf(0)
sections, offset := typelinks2() sections, offset := typelinks2()
for i, offs := range offset { for i, offs := range offset {

View File

@ -19,18 +19,12 @@ func typedslicecopy(elemType unsafe.Pointer, dst, src sliceHeader) int
//go:linkname mapassign reflect.mapassign //go:linkname mapassign reflect.mapassign
//go:noescape //go:noescape
func mapassign(rtype unsafe.Pointer, m unsafe.Pointer, key, val unsafe.Pointer) func mapassign(rtype unsafe.Pointer, m unsafe.Pointer, key unsafe.Pointer, val unsafe.Pointer)
//go:linkname mapaccess reflect.mapaccess //go:linkname mapaccess reflect.mapaccess
//go:noescape //go:noescape
func mapaccess(rtype unsafe.Pointer, m unsafe.Pointer, key unsafe.Pointer) (val unsafe.Pointer) func mapaccess(rtype unsafe.Pointer, m unsafe.Pointer, key unsafe.Pointer) (val unsafe.Pointer)
// m escapes into the return value, but the caller of mapiterinit
// doesn't let the return value escape.
//go:noescape
//go:linkname mapiterinit reflect.mapiterinit
func mapiterinit(rtype unsafe.Pointer, m unsafe.Pointer) *hiter
//go:noescape //go:noescape
//go:linkname mapiternext reflect.mapiternext //go:linkname mapiternext reflect.mapiternext
func mapiternext(it *hiter) func mapiternext(it *hiter)
@ -42,9 +36,21 @@ func ifaceE2I(rtype unsafe.Pointer, src interface{}, dst unsafe.Pointer)
// If you modify hiter, also change cmd/internal/gc/reflect.go to indicate // If you modify hiter, also change cmd/internal/gc/reflect.go to indicate
// the layout of this structure. // the layout of this structure.
type hiter struct { type hiter struct {
key unsafe.Pointer // Must be in first position. Write nil to indicate iteration end (see cmd/internal/gc/range.go). key unsafe.Pointer
value unsafe.Pointer // Must be in second position (see cmd/internal/gc/range.go). value unsafe.Pointer
// rest fields are ignored t unsafe.Pointer
h unsafe.Pointer
buckets unsafe.Pointer
bptr unsafe.Pointer
overflow *[]unsafe.Pointer
oldoverflow *[]unsafe.Pointer
startBucket uintptr
offset uint8
wrapped bool
B uint8
i uint8
bucket uintptr
checkBucket uintptr
} }
// add returns p+x. // add returns p+x.

View File

@ -107,14 +107,6 @@ func (type2 *UnsafeMapType) Iterate(obj interface{}) MapIterator {
return type2.UnsafeIterate(objEFace.data) return type2.UnsafeIterate(objEFace.data)
} }
func (type2 *UnsafeMapType) UnsafeIterate(obj unsafe.Pointer) MapIterator {
return &UnsafeMapIterator{
hiter: mapiterinit(type2.rtype, *(*unsafe.Pointer)(obj)),
pKeyRType: type2.pKeyRType,
pElemRType: type2.pElemRType,
}
}
type UnsafeMapIterator struct { type UnsafeMapIterator struct {
*hiter *hiter
pKeyRType unsafe.Pointer pKeyRType unsafe.Pointer

22
vendor/github.com/robfig/cron/.gitignore generated vendored Normal file
View File

@ -0,0 +1,22 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe

1
vendor/github.com/robfig/cron/.travis.yml generated vendored Normal file
View File

@ -0,0 +1 @@
language: go

21
vendor/github.com/robfig/cron/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
Copyright (C) 2012 Rob Figueiredo
All Rights Reserved.
MIT LICENSE
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

6
vendor/github.com/robfig/cron/README.md generated vendored Normal file
View File

@ -0,0 +1,6 @@
[![GoDoc](http://godoc.org/github.com/robfig/cron?status.png)](http://godoc.org/github.com/robfig/cron)
[![Build Status](https://travis-ci.org/robfig/cron.svg?branch=master)](https://travis-ci.org/robfig/cron)
# cron
Documentation here: https://godoc.org/github.com/robfig/cron

27
vendor/github.com/robfig/cron/constantdelay.go generated vendored Normal file
View File

@ -0,0 +1,27 @@
package cron
import "time"
// ConstantDelaySchedule represents a simple recurring duty cycle, e.g. "Every 5 minutes".
// It does not support jobs more frequent than once a second.
type ConstantDelaySchedule struct {
Delay time.Duration
}
// Every returns a crontab Schedule that activates once every duration.
// Delays of less than a second are not supported (will round up to 1 second).
// Any fields less than a Second are truncated.
func Every(duration time.Duration) ConstantDelaySchedule {
if duration < time.Second {
duration = time.Second
}
return ConstantDelaySchedule{
Delay: duration - time.Duration(duration.Nanoseconds())%time.Second,
}
}
// Next returns the next time this should be run.
// This rounds so that the next activation time will be on the second.
func (schedule ConstantDelaySchedule) Next(t time.Time) time.Time {
return t.Add(schedule.Delay - time.Duration(t.Nanosecond())*time.Nanosecond)
}

259
vendor/github.com/robfig/cron/cron.go generated vendored Normal file
View File

@ -0,0 +1,259 @@
package cron
import (
"log"
"runtime"
"sort"
"time"
)
// Cron keeps track of any number of entries, invoking the associated func as
// specified by the schedule. It may be started, stopped, and the entries may
// be inspected while running.
type Cron struct {
entries []*Entry
stop chan struct{}
add chan *Entry
snapshot chan []*Entry
running bool
ErrorLog *log.Logger
location *time.Location
}
// Job is an interface for submitted cron jobs.
type Job interface {
Run()
}
// The Schedule describes a job's duty cycle.
type Schedule interface {
// Return the next activation time, later than the given time.
// Next is invoked initially, and then each time the job is run.
Next(time.Time) time.Time
}
// Entry consists of a schedule and the func to execute on that schedule.
type Entry struct {
// The schedule on which this job should be run.
Schedule Schedule
// The next time the job will run. This is the zero time if Cron has not been
// started or this entry's schedule is unsatisfiable
Next time.Time
// The last time this job was run. This is the zero time if the job has never
// been run.
Prev time.Time
// The Job to run.
Job Job
}
// byTime is a wrapper for sorting the entry array by time
// (with zero time at the end).
type byTime []*Entry
func (s byTime) Len() int { return len(s) }
func (s byTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s byTime) Less(i, j int) bool {
// Two zero times should return false.
// Otherwise, zero is "greater" than any other time.
// (To sort it at the end of the list.)
if s[i].Next.IsZero() {
return false
}
if s[j].Next.IsZero() {
return true
}
return s[i].Next.Before(s[j].Next)
}
// New returns a new Cron job runner, in the Local time zone.
func New() *Cron {
return NewWithLocation(time.Now().Location())
}
// NewWithLocation returns a new Cron job runner.
func NewWithLocation(location *time.Location) *Cron {
return &Cron{
entries: nil,
add: make(chan *Entry),
stop: make(chan struct{}),
snapshot: make(chan []*Entry),
running: false,
ErrorLog: nil,
location: location,
}
}
// A wrapper that turns a func() into a cron.Job
type FuncJob func()
func (f FuncJob) Run() { f() }
// AddFunc adds a func to the Cron to be run on the given schedule.
func (c *Cron) AddFunc(spec string, cmd func()) error {
return c.AddJob(spec, FuncJob(cmd))
}
// AddJob adds a Job to the Cron to be run on the given schedule.
func (c *Cron) AddJob(spec string, cmd Job) error {
schedule, err := Parse(spec)
if err != nil {
return err
}
c.Schedule(schedule, cmd)
return nil
}
// Schedule adds a Job to the Cron to be run on the given schedule.
func (c *Cron) Schedule(schedule Schedule, cmd Job) {
entry := &Entry{
Schedule: schedule,
Job: cmd,
}
if !c.running {
c.entries = append(c.entries, entry)
return
}
c.add <- entry
}
// Entries returns a snapshot of the cron entries.
func (c *Cron) Entries() []*Entry {
if c.running {
c.snapshot <- nil
x := <-c.snapshot
return x
}
return c.entrySnapshot()
}
// Location gets the time zone location
func (c *Cron) Location() *time.Location {
return c.location
}
// Start the cron scheduler in its own go-routine, or no-op if already started.
func (c *Cron) Start() {
if c.running {
return
}
c.running = true
go c.run()
}
// Run the cron scheduler, or no-op if already running.
func (c *Cron) Run() {
if c.running {
return
}
c.running = true
c.run()
}
func (c *Cron) runWithRecovery(j Job) {
defer func() {
if r := recover(); r != nil {
const size = 64 << 10
buf := make([]byte, size)
buf = buf[:runtime.Stack(buf, false)]
c.logf("cron: panic running job: %v\n%s", r, buf)
}
}()
j.Run()
}
// Run the scheduler. this is private just due to the need to synchronize
// access to the 'running' state variable.
func (c *Cron) run() {
// Figure out the next activation times for each entry.
now := c.now()
for _, entry := range c.entries {
entry.Next = entry.Schedule.Next(now)
}
for {
// Determine the next entry to run.
sort.Sort(byTime(c.entries))
var timer *time.Timer
if len(c.entries) == 0 || c.entries[0].Next.IsZero() {
// If there are no entries yet, just sleep - it still handles new entries
// and stop requests.
timer = time.NewTimer(100000 * time.Hour)
} else {
timer = time.NewTimer(c.entries[0].Next.Sub(now))
}
for {
select {
case now = <-timer.C:
now = now.In(c.location)
// Run every entry whose next time was less than now
for _, e := range c.entries {
if e.Next.After(now) || e.Next.IsZero() {
break
}
go c.runWithRecovery(e.Job)
e.Prev = e.Next
e.Next = e.Schedule.Next(now)
}
case newEntry := <-c.add:
timer.Stop()
now = c.now()
newEntry.Next = newEntry.Schedule.Next(now)
c.entries = append(c.entries, newEntry)
case <-c.snapshot:
c.snapshot <- c.entrySnapshot()
continue
case <-c.stop:
timer.Stop()
return
}
break
}
}
}
// Logs an error to stderr or to the configured error log
func (c *Cron) logf(format string, args ...interface{}) {
if c.ErrorLog != nil {
c.ErrorLog.Printf(format, args...)
} else {
log.Printf(format, args...)
}
}
// Stop stops the cron scheduler if it is running; otherwise it does nothing.
func (c *Cron) Stop() {
if !c.running {
return
}
c.stop <- struct{}{}
c.running = false
}
// entrySnapshot returns a copy of the current cron entry list.
func (c *Cron) entrySnapshot() []*Entry {
entries := []*Entry{}
for _, e := range c.entries {
entries = append(entries, &Entry{
Schedule: e.Schedule,
Next: e.Next,
Prev: e.Prev,
Job: e.Job,
})
}
return entries
}
// now returns current time in c location
func (c *Cron) now() time.Time {
return time.Now().In(c.location)
}

129
vendor/github.com/robfig/cron/doc.go generated vendored Normal file
View File

@ -0,0 +1,129 @@
/*
Package cron implements a cron spec parser and job runner.
Usage
Callers may register Funcs to be invoked on a given schedule. Cron will run
them in their own goroutines.
c := cron.New()
c.AddFunc("0 30 * * * *", func() { fmt.Println("Every hour on the half hour") })
c.AddFunc("@hourly", func() { fmt.Println("Every hour") })
c.AddFunc("@every 1h30m", func() { fmt.Println("Every hour thirty") })
c.Start()
..
// Funcs are invoked in their own goroutine, asynchronously.
...
// Funcs may also be added to a running Cron
c.AddFunc("@daily", func() { fmt.Println("Every day") })
..
// Inspect the cron job entries' next and previous run times.
inspect(c.Entries())
..
c.Stop() // Stop the scheduler (does not stop any jobs already running).
CRON Expression Format
A cron expression represents a set of times, using 6 space-separated fields.
Field name | Mandatory? | Allowed values | Allowed special characters
---------- | ---------- | -------------- | --------------------------
Seconds | Yes | 0-59 | * / , -
Minutes | Yes | 0-59 | * / , -
Hours | Yes | 0-23 | * / , -
Day of month | Yes | 1-31 | * / , - ?
Month | Yes | 1-12 or JAN-DEC | * / , -
Day of week | Yes | 0-6 or SUN-SAT | * / , - ?
Note: Month and Day-of-week field values are case insensitive. "SUN", "Sun",
and "sun" are equally accepted.
Special Characters
Asterisk ( * )
The asterisk indicates that the cron expression will match for all values of the
field; e.g., using an asterisk in the 5th field (month) would indicate every
month.
Slash ( / )
Slashes are used to describe increments of ranges. For example 3-59/15 in the
1st field (minutes) would indicate the 3rd minute of the hour and every 15
minutes thereafter. The form "*\/..." is equivalent to the form "first-last/...",
that is, an increment over the largest possible range of the field. The form
"N/..." is accepted as meaning "N-MAX/...", that is, starting at N, use the
increment until the end of that specific range. It does not wrap around.
Comma ( , )
Commas are used to separate items of a list. For example, using "MON,WED,FRI" in
the 5th field (day of week) would mean Mondays, Wednesdays and Fridays.
Hyphen ( - )
Hyphens are used to define ranges. For example, 9-17 would indicate every
hour between 9am and 5pm inclusive.
Question mark ( ? )
Question mark may be used instead of '*' for leaving either day-of-month or
day-of-week blank.
Predefined schedules
You may use one of several pre-defined schedules in place of a cron expression.
Entry | Description | Equivalent To
----- | ----------- | -------------
@yearly (or @annually) | Run once a year, midnight, Jan. 1st | 0 0 0 1 1 *
@monthly | Run once a month, midnight, first of month | 0 0 0 1 * *
@weekly | Run once a week, midnight between Sat/Sun | 0 0 0 * * 0
@daily (or @midnight) | Run once a day, midnight | 0 0 0 * * *
@hourly | Run once an hour, beginning of hour | 0 0 * * * *
Intervals
You may also schedule a job to execute at fixed intervals, starting at the time it's added
or cron is run. This is supported by formatting the cron spec like this:
@every <duration>
where "duration" is a string accepted by time.ParseDuration
(http://golang.org/pkg/time/#ParseDuration).
For example, "@every 1h30m10s" would indicate a schedule that activates after
1 hour, 30 minutes, 10 seconds, and then every interval after that.
Note: The interval does not take the job runtime into account. For example,
if a job takes 3 minutes to run, and it is scheduled to run every 5 minutes,
it will have only 2 minutes of idle time between each run.
Time zones
All interpretation and scheduling is done in the machine's local time zone (as
provided by the Go time package (http://www.golang.org/pkg/time).
Be aware that jobs scheduled during daylight-savings leap-ahead transitions will
not be run!
Thread safety
Since the Cron service runs concurrently with the calling code, some amount of
care must be taken to ensure proper synchronization.
All cron methods are designed to be correctly synchronized as long as the caller
ensures that invocations have a clear happens-before ordering between them.
Implementation
Cron entries are stored in an array, sorted by their next activation time. Cron
sleeps until the next job is due to be run.
Upon waking:
- it runs each entry that is active on that second
- it calculates the next run times for the jobs that were run
- it re-sorts the array of entries by next activation time.
- it goes to sleep until the soonest job.
*/
package cron

380
vendor/github.com/robfig/cron/parser.go generated vendored Normal file
View File

@ -0,0 +1,380 @@
package cron
import (
"fmt"
"math"
"strconv"
"strings"
"time"
)
// Configuration options for creating a parser. Most options specify which
// fields should be included, while others enable features. If a field is not
// included the parser will assume a default value. These options do not change
// the order fields are parse in.
type ParseOption int
const (
Second ParseOption = 1 << iota // Seconds field, default 0
Minute // Minutes field, default 0
Hour // Hours field, default 0
Dom // Day of month field, default *
Month // Month field, default *
Dow // Day of week field, default *
DowOptional // Optional day of week field, default *
Descriptor // Allow descriptors such as @monthly, @weekly, etc.
)
var places = []ParseOption{
Second,
Minute,
Hour,
Dom,
Month,
Dow,
}
var defaults = []string{
"0",
"0",
"0",
"*",
"*",
"*",
}
// A custom Parser that can be configured.
type Parser struct {
options ParseOption
optionals int
}
// Creates a custom Parser with custom options.
//
// // Standard parser without descriptors
// specParser := NewParser(Minute | Hour | Dom | Month | Dow)
// sched, err := specParser.Parse("0 0 15 */3 *")
//
// // Same as above, just excludes time fields
// subsParser := NewParser(Dom | Month | Dow)
// sched, err := specParser.Parse("15 */3 *")
//
// // Same as above, just makes Dow optional
// subsParser := NewParser(Dom | Month | DowOptional)
// sched, err := specParser.Parse("15 */3")
//
func NewParser(options ParseOption) Parser {
optionals := 0
if options&DowOptional > 0 {
options |= Dow
optionals++
}
return Parser{options, optionals}
}
// Parse returns a new crontab schedule representing the given spec.
// It returns a descriptive error if the spec is not valid.
// It accepts crontab specs and features configured by NewParser.
func (p Parser) Parse(spec string) (Schedule, error) {
if len(spec) == 0 {
return nil, fmt.Errorf("Empty spec string")
}
if spec[0] == '@' && p.options&Descriptor > 0 {
return parseDescriptor(spec)
}
// Figure out how many fields we need
max := 0
for _, place := range places {
if p.options&place > 0 {
max++
}
}
min := max - p.optionals
// Split fields on whitespace
fields := strings.Fields(spec)
// Validate number of fields
if count := len(fields); count < min || count > max {
if min == max {
return nil, fmt.Errorf("Expected exactly %d fields, found %d: %s", min, count, spec)
}
return nil, fmt.Errorf("Expected %d to %d fields, found %d: %s", min, max, count, spec)
}
// Fill in missing fields
fields = expandFields(fields, p.options)
var err error
field := func(field string, r bounds) uint64 {
if err != nil {
return 0
}
var bits uint64
bits, err = getField(field, r)
return bits
}
var (
second = field(fields[0], seconds)
minute = field(fields[1], minutes)
hour = field(fields[2], hours)
dayofmonth = field(fields[3], dom)
month = field(fields[4], months)
dayofweek = field(fields[5], dow)
)
if err != nil {
return nil, err
}
return &SpecSchedule{
Second: second,
Minute: minute,
Hour: hour,
Dom: dayofmonth,
Month: month,
Dow: dayofweek,
}, nil
}
func expandFields(fields []string, options ParseOption) []string {
n := 0
count := len(fields)
expFields := make([]string, len(places))
copy(expFields, defaults)
for i, place := range places {
if options&place > 0 {
expFields[i] = fields[n]
n++
}
if n == count {
break
}
}
return expFields
}
var standardParser = NewParser(
Minute | Hour | Dom | Month | Dow | Descriptor,
)
// ParseStandard returns a new crontab schedule representing the given standardSpec
// (https://en.wikipedia.org/wiki/Cron). It differs from Parse requiring to always
// pass 5 entries representing: minute, hour, day of month, month and day of week,
// in that order. It returns a descriptive error if the spec is not valid.
//
// It accepts
// - Standard crontab specs, e.g. "* * * * ?"
// - Descriptors, e.g. "@midnight", "@every 1h30m"
func ParseStandard(standardSpec string) (Schedule, error) {
return standardParser.Parse(standardSpec)
}
var defaultParser = NewParser(
Second | Minute | Hour | Dom | Month | DowOptional | Descriptor,
)
// Parse returns a new crontab schedule representing the given spec.
// It returns a descriptive error if the spec is not valid.
//
// It accepts
// - Full crontab specs, e.g. "* * * * * ?"
// - Descriptors, e.g. "@midnight", "@every 1h30m"
func Parse(spec string) (Schedule, error) {
return defaultParser.Parse(spec)
}
// getField returns an Int with the bits set representing all of the times that
// the field represents or error parsing field value. A "field" is a comma-separated
// list of "ranges".
func getField(field string, r bounds) (uint64, error) {
var bits uint64
ranges := strings.FieldsFunc(field, func(r rune) bool { return r == ',' })
for _, expr := range ranges {
bit, err := getRange(expr, r)
if err != nil {
return bits, err
}
bits |= bit
}
return bits, nil
}
// getRange returns the bits indicated by the given expression:
// number | number "-" number [ "/" number ]
// or error parsing range.
func getRange(expr string, r bounds) (uint64, error) {
var (
start, end, step uint
rangeAndStep = strings.Split(expr, "/")
lowAndHigh = strings.Split(rangeAndStep[0], "-")
singleDigit = len(lowAndHigh) == 1
err error
)
var extra uint64
if lowAndHigh[0] == "*" || lowAndHigh[0] == "?" {
start = r.min
end = r.max
extra = starBit
} else {
start, err = parseIntOrName(lowAndHigh[0], r.names)
if err != nil {
return 0, err
}
switch len(lowAndHigh) {
case 1:
end = start
case 2:
end, err = parseIntOrName(lowAndHigh[1], r.names)
if err != nil {
return 0, err
}
default:
return 0, fmt.Errorf("Too many hyphens: %s", expr)
}
}
switch len(rangeAndStep) {
case 1:
step = 1
case 2:
step, err = mustParseInt(rangeAndStep[1])
if err != nil {
return 0, err
}
// Special handling: "N/step" means "N-max/step".
if singleDigit {
end = r.max
}
default:
return 0, fmt.Errorf("Too many slashes: %s", expr)
}
if start < r.min {
return 0, fmt.Errorf("Beginning of range (%d) below minimum (%d): %s", start, r.min, expr)
}
if end > r.max {
return 0, fmt.Errorf("End of range (%d) above maximum (%d): %s", end, r.max, expr)
}
if start > end {
return 0, fmt.Errorf("Beginning of range (%d) beyond end of range (%d): %s", start, end, expr)
}
if step == 0 {
return 0, fmt.Errorf("Step of range should be a positive number: %s", expr)
}
return getBits(start, end, step) | extra, nil
}
// parseIntOrName returns the (possibly-named) integer contained in expr.
func parseIntOrName(expr string, names map[string]uint) (uint, error) {
if names != nil {
if namedInt, ok := names[strings.ToLower(expr)]; ok {
return namedInt, nil
}
}
return mustParseInt(expr)
}
// mustParseInt parses the given expression as an int or returns an error.
func mustParseInt(expr string) (uint, error) {
num, err := strconv.Atoi(expr)
if err != nil {
return 0, fmt.Errorf("Failed to parse int from %s: %s", expr, err)
}
if num < 0 {
return 0, fmt.Errorf("Negative number (%d) not allowed: %s", num, expr)
}
return uint(num), nil
}
// getBits sets all bits in the range [min, max], modulo the given step size.
func getBits(min, max, step uint) uint64 {
var bits uint64
// If step is 1, use shifts.
if step == 1 {
return ^(math.MaxUint64 << (max + 1)) & (math.MaxUint64 << min)
}
// Else, use a simple loop.
for i := min; i <= max; i += step {
bits |= 1 << i
}
return bits
}
// all returns all bits within the given bounds. (plus the star bit)
func all(r bounds) uint64 {
return getBits(r.min, r.max, 1) | starBit
}
// parseDescriptor returns a predefined schedule for the expression, or error if none matches.
func parseDescriptor(descriptor string) (Schedule, error) {
switch descriptor {
case "@yearly", "@annually":
return &SpecSchedule{
Second: 1 << seconds.min,
Minute: 1 << minutes.min,
Hour: 1 << hours.min,
Dom: 1 << dom.min,
Month: 1 << months.min,
Dow: all(dow),
}, nil
case "@monthly":
return &SpecSchedule{
Second: 1 << seconds.min,
Minute: 1 << minutes.min,
Hour: 1 << hours.min,
Dom: 1 << dom.min,
Month: all(months),
Dow: all(dow),
}, nil
case "@weekly":
return &SpecSchedule{
Second: 1 << seconds.min,
Minute: 1 << minutes.min,
Hour: 1 << hours.min,
Dom: all(dom),
Month: all(months),
Dow: 1 << dow.min,
}, nil
case "@daily", "@midnight":
return &SpecSchedule{
Second: 1 << seconds.min,
Minute: 1 << minutes.min,
Hour: 1 << hours.min,
Dom: all(dom),
Month: all(months),
Dow: all(dow),
}, nil
case "@hourly":
return &SpecSchedule{
Second: 1 << seconds.min,
Minute: 1 << minutes.min,
Hour: all(hours),
Dom: all(dom),
Month: all(months),
Dow: all(dow),
}, nil
}
const every = "@every "
if strings.HasPrefix(descriptor, every) {
duration, err := time.ParseDuration(descriptor[len(every):])
if err != nil {
return nil, fmt.Errorf("Failed to parse duration %s: %s", descriptor, err)
}
return Every(duration), nil
}
return nil, fmt.Errorf("Unrecognized descriptor: %s", descriptor)
}

158
vendor/github.com/robfig/cron/spec.go generated vendored Normal file
View File

@ -0,0 +1,158 @@
package cron
import "time"
// SpecSchedule specifies a duty cycle (to the second granularity), based on a
// traditional crontab specification. It is computed initially and stored as bit sets.
type SpecSchedule struct {
Second, Minute, Hour, Dom, Month, Dow uint64
}
// bounds provides a range of acceptable values (plus a map of name to value).
type bounds struct {
min, max uint
names map[string]uint
}
// The bounds for each field.
var (
seconds = bounds{0, 59, nil}
minutes = bounds{0, 59, nil}
hours = bounds{0, 23, nil}
dom = bounds{1, 31, nil}
months = bounds{1, 12, map[string]uint{
"jan": 1,
"feb": 2,
"mar": 3,
"apr": 4,
"may": 5,
"jun": 6,
"jul": 7,
"aug": 8,
"sep": 9,
"oct": 10,
"nov": 11,
"dec": 12,
}}
dow = bounds{0, 6, map[string]uint{
"sun": 0,
"mon": 1,
"tue": 2,
"wed": 3,
"thu": 4,
"fri": 5,
"sat": 6,
}}
)
const (
// Set the top bit if a star was included in the expression.
starBit = 1 << 63
)
// Next returns the next time this schedule is activated, greater than the given
// time. If no time can be found to satisfy the schedule, return the zero time.
func (s *SpecSchedule) Next(t time.Time) time.Time {
// General approach:
// For Month, Day, Hour, Minute, Second:
// Check if the time value matches. If yes, continue to the next field.
// If the field doesn't match the schedule, then increment the field until it matches.
// While incrementing the field, a wrap-around brings it back to the beginning
// of the field list (since it is necessary to re-verify previous field
// values)
// Start at the earliest possible time (the upcoming second).
t = t.Add(1*time.Second - time.Duration(t.Nanosecond())*time.Nanosecond)
// This flag indicates whether a field has been incremented.
added := false
// If no time is found within five years, return zero.
yearLimit := t.Year() + 5
WRAP:
if t.Year() > yearLimit {
return time.Time{}
}
// Find the first applicable month.
// If it's this month, then do nothing.
for 1<<uint(t.Month())&s.Month == 0 {
// If we have to add a month, reset the other parts to 0.
if !added {
added = true
// Otherwise, set the date at the beginning (since the current time is irrelevant).
t = time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location())
}
t = t.AddDate(0, 1, 0)
// Wrapped around.
if t.Month() == time.January {
goto WRAP
}
}
// Now get a day in that month.
for !dayMatches(s, t) {
if !added {
added = true
t = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
}
t = t.AddDate(0, 0, 1)
if t.Day() == 1 {
goto WRAP
}
}
for 1<<uint(t.Hour())&s.Hour == 0 {
if !added {
added = true
t = time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), 0, 0, 0, t.Location())
}
t = t.Add(1 * time.Hour)
if t.Hour() == 0 {
goto WRAP
}
}
for 1<<uint(t.Minute())&s.Minute == 0 {
if !added {
added = true
t = t.Truncate(time.Minute)
}
t = t.Add(1 * time.Minute)
if t.Minute() == 0 {
goto WRAP
}
}
for 1<<uint(t.Second())&s.Second == 0 {
if !added {
added = true
t = t.Truncate(time.Second)
}
t = t.Add(1 * time.Second)
if t.Second() == 0 {
goto WRAP
}
}
return t
}
// dayMatches returns true if the schedule's day-of-week and day-of-month
// restrictions are satisfied by the given time.
func dayMatches(s *SpecSchedule, t time.Time) bool {
var (
domMatch bool = 1<<uint(t.Day())&s.Dom > 0
dowMatch bool = 1<<uint(t.Weekday())&s.Dow > 0
)
if s.Dom&starBit > 0 || s.Dow&starBit > 0 {
return domMatch && dowMatch
}
return domMatch || dowMatch
}

View File

@ -4,7 +4,7 @@
// Package acme provides an implementation of the // Package acme provides an implementation of the
// Automatic Certificate Management Environment (ACME) spec. // Automatic Certificate Management Environment (ACME) spec.
// The intial implementation was based on ACME draft-02 and // The initial implementation was based on ACME draft-02 and
// is now being extended to comply with RFC 8555. // is now being extended to comply with RFC 8555.
// See https://tools.ietf.org/html/draft-ietf-acme-acme-02 // See https://tools.ietf.org/html/draft-ietf-acme-acme-02
// and https://tools.ietf.org/html/rfc8555 for details. // and https://tools.ietf.org/html/rfc8555 for details.

View File

@ -410,3 +410,29 @@ func isAlreadyRevoked(err error) bool {
e, ok := err.(*Error) e, ok := err.(*Error)
return ok && e.ProblemType == "urn:ietf:params:acme:error:alreadyRevoked" return ok && e.ProblemType == "urn:ietf:params:acme:error:alreadyRevoked"
} }
// ListCertAlternates retrieves any alternate certificate chain URLs for the
// given certificate chain URL. These alternate URLs can be passed to FetchCert
// in order to retrieve the alternate certificate chains.
//
// If there are no alternate issuer certificate chains, a nil slice will be
// returned.
func (c *Client) ListCertAlternates(ctx context.Context, url string) ([]string, error) {
if _, err := c.Discover(ctx); err != nil { // required by c.accountKID
return nil, err
}
res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK))
if err != nil {
return nil, err
}
defer res.Body.Close()
// We don't need the body but we need to discard it so we don't end up
// preventing keep-alive
if _, err := io.Copy(ioutil.Discard, res.Body); err != nil {
return nil, fmt.Errorf("acme: cert alternates response stream: %v", err)
}
alts := linkHeader(res.Header, "alternate")
return alts, nil
}

View File

@ -16,6 +16,12 @@ import (
// ClientConnPool manages a pool of HTTP/2 client connections. // ClientConnPool manages a pool of HTTP/2 client connections.
type ClientConnPool interface { type ClientConnPool interface {
// GetClientConn returns a specific HTTP/2 connection (usually
// a TLS-TCP connection) to an HTTP/2 server. On success, the
// returned ClientConn accounts for the upcoming RoundTrip
// call, so the caller should not omit it. If the caller needs
// to, ClientConn.RoundTrip can be called with a bogus
// new(http.Request) to release the stream reservation.
GetClientConn(req *http.Request, addr string) (*ClientConn, error) GetClientConn(req *http.Request, addr string) (*ClientConn, error)
MarkDead(*ClientConn) MarkDead(*ClientConn)
} }
@ -42,7 +48,7 @@ type clientConnPool struct {
conns map[string][]*ClientConn // key is host:port conns map[string][]*ClientConn // key is host:port
dialing map[string]*dialCall // currently in-flight dials dialing map[string]*dialCall // currently in-flight dials
keys map[*ClientConn][]string keys map[*ClientConn][]string
addConnCalls map[string]*addConnCall // in-flight addConnIfNeede calls addConnCalls map[string]*addConnCall // in-flight addConnIfNeeded calls
} }
func (p *clientConnPool) GetClientConn(req *http.Request, addr string) (*ClientConn, error) { func (p *clientConnPool) GetClientConn(req *http.Request, addr string) (*ClientConn, error) {
@ -54,28 +60,8 @@ const (
noDialOnMiss = false noDialOnMiss = false
) )
// shouldTraceGetConn reports whether getClientConn should call any
// ClientTrace.GetConn hook associated with the http.Request.
//
// This complexity is needed to avoid double calls of the GetConn hook
// during the back-and-forth between net/http and x/net/http2 (when the
// net/http.Transport is upgraded to also speak http2), as well as support
// the case where x/net/http2 is being used directly.
func (p *clientConnPool) shouldTraceGetConn(st clientConnIdleState) bool {
// If our Transport wasn't made via ConfigureTransport, always
// trace the GetConn hook if provided, because that means the
// http2 package is being used directly and it's the one
// dialing, as opposed to net/http.
if _, ok := p.t.ConnPool.(noDialClientConnPool); !ok {
return true
}
// Otherwise, only use the GetConn hook if this connection has
// been used previously for other requests. For fresh
// connections, the net/http package does the dialing.
return !st.freshConn
}
func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMiss bool) (*ClientConn, error) { func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMiss bool) (*ClientConn, error) {
// TODO(dneil): Dial a new connection when t.DisableKeepAlives is set?
if isConnectionCloseRequest(req) && dialOnMiss { if isConnectionCloseRequest(req) && dialOnMiss {
// It gets its own connection. // It gets its own connection.
traceGetConn(req, addr) traceGetConn(req, addr)
@ -89,10 +75,14 @@ func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMis
for { for {
p.mu.Lock() p.mu.Lock()
for _, cc := range p.conns[addr] { for _, cc := range p.conns[addr] {
if st := cc.idleState(); st.canTakeNewRequest { if cc.ReserveNewRequest() {
if p.shouldTraceGetConn(st) { // When a connection is presented to us by the net/http package,
// the GetConn hook has already been called.
// Don't call it a second time here.
if !cc.getConnCalled {
traceGetConn(req, addr) traceGetConn(req, addr)
} }
cc.getConnCalled = false
p.mu.Unlock() p.mu.Unlock()
return cc, nil return cc, nil
} }
@ -108,7 +98,13 @@ func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMis
if shouldRetryDial(call, req) { if shouldRetryDial(call, req) {
continue continue
} }
return call.res, call.err cc, err := call.res, call.err
if err != nil {
return nil, err
}
if cc.ReserveNewRequest() {
return cc, nil
}
} }
} }
@ -205,6 +201,7 @@ func (c *addConnCall) run(t *Transport, key string, tc *tls.Conn) {
if err != nil { if err != nil {
c.err = err c.err = err
} else { } else {
cc.getConnCalled = true // already called by the net/http package
p.addConnLocked(key, cc) p.addConnLocked(key, cc)
} }
delete(p.addConnCalls, key) delete(p.addConnCalls, key)

View File

@ -53,6 +53,13 @@ func (e ErrCode) String() string {
return fmt.Sprintf("unknown error code 0x%x", uint32(e)) return fmt.Sprintf("unknown error code 0x%x", uint32(e))
} }
func (e ErrCode) stringToken() string {
if s, ok := errCodeName[e]; ok {
return s
}
return fmt.Sprintf("ERR_UNKNOWN_%d", uint32(e))
}
// ConnectionError is an error that results in the termination of the // ConnectionError is an error that results in the termination of the
// entire connection. // entire connection.
type ConnectionError ErrCode type ConnectionError ErrCode

View File

@ -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(fc *frameCache, fh FrameHeader, payload []byte) (Frame, error) type frameParser func(fc *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error)
var frameParsers = map[FrameType]frameParser{ var frameParsers = map[FrameType]frameParser{
FrameData: parseDataFrame, FrameData: parseDataFrame,
@ -267,6 +267,11 @@ type Framer struct {
lastFrame Frame lastFrame Frame
errDetail error errDetail error
// countError is a non-nil func that's called on a frame parse
// error with some unique error path token. It's initialized
// from Transport.CountError or Server.CountError.
countError func(errToken string)
// lastHeaderStream is non-zero if the last frame was an // lastHeaderStream is non-zero if the last frame was an
// unfinished HEADERS/CONTINUATION. // unfinished HEADERS/CONTINUATION.
lastHeaderStream uint32 lastHeaderStream uint32
@ -426,6 +431,7 @@ func NewFramer(w io.Writer, r io.Reader) *Framer {
fr := &Framer{ fr := &Framer{
w: w, w: w,
r: r, r: r,
countError: func(string) {},
logReads: logFrameReads, logReads: logFrameReads,
logWrites: logFrameWrites, logWrites: logFrameWrites,
debugReadLoggerf: log.Printf, debugReadLoggerf: log.Printf,
@ -500,7 +506,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)(fr.frameCache, fh, payload) f, err := typeFrameParser(fh.Type)(fr.frameCache, fh, fr.countError, 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)
@ -588,13 +594,14 @@ func (f *DataFrame) Data() []byte {
return f.data return f.data
} }
func parseDataFrame(fc *frameCache, fh FrameHeader, payload []byte) (Frame, error) { func parseDataFrame(fc *frameCache, fh FrameHeader, countError func(string), 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
// field is 0x0, the recipient MUST respond with a // field is 0x0, the recipient MUST respond with a
// connection error (Section 5.4.1) of type // connection error (Section 5.4.1) of type
// PROTOCOL_ERROR. // PROTOCOL_ERROR.
countError("frame_data_stream_0")
return nil, connError{ErrCodeProtocol, "DATA frame with stream ID 0"} return nil, connError{ErrCodeProtocol, "DATA frame with stream ID 0"}
} }
f := fc.getDataFrame() f := fc.getDataFrame()
@ -605,6 +612,7 @@ func parseDataFrame(fc *frameCache, fh FrameHeader, payload []byte) (Frame, erro
var err error var err error
payload, padSize, err = readByte(payload) payload, padSize, err = readByte(payload)
if err != nil { if err != nil {
countError("frame_data_pad_byte_short")
return nil, err return nil, err
} }
} }
@ -613,6 +621,7 @@ func parseDataFrame(fc *frameCache, fh FrameHeader, payload []byte) (Frame, erro
// length of the frame payload, the recipient MUST // length of the frame payload, the recipient MUST
// treat this as a connection error. // treat this as a connection error.
// Filed: https://github.com/http2/http2-spec/issues/610 // Filed: https://github.com/http2/http2-spec/issues/610
countError("frame_data_pad_too_big")
return nil, connError{ErrCodeProtocol, "pad size larger than data payload"} return nil, connError{ErrCodeProtocol, "pad size larger than data payload"}
} }
f.data = payload[:len(payload)-int(padSize)] f.data = payload[:len(payload)-int(padSize)]
@ -695,7 +704,7 @@ type SettingsFrame struct {
p []byte p []byte
} }
func parseSettingsFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) { func parseSettingsFrame(_ *frameCache, fh FrameHeader, countError func(string), 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
@ -703,6 +712,7 @@ func parseSettingsFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error)
// 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
// FRAME_SIZE_ERROR. // FRAME_SIZE_ERROR.
countError("frame_settings_ack_with_length")
return nil, ConnectionError(ErrCodeFrameSize) return nil, ConnectionError(ErrCodeFrameSize)
} }
if fh.StreamID != 0 { if fh.StreamID != 0 {
@ -713,14 +723,17 @@ func parseSettingsFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error)
// field is anything other than 0x0, the endpoint MUST // field is anything other than 0x0, the endpoint MUST
// respond with a connection error (Section 5.4.1) of // respond with a connection error (Section 5.4.1) of
// type PROTOCOL_ERROR. // type PROTOCOL_ERROR.
countError("frame_settings_has_stream")
return nil, ConnectionError(ErrCodeProtocol) return nil, ConnectionError(ErrCodeProtocol)
} }
if len(p)%6 != 0 { if len(p)%6 != 0 {
countError("frame_settings_mod_6")
// Expecting even number of 6 byte settings. // Expecting even number of 6 byte settings.
return nil, ConnectionError(ErrCodeFrameSize) return nil, ConnectionError(ErrCodeFrameSize)
} }
f := &SettingsFrame{FrameHeader: fh, p: p} f := &SettingsFrame{FrameHeader: fh, p: p}
if v, ok := f.Value(SettingInitialWindowSize); ok && v > (1<<31)-1 { if v, ok := f.Value(SettingInitialWindowSize); ok && v > (1<<31)-1 {
countError("frame_settings_window_size_too_big")
// Values above the maximum flow control window size of 2^31 - 1 MUST // Values above the maximum flow control window size of 2^31 - 1 MUST
// be treated as a connection error (Section 5.4.1) of type // be treated as a connection error (Section 5.4.1) of type
// FLOW_CONTROL_ERROR. // FLOW_CONTROL_ERROR.
@ -832,11 +845,13 @@ 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(_ *frameCache, fh FrameHeader, payload []byte) (Frame, error) { func parsePingFrame(_ *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error) {
if len(payload) != 8 { if len(payload) != 8 {
countError("frame_ping_length")
return nil, ConnectionError(ErrCodeFrameSize) return nil, ConnectionError(ErrCodeFrameSize)
} }
if fh.StreamID != 0 { if fh.StreamID != 0 {
countError("frame_ping_has_stream")
return nil, ConnectionError(ErrCodeProtocol) return nil, ConnectionError(ErrCodeProtocol)
} }
f := &PingFrame{FrameHeader: fh} f := &PingFrame{FrameHeader: fh}
@ -872,11 +887,13 @@ func (f *GoAwayFrame) DebugData() []byte {
return f.debugData return f.debugData
} }
func parseGoAwayFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) { func parseGoAwayFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
if fh.StreamID != 0 { if fh.StreamID != 0 {
countError("frame_goaway_has_stream")
return nil, ConnectionError(ErrCodeProtocol) return nil, ConnectionError(ErrCodeProtocol)
} }
if len(p) < 8 { if len(p) < 8 {
countError("frame_goaway_short")
return nil, ConnectionError(ErrCodeFrameSize) return nil, ConnectionError(ErrCodeFrameSize)
} }
return &GoAwayFrame{ return &GoAwayFrame{
@ -912,7 +929,7 @@ func (f *UnknownFrame) Payload() []byte {
return f.p return f.p
} }
func parseUnknownFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) { func parseUnknownFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
return &UnknownFrame{fh, p}, nil return &UnknownFrame{fh, p}, nil
} }
@ -923,8 +940,9 @@ type WindowUpdateFrame struct {
Increment uint32 // never read with high bit set Increment uint32 // never read with high bit set
} }
func parseWindowUpdateFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) { func parseWindowUpdateFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
if len(p) != 4 { if len(p) != 4 {
countError("frame_windowupdate_bad_len")
return nil, ConnectionError(ErrCodeFrameSize) return nil, ConnectionError(ErrCodeFrameSize)
} }
inc := binary.BigEndian.Uint32(p[:4]) & 0x7fffffff // mask off high reserved bit inc := binary.BigEndian.Uint32(p[:4]) & 0x7fffffff // mask off high reserved bit
@ -936,8 +954,10 @@ func parseWindowUpdateFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, err
// control window MUST be treated as a connection // control window MUST be treated as a connection
// error (Section 5.4.1). // error (Section 5.4.1).
if fh.StreamID == 0 { if fh.StreamID == 0 {
countError("frame_windowupdate_zero_inc_conn")
return nil, ConnectionError(ErrCodeProtocol) return nil, ConnectionError(ErrCodeProtocol)
} }
countError("frame_windowupdate_zero_inc_stream")
return nil, streamError(fh.StreamID, ErrCodeProtocol) return nil, streamError(fh.StreamID, ErrCodeProtocol)
} }
return &WindowUpdateFrame{ return &WindowUpdateFrame{
@ -988,7 +1008,7 @@ func (f *HeadersFrame) HasPriority() bool {
return f.FrameHeader.Flags.Has(FlagHeadersPriority) return f.FrameHeader.Flags.Has(FlagHeadersPriority)
} }
func parseHeadersFrame(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err error) { func parseHeadersFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (_ Frame, err error) {
hf := &HeadersFrame{ hf := &HeadersFrame{
FrameHeader: fh, FrameHeader: fh,
} }
@ -997,11 +1017,13 @@ func parseHeadersFrame(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err er
// 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.
countError("frame_headers_zero_stream")
return nil, connError{ErrCodeProtocol, "HEADERS frame with stream ID 0"} return nil, connError{ErrCodeProtocol, "HEADERS frame with stream ID 0"}
} }
var padLength uint8 var padLength uint8
if fh.Flags.Has(FlagHeadersPadded) { if fh.Flags.Has(FlagHeadersPadded) {
if p, padLength, err = readByte(p); err != nil { if p, padLength, err = readByte(p); err != nil {
countError("frame_headers_pad_short")
return return
} }
} }
@ -1009,16 +1031,19 @@ func parseHeadersFrame(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err er
var v uint32 var v uint32
p, v, err = readUint32(p) p, v, err = readUint32(p)
if err != nil { if err != nil {
countError("frame_headers_prio_short")
return nil, err return nil, err
} }
hf.Priority.StreamDep = v & 0x7fffffff hf.Priority.StreamDep = v & 0x7fffffff
hf.Priority.Exclusive = (v != hf.Priority.StreamDep) // high bit was set hf.Priority.Exclusive = (v != hf.Priority.StreamDep) // high bit was set
p, hf.Priority.Weight, err = readByte(p) p, hf.Priority.Weight, err = readByte(p)
if err != nil { if err != nil {
countError("frame_headers_prio_weight_short")
return nil, err return nil, err
} }
} }
if len(p)-int(padLength) < 0 { if len(p)-int(padLength) < 0 {
countError("frame_headers_pad_too_big")
return nil, streamError(fh.StreamID, ErrCodeProtocol) return nil, streamError(fh.StreamID, ErrCodeProtocol)
} }
hf.headerFragBuf = p[:len(p)-int(padLength)] hf.headerFragBuf = p[:len(p)-int(padLength)]
@ -1125,11 +1150,13 @@ func (p PriorityParam) IsZero() bool {
return p == PriorityParam{} return p == PriorityParam{}
} }
func parsePriorityFrame(_ *frameCache, fh FrameHeader, payload []byte) (Frame, error) { func parsePriorityFrame(_ *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error) {
if fh.StreamID == 0 { if fh.StreamID == 0 {
countError("frame_priority_zero_stream")
return nil, connError{ErrCodeProtocol, "PRIORITY frame with stream ID 0"} return nil, connError{ErrCodeProtocol, "PRIORITY frame with stream ID 0"}
} }
if len(payload) != 5 { if len(payload) != 5 {
countError("frame_priority_bad_length")
return nil, connError{ErrCodeFrameSize, fmt.Sprintf("PRIORITY frame payload size was %d; want 5", len(payload))} return nil, connError{ErrCodeFrameSize, fmt.Sprintf("PRIORITY frame payload size was %d; want 5", len(payload))}
} }
v := binary.BigEndian.Uint32(payload[:4]) v := binary.BigEndian.Uint32(payload[:4])
@ -1172,11 +1199,13 @@ type RSTStreamFrame struct {
ErrCode ErrCode ErrCode ErrCode
} }
func parseRSTStreamFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) { func parseRSTStreamFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
if len(p) != 4 { if len(p) != 4 {
countError("frame_rststream_bad_len")
return nil, ConnectionError(ErrCodeFrameSize) return nil, ConnectionError(ErrCodeFrameSize)
} }
if fh.StreamID == 0 { if fh.StreamID == 0 {
countError("frame_rststream_zero_stream")
return nil, ConnectionError(ErrCodeProtocol) return nil, ConnectionError(ErrCodeProtocol)
} }
return &RSTStreamFrame{fh, ErrCode(binary.BigEndian.Uint32(p[:4]))}, nil return &RSTStreamFrame{fh, ErrCode(binary.BigEndian.Uint32(p[:4]))}, nil
@ -1202,8 +1231,9 @@ type ContinuationFrame struct {
headerFragBuf []byte headerFragBuf []byte
} }
func parseContinuationFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) { func parseContinuationFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
if fh.StreamID == 0 { if fh.StreamID == 0 {
countError("frame_continuation_zero_stream")
return nil, connError{ErrCodeProtocol, "CONTINUATION frame with stream ID 0"} return nil, connError{ErrCodeProtocol, "CONTINUATION frame with stream ID 0"}
} }
return &ContinuationFrame{fh, p}, nil return &ContinuationFrame{fh, p}, nil
@ -1252,7 +1282,7 @@ func (f *PushPromiseFrame) HeadersEnded() bool {
return f.FrameHeader.Flags.Has(FlagPushPromiseEndHeaders) return f.FrameHeader.Flags.Has(FlagPushPromiseEndHeaders)
} }
func parsePushPromise(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err error) { func parsePushPromise(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (_ Frame, err error) {
pp := &PushPromiseFrame{ pp := &PushPromiseFrame{
FrameHeader: fh, FrameHeader: fh,
} }
@ -1263,6 +1293,7 @@ func parsePushPromise(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err err
// with. If the stream identifier field specifies the value // with. If the stream identifier field specifies the value
// 0x0, a recipient MUST respond with a connection error // 0x0, a recipient MUST respond with a connection error
// (Section 5.4.1) of type PROTOCOL_ERROR. // (Section 5.4.1) of type PROTOCOL_ERROR.
countError("frame_pushpromise_zero_stream")
return nil, ConnectionError(ErrCodeProtocol) return nil, ConnectionError(ErrCodeProtocol)
} }
// The PUSH_PROMISE frame includes optional padding. // The PUSH_PROMISE frame includes optional padding.
@ -1270,18 +1301,21 @@ func parsePushPromise(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err err
var padLength uint8 var padLength uint8
if fh.Flags.Has(FlagPushPromisePadded) { if fh.Flags.Has(FlagPushPromisePadded) {
if p, padLength, err = readByte(p); err != nil { if p, padLength, err = readByte(p); err != nil {
countError("frame_pushpromise_pad_short")
return return
} }
} }
p, pp.PromiseID, err = readUint32(p) p, pp.PromiseID, err = readUint32(p)
if err != nil { if err != nil {
countError("frame_pushpromise_promiseid_short")
return return
} }
pp.PromiseID = pp.PromiseID & (1<<31 - 1) pp.PromiseID = pp.PromiseID & (1<<31 - 1)
if int(padLength) > len(p) { if int(padLength) > len(p) {
// like the DATA frame, error out if padding is longer than the body. // like the DATA frame, error out if padding is longer than the body.
countError("frame_pushpromise_pad_too_big")
return nil, ConnectionError(ErrCodeProtocol) return nil, ConnectionError(ErrCodeProtocol)
} }
pp.headerFragBuf = p[:len(p)-int(padLength)] pp.headerFragBuf = p[:len(p)-int(padLength)]

View File

@ -140,12 +140,12 @@ func buildRootHuffmanNode() {
panic("unexpected size") panic("unexpected size")
} }
lazyRootHuffmanNode = newInternalNode() lazyRootHuffmanNode = newInternalNode()
for i, code := range huffmanCodes { // allocate a leaf node for each of the 256 symbols
addDecoderNode(byte(i), code, huffmanCodeLen[i]) leaves := new([256]node)
}
} for sym, code := range huffmanCodes {
codeLen := huffmanCodeLen[sym]
func addDecoderNode(sym byte, code uint32, codeLen uint8) {
cur := lazyRootHuffmanNode cur := lazyRootHuffmanNode
for codeLen > 8 { for codeLen > 8 {
codeLen -= 8 codeLen -= 8
@ -157,8 +157,12 @@ func addDecoderNode(sym byte, code uint32, codeLen uint8) {
} }
shift := 8 - codeLen shift := 8 - codeLen
start, end := int(uint8(code<<shift)), int(1<<shift) start, end := int(uint8(code<<shift)), int(1<<shift)
leaves[sym].sym = byte(sym)
leaves[sym].codeLen = codeLen
for i := start; i < start+end; i++ { for i := start; i < start+end; i++ {
cur.children[i] = &node{sym: sym, codeLen: codeLen} cur.children[i] = &leaves[sym]
}
} }
} }

View File

@ -30,6 +30,17 @@ type pipeBuffer interface {
io.Reader io.Reader
} }
// setBuffer initializes the pipe buffer.
// It has no effect if the pipe is already closed.
func (p *pipe) setBuffer(b pipeBuffer) {
p.mu.Lock()
defer p.mu.Unlock()
if p.err != nil || p.breakErr != nil {
return
}
p.b = b
}
func (p *pipe) Len() int { func (p *pipe) Len() int {
p.mu.Lock() p.mu.Lock()
defer p.mu.Unlock() defer p.mu.Unlock()

View File

@ -130,6 +130,12 @@ type Server struct {
// If nil, a default scheduler is chosen. // If nil, a default scheduler is chosen.
NewWriteScheduler func() WriteScheduler NewWriteScheduler func() WriteScheduler
// CountError, if non-nil, is called on HTTP/2 server errors.
// It's intended to increment a metric for monitoring, such
// as an expvar or Prometheus metric.
// The errType consists of only ASCII word characters.
CountError func(errType string)
// Internal state. This is a pointer (rather than embedded directly) // Internal state. This is a pointer (rather than embedded directly)
// so that we don't embed a Mutex in this struct, which will make the // so that we don't embed a Mutex in this struct, which will make the
// struct non-copyable, which might break some callers. // struct non-copyable, which might break some callers.
@ -405,6 +411,9 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf) sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
fr := NewFramer(sc.bw, c) fr := NewFramer(sc.bw, c)
if s.CountError != nil {
fr.countError = s.CountError
}
fr.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil) fr.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil)
fr.MaxHeaderListSize = sc.maxHeaderListSize() fr.MaxHeaderListSize = sc.maxHeaderListSize()
fr.SetMaxReadFrameSize(s.maxReadFrameSize()) fr.SetMaxReadFrameSize(s.maxReadFrameSize())
@ -710,7 +719,15 @@ func (sc *serverConn) canonicalHeader(v string) string {
sc.canonHeader = make(map[string]string) sc.canonHeader = make(map[string]string)
} }
cv = http.CanonicalHeaderKey(v) cv = http.CanonicalHeaderKey(v)
// maxCachedCanonicalHeaders is an arbitrarily-chosen limit on the number of
// entries in the canonHeader cache. This should be larger than the number
// of unique, uncommon header keys likely to be sent by the peer, while not
// so high as to permit unreaasonable memory usage if the peer sends an unbounded
// number of unique header keys.
const maxCachedCanonicalHeaders = 32
if len(sc.canonHeader) < maxCachedCanonicalHeaders {
sc.canonHeader[v] = cv sc.canonHeader[v] = cv
}
return cv return cv
} }
@ -1399,7 +1416,7 @@ func (sc *serverConn) processFrame(f Frame) error {
// First frame received must be SETTINGS. // First frame received must be SETTINGS.
if !sc.sawFirstSettings { if !sc.sawFirstSettings {
if _, ok := f.(*SettingsFrame); !ok { if _, ok := f.(*SettingsFrame); !ok {
return ConnectionError(ErrCodeProtocol) return sc.countError("first_settings", ConnectionError(ErrCodeProtocol))
} }
sc.sawFirstSettings = true sc.sawFirstSettings = true
} }
@ -1424,7 +1441,7 @@ func (sc *serverConn) processFrame(f Frame) error {
case *PushPromiseFrame: case *PushPromiseFrame:
// A client cannot push. Thus, servers MUST treat the receipt of a PUSH_PROMISE // A client cannot push. Thus, servers MUST treat the receipt of a PUSH_PROMISE
// frame as a connection error (Section 5.4.1) of type PROTOCOL_ERROR. // frame as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
return ConnectionError(ErrCodeProtocol) return sc.countError("push_promise", ConnectionError(ErrCodeProtocol))
default: default:
sc.vlogf("http2: server ignoring frame: %v", f.Header()) sc.vlogf("http2: server ignoring frame: %v", f.Header())
return nil return nil
@ -1444,7 +1461,7 @@ func (sc *serverConn) processPing(f *PingFrame) error {
// identifier field value other than 0x0, the recipient MUST // identifier field value other than 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."
return ConnectionError(ErrCodeProtocol) return sc.countError("ping_on_stream", ConnectionError(ErrCodeProtocol))
} }
if sc.inGoAway && sc.goAwayCode != ErrCodeNo { if sc.inGoAway && sc.goAwayCode != ErrCodeNo {
return nil return nil
@ -1463,7 +1480,7 @@ func (sc *serverConn) processWindowUpdate(f *WindowUpdateFrame) error {
// or PRIORITY on a stream in this state MUST be // or PRIORITY on a stream in this state MUST be
// treated as a connection error (Section 5.4.1) of // treated as a connection error (Section 5.4.1) of
// type PROTOCOL_ERROR." // type PROTOCOL_ERROR."
return ConnectionError(ErrCodeProtocol) return sc.countError("stream_idle", ConnectionError(ErrCodeProtocol))
} }
if st == nil { if st == nil {
// "WINDOW_UPDATE can be sent by a peer that has sent a // "WINDOW_UPDATE can be sent by a peer that has sent a
@ -1474,7 +1491,7 @@ func (sc *serverConn) processWindowUpdate(f *WindowUpdateFrame) error {
return nil return nil
} }
if !st.flow.add(int32(f.Increment)) { if !st.flow.add(int32(f.Increment)) {
return streamError(f.StreamID, ErrCodeFlowControl) return sc.countError("bad_flow", streamError(f.StreamID, ErrCodeFlowControl))
} }
default: // connection-level flow control default: // connection-level flow control
if !sc.flow.add(int32(f.Increment)) { if !sc.flow.add(int32(f.Increment)) {
@ -1495,7 +1512,7 @@ func (sc *serverConn) processResetStream(f *RSTStreamFrame) error {
// identifying an idle stream is received, the // identifying an idle stream is received, the
// recipient MUST treat this as a connection error // recipient MUST treat this as a connection error
// (Section 5.4.1) of type PROTOCOL_ERROR. // (Section 5.4.1) of type PROTOCOL_ERROR.
return ConnectionError(ErrCodeProtocol) return sc.countError("reset_idle_stream", ConnectionError(ErrCodeProtocol))
} }
if st != nil { if st != nil {
st.cancelCtx() st.cancelCtx()
@ -1547,7 +1564,7 @@ func (sc *serverConn) processSettings(f *SettingsFrame) error {
// Why is the peer ACKing settings we never sent? // Why is the peer ACKing settings we never sent?
// The spec doesn't mention this case, but // The spec doesn't mention this case, but
// hang up on them anyway. // hang up on them anyway.
return ConnectionError(ErrCodeProtocol) return sc.countError("ack_mystery", ConnectionError(ErrCodeProtocol))
} }
return nil return nil
} }
@ -1555,7 +1572,7 @@ func (sc *serverConn) processSettings(f *SettingsFrame) error {
// This isn't actually in the spec, but hang up on // This isn't actually in the spec, but hang up on
// suspiciously large settings frames or those with // suspiciously large settings frames or those with
// duplicate entries. // duplicate entries.
return ConnectionError(ErrCodeProtocol) return sc.countError("settings_big_or_dups", ConnectionError(ErrCodeProtocol))
} }
if err := f.ForeachSetting(sc.processSetting); err != nil { if err := f.ForeachSetting(sc.processSetting); err != nil {
return err return err
@ -1622,7 +1639,7 @@ func (sc *serverConn) processSettingInitialWindowSize(val uint32) error {
// control window to exceed the maximum size as a // control window to exceed the maximum size as a
// connection error (Section 5.4.1) of type // connection error (Section 5.4.1) of type
// FLOW_CONTROL_ERROR." // FLOW_CONTROL_ERROR."
return ConnectionError(ErrCodeFlowControl) return sc.countError("setting_win_size", ConnectionError(ErrCodeFlowControl))
} }
} }
return nil return nil
@ -1655,7 +1672,7 @@ func (sc *serverConn) processData(f *DataFrame) error {
// or PRIORITY on a stream in this state MUST be // or PRIORITY on a stream in this state MUST be
// treated as a connection error (Section 5.4.1) of // treated as a connection error (Section 5.4.1) of
// type PROTOCOL_ERROR." // type PROTOCOL_ERROR."
return ConnectionError(ErrCodeProtocol) return sc.countError("data_on_idle", ConnectionError(ErrCodeProtocol))
} }
// "If a DATA frame is received whose stream is not in "open" // "If a DATA frame is received whose stream is not in "open"
@ -1672,7 +1689,7 @@ func (sc *serverConn) processData(f *DataFrame) error {
// and return any flow control bytes since we're not going // and return any flow control bytes since we're not going
// to consume them. // to consume them.
if sc.inflow.available() < int32(f.Length) { if sc.inflow.available() < int32(f.Length) {
return streamError(id, ErrCodeFlowControl) return sc.countError("data_flow", streamError(id, ErrCodeFlowControl))
} }
// Deduct the flow control from inflow, since we're // Deduct the flow control from inflow, since we're
// going to immediately add it back in // going to immediately add it back in
@ -1685,7 +1702,7 @@ func (sc *serverConn) processData(f *DataFrame) error {
// Already have a stream error in flight. Don't send another. // Already have a stream error in flight. Don't send another.
return nil return nil
} }
return streamError(id, ErrCodeStreamClosed) return sc.countError("closed", streamError(id, ErrCodeStreamClosed))
} }
if st.body == nil { if st.body == nil {
panic("internal error: should have a body in this state") panic("internal error: should have a body in this state")
@ -1697,12 +1714,12 @@ func (sc *serverConn) processData(f *DataFrame) error {
// RFC 7540, sec 8.1.2.6: A request or response is also malformed if the // RFC 7540, sec 8.1.2.6: A request or response is also malformed if the
// value of a content-length header field does not equal the sum of the // value of a content-length header field does not equal the sum of the
// DATA frame payload lengths that form the body. // DATA frame payload lengths that form the body.
return streamError(id, ErrCodeProtocol) return sc.countError("send_too_much", streamError(id, ErrCodeProtocol))
} }
if f.Length > 0 { if f.Length > 0 {
// Check whether the client has flow control quota. // Check whether the client has flow control quota.
if st.inflow.available() < int32(f.Length) { if st.inflow.available() < int32(f.Length) {
return streamError(id, ErrCodeFlowControl) return sc.countError("flow_on_data_length", streamError(id, ErrCodeFlowControl))
} }
st.inflow.take(int32(f.Length)) st.inflow.take(int32(f.Length))
@ -1710,7 +1727,7 @@ func (sc *serverConn) processData(f *DataFrame) error {
wrote, err := st.body.Write(data) wrote, err := st.body.Write(data)
if err != nil { if err != nil {
sc.sendWindowUpdate(nil, int(f.Length)-wrote) sc.sendWindowUpdate(nil, int(f.Length)-wrote)
return streamError(id, ErrCodeStreamClosed) return sc.countError("body_write_err", streamError(id, ErrCodeStreamClosed))
} }
if wrote != len(data) { if wrote != len(data) {
panic("internal error: bad Writer") panic("internal error: bad Writer")
@ -1796,7 +1813,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
// stream identifier MUST respond with a connection error // stream identifier MUST respond with a connection error
// (Section 5.4.1) of type PROTOCOL_ERROR. // (Section 5.4.1) of type PROTOCOL_ERROR.
if id%2 != 1 { if id%2 != 1 {
return ConnectionError(ErrCodeProtocol) return sc.countError("headers_even", ConnectionError(ErrCodeProtocol))
} }
// A HEADERS frame can be used to create a new stream or // A HEADERS frame can be used to create a new stream or
// send a trailer for an open one. If we already have a stream // send a trailer for an open one. If we already have a stream
@ -1813,7 +1830,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
// this state, it MUST respond with a stream error (Section 5.4.2) of // this state, it MUST respond with a stream error (Section 5.4.2) of
// type STREAM_CLOSED. // type STREAM_CLOSED.
if st.state == stateHalfClosedRemote { if st.state == stateHalfClosedRemote {
return streamError(id, ErrCodeStreamClosed) return sc.countError("headers_half_closed", streamError(id, ErrCodeStreamClosed))
} }
return st.processTrailerHeaders(f) return st.processTrailerHeaders(f)
} }
@ -1824,7 +1841,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
// receives an unexpected stream identifier MUST respond with // receives an unexpected stream identifier MUST respond with
// a connection error (Section 5.4.1) of type PROTOCOL_ERROR. // a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
if id <= sc.maxClientStreamID { if id <= sc.maxClientStreamID {
return ConnectionError(ErrCodeProtocol) return sc.countError("stream_went_down", ConnectionError(ErrCodeProtocol))
} }
sc.maxClientStreamID = id sc.maxClientStreamID = id
@ -1841,14 +1858,14 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
if sc.curClientStreams+1 > sc.advMaxStreams { if sc.curClientStreams+1 > sc.advMaxStreams {
if sc.unackedSettings == 0 { if sc.unackedSettings == 0 {
// They should know better. // They should know better.
return streamError(id, ErrCodeProtocol) return sc.countError("over_max_streams", streamError(id, ErrCodeProtocol))
} }
// Assume it's a network race, where they just haven't // Assume it's a network race, where they just haven't
// received our last SETTINGS update. But actually // received our last SETTINGS update. But actually
// this can't happen yet, because we don't yet provide // this can't happen yet, because we don't yet provide
// a way for users to adjust server parameters at // a way for users to adjust server parameters at
// runtime. // runtime.
return streamError(id, ErrCodeRefusedStream) return sc.countError("over_max_streams_race", streamError(id, ErrCodeRefusedStream))
} }
initialState := stateOpen initialState := stateOpen
@ -1858,7 +1875,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
st := sc.newStream(id, 0, initialState) st := sc.newStream(id, 0, initialState)
if f.HasPriority() { if f.HasPriority() {
if err := checkPriority(f.StreamID, f.Priority); err != nil { if err := sc.checkPriority(f.StreamID, f.Priority); err != nil {
return err return err
} }
sc.writeSched.AdjustStream(st.id, f.Priority) sc.writeSched.AdjustStream(st.id, f.Priority)
@ -1902,15 +1919,15 @@ func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
sc := st.sc sc := st.sc
sc.serveG.check() sc.serveG.check()
if st.gotTrailerHeader { if st.gotTrailerHeader {
return ConnectionError(ErrCodeProtocol) return sc.countError("dup_trailers", ConnectionError(ErrCodeProtocol))
} }
st.gotTrailerHeader = true st.gotTrailerHeader = true
if !f.StreamEnded() { if !f.StreamEnded() {
return streamError(st.id, ErrCodeProtocol) return sc.countError("trailers_not_ended", streamError(st.id, ErrCodeProtocol))
} }
if len(f.PseudoFields()) > 0 { if len(f.PseudoFields()) > 0 {
return streamError(st.id, ErrCodeProtocol) return sc.countError("trailers_pseudo", streamError(st.id, ErrCodeProtocol))
} }
if st.trailer != nil { if st.trailer != nil {
for _, hf := range f.RegularFields() { for _, hf := range f.RegularFields() {
@ -1919,7 +1936,7 @@ func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
// TODO: send more details to the peer somehow. But http2 has // TODO: send more details to the peer somehow. But http2 has
// no way to send debug data at a stream level. Discuss with // no way to send debug data at a stream level. Discuss with
// HTTP folk. // HTTP folk.
return streamError(st.id, ErrCodeProtocol) return sc.countError("trailers_bogus", streamError(st.id, ErrCodeProtocol))
} }
st.trailer[key] = append(st.trailer[key], hf.Value) st.trailer[key] = append(st.trailer[key], hf.Value)
} }
@ -1928,13 +1945,13 @@ func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
return nil return nil
} }
func checkPriority(streamID uint32, p PriorityParam) error { func (sc *serverConn) checkPriority(streamID uint32, p PriorityParam) error {
if streamID == p.StreamDep { if streamID == p.StreamDep {
// Section 5.3.1: "A stream cannot depend on itself. An endpoint MUST treat // Section 5.3.1: "A stream cannot depend on itself. An endpoint MUST treat
// this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR." // this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR."
// Section 5.3.3 says that a stream can depend on one of its dependencies, // Section 5.3.3 says that a stream can depend on one of its dependencies,
// so it's only self-dependencies that are forbidden. // so it's only self-dependencies that are forbidden.
return streamError(streamID, ErrCodeProtocol) return sc.countError("priority", streamError(streamID, ErrCodeProtocol))
} }
return nil return nil
} }
@ -1943,7 +1960,7 @@ func (sc *serverConn) processPriority(f *PriorityFrame) error {
if sc.inGoAway { if sc.inGoAway {
return nil return nil
} }
if err := checkPriority(f.StreamID, f.PriorityParam); err != nil { if err := sc.checkPriority(f.StreamID, f.PriorityParam); err != nil {
return err return err
} }
sc.writeSched.AdjustStream(f.StreamID, f.PriorityParam) sc.writeSched.AdjustStream(f.StreamID, f.PriorityParam)
@ -2000,7 +2017,7 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
isConnect := rp.method == "CONNECT" isConnect := rp.method == "CONNECT"
if isConnect { if isConnect {
if rp.path != "" || rp.scheme != "" || rp.authority == "" { if rp.path != "" || rp.scheme != "" || rp.authority == "" {
return nil, nil, streamError(f.StreamID, ErrCodeProtocol) return nil, nil, sc.countError("bad_connect", streamError(f.StreamID, ErrCodeProtocol))
} }
} else if rp.method == "" || rp.path == "" || (rp.scheme != "https" && rp.scheme != "http") { } else if rp.method == "" || rp.path == "" || (rp.scheme != "https" && rp.scheme != "http") {
// See 8.1.2.6 Malformed Requests and Responses: // See 8.1.2.6 Malformed Requests and Responses:
@ -2013,13 +2030,13 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
// "All HTTP/2 requests MUST include exactly one valid // "All HTTP/2 requests MUST include exactly one valid
// value for the :method, :scheme, and :path // value for the :method, :scheme, and :path
// pseudo-header fields" // pseudo-header fields"
return nil, nil, streamError(f.StreamID, ErrCodeProtocol) return nil, nil, sc.countError("bad_path_method", streamError(f.StreamID, ErrCodeProtocol))
} }
bodyOpen := !f.StreamEnded() bodyOpen := !f.StreamEnded()
if rp.method == "HEAD" && bodyOpen { if rp.method == "HEAD" && bodyOpen {
// HEAD requests can't have bodies // HEAD requests can't have bodies
return nil, nil, streamError(f.StreamID, ErrCodeProtocol) return nil, nil, sc.countError("head_body", streamError(f.StreamID, ErrCodeProtocol))
} }
rp.header = make(http.Header) rp.header = make(http.Header)
@ -2102,7 +2119,7 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r
var err error var err error
url_, err = url.ParseRequestURI(rp.path) url_, err = url.ParseRequestURI(rp.path)
if err != nil { if err != nil {
return nil, nil, streamError(st.id, ErrCodeProtocol) return nil, nil, sc.countError("bad_path", streamError(st.id, ErrCodeProtocol))
} }
requestURI = rp.path requestURI = rp.path
} }
@ -2985,3 +3002,31 @@ func h1ServerKeepAlivesDisabled(hs *http.Server) bool {
} }
return false return false
} }
func (sc *serverConn) countError(name string, err error) error {
if sc == nil || sc.srv == nil {
return err
}
f := sc.srv.CountError
if f == nil {
return err
}
var typ string
var code ErrCode
switch e := err.(type) {
case ConnectionError:
typ = "conn"
code = ErrCode(e)
case StreamError:
typ = "stream"
code = ErrCode(e.Code)
default:
return err
}
codeStr := errCodeName[code]
if codeStr == "" {
codeStr = strconv.Itoa(int(code))
}
f(fmt.Sprintf("%s_%s_%s", typ, codeStr, name))
return err
}

File diff suppressed because it is too large Load Diff

View File

@ -32,7 +32,8 @@ type WriteScheduler interface {
// Pop dequeues the next frame to write. Returns false if no frames can // Pop dequeues the next frame to write. Returns false if no frames can
// be written. Frames with a given wr.StreamID() are Pop'd in the same // be written. Frames with a given wr.StreamID() are Pop'd in the same
// order they are Push'd. No frames should be discarded except by CloseStream. // order they are Push'd, except RST_STREAM frames. No frames should be
// discarded except by CloseStream.
Pop() (wr FrameWriteRequest, ok bool) Pop() (wr FrameWriteRequest, ok bool)
} }
@ -52,6 +53,7 @@ type FrameWriteRequest struct {
// stream is the stream on which this frame will be written. // stream is the stream on which this frame will be written.
// nil for non-stream frames like PING and SETTINGS. // nil for non-stream frames like PING and SETTINGS.
// nil for RST_STREAM streams, which use the StreamError.StreamID field instead.
stream *stream stream *stream
// done, if non-nil, must be a buffered channel with space for // done, if non-nil, must be a buffered channel with space for

View File

@ -45,11 +45,11 @@ func (ws *randomWriteScheduler) AdjustStream(streamID uint32, priority PriorityP
} }
func (ws *randomWriteScheduler) Push(wr FrameWriteRequest) { func (ws *randomWriteScheduler) Push(wr FrameWriteRequest) {
id := wr.StreamID() if wr.isControl() {
if id == 0 {
ws.zero.push(wr) ws.zero.push(wr)
return return
} }
id := wr.StreamID()
q, ok := ws.sq[id] q, ok := ws.sq[id]
if !ok { if !ok {
q = ws.queuePool.get() q = ws.queuePool.get()
@ -59,7 +59,7 @@ func (ws *randomWriteScheduler) Push(wr FrameWriteRequest) {
} }
func (ws *randomWriteScheduler) Pop() (FrameWriteRequest, bool) { func (ws *randomWriteScheduler) Pop() (FrameWriteRequest, bool) {
// Control frames first. // Control and RST_STREAM frames first.
if !ws.zero.empty() { if !ws.zero.empty() {
return ws.zero.shift(), true return ws.zero.shift(), true
} }

14
vendor/golang.org/x/net/idna/go118.go generated vendored Normal file
View File

@ -0,0 +1,14 @@
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.18
// +build go1.18
package idna
// Transitional processing is disabled by default in Go 1.18.
// https://golang.org/issue/47510
const transitionalLookup = false

View File

@ -59,10 +59,10 @@ type Option func(*options)
// Transitional sets a Profile to use the Transitional mapping as defined in UTS // Transitional sets a Profile to use the Transitional mapping as defined in UTS
// #46. This will cause, for example, "ß" to be mapped to "ss". Using the // #46. This will cause, for example, "ß" to be mapped to "ss". Using the
// transitional mapping provides a compromise between IDNA2003 and IDNA2008 // transitional mapping provides a compromise between IDNA2003 and IDNA2008
// compatibility. It is used by most browsers when resolving domain names. This // compatibility. It is used by some browsers when resolving domain names. This
// option is only meaningful if combined with MapForLookup. // option is only meaningful if combined with MapForLookup.
func Transitional(transitional bool) Option { func Transitional(transitional bool) Option {
return func(o *options) { o.transitional = true } return func(o *options) { o.transitional = transitional }
} }
// VerifyDNSLength sets whether a Profile should fail if any of the IDN parts // VerifyDNSLength sets whether a Profile should fail if any of the IDN parts
@ -284,7 +284,7 @@ var (
punycode = &Profile{} punycode = &Profile{}
lookup = &Profile{options{ lookup = &Profile{options{
transitional: true, transitional: transitionalLookup,
useSTD3Rules: true, useSTD3Rules: true,
checkHyphens: true, checkHyphens: true,
checkJoiners: true, checkJoiners: true,

View File

@ -58,10 +58,10 @@ type Option func(*options)
// Transitional sets a Profile to use the Transitional mapping as defined in UTS // Transitional sets a Profile to use the Transitional mapping as defined in UTS
// #46. This will cause, for example, "ß" to be mapped to "ss". Using the // #46. This will cause, for example, "ß" to be mapped to "ss". Using the
// transitional mapping provides a compromise between IDNA2003 and IDNA2008 // transitional mapping provides a compromise between IDNA2003 and IDNA2008
// compatibility. It is used by most browsers when resolving domain names. This // compatibility. It is used by some browsers when resolving domain names. This
// option is only meaningful if combined with MapForLookup. // option is only meaningful if combined with MapForLookup.
func Transitional(transitional bool) Option { func Transitional(transitional bool) Option {
return func(o *options) { o.transitional = true } return func(o *options) { o.transitional = transitional }
} }
// VerifyDNSLength sets whether a Profile should fail if any of the IDN parts // VerifyDNSLength sets whether a Profile should fail if any of the IDN parts

12
vendor/golang.org/x/net/idna/pre_go118.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !go1.18
// +build !go1.18
package idna
const transitionalLookup = true

View File

@ -49,6 +49,7 @@ func decode(encoded string) (string, error) {
} }
} }
i, n, bias := int32(0), initialN, initialBias i, n, bias := int32(0), initialN, initialBias
overflow := false
for pos < len(encoded) { for pos < len(encoded) {
oldI, w := i, int32(1) oldI, w := i, int32(1)
for k := base; ; k += base { for k := base; ; k += base {
@ -60,29 +61,32 @@ func decode(encoded string) (string, error) {
return "", punyError(encoded) return "", punyError(encoded)
} }
pos++ pos++
i += digit * w i, overflow = madd(i, digit, w)
if i < 0 { if overflow {
return "", punyError(encoded) return "", punyError(encoded)
} }
t := k - bias t := k - bias
if t < tmin { if k <= bias {
t = tmin t = tmin
} else if t > tmax { } else if k >= bias+tmax {
t = tmax t = tmax
} }
if digit < t { if digit < t {
break break
} }
w *= base - t w, overflow = madd(0, w, base-t)
if w >= math.MaxInt32/base { if overflow {
return "", punyError(encoded) return "", punyError(encoded)
} }
} }
if len(output) >= 1024 {
return "", punyError(encoded)
}
x := int32(len(output) + 1) x := int32(len(output) + 1)
bias = adapt(i-oldI, x, oldI == 0) bias = adapt(i-oldI, x, oldI == 0)
n += i / x n += i / x
i %= x i %= x
if n > utf8.MaxRune || len(output) >= 1024 { if n < 0 || n > utf8.MaxRune {
return "", punyError(encoded) return "", punyError(encoded)
} }
output = append(output, 0) output = append(output, 0)
@ -115,6 +119,7 @@ func encode(prefix, s string) (string, error) {
if b > 0 { if b > 0 {
output = append(output, '-') output = append(output, '-')
} }
overflow := false
for remaining != 0 { for remaining != 0 {
m := int32(0x7fffffff) m := int32(0x7fffffff)
for _, r := range s { for _, r := range s {
@ -122,8 +127,8 @@ func encode(prefix, s string) (string, error) {
m = r m = r
} }
} }
delta += (m - n) * (h + 1) delta, overflow = madd(delta, m-n, h+1)
if delta < 0 { if overflow {
return "", punyError(s) return "", punyError(s)
} }
n = m n = m
@ -141,9 +146,9 @@ func encode(prefix, s string) (string, error) {
q := delta q := delta
for k := base; ; k += base { for k := base; ; k += base {
t := k - bias t := k - bias
if t < tmin { if k <= bias {
t = tmin t = tmin
} else if t > tmax { } else if k >= bias+tmax {
t = tmax t = tmax
} }
if q < t { if q < t {
@ -164,6 +169,15 @@ func encode(prefix, s string) (string, error) {
return string(output), nil return string(output), nil
} }
// madd computes a + (b * c), detecting overflow.
func madd(a, b, c int32) (next int32, overflow bool) {
p := int64(b) * int64(c)
if p > math.MaxInt32-int64(a) {
return 0, true
}
return a + int32(p), false
}
func decodeDigit(x byte) (digit int32, ok bool) { func decodeDigit(x byte) (digit int32, ok bool) {
switch { switch {
case '0' <= x && x <= '9': case '0' <= x && x <= '9':

View File

@ -149,7 +149,7 @@ To add a constant, add the header that includes it to the appropriate variable.
Then, edit the regex (if necessary) to match the desired constant. Avoid making Then, edit the regex (if necessary) to match the desired constant. Avoid making
the regex too broad to avoid matching unintended constants. the regex too broad to avoid matching unintended constants.
### mkmerge.go ### internal/mkmerge
This program is used to extract duplicate const, func, and type declarations This program is used to extract duplicate const, func, and type declarations
from the generated architecture-specific files listed below, and merge these from the generated architecture-specific files listed below, and merge these

View File

@ -50,7 +50,7 @@ if [[ "$GOOS" = "linux" ]]; then
# Use the Docker-based build system # Use the Docker-based build system
# Files generated through docker (use $cmd so you can Ctl-C the build or run) # Files generated through docker (use $cmd so you can Ctl-C the build or run)
$cmd docker build --tag generate:$GOOS $GOOS $cmd docker build --tag generate:$GOOS $GOOS
$cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")" && /bin/pwd):/build generate:$GOOS $cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")/.." && /bin/pwd):/build generate:$GOOS
exit exit
fi fi

View File

@ -54,7 +54,7 @@ includes_AIX='
includes_Darwin=' includes_Darwin='
#define _DARWIN_C_SOURCE #define _DARWIN_C_SOURCE
#define KERNEL #define KERNEL 1
#define _DARWIN_USE_64_BIT_INODE #define _DARWIN_USE_64_BIT_INODE
#define __APPLE_USE_RFC_3542 #define __APPLE_USE_RFC_3542
#include <stdint.h> #include <stdint.h>
@ -75,6 +75,7 @@ includes_Darwin='
#include <sys/utsname.h> #include <sys/utsname.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/xattr.h> #include <sys/xattr.h>
#include <sys/vsock.h>
#include <net/bpf.h> #include <net/bpf.h>
#include <net/if.h> #include <net/if.h>
#include <net/if_types.h> #include <net/if_types.h>
@ -82,6 +83,9 @@ includes_Darwin='
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/ip.h> #include <netinet/ip.h>
#include <termios.h> #include <termios.h>
// for backwards compatibility because moved TIOCREMOTE to Kernel.framework after MacOSX12.0.sdk.
#define TIOCREMOTE 0x80047469
' '
includes_DragonFly=' includes_DragonFly='
@ -235,6 +239,7 @@ struct ltchars {
#include <linux/magic.h> #include <linux/magic.h>
#include <linux/memfd.h> #include <linux/memfd.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mount.h>
#include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nfnetlink.h>
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/net_namespace.h> #include <linux/net_namespace.h>
@ -466,7 +471,6 @@ ccflags="$@"
$2 !~ /^EQUIV_/ && $2 !~ /^EQUIV_/ &&
$2 !~ /^EXPR_/ && $2 !~ /^EXPR_/ &&
$2 !~ /^EVIOC/ && $2 !~ /^EVIOC/ &&
$2 !~ /^EV_/ &&
$2 ~ /^E[A-Z0-9_]+$/ || $2 ~ /^E[A-Z0-9_]+$/ ||
$2 ~ /^B[0-9_]+$/ || $2 ~ /^B[0-9_]+$/ ||
$2 ~ /^(OLD|NEW)DEV$/ || $2 ~ /^(OLD|NEW)DEV$/ ||
@ -517,7 +521,7 @@ ccflags="$@"
$2 ~ /^HW_MACHINE$/ || $2 ~ /^HW_MACHINE$/ ||
$2 ~ /^SYSCTL_VERS/ || $2 ~ /^SYSCTL_VERS/ ||
$2 !~ "MNT_BITS" && $2 !~ "MNT_BITS" &&
$2 ~ /^(MS|MNT|UMOUNT)_/ || $2 ~ /^(MS|MNT|MOUNT|UMOUNT)_/ ||
$2 ~ /^NS_GET_/ || $2 ~ /^NS_GET_/ ||
$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ || $2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT|TFD)_/ || $2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT|TFD)_/ ||

View File

@ -34,3 +34,52 @@ func ParseUnixCredentials(m *SocketControlMessage) (*Ucred, error) {
ucred := *(*Ucred)(unsafe.Pointer(&m.Data[0])) ucred := *(*Ucred)(unsafe.Pointer(&m.Data[0]))
return &ucred, nil return &ucred, nil
} }
// PktInfo4 encodes Inet4Pktinfo into a socket control message of type IP_PKTINFO.
func PktInfo4(info *Inet4Pktinfo) []byte {
b := make([]byte, CmsgSpace(SizeofInet4Pktinfo))
h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
h.Level = SOL_IP
h.Type = IP_PKTINFO
h.SetLen(CmsgLen(SizeofInet4Pktinfo))
*(*Inet4Pktinfo)(h.data(0)) = *info
return b
}
// PktInfo6 encodes Inet6Pktinfo into a socket control message of type IPV6_PKTINFO.
func PktInfo6(info *Inet6Pktinfo) []byte {
b := make([]byte, CmsgSpace(SizeofInet6Pktinfo))
h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
h.Level = SOL_IPV6
h.Type = IPV6_PKTINFO
h.SetLen(CmsgLen(SizeofInet6Pktinfo))
*(*Inet6Pktinfo)(h.data(0)) = *info
return b
}
// ParseOrigDstAddr decodes a socket control message containing the original
// destination address. To receive such a message the IP_RECVORIGDSTADDR or
// IPV6_RECVORIGDSTADDR option must be enabled on the socket.
func ParseOrigDstAddr(m *SocketControlMessage) (Sockaddr, error) {
switch {
case m.Header.Level == SOL_IP && m.Header.Type == IP_ORIGDSTADDR:
pp := (*RawSockaddrInet4)(unsafe.Pointer(&m.Data[0]))
sa := new(SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
sa.Addr = pp.Addr
return sa, nil
case m.Header.Level == SOL_IPV6 && m.Header.Type == IPV6_ORIGDSTADDR:
pp := (*RawSockaddrInet6)(unsafe.Pointer(&m.Data[0]))
sa := new(SockaddrInet6)
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
sa.ZoneId = pp.Scope_id
sa.Addr = pp.Addr
return sa, nil
default:
return nil, EINVAL
}
}

View File

@ -70,9 +70,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
p[0] = byte(sa.Port >> 8) p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port) p[1] = byte(sa.Port)
for i := 0; i < len(sa.Addr); i++ { sa.raw.Addr = sa.Addr
sa.raw.Addr[i] = sa.Addr[i]
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
} }
@ -85,9 +83,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
p[0] = byte(sa.Port >> 8) p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port) p[1] = byte(sa.Port)
sa.raw.Scope_id = sa.ZoneId sa.raw.Scope_id = sa.ZoneId
for i := 0; i < len(sa.Addr); i++ { sa.raw.Addr = sa.Addr
sa.raw.Addr[i] = sa.Addr[i]
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
} }
@ -261,9 +257,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
sa := new(SockaddrInet4) sa := new(SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port)) p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1]) sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ { sa.Addr = pp.Addr
sa.Addr[i] = pp.Addr[i]
}
return sa, nil return sa, nil
case AF_INET6: case AF_INET6:
@ -272,9 +266,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
p := (*[2]byte)(unsafe.Pointer(&pp.Port)) p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1]) sa.Port = int(p[0])<<8 + int(p[1])
sa.ZoneId = pp.Scope_id sa.ZoneId = pp.Scope_id
for i := 0; i < len(sa.Addr); i++ { sa.Addr = pp.Addr
sa.Addr[i] = pp.Addr[i]
}
return sa, nil return sa, nil
} }
return nil, EAFNOSUPPORT return nil, EAFNOSUPPORT
@ -385,6 +377,11 @@ func (w WaitStatus) TrapCause() int { return -1 }
//sys fcntl(fd int, cmd int, arg int) (val int, err error) //sys fcntl(fd int, cmd int, arg int) (val int, err error)
//sys fsyncRange(fd int, how int, start int64, length int64) (err error) = fsync_range
func Fsync(fd int) error {
return fsyncRange(fd, O_SYNC, 0, 0)
}
/* /*
* Direct access * Direct access
*/ */
@ -401,7 +398,6 @@ func (w WaitStatus) TrapCause() int { return -1 }
//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) //sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
//sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) //sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
//sys Fdatasync(fd int) (err error) //sys Fdatasync(fd int) (err error)
//sys Fsync(fd int) (err error)
// readdir_r // readdir_r
//sysnb Getpgid(pid int) (pgid int, err error) //sysnb Getpgid(pid int) (pgid int, err error)
@ -523,8 +519,10 @@ func Pipe(p []int) (err error) {
} }
var pp [2]_C_int var pp [2]_C_int
err = pipe(&pp) err = pipe(&pp)
if err == nil {
p[0] = int(pp[0]) p[0] = int(pp[0])
p[1] = int(pp[1]) p[1] = int(pp[1])
}
return return
} }

View File

@ -163,9 +163,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
p[0] = byte(sa.Port >> 8) p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port) p[1] = byte(sa.Port)
for i := 0; i < len(sa.Addr); i++ { sa.raw.Addr = sa.Addr
sa.raw.Addr[i] = sa.Addr[i]
}
return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
} }
@ -179,9 +177,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
p[0] = byte(sa.Port >> 8) p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port) p[1] = byte(sa.Port)
sa.raw.Scope_id = sa.ZoneId sa.raw.Scope_id = sa.ZoneId
for i := 0; i < len(sa.Addr); i++ { sa.raw.Addr = sa.Addr
sa.raw.Addr[i] = sa.Addr[i]
}
return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
} }
@ -210,9 +206,7 @@ func (sa *SockaddrDatalink) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Nlen = sa.Nlen sa.raw.Nlen = sa.Nlen
sa.raw.Alen = sa.Alen sa.raw.Alen = sa.Alen
sa.raw.Slen = sa.Slen sa.raw.Slen = sa.Slen
for i := 0; i < len(sa.raw.Data); i++ { sa.raw.Data = sa.Data
sa.raw.Data[i] = sa.Data[i]
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrDatalink, nil return unsafe.Pointer(&sa.raw), SizeofSockaddrDatalink, nil
} }
@ -228,9 +222,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
sa.Nlen = pp.Nlen sa.Nlen = pp.Nlen
sa.Alen = pp.Alen sa.Alen = pp.Alen
sa.Slen = pp.Slen sa.Slen = pp.Slen
for i := 0; i < len(sa.Data); i++ { sa.Data = pp.Data
sa.Data[i] = pp.Data[i]
}
return sa, nil return sa, nil
case AF_UNIX: case AF_UNIX:
@ -262,9 +254,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
sa := new(SockaddrInet4) sa := new(SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port)) p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1]) sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ { sa.Addr = pp.Addr
sa.Addr[i] = pp.Addr[i]
}
return sa, nil return sa, nil
case AF_INET6: case AF_INET6:
@ -273,9 +263,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
p := (*[2]byte)(unsafe.Pointer(&pp.Port)) p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1]) sa.Port = int(p[0])<<8 + int(p[1])
sa.ZoneId = pp.Scope_id sa.ZoneId = pp.Scope_id
for i := 0; i < len(sa.Addr); i++ { sa.Addr = pp.Addr
sa.Addr[i] = pp.Addr[i]
}
return sa, nil return sa, nil
} }
return anyToSockaddrGOOS(fd, rsa) return anyToSockaddrGOOS(fd, rsa)

View File

@ -48,6 +48,30 @@ func (sa *SockaddrCtl) sockaddr() (unsafe.Pointer, _Socklen, error) {
return unsafe.Pointer(&sa.raw), SizeofSockaddrCtl, nil return unsafe.Pointer(&sa.raw), SizeofSockaddrCtl, nil
} }
// SockaddrVM implements the Sockaddr interface for AF_VSOCK type sockets.
// SockaddrVM provides access to Darwin VM sockets: a mechanism that enables
// bidirectional communication between a hypervisor and its guest virtual
// machines.
type SockaddrVM struct {
// CID and Port specify a context ID and port address for a VM socket.
// Guests have a unique CID, and hosts may have a well-known CID of:
// - VMADDR_CID_HYPERVISOR: refers to the hypervisor process.
// - VMADDR_CID_LOCAL: refers to local communication (loopback).
// - VMADDR_CID_HOST: refers to other processes on the host.
CID uint32
Port uint32
raw RawSockaddrVM
}
func (sa *SockaddrVM) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Len = SizeofSockaddrVM
sa.raw.Family = AF_VSOCK
sa.raw.Port = sa.Port
sa.raw.Cid = sa.CID
return unsafe.Pointer(&sa.raw), SizeofSockaddrVM, nil
}
func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
switch rsa.Addr.Family { switch rsa.Addr.Family {
case AF_SYSTEM: case AF_SYSTEM:
@ -58,6 +82,13 @@ func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
sa.Unit = pp.Sc_unit sa.Unit = pp.Sc_unit
return sa, nil return sa, nil
} }
case AF_VSOCK:
pp := (*RawSockaddrVM)(unsafe.Pointer(rsa))
sa := &SockaddrVM{
CID: pp.Cid,
Port: pp.Port,
}
return sa, nil
} }
return nil, EAFNOSUPPORT return nil, EAFNOSUPPORT
} }
@ -128,8 +159,10 @@ func Pipe(p []int) (err error) {
} }
var x [2]int32 var x [2]int32
err = pipe(&x) err = pipe(&x)
if err == nil {
p[0] = int(x[0]) p[0] = int(x[0])
p[1] = int(x[1]) p[1] = int(x[1])
}
return return
} }
@ -399,8 +432,25 @@ func GetsockoptXucred(fd, level, opt int) (*Xucred, error) {
return x, err return x, err
} }
func SysctlKinfoProcSlice(name string) ([]KinfoProc, error) { func SysctlKinfoProc(name string, args ...int) (*KinfoProc, error) {
mib, err := sysctlmib(name) mib, err := sysctlmib(name, args...)
if err != nil {
return nil, err
}
var kinfo KinfoProc
n := uintptr(SizeofKinfoProc)
if err := sysctl(mib, (*byte)(unsafe.Pointer(&kinfo)), &n, nil, 0); err != nil {
return nil, err
}
if n != SizeofKinfoProc {
return nil, EIO
}
return &kinfo, nil
}
func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) {
mib, err := sysctlmib(name, args...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -433,6 +483,11 @@ func SysctlKinfoProcSlice(name string) ([]KinfoProc, error) {
//sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) //sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error)
//sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error)
//sys shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error)
//sys shmdt(addr uintptr) (err error)
//sys shmget(key int, size int, flag int) (id int, err error)
/* /*
* Exposed directly * Exposed directly
*/ */
@ -590,10 +645,6 @@ func SysctlKinfoProcSlice(name string) ([]KinfoProc, error) {
// Msgget // Msgget
// Msgsnd // Msgsnd
// Msgrcv // Msgrcv
// Shmat
// Shmctl
// Shmdt
// Shmget
// Shm_open // Shm_open
// Shm_unlink // Shm_unlink
// Sem_open // Sem_open

View File

@ -101,7 +101,10 @@ func Pipe(p []int) (err error) {
if len(p) != 2 { if len(p) != 2 {
return EINVAL return EINVAL
} }
p[0], p[1], err = pipe() r, w, err := pipe()
if err == nil {
p[0], p[1] = r, w
}
return return
} }
@ -114,7 +117,10 @@ func Pipe2(p []int, flags int) (err error) {
var pp [2]_C_int var pp [2]_C_int
// pipe2 on dragonfly takes an fds array as an argument, but still // pipe2 on dragonfly takes an fds array as an argument, but still
// returns the file descriptors. // returns the file descriptors.
p[0], p[1], err = pipe2(&pp, flags) r, w, err := pipe2(&pp, flags)
if err == nil {
p[0], p[1] = r, w
}
return err return err
} }

View File

@ -110,8 +110,10 @@ func Pipe2(p []int, flags int) error {
} }
var pp [2]_C_int var pp [2]_C_int
err := pipe2(&pp, flags) err := pipe2(&pp, flags)
if err == nil {
p[0] = int(pp[0]) p[0] = int(pp[0])
p[1] = int(pp[1]) p[1] = int(pp[1])
}
return err return err
} }

View File

@ -13,7 +13,6 @@ package unix
import ( import (
"encoding/binary" "encoding/binary"
"runtime"
"syscall" "syscall"
"unsafe" "unsafe"
) )
@ -38,6 +37,13 @@ func Creat(path string, mode uint32) (fd int, err error) {
return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode) return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode)
} }
func EpollCreate(size int) (fd int, err error) {
if size <= 0 {
return -1, EINVAL
}
return EpollCreate1(0)
}
//sys FanotifyInit(flags uint, event_f_flags uint) (fd int, err error) //sys FanotifyInit(flags uint, event_f_flags uint) (fd int, err error)
//sys fanotifyMark(fd int, flags uint, mask uint64, dirFd int, pathname *byte) (err error) //sys fanotifyMark(fd int, flags uint, mask uint64, dirFd int, pathname *byte) (err error)
@ -113,6 +119,25 @@ func Openat2(dirfd int, path string, how *OpenHow) (fd int, err error) {
return openat2(dirfd, path, how, SizeofOpenHow) return openat2(dirfd, path, how, SizeofOpenHow)
} }
func Pipe(p []int) error {
return Pipe2(p, 0)
}
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
func Pipe2(p []int, flags int) error {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err := pipe2(&pp, flags)
if err == nil {
p[0] = int(pp[0])
p[1] = int(pp[1])
}
return err
}
//sys ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) //sys ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error)
func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
@ -122,6 +147,15 @@ func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error
return ppoll(&fds[0], len(fds), timeout, sigmask) return ppoll(&fds[0], len(fds), timeout, sigmask)
} }
func Poll(fds []PollFd, timeout int) (n int, err error) {
var ts *Timespec
if timeout >= 0 {
ts = new(Timespec)
*ts = NsecToTimespec(int64(timeout) * 1e6)
}
return Ppoll(fds, ts, nil)
}
//sys Readlinkat(dirfd int, path string, buf []byte) (n int, err error) //sys Readlinkat(dirfd int, path string, buf []byte) (n int, err error)
func Readlink(path string, buf []byte) (n int, err error) { func Readlink(path string, buf []byte) (n int, err error) {
@ -340,9 +374,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
p[0] = byte(sa.Port >> 8) p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port) p[1] = byte(sa.Port)
for i := 0; i < len(sa.Addr); i++ { sa.raw.Addr = sa.Addr
sa.raw.Addr[i] = sa.Addr[i]
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
} }
@ -355,9 +387,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
p[0] = byte(sa.Port >> 8) p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port) p[1] = byte(sa.Port)
sa.raw.Scope_id = sa.ZoneId sa.raw.Scope_id = sa.ZoneId
for i := 0; i < len(sa.Addr); i++ { sa.raw.Addr = sa.Addr
sa.raw.Addr[i] = sa.Addr[i]
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
} }
@ -406,9 +436,7 @@ func (sa *SockaddrLinklayer) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Hatype = sa.Hatype sa.raw.Hatype = sa.Hatype
sa.raw.Pkttype = sa.Pkttype sa.raw.Pkttype = sa.Pkttype
sa.raw.Halen = sa.Halen sa.raw.Halen = sa.Halen
for i := 0; i < len(sa.Addr); i++ { sa.raw.Addr = sa.Addr
sa.raw.Addr[i] = sa.Addr[i]
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrLinklayer, nil return unsafe.Pointer(&sa.raw), SizeofSockaddrLinklayer, nil
} }
@ -823,12 +851,10 @@ func (sa *SockaddrTIPC) sockaddr() (unsafe.Pointer, _Socklen, error) {
if sa.Addr == nil { if sa.Addr == nil {
return nil, 0, EINVAL return nil, 0, EINVAL
} }
sa.raw.Family = AF_TIPC sa.raw.Family = AF_TIPC
sa.raw.Scope = int8(sa.Scope) sa.raw.Scope = int8(sa.Scope)
sa.raw.Addrtype = sa.Addr.tipcAddrtype() sa.raw.Addrtype = sa.Addr.tipcAddrtype()
sa.raw.Addr = sa.Addr.tipcAddr() sa.raw.Addr = sa.Addr.tipcAddr()
return unsafe.Pointer(&sa.raw), SizeofSockaddrTIPC, nil return unsafe.Pointer(&sa.raw), SizeofSockaddrTIPC, nil
} }
@ -842,9 +868,7 @@ type SockaddrL2TPIP struct {
func (sa *SockaddrL2TPIP) sockaddr() (unsafe.Pointer, _Socklen, error) { func (sa *SockaddrL2TPIP) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Family = AF_INET sa.raw.Family = AF_INET
sa.raw.Conn_id = sa.ConnId sa.raw.Conn_id = sa.ConnId
for i := 0; i < len(sa.Addr); i++ { sa.raw.Addr = sa.Addr
sa.raw.Addr[i] = sa.Addr[i]
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrL2TPIP, nil return unsafe.Pointer(&sa.raw), SizeofSockaddrL2TPIP, nil
} }
@ -860,9 +884,7 @@ func (sa *SockaddrL2TPIP6) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Family = AF_INET6 sa.raw.Family = AF_INET6
sa.raw.Conn_id = sa.ConnId sa.raw.Conn_id = sa.ConnId
sa.raw.Scope_id = sa.ZoneId sa.raw.Scope_id = sa.ZoneId
for i := 0; i < len(sa.Addr); i++ { sa.raw.Addr = sa.Addr
sa.raw.Addr[i] = sa.Addr[i]
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrL2TPIP6, nil return unsafe.Pointer(&sa.raw), SizeofSockaddrL2TPIP6, nil
} }
@ -958,9 +980,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
sa.Hatype = pp.Hatype sa.Hatype = pp.Hatype
sa.Pkttype = pp.Pkttype sa.Pkttype = pp.Pkttype
sa.Halen = pp.Halen sa.Halen = pp.Halen
for i := 0; i < len(sa.Addr); i++ { sa.Addr = pp.Addr
sa.Addr[i] = pp.Addr[i]
}
return sa, nil return sa, nil
case AF_UNIX: case AF_UNIX:
@ -999,18 +1019,14 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
pp := (*RawSockaddrL2TPIP)(unsafe.Pointer(rsa)) pp := (*RawSockaddrL2TPIP)(unsafe.Pointer(rsa))
sa := new(SockaddrL2TPIP) sa := new(SockaddrL2TPIP)
sa.ConnId = pp.Conn_id sa.ConnId = pp.Conn_id
for i := 0; i < len(sa.Addr); i++ { sa.Addr = pp.Addr
sa.Addr[i] = pp.Addr[i]
}
return sa, nil return sa, nil
default: default:
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
sa := new(SockaddrInet4) sa := new(SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port)) p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1]) sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ { sa.Addr = pp.Addr
sa.Addr[i] = pp.Addr[i]
}
return sa, nil return sa, nil
} }
@ -1026,9 +1042,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
sa := new(SockaddrL2TPIP6) sa := new(SockaddrL2TPIP6)
sa.ConnId = pp.Conn_id sa.ConnId = pp.Conn_id
sa.ZoneId = pp.Scope_id sa.ZoneId = pp.Scope_id
for i := 0; i < len(sa.Addr); i++ { sa.Addr = pp.Addr
sa.Addr[i] = pp.Addr[i]
}
return sa, nil return sa, nil
default: default:
pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
@ -1036,9 +1050,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
p := (*[2]byte)(unsafe.Pointer(&pp.Port)) p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1]) sa.Port = int(p[0])<<8 + int(p[1])
sa.ZoneId = pp.Scope_id sa.ZoneId = pp.Scope_id
for i := 0; i < len(sa.Addr); i++ { sa.Addr = pp.Addr
sa.Addr[i] = pp.Addr[i]
}
return sa, nil return sa, nil
} }
@ -1765,6 +1777,16 @@ func Mount(source string, target string, fstype string, flags uintptr, data stri
return mount(source, target, fstype, flags, datap) return mount(source, target, fstype, flags, datap)
} }
//sys mountSetattr(dirfd int, pathname string, flags uint, attr *MountAttr, size uintptr) (err error) = SYS_MOUNT_SETATTR
// MountSetattr is a wrapper for mount_setattr(2).
// https://man7.org/linux/man-pages/man2/mount_setattr.2.html
//
// Requires kernel >= 5.12.
func MountSetattr(dirfd int, pathname string, flags uint, attr *MountAttr) error {
return mountSetattr(dirfd, pathname, flags, attr, unsafe.Sizeof(*attr))
}
func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
if raceenabled { if raceenabled {
raceReleaseMerge(unsafe.Pointer(&ioSync)) raceReleaseMerge(unsafe.Pointer(&ioSync))
@ -1796,11 +1818,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sys Dup(oldfd int) (fd int, err error) //sys Dup(oldfd int) (fd int, err error)
func Dup2(oldfd, newfd int) error { func Dup2(oldfd, newfd int) error {
// Android O and newer blocks dup2; riscv and arm64 don't implement dup2.
if runtime.GOOS == "android" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "arm64" {
return Dup3(oldfd, newfd, 0) return Dup3(oldfd, newfd, 0)
}
return dup2(oldfd, newfd)
} }
//sys Dup3(oldfd int, newfd int, flags int) (err error) //sys Dup3(oldfd int, newfd int, flags int) (err error)
@ -2291,6 +2309,11 @@ type RemoteIovec struct {
//sys PidfdOpen(pid int, flags int) (fd int, err error) = SYS_PIDFD_OPEN //sys PidfdOpen(pid int, flags int) (fd int, err error) = SYS_PIDFD_OPEN
//sys PidfdGetfd(pidfd int, targetfd int, flags int) (fd int, err error) = SYS_PIDFD_GETFD //sys PidfdGetfd(pidfd int, targetfd int, flags int) (fd int, err error) = SYS_PIDFD_GETFD
//sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error)
//sys shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error)
//sys shmdt(addr uintptr) (err error)
//sys shmget(key int, size int, flag int) (id int, err error)
/* /*
* Unimplemented * Unimplemented
*/ */
@ -2372,10 +2395,6 @@ type RemoteIovec struct {
// SetRobustList // SetRobustList
// SetThreadArea // SetThreadArea
// SetTidAddress // SetTidAddress
// Shmat
// Shmctl
// Shmdt
// Shmget
// Sigaltstack // Sigaltstack
// Swapoff // Swapoff
// Swapon // Swapon

View File

@ -19,36 +19,8 @@ func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: int32(sec), Usec: int32(usec)} return Timeval{Sec: int32(sec), Usec: int32(usec)}
} }
//sysnb pipe(p *[2]_C_int) (err error)
func Pipe(p []int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe(&pp)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
func Pipe2(p []int, flags int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
// 64-bit file system and 32-bit uid calls // 64-bit file system and 32-bit uid calls
// (386 default is 32-bit file system and 16-bit uid). // (386 default is 32-bit file system and 16-bit uid).
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64_64 //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64_64
//sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32 //sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32
@ -380,12 +352,3 @@ func (cmsg *Cmsghdr) SetLen(length int) {
func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
rsa.Service_name_len = uint32(length) rsa.Service_name_len = uint32(length)
} }
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {
if len(fds) == 0 {
return poll(nil, 0, timeout)
}
return poll(&fds[0], len(fds), timeout)
}

View File

@ -7,8 +7,6 @@
package unix package unix
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
//sys Fchown(fd int, uid int, gid int) (err error) //sys Fchown(fd int, uid int, gid int) (err error)
@ -115,32 +113,6 @@ func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: sec, Usec: usec} return Timeval{Sec: sec, Usec: usec}
} }
//sysnb pipe(p *[2]_C_int) (err error)
func Pipe(p []int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe(&pp)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
func Pipe2(p []int, flags int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
func (r *PtraceRegs) PC() uint64 { return r.Rip } func (r *PtraceRegs) PC() uint64 { return r.Rip }
func (r *PtraceRegs) SetPC(pc uint64) { r.Rip = pc } func (r *PtraceRegs) SetPC(pc uint64) { r.Rip = pc }
@ -165,15 +137,6 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
rsa.Service_name_len = uint64(length) rsa.Service_name_len = uint64(length)
} }
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {
if len(fds) == 0 {
return poll(nil, 0, timeout)
}
return poll(&fds[0], len(fds), timeout)
}
//sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) //sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error)
func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error { func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error {

View File

@ -19,32 +19,6 @@ func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: int32(sec), Usec: int32(usec)} return Timeval{Sec: int32(sec), Usec: int32(usec)}
} }
//sysnb pipe(p *[2]_C_int) (err error)
func Pipe(p []int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, 0)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
func Pipe2(p []int, flags int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
newoffset, errno := seek(fd, offset, whence) newoffset, errno := seek(fd, offset, whence)
if errno != 0 { if errno != 0 {
@ -72,8 +46,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
// 64-bit file system and 32-bit uid calls // 64-bit file system and 32-bit uid calls
// (16-bit uid calls are not always supported in newer kernels) // (16-bit uid calls are not always supported in newer kernels)
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32 //sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64 //sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
@ -255,15 +227,6 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
rsa.Service_name_len = uint32(length) rsa.Service_name_len = uint32(length)
} }
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {
if len(fds) == 0 {
return poll(nil, 0, timeout)
}
return poll(&fds[0], len(fds), timeout)
}
//sys armSyncFileRange(fd int, flags int, off int64, n int64) (err error) = SYS_ARM_SYNC_FILE_RANGE //sys armSyncFileRange(fd int, flags int, off int64, n int64) (err error) = SYS_ARM_SYNC_FILE_RANGE
func SyncFileRange(fd int, off int64, n int64, flags int) error { func SyncFileRange(fd int, off int64, n int64, flags int) error {

View File

@ -9,13 +9,6 @@ package unix
import "unsafe" import "unsafe"
func EpollCreate(size int) (fd int, err error) {
if size <= 0 {
return -1, EINVAL
}
return EpollCreate1(0)
}
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
//sys Fchown(fd int, uid int, gid int) (err error) //sys Fchown(fd int, uid int, gid int) (err error)
@ -145,30 +138,6 @@ func utimes(path string, tv *[2]Timeval) (err error) {
return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
} }
func Pipe(p []int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, 0)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
func Pipe2(p []int, flags int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
// Getrlimit prefers the prlimit64 system call. See issue 38604. // Getrlimit prefers the prlimit64 system call. See issue 38604.
func Getrlimit(resource int, rlim *Rlimit) error { func Getrlimit(resource int, rlim *Rlimit) error {
err := Prlimit(0, resource, nil, rlim) err := Prlimit(0, resource, nil, rlim)
@ -211,27 +180,11 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
rsa.Service_name_len = uint64(length) rsa.Service_name_len = uint64(length)
} }
// dup2 exists because func Dup3 in syscall_linux.go references
// it in an unreachable path. dup2 isn't available on arm64.
func dup2(oldfd int, newfd int) error
func Pause() error { func Pause() error {
_, err := ppoll(nil, 0, nil, nil) _, err := ppoll(nil, 0, nil, nil)
return err return err
} }
func Poll(fds []PollFd, timeout int) (n int, err error) {
var ts *Timespec
if timeout >= 0 {
ts = new(Timespec)
*ts = NsecToTimespec(int64(timeout) * 1e6)
}
if len(fds) == 0 {
return ppoll(nil, 0, ts, nil)
}
return ppoll(&fds[0], len(fds), ts, nil)
}
//sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) //sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error)
func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error { func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error {

View File

@ -8,8 +8,6 @@
package unix package unix
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
//sys Fchown(fd int, uid int, gid int) (err error) //sys Fchown(fd int, uid int, gid int) (err error)
@ -94,30 +92,6 @@ func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: sec, Usec: usec} return Timeval{Sec: sec, Usec: usec}
} }
func Pipe(p []int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, 0)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
func Pipe2(p []int, flags int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
func Ioperm(from int, num int, on int) (err error) { func Ioperm(from int, num int, on int) (err error) {
return ENOSYS return ENOSYS
} }
@ -220,12 +194,3 @@ func (cmsg *Cmsghdr) SetLen(length int) {
func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
rsa.Service_name_len = uint64(length) rsa.Service_name_len = uint64(length)
} }
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {
if len(fds) == 0 {
return poll(nil, 0, timeout)
}
return poll(&fds[0], len(fds), timeout)
}

View File

@ -15,8 +15,6 @@ import (
func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
//sys Fchown(fd int, uid int, gid int) (err error) //sys Fchown(fd int, uid int, gid int) (err error)
@ -112,29 +110,6 @@ func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: int32(sec), Usec: int32(usec)} return Timeval{Sec: int32(sec), Usec: int32(usec)}
} }
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
func Pipe2(p []int, flags int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
//sysnb pipe() (p1 int, p2 int, err error)
func Pipe(p []int) (err error) {
if len(p) != 2 {
return EINVAL
}
p[0], p[1], err = pipe()
return
}
//sys mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error) //sys mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error)
func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) { func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
@ -231,12 +206,3 @@ func (cmsg *Cmsghdr) SetLen(length int) {
func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
rsa.Service_name_len = uint32(length) rsa.Service_name_len = uint32(length)
} }
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {
if len(fds) == 0 {
return poll(nil, 0, timeout)
}
return poll(&fds[0], len(fds), timeout)
}

View File

@ -12,8 +12,6 @@ import (
"unsafe" "unsafe"
) )
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fchown(fd int, uid int, gid int) (err error) //sys Fchown(fd int, uid int, gid int) (err error)
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64 //sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
@ -217,41 +215,6 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
rsa.Service_name_len = uint32(length) rsa.Service_name_len = uint32(length)
} }
//sysnb pipe(p *[2]_C_int) (err error)
func Pipe(p []int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe(&pp)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
func Pipe2(p []int, flags int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {
if len(fds) == 0 {
return poll(nil, 0, timeout)
}
return poll(&fds[0], len(fds), timeout)
}
//sys syncFileRange2(fd int, flags int, off int64, n int64) (err error) = SYS_SYNC_FILE_RANGE2 //sys syncFileRange2(fd int, flags int, off int64, n int64) (err error) = SYS_SYNC_FILE_RANGE2
func SyncFileRange(fd int, off int64, n int64, flags int) error { func SyncFileRange(fd int, off int64, n int64, flags int) error {

View File

@ -8,8 +8,6 @@
package unix package unix
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
//sys Fchown(fd int, uid int, gid int) (err error) //sys Fchown(fd int, uid int, gid int) (err error)
@ -103,41 +101,6 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
rsa.Service_name_len = uint64(length) rsa.Service_name_len = uint64(length)
} }
//sysnb pipe(p *[2]_C_int) (err error)
func Pipe(p []int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe(&pp)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
func Pipe2(p []int, flags int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {
if len(fds) == 0 {
return poll(nil, 0, timeout)
}
return poll(&fds[0], len(fds), timeout)
}
//sys syncFileRange2(fd int, flags int, off int64, n int64) (err error) = SYS_SYNC_FILE_RANGE2 //sys syncFileRange2(fd int, flags int, off int64, n int64) (err error) = SYS_SYNC_FILE_RANGE2
func SyncFileRange(fd int, off int64, n int64, flags int) error { func SyncFileRange(fd int, off int64, n int64, flags int) error {

View File

@ -9,13 +9,6 @@ package unix
import "unsafe" import "unsafe"
func EpollCreate(size int) (fd int, err error) {
if size <= 0 {
return -1, EINVAL
}
return EpollCreate1(0)
}
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
//sys Fchown(fd int, uid int, gid int) (err error) //sys Fchown(fd int, uid int, gid int) (err error)
@ -144,30 +137,6 @@ func utimes(path string, tv *[2]Timeval) (err error) {
return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
} }
func Pipe(p []int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, 0)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
func Pipe2(p []int, flags int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
func (r *PtraceRegs) PC() uint64 { return r.Pc } func (r *PtraceRegs) PC() uint64 { return r.Pc }
func (r *PtraceRegs) SetPC(pc uint64) { r.Pc = pc } func (r *PtraceRegs) SetPC(pc uint64) { r.Pc = pc }
@ -197,18 +166,6 @@ func Pause() error {
return err return err
} }
func Poll(fds []PollFd, timeout int) (n int, err error) {
var ts *Timespec
if timeout >= 0 {
ts = new(Timespec)
*ts = NsecToTimespec(int64(timeout) * 1e6)
}
if len(fds) == 0 {
return ppoll(nil, 0, ts, nil)
}
return ppoll(&fds[0], len(fds), ts, nil)
}
func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) { func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
return Renameat2(olddirfd, oldpath, newdirfd, newpath, 0) return Renameat2(olddirfd, oldpath, newdirfd, newpath, 0)
} }
@ -225,7 +182,3 @@ func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error
} }
return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags) return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags)
} }
// dup2 exists because func Dup3 in syscall_linux.go references
// it in an unreachable path. dup2 isn't available on arm64.
func dup2(oldfd int, newfd int) error

View File

@ -11,8 +11,6 @@ import (
"unsafe" "unsafe"
) )
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
//sys Fchown(fd int, uid int, gid int) (err error) //sys Fchown(fd int, uid int, gid int) (err error)
@ -76,30 +74,6 @@ func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: sec, Usec: usec} return Timeval{Sec: sec, Usec: usec}
} }
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
func Pipe(p []int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, 0) // pipe2 is the same as pipe when flags are set to 0.
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
func Pipe2(p []int, flags int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
func Ioperm(from int, num int, on int) (err error) { func Ioperm(from int, num int, on int) (err error) {
return ENOSYS return ENOSYS
} }
@ -323,15 +297,6 @@ func Shutdown(s, how int) error {
return nil return nil
} }
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {
if len(fds) == 0 {
return poll(nil, 0, timeout)
}
return poll(&fds[0], len(fds), timeout)
}
//sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) //sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error)
func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error { func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error {

Some files were not shown because too many files have changed in this diff Show More