Этот коммит содержится в:
Christopher Speller
2017-04-24 20:11:36 -04:00
коммит произвёл Joram Wilander
родитель 7f68a60f8c
Коммит f5437632f4
389 изменённых файлов: 123993 добавлений и 97347 удалений

63
glide.lock сгенерированный
Просмотреть файл

@@ -1,5 +1,5 @@
hash: 193ce14426dc6d4ae2da1c1aad08389a157529f829ed12948095239e18e045a5
updated: 2017-03-30T22:26:27.084209918-07:00
hash: 024025a74451af061cc996e2b9192bad74cfd0952515fab332e3ad2968606909
updated: 2017-04-24T11:23:43.046980248-04:00
imports:
- name: github.com/alecthomas/log4go
version: 3fbce08846379ec7f4f6bc7fce6dd01ce28fae4c
@@ -8,10 +8,12 @@ imports:
version: 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
subpackages:
- quantile
- name: github.com/cpanato/html2text
version: d788b7d6dc58bea298b318059332a25442583880
- name: github.com/dgryski/dgoogauth
version: 96977cbd42e27be71f9f731db6634123de7e861a
- name: github.com/disintegration/imaging
version: 243d2d8673c1225a6afceeb9b3b4423d485dc8df
version: ac27d1805a555e1754fa177216ee07f4e63c30b5
- name: github.com/dyatlov/go-opengraph
version: 41a3523719dfbe7e8f853fbd4061867543db5270
subpackages:
@@ -25,12 +27,12 @@ imports:
- name: github.com/go-sql-driver/mysql
version: a0583e0143b1624142adab07e0e97fe106d99561
- name: github.com/golang/freetype
version: d9be45aaf7452cc30c0ceb1b1bf7efe1d17b7c87
version: b12e98108289d6367ecd1a819deee597b2c3fa57
subpackages:
- raster
- truetype
- name: github.com/golang/protobuf
version: c9c7427a2a70d2eb3bafa0ab2dc163e45f143317
version: 2bba0603135d7d7f5cb73b2125beeda19c09f4ef
subpackages:
- proto
- name: github.com/gorilla/context
@@ -46,7 +48,7 @@ imports:
subpackages:
- simplelru
- name: github.com/hashicorp/hcl
version: 630949a3c5fa3c613328e1b8256052cbc2327c9b
version: 7fa7fff964d035e8a162cce3a164b3ad02ad651b
subpackages:
- hcl/ast
- hcl/parser
@@ -58,12 +60,10 @@ imports:
- json/token
- name: github.com/inconshreveable/mousetrap
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
- name: github.com/jaytaylor/html2text
version: f3b8a7ca0a23f0a806b2e1ad1247de39ecde54bf
- name: github.com/jehiah/go-strftime
version: 834e15c05a45371503440cc195bbd05c9a0968d9
- name: github.com/lib/pq
version: 472a0745531a17dbac346e828b4c60e73ddff30c
version: 2704adc878c21e1329f46f6e56a1c387d788ff94
subpackages:
- oid
- name: github.com/magiconair/properties
@@ -79,33 +79,33 @@ imports:
subpackages:
- pbutil
- name: github.com/miekg/dns
version: b54e1be39a9c14cd0bcea6df97eb15b3ec5e8cde
version: 6ebcb714d36901126ee2807031543b38c56de963
- name: github.com/minio/minio-go
version: 52cc94e879db78c2e2c6e160869df943137ec4cd
version: dcaae9ec4d0b0a81d17f22f6d7a186491f6a55ec
subpackages:
- pkg/policy
- pkg/s3signer
- pkg/s3utils
- pkg/set
- name: github.com/mitchellh/mapstructure
version: 53818660ed4955e899c0bcafa97299a388bd7c8e
version: cc8532a8e9a55ea36402aa21efdf403a60d34096
- name: github.com/mssola/user_agent
version: 85b2f5798558a46fc23443c596e781712f4b7792
- name: github.com/nicksnyder/go-i18n
version: f757c9f9b69c16ff69d38dbf224be28a7b6537bb
version: fed5740db6b83ee8ba7c1b07ff063115bc6f4b96
subpackages:
- i18n
- i18n/bundle
- i18n/language
- i18n/translation
- name: github.com/NYTimes/gziphandler
version: 3b0c4852c5b9710340f1ed7b1a529c46a3bc0fc1
version: 22d4470af89e09998fc16b35029df973932df4ae
- name: github.com/pborman/uuid
version: a97ce2ca70fa5a848076093f05e639a89ca34d06
- name: github.com/pelletier/go-buffruneio
version: c37440a7cf42ac63b919c752ca73a85067e05992
- name: github.com/pelletier/go-toml
version: e32a2e04744250647a72bf17da1b09befc03b6b1
version: fe206efb84b2bc8e8cfafe6b4c1826622be969e3
- name: github.com/prometheus/client_golang
version: c5b7fccd204277076155f10851dad72b76a49317
subpackages:
@@ -115,11 +115,11 @@ imports:
subpackages:
- go
- name: github.com/prometheus/common
version: 49fee292b27bfff7f354ee0f64e1bc4850462edf
version: 9e0844febd9e2856f839c9cb974fbd676d1755a8
subpackages:
- expfmt
- name: github.com/prometheus/procfs
version: a1dba9ce8baed984a2495b658c82687f8157b98f
version: 332f6238064950a97bc3ed3f5421f6418537e707
- name: github.com/rsc/letsencrypt
version: 76104d26167d38b6a0010f42bfc8ec5487742e8b
- name: github.com/rwcarlsen/goexif
@@ -136,31 +136,31 @@ imports:
subpackages:
- mem
- name: github.com/spf13/cast
version: ce135a4ebeee6cfe9a26c93ee0d37825f26113c7
version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4
- name: github.com/spf13/cobra
version: 7be4beda01ec05d0b93d80b3facd2b6f44080d94
version: f4f10f6873175e78bb1503da7e78c260a7f3ef63
- name: github.com/spf13/jwalterweatherman
version: fa7ca7e836cf3a8bb4ebf799f472c12d7e903d66
- name: github.com/spf13/pflag
version: 9ff6c6923cfffbcd502984b8e0c80539a94968b7
version: 2300d0f8576fe575f71aaa5b9bbe4e1b0dc2eb51
- name: github.com/spf13/viper
version: 84f94806c67f59dd7ae87bc5351f7a9c94a4558d
version: 0967fc9aceab2ce9da34061253ac10fb99bba5b2
- name: github.com/tylerb/graceful
version: d72b0151351a13d0421b763b88f791469c4f5dc7
version: 4654dfbb6ad53cb5e27f37d99b02e16c1872fbbb
- name: github.com/xenolf/lego
version: 0e2937900b224325f4476745a9b53aef246b7410
version: 5dfe609afb1ebe9da97c9846d97a55415e5a5ccd
subpackages:
- acme
- name: github.com/xtgo/uuid
version: a0b114877d4caeffbd7f87e3757c17fce570fea7
- name: golang.org/x/crypto
version: 459e26527287adbc2adcc5d0d49abff9a5f315a7
version: 3543873453996aaab2fc6b3928a35fc5ca2b5afb
subpackages:
- bcrypt
- blowfish
- ocsp
- name: golang.org/x/image
version: c0851fbc5b9272dd7d08a021e9e3d2a21027b51f
version: 3210c0296b49a552ad9668ede9c61008df821b94
subpackages:
- bmp
- font
@@ -168,29 +168,27 @@ imports:
- tiff
- tiff/lzw
- name: golang.org/x/net
version: 78ebe5c8b6a27ec13109c73c22193d618270e1e1
version: d212a1ef2de2f5d441c327b8f26cf3ea3ea9f265
subpackages:
- context
- html
- html/atom
- publicsuffix
- name: golang.org/x/sys
version: 8fd966b47dbdd4faa03de0d06e3d733baeb9a1a9
version: ea9bcade75cb975a0b9738936568ab388b845617
subpackages:
- unix
- name: golang.org/x/text
version: 65f4f820a7954b82e5c9325e1e088a4fda098f36
version: a9a820217f98f7c8a207ec1e45a874e1fe12c478
subpackages:
- transform
- unicode/norm
- name: golang.org/x/time
version: f51c12702a4d776e4c1fa9b0fabab841babae631
version: c06e80d9300e4443158a03817b8a8cb37d230320
subpackages:
- rate
- name: gopkg.in/asn1-ber.v1
version: 4e86f4367175e39f69d9358a5f17b4dda270378d
- name: gopkg.in/gomail.v2
version: 41f3572897373c5538c50a2402db15db079fa4fd
- name: gopkg.in/square/go-jose.v1
version: aa2e30fdd1fe9dd3394119af66451ae790d50e0d
subpackages:
@@ -199,8 +197,7 @@ imports:
- name: gopkg.in/throttled/throttled.v2
version: b5675e93f9d999b22f92d859a5bf2138d3641af4
subpackages:
- store
- store/memstore
- name: gopkg.in/yaml.v2
version: a3f3340b5840cee44f372bddb5880fcbc419b46a
version: cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b
testImports: []

Просмотреть файл

@@ -5,7 +5,12 @@ import:
repo: https://github.com/mattermost/log4go.git
- package: github.com/dgryski/dgoogauth
- package: github.com/disintegration/imaging
version: v1.0.0
version: v1.1.0
- package: github.com/dyatlov/go-opengraph
subpackages:
- opengraph
- package: github.com/fsnotify/fsnotify
version: v1.4.2
- package: github.com/go-gorp/gorp
version: 0c9bc0918534d133cedb439a24adc7cbe66e4a9d
- package: github.com/go-ldap/ldap
@@ -23,17 +28,27 @@ import:
- package: github.com/mattermost/rsc
subpackages:
- qr
- package: github.com/minio/minio-go
version: v2.0.4
- package: github.com/mssola/user_agent
version: v0.4.1
- package: github.com/nicksnyder/go-i18n
version: v1.7.0
version: v1.8.0
subpackages:
- i18n
- package: github.com/pborman/uuid
version: v1.0
- package: github.com/rsc/letsencrypt
- package: github.com/rwcarlsen/goexif
subpackages:
- exif
- package: github.com/segmentio/analytics-go
version: 2.1.1
- package: github.com/spf13/cobra
- package: github.com/spf13/pflag
- package: github.com/spf13/viper
- package: github.com/tylerb/graceful
version: v1.2.15
- package: golang.org/x/crypto
subpackages:
- bcrypt
@@ -43,12 +58,10 @@ import:
- package: gopkg.in/throttled/throttled.v2
version: v2.0.3
subpackages:
- store
- store/memstore
- package: github.com/segmentio/analytics-go
version: 2.1.1
- package: github.com/rsc/letsencrypt
- package: github.com/minio/minio-go
version: v2.0.3
- package: github.com/prometheus/client_golang
version: v0.8.0
subpackages:
@@ -75,9 +88,5 @@ import:
- package: github.com/dyatlov/go-opengraph
subpackages:
- opengraph
- package: github.com/jaytaylor/html2text
- package: gopkg.in/gomail.v2
version: 2.0.0
- package: github.com/spf13/viper
- package: github.com/fsnotify/fsnotify
version: v1.4.2
- package: github.com/cpanato/html2text

1
vendor/github.com/NYTimes/gziphandler/.travis.yml сгенерированный поставляемый
Просмотреть файл

@@ -2,4 +2,5 @@ language: go
go:
- 1.7
- 1.8
- tip

4
vendor/github.com/NYTimes/gziphandler/README.md сгенерированный поставляемый
Просмотреть файл

@@ -38,12 +38,12 @@ func main() {
## Documentation
The docs can be found at [godoc.org] [docs], as usual.
The docs can be found at [godoc.org][docs], as usual.
## License
[Apache 2.0] [license].
[Apache 2.0][license].

129
vendor/github.com/NYTimes/gziphandler/gzip.go сгенерированный поставляемый
Просмотреть файл

@@ -4,6 +4,7 @@ import (
"bufio"
"compress/gzip"
"fmt"
"io"
"net"
"net/http"
"strconv"
@@ -21,10 +22,16 @@ const (
type codings map[string]float64
// The default qvalue to assign to an encoding if no explicit qvalue is set.
// This is actually kind of ambiguous in RFC 2616, so hopefully it's correct.
// The examples seem to indicate that it is.
const DEFAULT_QVALUE = 1.0
const (
// DefaultQValue is the default qvalue to assign to an encoding if no explicit qvalue is set.
// This is actually kind of ambiguous in RFC 2616, so hopefully it's correct.
// The examples seem to indicate that it is.
DefaultQValue = 1.0
// DefaultMinSize defines the minimum size to reach to enable compression.
// It's 512 bytes.
DefaultMinSize = 512
)
// gzipWriterPools stores a sync.Pool for each compression level for reuse of
// gzip.Writers. Use poolIndex to covert a compression level to an index into
@@ -63,35 +70,88 @@ func addLevelPool(level int) {
// GzipResponseWriter provides an http.ResponseWriter interface, which gzips
// bytes before writing them to the underlying response. This doesn't close the
// writers, so don't forget to do that.
// It can be configured to skip response smaller than minSize.
type GzipResponseWriter struct {
http.ResponseWriter
index int // Index for gzipWriterPools.
gw *gzip.Writer
code int // Saves the WriteHeader value.
minSize int // Specifed the minimum response size to gzip. If the response length is bigger than this value, it is compressed.
buf []byte // Holds the first part of the write before reaching the minSize or the end of the write.
}
// Write appends data to the gzip writer.
func (w *GzipResponseWriter) Write(b []byte) (int, error) {
// Lazily create the gzip.Writer, this allows empty bodies to be actually
// empty, for example in the case of status code 204 (no content).
if w.gw == nil {
w.init()
}
// If content type is not set.
if _, ok := w.Header()[contentType]; !ok {
// If content type is not set, infer it from the uncompressed body.
// It infer it from the uncompressed body.
w.Header().Set(contentType, http.DetectContentType(b))
}
return w.gw.Write(b)
// GZIP responseWriter is initialized. Use the GZIP responseWriter.
if w.gw != nil {
n, err := w.gw.Write(b)
return n, err
}
// Save the write into a buffer for later use in GZIP responseWriter (if content is long enough) or at close with regular responseWriter.
w.buf = append(w.buf, b...)
// If the global writes are bigger than the minSize, compression is enable.
if len(w.buf) >= w.minSize {
err := w.startGzip()
if err != nil {
return 0, err
}
}
return len(b), nil
}
// WriteHeader will check if the gzip writer needs to be lazily initiated and
// then pass the code along to the underlying ResponseWriter.
func (w *GzipResponseWriter) WriteHeader(code int) {
if w.gw == nil &&
code != http.StatusNotModified && code != http.StatusNoContent {
w.init()
// startGzip initialize any GZIP specific informations.
func (w *GzipResponseWriter) startGzip() error {
// Set the GZIP header.
w.Header().Set(contentEncoding, "gzip")
// if the Content-Length is already set, then calls to Write on gzip
// will fail to set the Content-Length header since its already set
// See: https://github.com/golang/go/issues/14975.
w.Header().Del(contentLength)
// Write the header to gzip response.
w.writeHeader()
// Initialize the GZIP response.
w.init()
// Flush the buffer into the gzip reponse.
n, err := w.gw.Write(w.buf)
// This should never happen (per io.Writer docs), but if the write didn't
// accept the entire buffer but returned no specific error, we have no clue
// what's going on, so abort just to be safe.
if err == nil && n < len(w.buf) {
return io.ErrShortWrite
}
w.ResponseWriter.WriteHeader(code)
w.buf = nil
return err
}
// WriteHeader just saves the response code until close or GZIP effective writes.
func (w *GzipResponseWriter) WriteHeader(code int) {
w.code = code
}
// writeHeader uses the saved code to send it to the ResponseWriter.
func (w *GzipResponseWriter) writeHeader() {
if w.code == 0 {
w.code = http.StatusOK
}
w.ResponseWriter.WriteHeader(w.code)
}
// init graps a new gzip writer from the gzipWriterPool and writes the correct
@@ -102,15 +162,22 @@ func (w *GzipResponseWriter) init() {
gzw := gzipWriterPools[w.index].Get().(*gzip.Writer)
gzw.Reset(w.ResponseWriter)
w.gw = gzw
w.ResponseWriter.Header().Set(contentEncoding, "gzip")
// if the Content-Length is already set, then calls to Write on gzip
// will fail to set the Content-Length header since its already set
// See: https://github.com/golang/go/issues/14975
w.ResponseWriter.Header().Del(contentLength)
}
// Close will close the gzip.Writer and will put it back in the gzipWriterPool.
func (w *GzipResponseWriter) Close() error {
// Buffer not nil means the regular response must be returned.
if w.buf != nil {
w.writeHeader()
// Make the write into the regular response.
_, writeErr := w.ResponseWriter.Write(w.buf)
// Returns the error if any at write.
if writeErr != nil {
return fmt.Errorf("gziphandler: write to regular responseWriter at close gets error: %q", writeErr.Error())
}
}
// If the GZIP responseWriter is not set no needs to close it.
if w.gw == nil {
return nil
}
@@ -163,9 +230,18 @@ func MustNewGzipLevelHandler(level int) func(http.Handler) http.Handler {
// if an invalid gzip compression level is given, so if one can ensure the level
// is valid, the returned error can be safely ignored.
func NewGzipLevelHandler(level int) (func(http.Handler) http.Handler, error) {
return NewGzipLevelAndMinSize(level, DefaultMinSize)
}
// NewGzipLevelAndMinSize behave as NewGzipLevelHandler except it let the caller
// specify the minimum size before compression.
func NewGzipLevelAndMinSize(level, minSize int) (func(http.Handler) http.Handler, error) {
if level != gzip.DefaultCompression && (level < gzip.BestSpeed || level > gzip.BestCompression) {
return nil, fmt.Errorf("invalid compression level requested: %d", level)
}
if minSize < 0 {
return nil, fmt.Errorf("minimum size must be more than zero")
}
return func(h http.Handler) http.Handler {
index := poolIndex(level)
@@ -176,6 +252,9 @@ func NewGzipLevelHandler(level int) (func(http.Handler) http.Handler, error) {
gw := &GzipResponseWriter{
ResponseWriter: w,
index: index,
minSize: minSize,
buf: []byte{},
}
defer gw.Close()
@@ -238,7 +317,7 @@ func parseEncodings(s string) (codings, error) {
func parseCoding(s string) (coding string, qvalue float64, err error) {
for n, part := range strings.Split(s, ";") {
part = strings.TrimSpace(part)
qvalue = DEFAULT_QVALUE
qvalue = DefaultQValue
if n == 0 {
coding = strings.ToLower(part)

43
vendor/github.com/NYTimes/gziphandler/gzip_go18.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,43 @@
// +build go1.8
package gziphandler
import "net/http"
// Push initiates an HTTP/2 server push.
// Push returns ErrNotSupported if the client has disabled push or if push
// is not supported on the underlying connection.
func (w *GzipResponseWriter) Push(target string, opts *http.PushOptions) error {
pusher, ok := w.ResponseWriter.(http.Pusher)
if ok && pusher != nil {
return pusher.Push(target, setAcceptEncodingForPushOptions(opts))
}
return http.ErrNotSupported
}
// setAcceptEncodingForPushOptions sets "Accept-Encoding" : "gzip" for PushOptions without overriding existing headers.
func setAcceptEncodingForPushOptions(opts *http.PushOptions) *http.PushOptions {
if opts == nil {
opts = &http.PushOptions{
Header: http.Header{
acceptEncoding: []string{"gzip"},
},
}
return opts
}
if opts.Header == nil {
opts.Header = http.Header{
acceptEncoding: []string{"gzip"},
}
return opts
}
if encoding := opts.Header.Get(acceptEncoding); encoding == "" {
opts.Header.Add(acceptEncoding, "gzip")
return opts
}
return opts
}

70
vendor/github.com/NYTimes/gziphandler/gzip_go18_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,70 @@
// +build go1.8
package gziphandler
import (
"net/http"
"testing"
"github.com/stretchr/testify/assert"
)
func TestSetAcceptEncodingForPushOptionsWithoutHeaders(t *testing.T) {
var opts *http.PushOptions
opts = setAcceptEncodingForPushOptions(opts)
assert.NotNil(t, opts)
assert.NotNil(t, opts.Header)
for k, v := range opts.Header {
assert.Equal(t, "Accept-Encoding", k)
assert.Len(t, v, 1)
assert.Equal(t, "gzip", v[0])
}
opts = &http.PushOptions{}
opts = setAcceptEncodingForPushOptions(opts)
assert.NotNil(t, opts)
assert.NotNil(t, opts.Header)
for k, v := range opts.Header {
assert.Equal(t, "Accept-Encoding", k)
assert.Len(t, v, 1)
assert.Equal(t, "gzip", v[0])
}
}
func TestSetAcceptEncodingForPushOptionsWithHeaders(t *testing.T) {
opts := &http.PushOptions{
Header: http.Header{
"User-Agent": []string{"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36"},
},
}
opts = setAcceptEncodingForPushOptions(opts)
assert.NotNil(t, opts)
assert.NotNil(t, opts.Header)
assert.Equal(t, "gzip", opts.Header.Get("Accept-Encoding"))
assert.Equal(t, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36", opts.Header.Get("User-Agent"))
opts = &http.PushOptions{
Header: http.Header{
"User-Agent": []string{"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36"},
acceptEncoding: []string{"deflate"},
},
}
opts = setAcceptEncodingForPushOptions(opts)
assert.NotNil(t, opts)
assert.NotNil(t, opts.Header)
e, found := opts.Header["Accept-Encoding"]
if !found {
assert.Fail(t, "Missing Accept-Encoding header value")
}
assert.Len(t, e, 1)
assert.Equal(t, "deflate", e[0])
assert.Equal(t, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36", opts.Header.Get("User-Agent"))
}

69
vendor/github.com/NYTimes/gziphandler/gzip_test.go сгенерированный поставляемый
Просмотреть файл

@@ -16,8 +16,12 @@ import (
"github.com/stretchr/testify/assert"
)
func TestParseEncodings(t *testing.T) {
const (
smallTestBody = "aaabbcaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbccc"
testBody = "aaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbccc"
)
func TestParseEncodings(t *testing.T) {
examples := map[string]codings{
// Examples from RFC 2616
@@ -39,8 +43,6 @@ func TestParseEncodings(t *testing.T) {
}
func TestGzipHandler(t *testing.T) {
testBody := "aaabbbccc"
// This just exists to provide something for GzipHandler to wrap.
handler := newTestHandler(testBody)
@@ -80,7 +82,6 @@ func TestGzipHandler(t *testing.T) {
}
func TestNewGzipLevelHandler(t *testing.T) {
testBody := "aaabbbccc"
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
io.WriteString(w, testBody)
@@ -102,7 +103,6 @@ func TestNewGzipLevelHandler(t *testing.T) {
assert.Equal(t, "gzip", res.Header.Get("Content-Encoding"))
assert.Equal(t, "Accept-Encoding", res.Header.Get("Vary"))
assert.Equal(t, gzipStrLevel(testBody, lvl), resp.Body.Bytes())
}
}
@@ -135,7 +135,7 @@ func TestGzipHandlerNoBody(t *testing.T) {
{http.StatusNoContent, "", 0},
{http.StatusNotModified, "", 0},
// Body is going to get gzip'd no matter what.
{http.StatusOK, "gzip", 23},
{http.StatusOK, "", 0},
}
for num, test := range tests {
@@ -170,7 +170,7 @@ func TestGzipHandlerNoBody(t *testing.T) {
}
func TestGzipHandlerContentLength(t *testing.T) {
b := []byte("testtesttesttesttesttesttesttesttesttesttesttesttest")
b := []byte(testBody)
handler := GzipHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Length", strconv.Itoa(len(b)))
w.Write(b)
@@ -215,6 +215,48 @@ func TestGzipHandlerContentLength(t *testing.T) {
assert.NotEqual(t, b, body)
}
func TestGzipHandlerMinSizeMustBePositive(t *testing.T) {
_, err := NewGzipLevelAndMinSize(gzip.DefaultCompression, -1)
assert.Error(t, err)
}
func TestGzipHandlerMinSize(t *testing.T) {
responseLength := 0
b := []byte{'x'}
wrapper, _ := NewGzipLevelAndMinSize(gzip.DefaultCompression, 128)
handler := wrapper(http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
// Write responses one byte at a time to ensure that the flush
// mechanism, if used, is working properly.
for i := 0; i < responseLength; i++ {
n, err := w.Write(b)
assert.Equal(t, 1, n)
assert.Nil(t, err)
}
},
))
r, _ := http.NewRequest("GET", "/whatever", &bytes.Buffer{})
r.Header.Add("Accept-Encoding", "gzip")
// Short response is not compressed
responseLength = 127
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
if w.Result().Header.Get(contentEncoding) == "gzip" {
t.Error("Expected uncompressed response, got compressed")
}
// Long response is not compressed
responseLength = 128
w = httptest.NewRecorder()
handler.ServeHTTP(w, r)
if w.Result().Header.Get(contentEncoding) != "gzip" {
t.Error("Expected compressed response, got uncompressed")
}
}
func TestGzipDoubleClose(t *testing.T) {
// reset the pool for the default compression so we can make sure duplicates
// aren't added back by double close
@@ -240,6 +282,19 @@ func TestGzipDoubleClose(t *testing.T) {
assert.False(t, w1 == w2)
}
func TestStatusCodes(t *testing.T) {
handler := GzipHandler(http.NotFoundHandler())
r := httptest.NewRequest("GET", "/", nil)
r.Header.Set("Accept-Encoding", "gzip")
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
result := w.Result()
if result.StatusCode != 404 {
t.Errorf("StatusCode should have been 404 but was %d", result.StatusCode)
}
}
// --------------------------------------------------------------------
func BenchmarkGzipHandler_S2k(b *testing.B) { benchmark(b, false, 2048) }

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@@ -1,8 +1,12 @@
# html2text
[![Documentation](https://godoc.org/github.com/jaytaylor/html2text?status.svg)](https://godoc.org/github.com/jaytaylor/html2text)
[![Build Status](https://travis-ci.org/jaytaylor/html2text.svg?branch=master)](https://travis-ci.org/jaytaylor/html2text)
[![Report Card](https://goreportcard.com/badge/github.com/jaytaylor/html2text)](https://goreportcard.com/report/github.com/jaytaylor/html2text)
[![Documentation](https://godoc.org/github.com/cpanato/html2text?status.svg)](https://godoc.org/github.com/cpanato/html2text)
[![Build Status](https://travis-ci.org/cpanato/html2text.svg?branch=master)](https://travis-ci.org/cpanato/html2text)
[![Report Card](https://goreportcard.com/badge/github.com/jaytaylor/html2text)](https://goreportcard.com/report/github.com/cpanato/html2text)
### Initial information
This project was forked from [github.com/jaytaylor/html2text](https://github.com/jaytaylor/html2text) in order to use another clean bom library due the original one has no license.
### Converts HTML into text
@@ -23,7 +27,7 @@ It requires go 1.x or newer ;)
## Download the package
```bash
go get github.com/jaytaylor/html2text
go get github.com/cpanato/html2text
```
## Example usage
@@ -34,7 +38,7 @@ package main
import (
"fmt"
"github.com/jaytaylor/html2text"
"github.com/cpanato/html2text"
)
func main() {
@@ -45,17 +49,17 @@ func main() {
<link rel=\"stylesheet\" href=\"main.css\">
<style type=\"text/css\">body { color: #fff; }</style>
</head>
<body>
<div class="logo">
<a href="http://mymegaservice.com/"><img src="/logo-image.jpg" alt="Mega Service"/></a>
</div>
<h1>Welcome to your new account on my service!</h1>
<p>
Here is some more information:
<ul>
<li>Link 1: <a href="https://example.com">Example.com</a></li>
<li>Link 2: <a href="https://example2.com">Example2.com</a></li>
@@ -102,15 +106,3 @@ go test
# License
Permissive MIT license.
## Contact
You are more than welcome to open issues and send pull requests if you find a bug or want a new feature.
If you appreciate this library please feel free to drop me a line and tell me! It's always nice to hear from people who have benefitted from my work.
Email: jay at (my github username).com
Twitter: [@jtaylor](https://twitter.com/jtaylor)

Просмотреть файл

@@ -3,11 +3,12 @@ package html2text
import (
"bytes"
"io"
"io/ioutil"
"regexp"
"strings"
"unicode"
"github.com/ssor/bom"
"github.com/dimchansky/utfbom"
"golang.org/x/net/html"
"golang.org/x/net/html/atom"
@@ -291,10 +292,9 @@ func FromHtmlNode(doc *html.Node) (string, error) {
}
func FromReader(reader io.Reader) (string, error) {
newReader, err := bom.NewReaderWithoutBom(reader)
if err != nil {
return "", err
}
bs, err := ioutil.ReadAll(reader)
newReader, _ := utfbom.Skip(bytes.NewReader(bs))
doc, err := html.Parse(newReader)
if err != nil {
return "", err
@@ -303,8 +303,8 @@ func FromReader(reader io.Reader) (string, error) {
}
func FromString(input string) (string, error) {
bs := bom.CleanBom([]byte(input))
text, err := FromReader(bytes.NewReader(bs))
bs := utfbom.SkipOnly(bytes.NewReader([]byte(input)))
text, err := FromReader(bs)
if err != nil {
return "", err
}

Просмотреть файл

Просмотреть файл

Просмотреть файл

1
vendor/github.com/disintegration/imaging/.travis.yml сгенерированный поставляемый
Просмотреть файл

@@ -9,6 +9,7 @@ go:
- 1.5
- 1.6
- 1.7
- 1.8
before_install:
- go get golang.org/x/tools/cmd/cover

2
vendor/github.com/disintegration/imaging/LICENSE сгенерированный поставляемый
Просмотреть файл

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2012-2014 Grigory Dryapak
Copyright (c) 2012-2017 Grigory Dryapak
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

181
vendor/github.com/disintegration/imaging/README.md сгенерированный поставляемый
Просмотреть файл

@@ -26,17 +26,18 @@ http://godoc.org/github.com/disintegration/imaging
A few usage examples can be found below. See the documentation for the full list of supported functions.
### Image resizing
```go
// resize srcImage to size = 128x128px using the Lanczos filter
// Resize srcImage to size = 128x128px using the Lanczos filter.
dstImage128 := imaging.Resize(srcImage, 128, 128, imaging.Lanczos)
// resize srcImage to width = 800px preserving the aspect ratio
// Resize srcImage to width = 800px preserving the aspect ratio.
dstImage800 := imaging.Resize(srcImage, 800, 0, imaging.Lanczos)
// scale down srcImage to fit the 800x600px bounding box
// Scale down srcImage to fit the 800x600px bounding box.
dstImageFit := imaging.Fit(srcImage, 800, 600, imaging.Lanczos)
// resize and crop the srcImage to fill the 100x100px area
// Resize and crop the srcImage to fill the 100x100px area.
dstImageFill := imaging.Fill(srcImage, 100, 100, imaging.Center, imaging.Lanczos)
```
@@ -53,146 +54,138 @@ The full list of supported filters: NearestNeighbor, Box, Linear, Hermite, Mitc
**Resampling filters comparison**
Original image. Will be resized from 512x512px to 128x128px.
The original image.
![srcImage](http://disintegration.github.io/imaging/in_lena_bw_512.png)
![srcImage](testdata/lena_512.png)
Filter | Resize result
---|---
`imaging.NearestNeighbor` | ![dstImage](http://disintegration.github.io/imaging/out_resize_down_nearest.png)
`imaging.Box` | ![dstImage](http://disintegration.github.io/imaging/out_resize_down_box.png)
`imaging.Linear` | ![dstImage](http://disintegration.github.io/imaging/out_resize_down_linear.png)
`imaging.MitchellNetravali` | ![dstImage](http://disintegration.github.io/imaging/out_resize_down_mitchell.png)
`imaging.CatmullRom` | ![dstImage](http://disintegration.github.io/imaging/out_resize_down_catrom.png)
`imaging.Gaussian` | ![dstImage](http://disintegration.github.io/imaging/out_resize_down_gaussian.png)
`imaging.Lanczos` | ![dstImage](http://disintegration.github.io/imaging/out_resize_down_lanczos.png)
The same image resized from 512x512px to 128x128px using different resampling filters.
From faster (lower quality) to slower (higher quality):
**Resize functions comparison**
Filter | Resize result
--------------------------|---------------------------------------------
`imaging.NearestNeighbor` | ![dstImage](testdata/out_resize_nearest.png)
`imaging.Linear` | ![dstImage](testdata/out_resize_linear.png)
`imaging.CatmullRom` | ![dstImage](testdata/out_resize_catrom.png)
`imaging.Lanczos` | ![dstImage](testdata/out_resize_lanczos.png)
Original image:
![srcImage](http://disintegration.github.io/imaging/in.jpg)
Resize the image to width=100px and height=100px:
```go
dstImage := imaging.Resize(srcImage, 100, 100, imaging.Lanczos)
```
![dstImage](http://disintegration.github.io/imaging/out-comp-resize.jpg)
Resize the image to width=100px preserving the aspect ratio:
```go
dstImage := imaging.Resize(srcImage, 100, 0, imaging.Lanczos)
```
![dstImage](http://disintegration.github.io/imaging/out-comp-fit.jpg)
Resize the image to fit the 100x100px boundng box preserving the aspect ratio:
```go
dstImage := imaging.Fit(srcImage, 100, 100, imaging.Lanczos)
```
![dstImage](http://disintegration.github.io/imaging/out-comp-fit.jpg)
Resize and crop the image with a center anchor point to fill the 100x100px area:
```go
dstImage := imaging.Fill(srcImage, 100, 100, imaging.Center, imaging.Lanczos)
```
![dstImage](http://disintegration.github.io/imaging/out-comp-fill.jpg)
### Gaussian Blur
```go
dstImage := imaging.Blur(srcImage, 0.5)
```
Sigma parameter allows to control the strength of the blurring effect.
Original image | Sigma = 0.5 | Sigma = 1.5
---|---|---
![srcImage](http://disintegration.github.io/imaging/in_lena_bw_128.png) | ![dstImage](http://disintegration.github.io/imaging/out_blur_0.5.png) | ![dstImage](http://disintegration.github.io/imaging/out_blur_1.5.png)
Original image | Sigma = 0.5 | Sigma = 1.5
-----------------------------------|----------------------------------------|---------------------------------------
![srcImage](testdata/lena_128.png) | ![dstImage](testdata/out_blur_0.5.png) | ![dstImage](testdata/out_blur_1.5.png)
### Sharpening
```go
dstImage := imaging.Sharpen(srcImage, 0.5)
```
Uses gaussian function internally. Sigma parameter allows to control the strength of the sharpening effect.
`Sharpen` uses gaussian function internally. Sigma parameter allows to control the strength of the sharpening effect.
Original image | Sigma = 0.5 | Sigma = 1.5
---|---|---
![srcImage](http://disintegration.github.io/imaging/in_lena_bw_128.png) | ![dstImage](http://disintegration.github.io/imaging/out_sharpen_0.5.png) | ![dstImage](http://disintegration.github.io/imaging/out_sharpen_1.5.png)
Original image | Sigma = 0.5 | Sigma = 1.5
-----------------------------------|-------------------------------------------|------------------------------------------
![srcImage](testdata/lena_128.png) | ![dstImage](testdata/out_sharpen_0.5.png) | ![dstImage](testdata/out_sharpen_1.5.png)
### Gamma correction
```go
dstImage := imaging.AdjustGamma(srcImage, 0.75)
```
Original image | Gamma = 0.75 | Gamma = 1.25
---|---|---
![srcImage](http://disintegration.github.io/imaging/in_lena_bw_128.png) | ![dstImage](http://disintegration.github.io/imaging/out_gamma_0.75.png) | ![dstImage](http://disintegration.github.io/imaging/out_gamma_1.25.png)
Original image | Gamma = 0.75 | Gamma = 1.25
-----------------------------------|------------------------------------------|-----------------------------------------
![srcImage](testdata/lena_128.png) | ![dstImage](testdata/out_gamma_0.75.png) | ![dstImage](testdata/out_gamma_1.25.png)
### Contrast adjustment
```go
dstImage := imaging.AdjustContrast(srcImage, 20)
```
Original image | Contrast = 20 | Contrast = -20
---|---|---
![srcImage](http://disintegration.github.io/imaging/in_lena_bw_128.png) | ![dstImage](http://disintegration.github.io/imaging/out_contrast_p20.png) | ![dstImage](http://disintegration.github.io/imaging/out_contrast_m20.png)
Original image | Contrast = 10 | Contrast = -10
-----------------------------------|--------------------------------------------|-------------------------------------------
![srcImage](testdata/lena_128.png) | ![dstImage](testdata/out_contrast_p10.png) | ![dstImage](testdata/out_contrast_m10.png)
### Brightness adjustment
```go
dstImage := imaging.AdjustBrightness(srcImage, 20)
```
Original image | Brightness = 20 | Brightness = -20
---|---|---
![srcImage](http://disintegration.github.io/imaging/in_lena_bw_128.png) | ![dstImage](http://disintegration.github.io/imaging/out_brightness_p20.png) | ![dstImage](http://disintegration.github.io/imaging/out_brightness_m20.png)
Original image | Brightness = 10 | Brightness = -10
-----------------------------------|----------------------------------------------|---------------------------------------------
![srcImage](testdata/lena_128.png) | ![dstImage](testdata/out_brightness_p10.png) | ![dstImage](testdata/out_brightness_m10.png)
### Complete code example
Here is the code example that loads several images, makes thumbnails of them
and combines them together side-by-side.
## Example code
```go
package main
import (
"image"
"image/color"
"github.com/disintegration/imaging"
"image"
"image/color"
"log"
"github.com/disintegration/imaging"
)
func main() {
// Open the test image.
src, err := imaging.Open("testdata/lena_512.png")
if err != nil {
log.Fatalf("Open failed: %v", err)
}
// input files
files := []string{"01.jpg", "02.jpg", "03.jpg"}
// Crop the original image to 350x350px size using the center anchor.
src = imaging.CropAnchor(src, 350, 350, imaging.Center)
// load images and make 100x100 thumbnails of them
var thumbnails []image.Image
for _, file := range files {
img, err := imaging.Open(file)
if err != nil {
panic(err)
}
thumb := imaging.Thumbnail(img, 100, 100, imaging.CatmullRom)
thumbnails = append(thumbnails, thumb)
}
// Resize the cropped image to width = 256px preserving the aspect ratio.
src = imaging.Resize(src, 256, 0, imaging.Lanczos)
// create a new blank image
dst := imaging.New(100*len(thumbnails), 100, color.NRGBA{0, 0, 0, 0})
// Create a blurred version of the image.
img1 := imaging.Blur(src, 2)
// paste thumbnails into the new image side by side
for i, thumb := range thumbnails {
dst = imaging.Paste(dst, thumb, image.Pt(i*100, 0))
}
// Create a grayscale version of the image with higher contrast and sharpness.
img2 := imaging.Grayscale(src)
img2 = imaging.AdjustContrast(img2, 20)
img2 = imaging.Sharpen(img2, 2)
// save the combined image to file
err := imaging.Save(dst, "dst.jpg")
if err != nil {
panic(err)
}
// Create an inverted version of the image.
img3 := imaging.Invert(src)
// Create an embossed version of the image using a convolution filter.
img4 := imaging.Convolve3x3(
src,
[9]float64{
-1, -1, 0,
-1, 1, 1,
0, 1, 1,
},
nil,
)
// Create a new image and paste the four produced images into it.
dst := imaging.New(512, 512, color.NRGBA{0, 0, 0, 0})
dst = imaging.Paste(dst, img1, image.Pt(0, 0))
dst = imaging.Paste(dst, img2, image.Pt(0, 256))
dst = imaging.Paste(dst, img3, image.Pt(256, 0))
dst = imaging.Paste(dst, img4, image.Pt(256, 256))
// Save the resulting image using JPEG format.
err = imaging.Save(dst, "testdata/out_example.jpg")
if err != nil {
log.Fatalf("Save failed: %v", err)
}
}
```
Output:
![dstImage](testdata/out_example.jpg)

60
vendor/github.com/disintegration/imaging/adjust_test.go сгенерированный поставляемый
Просмотреть файл

@@ -206,6 +206,26 @@ func TestAdjustContrast(t *testing.T) {
}
}
func TestAdjustContrastGolden(t *testing.T) {
src, err := Open("testdata/lena_128.png")
if err != nil {
t.Errorf("Open: %v", err)
}
for name, p := range map[string]float64{
"out_contrast_m10.png": -10,
"out_contrast_p10.png": 10,
} {
got := AdjustContrast(src, p)
want, err := Open("testdata/" + name)
if err != nil {
t.Errorf("Open: %v", err)
}
if !compareNRGBA(got, toNRGBA(want), 0) {
t.Errorf("resulting image differs from golden: %s", name)
}
}
}
func TestAdjustBrightness(t *testing.T) {
td := []struct {
desc string
@@ -333,6 +353,26 @@ func TestAdjustBrightness(t *testing.T) {
}
}
func TestAdjustBrightnessGolden(t *testing.T) {
src, err := Open("testdata/lena_128.png")
if err != nil {
t.Errorf("Open: %v", err)
}
for name, p := range map[string]float64{
"out_brightness_m10.png": -10,
"out_brightness_p10.png": 10,
} {
got := AdjustBrightness(src, p)
want, err := Open("testdata/" + name)
if err != nil {
t.Errorf("Open: %v", err)
}
if !compareNRGBA(got, toNRGBA(want), 0) {
t.Errorf("resulting image differs from golden: %s", name)
}
}
}
func TestAdjustGamma(t *testing.T) {
td := []struct {
desc string
@@ -416,6 +456,26 @@ func TestAdjustGamma(t *testing.T) {
}
}
func TestAdjustGammaGolden(t *testing.T) {
src, err := Open("testdata/lena_128.png")
if err != nil {
t.Errorf("Open: %v", err)
}
for name, g := range map[string]float64{
"out_gamma_0.75.png": 0.75,
"out_gamma_1.25.png": 1.25,
} {
got := AdjustGamma(src, g)
want, err := Open("testdata/" + name)
if err != nil {
t.Errorf("Open: %v", err)
}
if !compareNRGBA(got, toNRGBA(want), 0) {
t.Errorf("resulting image differs from golden: %s", name)
}
}
}
func TestAdjustSigmoid(t *testing.T) {
td := []struct {
desc string

148
vendor/github.com/disintegration/imaging/convolution.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,148 @@
package imaging
import (
"image"
)
// ConvolveOptions are convolution parameters.
type ConvolveOptions struct {
// If Normalize is true the kernel is normalized before convolution.
Normalize bool
// If Abs is true the absolute value of each color channel is taken after convolution.
Abs bool
// Bias is added to each color channel value after convolution.
Bias int
}
// Convolve3x3 convolves the image with the specified 3x3 convolution kernel.
// Default parameters are used if a nil *ConvolveOptions is passed.
func Convolve3x3(img image.Image, kernel [9]float64, options *ConvolveOptions) *image.NRGBA {
return convolve(img, kernel[:], options)
}
// Convolve5x5 convolves the image with the specified 5x5 convolution kernel.
// Default parameters are used if a nil *ConvolveOptions is passed.
func Convolve5x5(img image.Image, kernel [25]float64, options *ConvolveOptions) *image.NRGBA {
return convolve(img, kernel[:], options)
}
func convolve(img image.Image, kernel []float64, options *ConvolveOptions) *image.NRGBA {
src := toNRGBA(img)
w := src.Bounds().Max.X
h := src.Bounds().Max.Y
dst := image.NewNRGBA(image.Rect(0, 0, w, h))
if w < 1 || h < 1 {
return dst
}
if options == nil {
options = &ConvolveOptions{}
}
if options.Normalize {
normalizeKernel(kernel)
}
type coef struct {
x, y int
k float64
}
var coefs []coef
var m int
switch len(kernel) {
case 9:
m = 1
case 25:
m = 2
default:
return dst
}
i := 0
for y := -m; y <= m; y++ {
for x := -m; x <= m; x++ {
if kernel[i] != 0 {
coefs = append(coefs, coef{x: x, y: y, k: kernel[i]})
}
i++
}
}
parallel(h, func(partStart, partEnd int) {
for y := partStart; y < partEnd; y++ {
for x := 0; x < w; x++ {
var r, g, b float64
for _, c := range coefs {
ix := x + c.x
if ix < 0 {
ix = 0
} else if ix >= w {
ix = w - 1
}
iy := y + c.y
if iy < 0 {
iy = 0
} else if iy >= h {
iy = h - 1
}
off := iy*src.Stride + ix*4
r += float64(src.Pix[off+0]) * c.k
g += float64(src.Pix[off+1]) * c.k
b += float64(src.Pix[off+2]) * c.k
}
if options.Abs {
if r < 0 {
r = -r
}
if g < 0 {
g = -g
}
if b < 0 {
b = -b
}
}
if options.Bias != 0 {
r += float64(options.Bias)
g += float64(options.Bias)
b += float64(options.Bias)
}
srcOff := y*src.Stride + x*4
dstOff := y*dst.Stride + x*4
dst.Pix[dstOff+0] = clamp(r)
dst.Pix[dstOff+1] = clamp(g)
dst.Pix[dstOff+2] = clamp(b)
dst.Pix[dstOff+3] = src.Pix[srcOff+3]
}
}
})
return dst
}
func normalizeKernel(kernel []float64) {
var sum, sumpos float64
for i := range kernel {
sum += kernel[i]
if kernel[i] > 0 {
sumpos += kernel[i]
}
}
if sum != 0 {
for i := range kernel {
kernel[i] /= sum
}
} else if sumpos != 0 {
for i := range kernel {
kernel[i] /= sumpos
}
}
}

275
vendor/github.com/disintegration/imaging/convolution_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,275 @@
package imaging
import (
"image"
"testing"
)
func TestConvolve3x3(t *testing.T) {
testCases := []struct {
desc string
src image.Image
kernel [9]float64
options *ConvolveOptions
want *image.NRGBA
}{
{
"Convolve3x3 0x0",
&image.NRGBA{
Rect: image.Rect(0, 0, 0, 0),
Stride: 0,
Pix: []uint8{},
},
[9]float64{
0, 0, 0,
0, 1, 0,
0, 0, 0,
},
nil,
&image.NRGBA{Rect: image.Rect(0, 0, 0, 0)},
},
{
"Convolve3x3 4x4 identity",
&image.NRGBA{
Rect: image.Rect(-1, -1, 3, 3),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
[9]float64{
0, 0, 0,
0, 1, 0,
0, 0, 0,
},
nil,
&image.NRGBA{
Rect: image.Rect(0, 0, 4, 4),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
},
{
"Convolve3x3 4x4 abs",
&image.NRGBA{
Rect: image.Rect(-1, -1, 3, 3),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
[9]float64{
0, 0, 0,
0, -1, 0,
0, 0, 0,
},
&ConvolveOptions{Abs: true},
&image.NRGBA{
Rect: image.Rect(0, 0, 4, 4),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
},
{
"Convolve3x3 4x4 bias",
&image.NRGBA{
Rect: image.Rect(-1, -1, 3, 3),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
[9]float64{
0, 0, 0,
0, 1, 0,
0, 0, 0,
},
&ConvolveOptions{Bias: 0x10},
&image.NRGBA{
Rect: image.Rect(0, 0, 4, 4),
Stride: 4 * 4,
Pix: []uint8{
0x10, 0x11, 0x12, 0x03, 0x14, 0x15, 0x16, 0x07, 0x18, 0x19, 0x1a, 0x0b, 0x1c, 0x1d, 0x1e, 0x0f,
0x20, 0x21, 0x22, 0x13, 0x24, 0x25, 0x26, 0x17, 0x28, 0x29, 0x2a, 0x1b, 0x2c, 0x2d, 0x2e, 0x1f,
0x30, 0x31, 0x32, 0x23, 0x34, 0x35, 0x36, 0x27, 0x38, 0x39, 0x3a, 0x2b, 0x3c, 0x3d, 0x3e, 0x2f,
0x40, 0x41, 0x42, 0x33, 0x44, 0x45, 0x46, 0x37, 0x48, 0x49, 0x4a, 0x3b, 0x4c, 0x4d, 0x4e, 0x3f,
},
},
},
{
"Convolve3x3 4x4 norm",
&image.NRGBA{
Rect: image.Rect(-1, -1, 3, 3),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
[9]float64{
1, 1, 1,
1, 1, 1,
1, 1, 1,
},
&ConvolveOptions{Normalize: true},
&image.NRGBA{
Rect: image.Rect(0, 0, 4, 4),
Stride: 4 * 4,
Pix: []uint8{
0x07, 0x08, 0x09, 0x03, 0x09, 0x0a, 0x0b, 0x07, 0x0d, 0x0e, 0x0f, 0x0b, 0x10, 0x11, 0x12, 0x0f,
0x11, 0x12, 0x13, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1b, 0x1c, 0x1d, 0x1f,
0x21, 0x22, 0x23, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2b, 0x2c, 0x2d, 0x2f,
0x2c, 0x2d, 0x2e, 0x33, 0x2f, 0x30, 0x31, 0x37, 0x33, 0x34, 0x35, 0x3b, 0x35, 0x36, 0x37, 0x3f,
},
},
},
{
"Convolve3x3 3x3 laplacian",
&image.NRGBA{
Rect: image.Rect(-1, -1, 2, 2),
Stride: 3 * 4,
Pix: []uint8{
0x00, 0x01, 0x01, 0xff, 0x00, 0x01, 0x02, 0xff, 0x00, 0x01, 0x03, 0xff,
0x00, 0x01, 0x04, 0xff, 0x10, 0x10, 0x10, 0xff, 0x00, 0x01, 0x05, 0xff,
0x00, 0x01, 0x06, 0xff, 0x00, 0x01, 0x07, 0xff, 0x00, 0x01, 0x08, 0xff,
},
},
[9]float64{
-1, -1, -1,
-1, 8, -1,
-1, -1, -1,
},
nil,
&image.NRGBA{
Rect: image.Rect(0, 0, 3, 3),
Stride: 3 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0xff, 0x80, 0x78, 0x5c, 0xff, 0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
},
},
},
}
for _, tc := range testCases {
got := Convolve3x3(tc.src, tc.kernel, tc.options)
want := tc.want
if !compareNRGBA(got, want, 0) {
t.Errorf("test [%s] failed: want %#v got %#v", tc.desc, want, got)
}
}
}
func TestConvolve5x5(t *testing.T) {
testCases := []struct {
desc string
src image.Image
kernel [25]float64
options *ConvolveOptions
want *image.NRGBA
}{
{
"Convolve5x5 4x4 translate",
&image.NRGBA{
Rect: image.Rect(-1, -1, 3, 3),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
[25]float64{
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 1,
},
nil,
&image.NRGBA{
Rect: image.Rect(0, 0, 4, 4),
Stride: 4 * 4,
Pix: []uint8{
0x28, 0x29, 0x2a, 0x03, 0x2c, 0x2d, 0x2e, 0x07, 0x2c, 0x2d, 0x2e, 0x0b, 0x2c, 0x2d, 0x2e, 0x0f,
0x38, 0x39, 0x3a, 0x13, 0x3c, 0x3d, 0x3e, 0x17, 0x3c, 0x3d, 0x3e, 0x1b, 0x3c, 0x3d, 0x3e, 0x1f,
0x38, 0x39, 0x3a, 0x23, 0x3c, 0x3d, 0x3e, 0x27, 0x3c, 0x3d, 0x3e, 0x2b, 0x3c, 0x3d, 0x3e, 0x2f,
0x38, 0x39, 0x3a, 0x33, 0x3c, 0x3d, 0x3e, 0x37, 0x3c, 0x3d, 0x3e, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
},
}
for _, tc := range testCases {
got := Convolve5x5(tc.src, tc.kernel, tc.options)
want := tc.want
if !compareNRGBA(got, want, 0) {
t.Errorf("test [%s] failed: want %#v got %#v", tc.desc, want, got)
}
}
}
func BenchmarkConvolve3x3(b *testing.B) {
b.StopTimer()
img, err := Open("testdata/lena_512.png")
if err != nil {
b.Fatalf("Open: %v", err)
}
b.StartTimer()
for i := 0; i < b.N; i++ {
Convolve3x3(
img,
[9]float64{
-1, -1, 0,
-1, 0, 1,
0, 1, 1,
},
nil,
)
}
}
func BenchmarkConvolve5x5(b *testing.B) {
b.StopTimer()
img, err := Open("testdata/lena_512.png")
if err != nil {
b.Fatalf("Open: %v", err)
}
b.StartTimer()
for i := 0; i < b.N; i++ {
Convolve5x5(
img,
[25]float64{
-1, -1, -1, -1, 0,
-1, -1, -1, 0, 1,
-1, -1, 0, 1, 1,
-1, 0, 1, 1, 1,
0, 1, 1, 1, 1,
},
nil,
)
}
}

36
vendor/github.com/disintegration/imaging/effects.go сгенерированный поставляемый
Просмотреть файл

@@ -62,8 +62,7 @@ func blurHorizontal(src *image.NRGBA, kernel []float64) *image.NRGBA {
}
for y := 0; y < height; y++ {
r, g, b, a := 0.0, 0.0, 0.0, 0.0
var r, g, b, a float64
for ix := start; ix <= end; ix++ {
weight := kernel[absint(x-ix)]
i := y*src.Stride + ix*4
@@ -74,17 +73,11 @@ func blurHorizontal(src *image.NRGBA, kernel []float64) *image.NRGBA {
a += wa
}
r = math.Min(math.Max(r/a, 0.0), 255.0)
g = math.Min(math.Max(g/a, 0.0), 255.0)
b = math.Min(math.Max(b/a, 0.0), 255.0)
a = math.Min(math.Max(a/weightSum, 0.0), 255.0)
j := y*dst.Stride + x*4
dst.Pix[j+0] = uint8(r + 0.5)
dst.Pix[j+1] = uint8(g + 0.5)
dst.Pix[j+2] = uint8(b + 0.5)
dst.Pix[j+3] = uint8(a + 0.5)
dst.Pix[j+0] = clamp(r / a)
dst.Pix[j+1] = clamp(g / a)
dst.Pix[j+2] = clamp(b / a)
dst.Pix[j+3] = clamp(a / weightSum)
}
}
})
@@ -117,8 +110,7 @@ func blurVertical(src *image.NRGBA, kernel []float64) *image.NRGBA {
}
for x := 0; x < width; x++ {
r, g, b, a := 0.0, 0.0, 0.0, 0.0
var r, g, b, a float64
for iy := start; iy <= end; iy++ {
weight := kernel[absint(y-iy)]
i := iy*src.Stride + x*4
@@ -129,17 +121,11 @@ func blurVertical(src *image.NRGBA, kernel []float64) *image.NRGBA {
a += wa
}
r = math.Min(math.Max(r/a, 0.0), 255.0)
g = math.Min(math.Max(g/a, 0.0), 255.0)
b = math.Min(math.Max(b/a, 0.0), 255.0)
a = math.Min(math.Max(a/weightSum, 0.0), 255.0)
j := y*dst.Stride + x*4
dst.Pix[j+0] = uint8(r + 0.5)
dst.Pix[j+1] = uint8(g + 0.5)
dst.Pix[j+2] = uint8(b + 0.5)
dst.Pix[j+3] = uint8(a + 0.5)
dst.Pix[j+0] = clamp(r / a)
dst.Pix[j+1] = clamp(g / a)
dst.Pix[j+2] = clamp(b / a)
dst.Pix[j+3] = clamp(a / weightSum)
}
}
})
@@ -173,7 +159,7 @@ func Sharpen(img image.Image, sigma float64) *image.NRGBA {
i := y*src.Stride + x*4
for j := 0; j < 4; j++ {
k := i + j
val := int(src.Pix[k]) + (int(src.Pix[k]) - int(blurred.Pix[k]))
val := int(src.Pix[k])<<1 - int(blurred.Pix[k])
if val < 0 {
val = 0
} else if val > 255 {

64
vendor/github.com/disintegration/imaging/effects_test.go сгенерированный поставляемый
Просмотреть файл

@@ -88,6 +88,38 @@ func TestBlur(t *testing.T) {
}
}
func TestBlurGolden(t *testing.T) {
src, err := Open("testdata/lena_128.png")
if err != nil {
t.Errorf("Open: %v", err)
}
for name, sigma := range map[string]float64{
"out_blur_0.5.png": 0.5,
"out_blur_1.5.png": 1.5,
} {
got := Blur(src, sigma)
want, err := Open("testdata/" + name)
if err != nil {
t.Errorf("Open: %v", err)
}
if !compareNRGBA(got, toNRGBA(want), 0) {
t.Errorf("resulting image differs from golden: %s", name)
}
}
}
func BenchmarkBlur(b *testing.B) {
b.StopTimer()
img, err := Open("testdata/lena_512.png")
if err != nil {
b.Fatalf("Open: %v", err)
}
b.StartTimer()
for i := 0; i < b.N; i++ {
Blur(img, 3)
}
}
func TestSharpen(t *testing.T) {
td := []struct {
desc string
@@ -188,3 +220,35 @@ func TestSharpen(t *testing.T) {
}
}
}
func TestSharpenGolden(t *testing.T) {
src, err := Open("testdata/lena_128.png")
if err != nil {
t.Errorf("Open: %v", err)
}
for name, sigma := range map[string]float64{
"out_sharpen_0.5.png": 0.5,
"out_sharpen_1.5.png": 1.5,
} {
got := Sharpen(src, sigma)
want, err := Open("testdata/" + name)
if err != nil {
t.Errorf("Open: %v", err)
}
if !compareNRGBA(got, toNRGBA(want), 0) {
t.Errorf("resulting image differs from golden: %s", name)
}
}
}
func BenchmarkSharpen(b *testing.B) {
b.StopTimer()
img, err := Open("testdata/lena_512.png")
if err != nil {
b.Fatalf("Open: %v", err)
}
b.StartTimer()
for i := 0; i < b.N; i++ {
Sharpen(img, 3)
}
}

58
vendor/github.com/disintegration/imaging/example_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,58 @@
package imaging_test
import (
"image"
"image/color"
"log"
"github.com/disintegration/imaging"
)
func Example() {
// Open the test image.
src, err := imaging.Open("testdata/lena_512.png")
if err != nil {
log.Fatalf("Open failed: %v", err)
}
// Crop the original image to 350x350px size using the center anchor.
src = imaging.CropAnchor(src, 350, 350, imaging.Center)
// Resize the cropped image to width = 256px preserving the aspect ratio.
src = imaging.Resize(src, 256, 0, imaging.Lanczos)
// Create a blurred version of the image.
img1 := imaging.Blur(src, 2)
// Create a grayscale version of the image with higher contrast and sharpness.
img2 := imaging.Grayscale(src)
img2 = imaging.AdjustContrast(img2, 20)
img2 = imaging.Sharpen(img2, 2)
// Create an inverted version of the image.
img3 := imaging.Invert(src)
// Create an embossed version of the image using a convolution filter.
img4 := imaging.Convolve3x3(
src,
[9]float64{
-1, -1, 0,
-1, 1, 1,
0, 1, 1,
},
nil,
)
// Create a new image and paste the four produced images into it.
dst := imaging.New(512, 512, color.NRGBA{0, 0, 0, 0})
dst = imaging.Paste(dst, img1, image.Pt(0, 0))
dst = imaging.Paste(dst, img2, image.Pt(0, 256))
dst = imaging.Paste(dst, img3, image.Pt(256, 0))
dst = imaging.Paste(dst, img4, image.Pt(256, 256))
// Save the resulting image using JPEG format.
err = imaging.Save(dst, "testdata/out_example.jpg")
if err != nil {
log.Fatalf("Save failed: %v", err)
}
}

44
vendor/github.com/disintegration/imaging/helpers.go сгенерированный поставляемый
Просмотреть файл

@@ -1,11 +1,9 @@
/*
Package imaging provides basic image manipulation functions (resize, rotate, flip, crop, etc.).
This package is based on the standard Go image package and works best along with it.
Image manipulation functions provided by the package take any image type
that implements `image.Image` interface as an input, and return a new image of
`*image.NRGBA` type (32bit RGBA colors, not premultiplied by alpha).
*/
// Package imaging provides basic image manipulation functions (resize, rotate, flip, crop, etc.).
// This package is based on the standard Go image package and works best along with it.
//
// Image manipulation functions provided by the package take any image type
// that implements `image.Image` interface as an input, and return a new image of
// `*image.NRGBA` type (32bit RGBA colors, not premultiplied by alpha).
package imaging
import (
@@ -24,8 +22,10 @@ import (
"golang.org/x/image/tiff"
)
// Format is an image file format.
type Format int
// Image file formats.
const (
JPEG Format = iota
PNG
@@ -52,6 +52,7 @@ func (f Format) String() string {
}
var (
// ErrUnsupportedFormat means the given image format (or file extension) is unsupported.
ErrUnsupportedFormat = errors.New("imaging: unsupported image format")
)
@@ -194,15 +195,12 @@ func Clone(img image.Image) *image.NRGBA {
di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ {
dst.Pix[di+0] = src.Pix[si+0]
dst.Pix[di+1] = src.Pix[si+2]
dst.Pix[di+2] = src.Pix[si+4]
dst.Pix[di+3] = src.Pix[si+6]
di += 4
si += 8
}
}
})
@@ -213,9 +211,9 @@ func Clone(img image.Image) *image.NRGBA {
di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ {
a := src.Pix[si+3]
dst.Pix[di+3] = a
switch a {
case 0:
dst.Pix[di+0] = 0
@@ -237,7 +235,6 @@ func Clone(img image.Image) *image.NRGBA {
di += 4
si += 4
}
}
})
@@ -248,9 +245,9 @@ func Clone(img image.Image) *image.NRGBA {
di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ {
a := src.Pix[si+6]
dst.Pix[di+3] = a
switch a {
case 0:
dst.Pix[di+0] = 0
@@ -272,7 +269,6 @@ func Clone(img image.Image) *image.NRGBA {
di += 4
si += 8
}
}
})
@@ -283,16 +279,13 @@ func Clone(img image.Image) *image.NRGBA {
di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ {
c := src.Pix[si]
dst.Pix[di+0] = c
dst.Pix[di+1] = c
dst.Pix[di+2] = c
dst.Pix[di+3] = 0xff
di += 4
si += 1
}
}
})
@@ -303,16 +296,13 @@ func Clone(img image.Image) *image.NRGBA {
di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ {
c := src.Pix[si]
dst.Pix[di+0] = c
dst.Pix[di+1] = c
dst.Pix[di+2] = c
dst.Pix[di+3] = 0xff
di += 4
si += 2
}
}
})
@@ -322,7 +312,6 @@ func Clone(img image.Image) *image.NRGBA {
for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY)
for dstX := 0; dstX < dstW; dstX++ {
srcX := srcMinX + dstX
srcY := srcMinY + dstY
siy := src.YOffset(srcX, srcY)
@@ -332,9 +321,7 @@ func Clone(img image.Image) *image.NRGBA {
dst.Pix[di+1] = g
dst.Pix[di+2] = b
dst.Pix[di+3] = 0xff
di += 4
}
}
})
@@ -345,22 +332,18 @@ func Clone(img image.Image) *image.NRGBA {
for i := 0; i < plen; i++ {
pnew[i] = color.NRGBAModel.Convert(src.Palette[i]).(color.NRGBA)
}
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ {
c := pnew[src.Pix[si]]
dst.Pix[di+0] = c.R
dst.Pix[di+1] = c.G
dst.Pix[di+2] = c.B
dst.Pix[di+3] = c.A
di += 4
si += 1
}
}
})
@@ -370,15 +353,12 @@ func Clone(img image.Image) *image.NRGBA {
for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY)
for dstX := 0; dstX < dstW; dstX++ {
c := color.NRGBAModel.Convert(img.At(srcMinX+dstX, srcMinY+dstY)).(color.NRGBA)
dst.Pix[di+0] = c.R
dst.Pix[di+1] = c.G
dst.Pix[di+2] = c.B
dst.Pix[di+3] = c.A
di += 4
}
}
})
@@ -388,7 +368,7 @@ func Clone(img image.Image) *image.NRGBA {
return dst
}
// This function used internally to convert any image type to NRGBA if needed.
// toNRGBA converts any image type to *image.NRGBA with min-point at (0, 0).
func toNRGBA(img image.Image) *image.NRGBA {
srcBounds := img.Bounds()
if srcBounds.Min.X == 0 && srcBounds.Min.Y == 0 {

2
vendor/github.com/disintegration/imaging/histogram.go сгенерированный поставляемый
Просмотреть файл

@@ -17,7 +17,7 @@ func Histogram(img image.Image) [256]float64 {
var total float64
if width == 0 || height == 0 {
return histogram
return histogram
}
for y := 0; y < height; y++ {

2
vendor/github.com/disintegration/imaging/histogram_test.go сгенерированный поставляемый
Просмотреть файл

@@ -36,7 +36,7 @@ func TestHistogram(t *testing.T) {
for _, val := range h {
if val != 0 {
t.Errorf("Histogram for an empty image should be a zero histogram.")
return
return
}
}
}

132
vendor/github.com/disintegration/imaging/resize.go сгенерированный поставляемый
Просмотреть файл

@@ -5,17 +5,12 @@ import (
"math"
)
type iwpair struct {
i int
w int32
type indexWeight struct {
index int
weight float64
}
type pweights struct {
iwpairs []iwpair
wsum int32
}
func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) []pweights {
func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) [][]indexWeight {
du := float64(srcSize) / float64(dstSize)
scale := du
if scale < 1.0 {
@@ -23,7 +18,7 @@ func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) []pweights {
}
ru := math.Ceil(scale * filter.Support)
out := make([]pweights, dstSize)
out := make([][]indexWeight, dstSize)
for v := 0; v < dstSize; v++ {
fu := (float64(v)+0.5)*du - 0.5
@@ -37,15 +32,19 @@ func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) []pweights {
endu = srcSize - 1
}
wsum := int32(0)
var sum float64
for u := startu; u <= endu; u++ {
w := int32(0xff * filter.Kernel((float64(u)-fu)/scale))
w := filter.Kernel((float64(u) - fu) / scale)
if w != 0 {
wsum += w
out[v].iwpairs = append(out[v].iwpairs, iwpair{u, w})
sum += w
out[v] = append(out[v], indexWeight{index: u, weight: w})
}
}
if sum != 0 {
for i := range out[v] {
out[v][i].weight /= sum
}
}
out[v].wsum = wsum
}
return out
@@ -127,22 +126,26 @@ func resizeHorizontal(src *image.NRGBA, width int, filter ResampleFilter) *image
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
i0 := dstY * src.Stride
j0 := dstY * dst.Stride
for dstX := 0; dstX < dstW; dstX++ {
var c [4]int64
for _, iw := range weights[dstX].iwpairs {
i := dstY*src.Stride + iw.i*4
a := int64(src.Pix[i+3]) * int64(iw.w)
c[0] += int64(src.Pix[i+0]) * a
c[1] += int64(src.Pix[i+1]) * a
c[2] += int64(src.Pix[i+2]) * a
c[3] += a
var r, g, b, a float64
for _, w := range weights[dstX] {
i := i0 + w.index*4
aw := float64(src.Pix[i+3]) * w.weight
r += float64(src.Pix[i+0]) * aw
g += float64(src.Pix[i+1]) * aw
b += float64(src.Pix[i+2]) * aw
a += aw
}
if a != 0 {
aInv := 1 / a
j := j0 + dstX*4
dst.Pix[j+0] = clamp(r * aInv)
dst.Pix[j+1] = clamp(g * aInv)
dst.Pix[j+2] = clamp(b * aInv)
dst.Pix[j+3] = clamp(a)
}
j := dstY*dst.Stride + dstX*4
sum := weights[dstX].wsum
dst.Pix[j+0] = clampint32(int32(float64(c[0])/float64(c[3]) + 0.5))
dst.Pix[j+1] = clampint32(int32(float64(c[1])/float64(c[3]) + 0.5))
dst.Pix[j+2] = clampint32(int32(float64(c[2])/float64(c[3]) + 0.5))
dst.Pix[j+3] = clampint32(int32(float64(c[3])/float64(sum) + 0.5))
}
}
})
@@ -163,33 +166,33 @@ func resizeVertical(src *image.NRGBA, height int, filter ResampleFilter) *image.
weights := precomputeWeights(dstH, srcH, filter)
parallel(dstW, func(partStart, partEnd int) {
for dstX := partStart; dstX < partEnd; dstX++ {
for dstY := 0; dstY < dstH; dstY++ {
var c [4]int64
for _, iw := range weights[dstY].iwpairs {
i := iw.i*src.Stride + dstX*4
a := int64(src.Pix[i+3]) * int64(iw.w)
c[0] += int64(src.Pix[i+0]) * a
c[1] += int64(src.Pix[i+1]) * a
c[2] += int64(src.Pix[i+2]) * a
c[3] += a
var r, g, b, a float64
for _, w := range weights[dstY] {
i := w.index*src.Stride + dstX*4
aw := float64(src.Pix[i+3]) * w.weight
r += float64(src.Pix[i+0]) * aw
g += float64(src.Pix[i+1]) * aw
b += float64(src.Pix[i+2]) * aw
a += aw
}
if a != 0 {
aInv := 1 / a
j := dstY*dst.Stride + dstX*4
dst.Pix[j+0] = clamp(r * aInv)
dst.Pix[j+1] = clamp(g * aInv)
dst.Pix[j+2] = clamp(b * aInv)
dst.Pix[j+3] = clamp(a)
}
j := dstY*dst.Stride + dstX*4
sum := weights[dstY].wsum
dst.Pix[j+0] = clampint32(int32(float64(c[0])/float64(c[3]) + 0.5))
dst.Pix[j+1] = clampint32(int32(float64(c[1])/float64(c[3]) + 0.5))
dst.Pix[j+2] = clampint32(int32(float64(c[2])/float64(c[3]) + 0.5))
dst.Pix[j+3] = clampint32(int32(float64(c[3])/float64(sum) + 0.5))
}
}
})
return dst
}
// fast nearest-neighbor resize, no filtering
// resizeNearest is a fast nearest-neighbor resize, no filtering.
func resizeNearest(src *image.NRGBA, width, height int) *image.NRGBA {
dstW, dstH := width, height
@@ -205,13 +208,16 @@ func resizeNearest(src *image.NRGBA, width, height int) *image.NRGBA {
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
fy := (float64(dstY)+0.5)*dy - 0.5
srcY := int((float64(dstY) + 0.5) * dy)
if srcY > srcH-1 {
srcY = srcH - 1
}
for dstX := 0; dstX < dstW; dstX++ {
fx := (float64(dstX)+0.5)*dx - 0.5
srcX := int(math.Min(math.Max(math.Floor(fx+0.5), 0.0), float64(srcW)))
srcY := int(math.Min(math.Max(math.Floor(fy+0.5), 0.0), float64(srcH)))
srcX := int((float64(dstX) + 0.5) * dx)
if srcX > srcW-1 {
srcX = srcW - 1
}
srcOff := srcY*src.Stride + srcX*4
dstOff := dstY*dst.Stride + dstX*4
@@ -326,7 +332,7 @@ func Thumbnail(img image.Image, width, height int, filter ResampleFilter) *image
return Fill(img, width, height, Center, filter)
}
// Resample filter struct. It can be used to make custom filters.
// ResampleFilter is a resampling filter struct. It can be used to define custom filters.
//
// Supported resample filters: NearestNeighbor, Box, Linear, Hermite, MitchellNetravali,
// CatmullRom, BSpline, Gaussian, Lanczos, Hann, Hamming, Blackman, Bartlett, Welch, Cosine.
@@ -361,7 +367,7 @@ type ResampleFilter struct {
Kernel func(float64) float64
}
// Nearest-neighbor filter, no anti-aliasing.
// NearestNeighbor is a nearest-neighbor filter (no anti-aliasing).
var NearestNeighbor ResampleFilter
// Box filter (averaging pixels).
@@ -373,37 +379,37 @@ var Linear ResampleFilter
// Hermite cubic spline filter (BC-spline; B=0; C=0).
var Hermite ResampleFilter
// Mitchell-Netravali cubic filter (BC-spline; B=1/3; C=1/3).
// MitchellNetravali is Mitchell-Netravali cubic filter (BC-spline; B=1/3; C=1/3).
var MitchellNetravali ResampleFilter
// Catmull-Rom - sharp cubic filter (BC-spline; B=0; C=0.5).
// CatmullRom is a Catmull-Rom - sharp cubic filter (BC-spline; B=0; C=0.5).
var CatmullRom ResampleFilter
// Cubic B-spline - smooth cubic filter (BC-spline; B=1; C=0).
// BSpline is a smooth cubic filter (BC-spline; B=1; C=0).
var BSpline ResampleFilter
// Gaussian Blurring Filter.
// Gaussian is a Gaussian blurring Filter.
var Gaussian ResampleFilter
// Bartlett-windowed sinc filter (3 lobes).
// Bartlett is a Bartlett-windowed sinc filter (3 lobes).
var Bartlett ResampleFilter
// Lanczos filter (3 lobes).
var Lanczos ResampleFilter
// Hann-windowed sinc filter (3 lobes).
// Hann is a Hann-windowed sinc filter (3 lobes).
var Hann ResampleFilter
// Hamming-windowed sinc filter (3 lobes).
// Hamming is a Hamming-windowed sinc filter (3 lobes).
var Hamming ResampleFilter
// Blackman-windowed sinc filter (3 lobes).
// Blackman is a Blackman-windowed sinc filter (3 lobes).
var Blackman ResampleFilter
// Welch-windowed sinc filter (parabolic window, 3 lobes).
// Welch is a Welch-windowed sinc filter (parabolic window, 3 lobes).
var Welch ResampleFilter
// Cosine-windowed sinc filter (3 lobes).
// Cosine is a Cosine-windowed sinc filter (3 lobes).
var Cosine ResampleFilter
func bcspline(x, b, c float64) float64 {

68
vendor/github.com/disintegration/imaging/resize_test.go сгенерированный поставляемый
Просмотреть файл

@@ -108,10 +108,10 @@ func TestResize(t *testing.T) {
Rect: image.Rect(0, 0, 4, 4),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x3f, 0xff, 0x00, 0x00, 0xc0, 0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0x3f, 0x6d, 0x6e, 0x24, 0x6f, 0xb1, 0x13, 0x3a, 0xd0, 0xc0, 0x00, 0x3f, 0xff,
0x00, 0xff, 0x00, 0xc0, 0x13, 0xb2, 0x3a, 0xcf, 0x33, 0x32, 0x9a, 0xef, 0x3f, 0x00, 0xc0, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0xc0, 0x3f, 0xff, 0x00, 0x3f, 0xc0, 0xff, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x40, 0xff, 0x00, 0x00, 0xbf, 0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0x40, 0x6e, 0x6d, 0x25, 0x70, 0xb0, 0x14, 0x3b, 0xcf, 0xbf, 0x00, 0x40, 0xff,
0x00, 0xff, 0x00, 0xbf, 0x14, 0xb0, 0x3b, 0xcf, 0x33, 0x33, 0x99, 0xef, 0x40, 0x00, 0xbf, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0xbf, 0x40, 0xff, 0x00, 0x40, 0xbf, 0xff, 0x00, 0x00, 0xff, 0xff,
},
},
},
@@ -158,7 +158,7 @@ func TestResize(t *testing.T) {
for _, d := range td {
got := Resize(d.src, d.w, d.h, d.f)
want := d.want
if !compareNRGBA(got, want, 1) {
if !compareNRGBA(got, want, 0) {
t.Errorf("test [%s] failed: %#v", d.desc, got)
}
}
@@ -201,6 +201,28 @@ func TestResize(t *testing.T) {
}
}
func TestResizeGolden(t *testing.T) {
src, err := Open("testdata/lena_512.png")
if err != nil {
t.Errorf("Open: %v", err)
}
for name, filter := range map[string]ResampleFilter{
"out_resize_nearest.png": NearestNeighbor,
"out_resize_linear.png": Linear,
"out_resize_catrom.png": CatmullRom,
"out_resize_lanczos.png": Lanczos,
} {
got := Resize(src, 128, 0, filter)
want, err := Open("testdata/" + name)
if err != nil {
t.Errorf("Open: %v", err)
}
if !compareNRGBA(got, toNRGBA(want), 0) {
t.Errorf("resulting image differs from golden: %s", name)
}
}
}
func TestFit(t *testing.T) {
td := []struct {
desc string
@@ -568,3 +590,39 @@ func TestThumbnail(t *testing.T) {
}
}
}
func BenchmarkResizeLanczosUp(b *testing.B) {
benchmarkResize(b, "testdata/lena_128.png", 512, Lanczos)
}
func BenchmarkResizeLinearUp(b *testing.B) {
benchmarkResize(b, "testdata/lena_128.png", 512, Linear)
}
func BenchmarkResizeNearestNeighborUp(b *testing.B) {
benchmarkResize(b, "testdata/lena_128.png", 512, NearestNeighbor)
}
func BenchmarkResizeLanczosDown(b *testing.B) {
benchmarkResize(b, "testdata/lena_512.png", 128, Lanczos)
}
func BenchmarkResizeLinearDown(b *testing.B) {
benchmarkResize(b, "testdata/lena_512.png", 128, Linear)
}
func BenchmarkResizeNearestNeighborDown(b *testing.B) {
benchmarkResize(b, "testdata/lena_512.png", 128, NearestNeighbor)
}
func benchmarkResize(b *testing.B, filename string, size int, f ResampleFilter) {
b.StopTimer()
img, err := Open(filename)
if err != nil {
b.Fatalf("Open: %v", err)
}
b.StartTimer()
for i := 0; i < b.N; i++ {
Resize(img, size, size, f)
}
}

Двоичные данные
vendor/github.com/disintegration/imaging/testdata/lena_128.png сгенерированный поставляемый Обычный файл

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

После

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

Двоичные данные
vendor/github.com/disintegration/imaging/testdata/lena_512.png сгенерированный поставляемый Обычный файл

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

После

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

Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_blur_0.5.png сгенерированный поставляемый Обычный файл

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

После

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

Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_blur_1.5.png сгенерированный поставляемый Обычный файл

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

После

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

Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_brightness_m10.png сгенерированный поставляемый Обычный файл

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

После

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

Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_brightness_p10.png сгенерированный поставляемый Обычный файл

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

После

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

Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_contrast_m10.png сгенерированный поставляемый Обычный файл

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

После

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

Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_contrast_p10.png сгенерированный поставляемый Обычный файл

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

После

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

Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_example.jpg сгенерированный поставляемый Обычный файл

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

После

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

Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_gamma_0.75.png сгенерированный поставляемый Обычный файл

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

После

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

Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_gamma_1.25.png сгенерированный поставляемый Обычный файл

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

После

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

Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_resize_catrom.png сгенерированный поставляемый Обычный файл

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

После

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

Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_resize_lanczos.png сгенерированный поставляемый Обычный файл

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

После

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

Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_resize_linear.png сгенерированный поставляемый Обычный файл

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

После

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

Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_resize_nearest.png сгенерированный поставляемый Обычный файл

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

После

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

Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_sharpen_0.5.png сгенерированный поставляемый Обычный файл

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

После

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

Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_sharpen_1.5.png сгенерированный поставляемый Обычный файл

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

После

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

1
vendor/github.com/disintegration/imaging/tools.go сгенерированный поставляемый
Просмотреть файл

@@ -8,6 +8,7 @@ import (
// Anchor is the anchor point for image alignment.
type Anchor int
// Anchor point positions.
const (
Center Anchor = iota
TopLeft

2
vendor/github.com/disintegration/imaging/tools_test.go сгенерированный поставляемый
Просмотреть файл

@@ -598,7 +598,7 @@ func TestOverlay(t *testing.T) {
for _, d := range td {
got := Overlay(d.src1, d.src2, d.p, d.a)
want := d.want
if !compareNRGBA(got, want, 1) {
if !compareNRGBA(got, want, 0) {
t.Errorf("test [%s] failed: %#v", d.desc, got)
}
}

42
vendor/github.com/disintegration/imaging/utils.go сгенерированный поставляемый
Просмотреть файл

@@ -1,28 +1,24 @@
package imaging
import (
"math"
"runtime"
"sync"
"sync/atomic"
)
var parallelizationEnabled = true
// if GOMAXPROCS = 1: no goroutines used
// if GOMAXPROCS > 1: spawn N=GOMAXPROCS workers in separate goroutines
// parallel starts parallel image processing based on the current GOMAXPROCS value.
// If GOMAXPROCS = 1 it uses no parallelization.
// If GOMAXPROCS > 1 it spawns N=GOMAXPROCS workers in separate goroutines.
func parallel(dataSize int, fn func(partStart, partEnd int)) {
numGoroutines := 1
partSize := dataSize
if parallelizationEnabled {
numProcs := runtime.GOMAXPROCS(0)
if numProcs > 1 {
numGoroutines = numProcs
partSize = dataSize / (numGoroutines * 10)
if partSize < 1 {
partSize = 1
}
numProcs := runtime.GOMAXPROCS(0)
if numProcs > 1 {
numGoroutines = numProcs
partSize = dataSize / (numGoroutines * 10)
if partSize < 1 {
partSize = 1
}
}
@@ -54,6 +50,7 @@ func parallel(dataSize int, fn func(partStart, partEnd int)) {
}
}
// absint returns the absolute value of i.
func absint(i int) int {
if i < 0 {
return -i
@@ -61,17 +58,14 @@ func absint(i int) int {
return i
}
// clamp & round float64 to uint8 (0..255)
func clamp(v float64) uint8 {
return uint8(math.Min(math.Max(v, 0.0), 255.0) + 0.5)
}
// clamp int32 to uint8 (0..255)
func clampint32(v int32) uint8 {
if v < 0 {
return 0
} else if v > 255 {
// clamp rounds and clamps float64 value to fit into uint8.
func clamp(x float64) uint8 {
v := int64(x + 0.5)
if v > 255 {
return 255
}
return uint8(v)
if v > 0 {
return uint8(v)
}
return 0
}

24
vendor/github.com/disintegration/imaging/utils_test.go сгенерированный поставляемый
Просмотреть файл

@@ -15,7 +15,7 @@ func testParallelN(enabled bool, n, procs int) bool {
}
})
for i := 0; i < n; i++ {
if data[i] != true {
if !data[i] {
return false
}
}
@@ -27,7 +27,7 @@ func TestParallel(t *testing.T) {
for _, e := range []bool{true, false} {
for _, n := range []int{1, 10, 100, 1000} {
for _, p := range []int{1, 2, 4, 8, 16, 100} {
if testParallelN(e, n, p) != true {
if !testParallelN(e, n, p) {
t.Errorf("test [parallel %v %d %d] failed", e, n, p)
}
}
@@ -59,23 +59,3 @@ func TestClamp(t *testing.T) {
}
}
}
func TestClampint32(t *testing.T) {
td := []struct {
i int32
u uint8
}{
{0, 0},
{255, 255},
{128, 128},
{256, 255},
{2500, 255},
{-10, 0},
}
for _, d := range td {
if clampint32(d.i) != d.u {
t.Errorf("test [clampint32 %v %v] failed: %v", d.i, d.u, clampint32(d.i))
}
}
}

13
vendor/github.com/golang/freetype/truetype/truetype.go сгенерированный поставляемый
Просмотреть файл

@@ -57,7 +57,8 @@ const (
// A 32-bit encoding consists of a most-significant 16-bit Platform ID and a
// least-significant 16-bit Platform Specific ID. The magic numbers are
// specified at https://www.microsoft.com/typography/otspec/name.htm
unicodeEncoding = 0x00000003 // PID = 0 (Unicode), PSID = 3 (Unicode 2.0)
unicodeEncodingBMPOnly = 0x00000003 // PID = 0 (Unicode), PSID = 3 (Unicode 2.0 BMP Only)
unicodeEncodingFull = 0x00000004 // PID = 0 (Unicode), PSID = 4 (Unicode 2.0 Full Repertoire)
microsoftSymbolEncoding = 0x00030000 // PID = 3 (Microsoft), PSID = 0 (Symbol)
microsoftUCS2Encoding = 0x00030001 // PID = 3 (Microsoft), PSID = 1 (UCS-2)
microsoftUCS4Encoding = 0x0003000a // PID = 3 (Microsoft), PSID = 10 (UCS-4)
@@ -142,7 +143,7 @@ func parseSubtables(table []byte, name string, offset, size int, pred func([]byt
pidPsid := u32(table, offset)
// We prefer the Unicode cmap encoding. Failing to find that, we fall
// back onto the Microsoft cmap encoding.
if pidPsid == unicodeEncoding {
if pidPsid == unicodeEncodingBMPOnly || pidPsid == unicodeEncodingFull {
bestOffset, bestPID, ok = offset, pidPsid>>16, true
break
@@ -550,8 +551,7 @@ func parse(ttf []byte, offset int) (font *Font, err error) {
return
}
ttcVersion, offset := u32(ttf, offset), offset+4
if ttcVersion != 0x00010000 {
// TODO: support TTC version 2.0, once I have such a .ttc file to test with.
if ttcVersion != 0x00010000 && ttcVersion != 0x00020000 {
err = FormatError("bad TTC version")
return
}
@@ -578,14 +578,15 @@ func parse(ttf []byte, offset int) (font *Font, err error) {
return
}
n, offset := int(u16(ttf, offset)), offset+2
if len(ttf) < 16*n+12 {
offset += 6 // Skip the searchRange, entrySelector and rangeShift.
if len(ttf) < 16*n+offset {
err = FormatError("TTF data is too short")
return
}
f := new(Font)
// Assign the table slices.
for i := 0; i < n; i++ {
x := 16*i + 12
x := 16*i + offset
switch string(ttf[x : x+4]) {
case "cmap":
f.cmap, err = readTable(ttf, ttf[x+8:x+16])

2
vendor/github.com/hashicorp/hcl/json/parser/parser.go сгенерированный поставляемый
Просмотреть файл

@@ -147,7 +147,7 @@ func (p *Parser) objectKey() ([]*ast.ObjectKey, error) {
// Done
return keys, nil
case token.ILLEGAL:
fmt.Println("illegal")
return nil, errors.New("illegal")
default:
return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type)
}

6
vendor/github.com/lib/pq/conn.go сгенерированный поставляемый
Просмотреть файл

@@ -35,14 +35,14 @@ var (
errNoLastInsertId = errors.New("no LastInsertId available after the empty statement")
)
type drv struct{}
type Driver struct{}
func (d *drv) Open(name string) (driver.Conn, error) {
func (d *Driver) Open(name string) (driver.Conn, error) {
return Open(name)
}
func init() {
sql.Register("postgres", &drv{})
sql.Register("postgres", &Driver{})
}
type parameterStatus struct {

2
vendor/github.com/miekg/dns/README.md сгенерированный поставляемый
Просмотреть файл

@@ -19,7 +19,7 @@ two versions of Go, currently: 1.6 and 1.7.
* KISS;
* Fast;
* Small API, if its easy to code in Go, don't make a function for it.
* Small API. If it's easy to code in Go, don't make a function for it.
# Users

2
vendor/github.com/miekg/dns/dnssec.go сгенерированный поставляемый
Просмотреть файл

@@ -515,7 +515,7 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
}
// Remainder
expo += uint64(keybuf[keyoff])
if expo > 2<<31 {
if expo > (2<<31)+1 {
// Larger expo than supported.
// println("dns: F5 primes (or larger) are not supported")
return nil

3
vendor/github.com/miekg/dns/labels.go сгенерированный поставляемый
Просмотреть файл

@@ -1,5 +1,7 @@
package dns
import "strings"
// Holds a bunch of helper functions for dealing with labels.
// SplitDomainName splits a name string into it's labels.
@@ -50,6 +52,7 @@ func SplitDomainName(s string) (labels []string) {
//
// s1 and s2 must be syntactically valid domain names.
func CompareDomainName(s1, s2 string) (n int) {
s1, s2 = strings.ToLower(s1), strings.ToLower(s2)
s1 = Fqdn(s1)
s2 = Fqdn(s2)
l1 := Split(s1)

3
vendor/github.com/miekg/dns/labels_test.go сгенерированный поставляемый
Просмотреть файл

@@ -33,6 +33,9 @@ func TestCompareDomainName(t *testing.T) {
if CompareDomainName(".", ".") != 0 {
t.Errorf("%s with %s should be %d", ".", ".", 0)
}
if CompareDomainName("test.com.", "TEST.COM.") != 2 {
t.Errorf("test.com. and TEST.COM. should be an exact match")
}
}
func TestSplit(t *testing.T) {

20
vendor/github.com/miekg/dns/msg.go сгенерированный поставляемый
Просмотреть файл

@@ -14,13 +14,17 @@ package dns
import (
crand "crypto/rand"
"encoding/binary"
"fmt"
"math/big"
"math/rand"
"strconv"
"sync"
)
const maxCompressionOffset = 2 << 13 // We have 14 bits for the compression pointer
const (
maxCompressionOffset = 2 << 13 // We have 14 bits for the compression pointer
maxDomainNameWireOctets = 255 // See RFC 1035 section 2.3.4
)
var (
ErrAlg error = &Error{err: "bad algorithm"} // ErrAlg indicates an error with the (DNSSEC) algorithm.
@@ -33,6 +37,7 @@ var (
ErrKeyAlg error = &Error{err: "bad key algorithm"} // ErrKeyAlg indicates that the algorithm in the key is not valid.
ErrKey error = &Error{err: "bad key"}
ErrKeySize error = &Error{err: "bad key size"}
ErrLongDomain error = &Error{err: fmt.Sprintf("domain name exceeded %d wire-format octets", maxDomainNameWireOctets)}
ErrNoSig error = &Error{err: "no signature found"}
ErrPrivKey error = &Error{err: "bad private key"}
ErrRcode error = &Error{err: "bad rcode"}
@@ -329,6 +334,7 @@ func UnpackDomainName(msg []byte, off int) (string, int, error) {
s := make([]byte, 0, 64)
off1 := 0
lenmsg := len(msg)
maxLen := maxDomainNameWireOctets
ptr := 0 // number of pointers followed
Loop:
for {
@@ -353,8 +359,10 @@ Loop:
fallthrough
case '"', '\\':
s = append(s, '\\', b)
// presentation-format \X escapes add an extra byte
maxLen += 1
default:
if b < 32 || b >= 127 { // unprintable use \DDD
if b < 32 || b >= 127 { // unprintable, use \DDD
var buf [3]byte
bufs := strconv.AppendInt(buf[:0], int64(b), 10)
s = append(s, '\\')
@@ -364,6 +372,8 @@ Loop:
for _, r := range bufs {
s = append(s, r)
}
// presentation-format \DDD escapes add 3 extra bytes
maxLen += 3
} else {
s = append(s, b)
}
@@ -388,6 +398,9 @@ Loop:
if ptr++; ptr > 10 {
return "", lenmsg, &Error{err: "too many compression pointers"}
}
// pointer should guarantee that it advances and points forwards at least
// but the condition on previous three lines guarantees that it's
// at least loop-free
off = (c^0xC0)<<8 | int(c1)
default:
// 0x80 and 0x40 are reserved
@@ -399,6 +412,9 @@ Loop:
}
if len(s) == 0 {
s = []byte(".")
} else if len(s) >= maxLen {
// error if the name is too long, but don't throw it away
return string(s), lenmsg, ErrLongDomain
}
return string(s), off1, nil
}

124
vendor/github.com/miekg/dns/msg_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,124 @@
package dns
import (
"fmt"
"regexp"
"strconv"
"strings"
"testing"
)
const (
maxPrintableLabel = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789x"
tooLongLabel = maxPrintableLabel + "x"
)
var (
longDomain = maxPrintableLabel[:53] + strings.TrimSuffix(
strings.Join([]string{".", ".", ".", ".", "."}, maxPrintableLabel[:49]), ".")
reChar = regexp.MustCompile(`.`)
i = -1
maxUnprintableLabel = reChar.ReplaceAllStringFunc(maxPrintableLabel, func(ch string) string {
if i++; i >= 32 {
i = 0
}
return fmt.Sprintf("\\%03d", i)
})
)
func TestUnpackDomainName(t *testing.T) {
var cases = []struct {
label string
input string
expectedOutput string
expectedError string
}{
{"empty domain",
"\x00",
".",
""},
{"long label",
string(63) + maxPrintableLabel + "\x00",
maxPrintableLabel + ".",
""},
{"unprintable label",
string(63) + regexp.MustCompile(`\\[0-9]+`).ReplaceAllStringFunc(maxUnprintableLabel,
func(escape string) string {
n, _ := strconv.ParseInt(escape[1:], 10, 8)
return string(n)
}) + "\x00",
maxUnprintableLabel + ".",
""},
{"long domain",
string(53) + strings.Replace(longDomain, ".", string(49), -1) + "\x00",
longDomain + ".",
""},
{"compression pointer",
// an unrealistic but functional test referencing an offset _inside_ a label
"\x03foo" + "\x05\x03com\x00" + "\x07example" + "\xC0\x05",
"foo.\\003com\\000.example.com.",
""},
{"too long domain",
string(54) + "x" + strings.Replace(longDomain, ".", string(49), -1) + "\x00",
"x" + longDomain + ".",
ErrLongDomain.Error()},
{"too long by pointer",
// a matryoshka doll name to get over 255 octets after expansion via internal pointers
string([]byte{
// 11 length values, first to last
40, 37, 34, 31, 28, 25, 22, 19, 16, 13, 0,
// 12 filler values
120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120,
// 10 pointers, last to first
192, 10, 192, 9, 192, 8, 192, 7, 192, 6, 192, 5, 192, 4, 192, 3, 192, 2, 192, 1,
}),
"",
ErrLongDomain.Error()},
{"long by pointer",
// a matryoshka doll name _not_ exceeding 255 octets after expansion
string([]byte{
// 11 length values, first to last
37, 34, 31, 28, 25, 22, 19, 16, 13, 10, 0,
// 9 filler values
120, 120, 120, 120, 120, 120, 120, 120, 120,
// 10 pointers, last to first
192, 10, 192, 9, 192, 8, 192, 7, 192, 6, 192, 5, 192, 4, 192, 3, 192, 2, 192, 1,
}),
"" +
(`\"\031\028\025\022\019\016\013\010\000xxxxxxxxx` +
`\192\010\192\009\192\008\192\007\192\006\192\005\192\004\192\003\192\002.`) +
(`\031\028\025\022\019\016\013\010\000xxxxxxxxx` +
`\192\010\192\009\192\008\192\007\192\006\192\005\192\004\192\003.`) +
(`\028\025\022\019\016\013\010\000xxxxxxxxx` +
`\192\010\192\009\192\008\192\007\192\006\192\005\192\004.`) +
(`\025\022\019\016\013\010\000xxxxxxxxx` +
`\192\010\192\009\192\008\192\007\192\006\192\005.`) +
`\022\019\016\013\010\000xxxxxxxxx\192\010\192\009\192\008\192\007\192\006.` +
`\019\016\013\010\000xxxxxxxxx\192\010\192\009\192\008\192\007.` +
`\016\013\010\000xxxxxxxxx\192\010\192\009\192\008.` +
`\013\010\000xxxxxxxxx\192\010\192\009.` +
`\010\000xxxxxxxxx\192\010.` +
`\000xxxxxxxxx.`,
""},
{"truncated name", "\x07example\x03", "", "dns: buffer size too small"},
{"non-absolute name", "\x07example\x03com", "", "dns: buffer size too small"},
{"compression pointer cycle",
"\x03foo" + "\x03bar" + "\x07example" + "\xC0\x04",
"",
"dns: too many compression pointers"},
{"reserved compression pointer 0b10", "\x07example\x80", "", "dns: bad rdata"},
{"reserved compression pointer 0b01", "\x07example\x40", "", "dns: bad rdata"},
}
for _, test := range cases {
output, idx, err := UnpackDomainName([]byte(test.input), 0)
if test.expectedOutput != "" && output != test.expectedOutput {
t.Errorf("%s: expected %s, got %s", test.label, test.expectedOutput, output)
}
if test.expectedError == "" && err != nil {
t.Errorf("%s: expected no error, got %d %v", test.label, idx, err)
} else if test.expectedError != "" && (err == nil || err.Error() != test.expectedError) {
t.Errorf("%s: expected error %s, got %d %v", test.label, test.expectedError, idx, err)
}
}
}

76
vendor/github.com/miekg/dns/nsecx.go сгенерированный поставляемый
Просмотреть файл

@@ -48,62 +48,50 @@ func HashName(label string, ha uint8, iter uint16, salt string) string {
return toBase32(nsec3)
}
// Denialer is an interface that should be implemented by types that are used to denial
// answers in DNSSEC.
type Denialer interface {
// Cover will check if the (unhashed) name is being covered by this NSEC or NSEC3.
Cover(name string) bool
// Match will check if the ownername matches the (unhashed) name for this NSEC3 or NSEC3.
Match(name string) bool
}
// Cover implements the Denialer interface.
func (rr *NSEC) Cover(name string) bool {
return true
}
// Match implements the Denialer interface.
func (rr *NSEC) Match(name string) bool {
return true
}
// Cover implements the Denialer interface.
// Cover returns true if a name is covered by the NSEC3 record
func (rr *NSEC3) Cover(name string) bool {
// FIXME(miek): check if the zones match
// FIXME(miek): check if we're not dealing with parent nsec3
hname := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
labels := Split(rr.Hdr.Name)
if len(labels) < 2 {
nameHash := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
owner := strings.ToUpper(rr.Hdr.Name)
labelIndices := Split(owner)
if len(labelIndices) < 2 {
return false
}
hash := strings.ToUpper(rr.Hdr.Name[labels[0] : labels[1]-1]) // -1 to remove the dot
if hash == rr.NextDomain {
return false // empty interval
}
if hash > rr.NextDomain { // last name, points to apex
// hname > hash
// hname > rr.NextDomain
// TODO(miek)
}
if hname <= hash {
ownerHash := owner[:labelIndices[1]-1]
ownerZone := owner[labelIndices[1]:]
if !IsSubDomain(ownerZone, strings.ToUpper(name)) { // name is outside owner zone
return false
}
if hname >= rr.NextDomain {
nextHash := rr.NextDomain
if ownerHash == nextHash { // empty interval
return false
}
return true
if ownerHash > nextHash { // end of zone
if nameHash > ownerHash { // covered since there is nothing after ownerHash
return true
}
return nameHash < nextHash // if nameHash is before beginning of zone it is covered
}
if nameHash < ownerHash { // nameHash is before ownerHash, not covered
return false
}
return nameHash < nextHash // if nameHash is before nextHash is it covered (between ownerHash and nextHash)
}
// Match implements the Denialer interface.
// Match returns true if a name matches the NSEC3 record
func (rr *NSEC3) Match(name string) bool {
// FIXME(miek): Check if we are in the same zone
hname := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
labels := Split(rr.Hdr.Name)
if len(labels) < 2 {
nameHash := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
owner := strings.ToUpper(rr.Hdr.Name)
labelIndices := Split(owner)
if len(labelIndices) < 2 {
return false
}
hash := strings.ToUpper(rr.Hdr.Name[labels[0] : labels[1]-1]) // -1 to remove the .
if hash == hname {
ownerHash := owner[:labelIndices[1]-1]
ownerZone := owner[labelIndices[1]:]
if !IsSubDomain(ownerZone, strings.ToUpper(name)) { // name is outside owner zone
return false
}
if ownerHash == nameHash {
return true
}
return false

124
vendor/github.com/miekg/dns/nsecx_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,8 +1,6 @@
package dns
import (
"testing"
)
import "testing"
func TestPackNsec3(t *testing.T) {
nsec3 := HashName("dnsex.nl.", SHA1, 0, "DEAD")
@@ -17,13 +15,119 @@ func TestPackNsec3(t *testing.T) {
}
func TestNsec3(t *testing.T) {
// examples taken from .nl
nsec3, _ := NewRR("39p91242oslggest5e6a7cci4iaeqvnk.nl. IN NSEC3 1 1 5 F10E9F7EA83FC8F3 39P99DCGG0MDLARTCRMCF6OFLLUL7PR6 NS DS RRSIG")
if !nsec3.(*NSEC3).Cover("snasajsksasasa.nl.") { // 39p94jrinub66hnpem8qdpstrec86pg3
t.Error("39p94jrinub66hnpem8qdpstrec86pg3. should be covered by 39p91242oslggest5e6a7cci4iaeqvnk.nl. - 39P99DCGG0MDLARTCRMCF6OFLLUL7PR6")
nsec3, _ := NewRR("sk4e8fj94u78smusb40o1n0oltbblu2r.nl. IN NSEC3 1 1 5 F10E9F7EA83FC8F3 SK4F38CQ0ATIEI8MH3RGD0P5I4II6QAN NS SOA TXT RRSIG DNSKEY NSEC3PARAM")
if !nsec3.(*NSEC3).Match("nl.") { // name hash = sk4e8fj94u78smusb40o1n0oltbblu2r
t.Fatal("sk4e8fj94u78smusb40o1n0oltbblu2r.nl. should match sk4e8fj94u78smusb40o1n0oltbblu2r.nl.")
}
nsec3, _ = NewRR("sk4e8fj94u78smusb40o1n0oltbblu2r.nl. IN NSEC3 1 1 5 F10E9F7EA83FC8F3 SK4F38CQ0ATIEI8MH3RGD0P5I4II6QAN NS SOA TXT RRSIG DNSKEY NSEC3PARAM")
if !nsec3.(*NSEC3).Match("nl.") { // sk4e8fj94u78smusb40o1n0oltbblu2r.nl.
t.Error("sk4e8fj94u78smusb40o1n0oltbblu2r.nl. should match sk4e8fj94u78smusb40o1n0oltbblu2r.nl.")
if !nsec3.(*NSEC3).Match("NL.") { // name hash = sk4e8fj94u78smusb40o1n0oltbblu2r
t.Fatal("sk4e8fj94u78smusb40o1n0oltbblu2r.NL. should match sk4e8fj94u78smusb40o1n0oltbblu2r.nl.")
}
if nsec3.(*NSEC3).Match("com.") { //
t.Fatal("com. is not in the zone nl.")
}
if nsec3.(*NSEC3).Match("test.nl.") { // name hash = gd0ptr5bnfpimpu2d3v6gd4n0bai7s0q
t.Fatal("gd0ptr5bnfpimpu2d3v6gd4n0bai7s0q.nl. should not match sk4e8fj94u78smusb40o1n0oltbblu2r.nl.")
}
nsec3, _ = NewRR("nl. IN NSEC3 1 1 5 F10E9F7EA83FC8F3 SK4F38CQ0ATIEI8MH3RGD0P5I4II6QAN NS SOA TXT RRSIG DNSKEY NSEC3PARAM")
if nsec3.(*NSEC3).Match("nl.") {
t.Fatal("sk4e8fj94u78smusb40o1n0oltbblu2r.nl. should not match a record without a owner hash")
}
for _, tc := range []struct {
rr *NSEC3
name string
covers bool
}{
// positive tests
{ // name hash between owner hash and next hash
rr: &NSEC3{
Hdr: RR_Header{Name: "2N1TB3VAIRUOBL6RKDVII42N9TFMIALP.com."},
Hash: 1,
Flags: 1,
Iterations: 5,
Salt: "F10E9F7EA83FC8F3",
NextDomain: "PT3RON8N7PM3A0OE989IB84OOSADP7O8",
},
name: "bsd.com.",
covers: true,
},
{ // end of zone, name hash is after owner hash
rr: &NSEC3{
Hdr: RR_Header{Name: "3v62ulr0nre83v0rja2vjgtlif9v6rab.com."},
Hash: 1,
Flags: 1,
Iterations: 5,
Salt: "F10E9F7EA83FC8F3",
NextDomain: "2N1TB3VAIRUOBL6RKDVII42N9TFMIALP",
},
name: "csd.com.",
covers: true,
},
{ // end of zone, name hash is before beginning of zone
rr: &NSEC3{
Hdr: RR_Header{Name: "PT3RON8N7PM3A0OE989IB84OOSADP7O8.com."},
Hash: 1,
Flags: 1,
Iterations: 5,
Salt: "F10E9F7EA83FC8F3",
NextDomain: "3V62ULR0NRE83V0RJA2VJGTLIF9V6RAB",
},
name: "asd.com.",
covers: true,
},
// negative tests
{ // too short owner name
rr: &NSEC3{
Hdr: RR_Header{Name: "nl."},
Hash: 1,
Flags: 1,
Iterations: 5,
Salt: "F10E9F7EA83FC8F3",
NextDomain: "39P99DCGG0MDLARTCRMCF6OFLLUL7PR6",
},
name: "asd.com.",
covers: false,
},
{ // outside of zone
rr: &NSEC3{
Hdr: RR_Header{Name: "39p91242oslggest5e6a7cci4iaeqvnk.nl."},
Hash: 1,
Flags: 1,
Iterations: 5,
Salt: "F10E9F7EA83FC8F3",
NextDomain: "39P99DCGG0MDLARTCRMCF6OFLLUL7PR6",
},
name: "asd.com.",
covers: false,
},
{ // empty interval
rr: &NSEC3{
Hdr: RR_Header{Name: "2n1tb3vairuobl6rkdvii42n9tfmialp.com."},
Hash: 1,
Flags: 1,
Iterations: 5,
Salt: "F10E9F7EA83FC8F3",
NextDomain: "2N1TB3VAIRUOBL6RKDVII42N9TFMIALP",
},
name: "asd.com.",
covers: false,
},
{ // name hash is before owner hash, not covered
rr: &NSEC3{
Hdr: RR_Header{Name: "3V62ULR0NRE83V0RJA2VJGTLIF9V6RAB.com."},
Hash: 1,
Flags: 1,
Iterations: 5,
Salt: "F10E9F7EA83FC8F3",
NextDomain: "PT3RON8N7PM3A0OE989IB84OOSADP7O8",
},
name: "asd.com.",
covers: false,
},
} {
covers := tc.rr.Cover(tc.name)
if tc.covers != covers {
t.Fatalf("Cover failed for %s: expected %t, got %t [record: %s]", tc.name, tc.covers, covers, tc.rr)
}
}
}

18
vendor/github.com/miekg/dns/parse_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1509,3 +1509,21 @@ func TestParseURI(t *testing.T) {
}
}
}
func TestParseAVC(t *testing.T) {
avcs := map[string]string{
`example.org. IN AVC "app-name:WOLFGANG|app-class:OAM|business=yes"`: `example.org. 3600 IN AVC "app-name:WOLFGANG|app-class:OAM|business=yes"`,
}
for avc, o := range avcs {
rr, err := NewRR(avc)
if err != nil {
t.Error("failed to parse RR: ", err)
continue
}
if rr.String() != o {
t.Errorf("`%s' should be equal to\n`%s', but is `%s'", avc, o, rr.String())
} else {
t.Logf("RR is OK: `%s'", rr.String())
}
}
}

13
vendor/github.com/miekg/dns/scan_rr.go сгенерированный поставляемый
Просмотреть файл

@@ -1807,6 +1807,18 @@ func setSPF(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
return rr, nil, c1
}
func setAVC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(AVC)
rr.Hdr = h
s, e, c1 := endingToTxtSlice(c, "bad AVC Txt", f)
if e != nil {
return nil, e, ""
}
rr.Txt = s
return rr, nil, c1
}
func setTXT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(TXT)
rr.Hdr = h
@@ -2158,6 +2170,7 @@ var typeToparserFunc = map[uint16]parserFunc{
TypeSMIMEA: {setSMIMEA, true},
TypeSOA: {setSOA, false},
TypeSPF: {setSPF, true},
TypeAVC: {setAVC, true},
TypeSRV: {setSRV, false},
TypeSSHFP: {setSSHFP, true},
TypeTALINK: {setTALINK, false},

8
vendor/github.com/miekg/dns/types.go сгенерированный поставляемый
Просмотреть файл

@@ -91,6 +91,7 @@ const (
TypeEUI64 uint16 = 109
TypeURI uint16 = 256
TypeCAA uint16 = 257
TypeAVC uint16 = 258
TypeTKEY uint16 = 249
TypeTSIG uint16 = 250
@@ -530,6 +531,13 @@ type SPF struct {
func (rr *SPF) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
type AVC struct {
Hdr RR_Header
Txt []string `dns:"txt"`
}
func (rr *AVC) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
type SRV struct {
Hdr RR_Header
Priority uint16

146
vendor/github.com/miekg/dns/zcompress.go сгенерированный поставляемый
Просмотреть файл

@@ -5,99 +5,95 @@ package dns
func compressionLenHelperType(c map[string]int, r RR) {
switch x := r.(type) {
case *KX:
compressionLenHelper(c, x.Exchanger)
case *MX:
compressionLenHelper(c, x.Mx)
case *NSEC:
compressionLenHelper(c, x.NextDomain)
case *DNAME:
compressionLenHelper(c, x.Target)
case *HIP:
for i := range x.RendezvousServers {
compressionLenHelper(c, x.RendezvousServers[i])
}
case *CNAME:
compressionLenHelper(c, x.Target)
case *MR:
compressionLenHelper(c, x.Mr)
case *PX:
compressionLenHelper(c, x.Map822)
compressionLenHelper(c, x.Mapx400)
case *SIG:
compressionLenHelper(c, x.SignerName)
case *SRV:
compressionLenHelper(c, x.Target)
case *TALINK:
compressionLenHelper(c, x.PreviousName)
compressionLenHelper(c, x.NextName)
case *LP:
compressionLenHelper(c, x.Fqdn)
case *NAPTR:
compressionLenHelper(c, x.Replacement)
case *NS:
compressionLenHelper(c, x.Ns)
case *RP:
compressionLenHelper(c, x.Mbox)
compressionLenHelper(c, x.Txt)
case *RRSIG:
compressionLenHelper(c, x.SignerName)
case *TKEY:
compressionLenHelper(c, x.Algorithm)
case *TSIG:
compressionLenHelper(c, x.Algorithm)
case *AFSDB:
compressionLenHelper(c, x.Hostname)
case *MF:
compressionLenHelper(c, x.Mf)
case *RT:
compressionLenHelper(c, x.Host)
case *MINFO:
compressionLenHelper(c, x.Rmail)
compressionLenHelper(c, x.Email)
case *PTR:
compressionLenHelper(c, x.Ptr)
case *SOA:
compressionLenHelper(c, x.Ns)
compressionLenHelper(c, x.Mbox)
case *MD:
compressionLenHelper(c, x.Md)
case *NSAPPTR:
compressionLenHelper(c, x.Ptr)
case *MG:
compressionLenHelper(c, x.Mg)
case *AFSDB:
compressionLenHelper(c, x.Hostname)
case *HIP:
for i := range x.RendezvousServers {
compressionLenHelper(c, x.RendezvousServers[i])
}
case *LP:
compressionLenHelper(c, x.Fqdn)
case *CNAME:
compressionLenHelper(c, x.Target)
case *MB:
compressionLenHelper(c, x.Mb)
case *RP:
compressionLenHelper(c, x.Mbox)
compressionLenHelper(c, x.Txt)
case *RRSIG:
compressionLenHelper(c, x.SignerName)
case *MF:
compressionLenHelper(c, x.Mf)
case *MINFO:
compressionLenHelper(c, x.Rmail)
compressionLenHelper(c, x.Email)
case *SIG:
compressionLenHelper(c, x.SignerName)
case *SRV:
compressionLenHelper(c, x.Target)
case *TSIG:
compressionLenHelper(c, x.Algorithm)
case *KX:
compressionLenHelper(c, x.Exchanger)
case *MG:
compressionLenHelper(c, x.Mg)
case *NSAPPTR:
compressionLenHelper(c, x.Ptr)
case *PX:
compressionLenHelper(c, x.Map822)
compressionLenHelper(c, x.Mapx400)
case *DNAME:
compressionLenHelper(c, x.Target)
case *MR:
compressionLenHelper(c, x.Mr)
case *MX:
compressionLenHelper(c, x.Mx)
case *TKEY:
compressionLenHelper(c, x.Algorithm)
case *NSEC:
compressionLenHelper(c, x.NextDomain)
case *TALINK:
compressionLenHelper(c, x.PreviousName)
compressionLenHelper(c, x.NextName)
case *MD:
compressionLenHelper(c, x.Md)
case *NAPTR:
compressionLenHelper(c, x.Replacement)
case *NS:
compressionLenHelper(c, x.Ns)
case *RT:
compressionLenHelper(c, x.Host)
}
}
func compressionLenSearchType(c map[string]int, r RR) (int, bool) {
switch x := r.(type) {
case *MF:
k1, ok1 := compressionLenSearch(c, x.Mf)
return k1, ok1
case *MG:
k1, ok1 := compressionLenSearch(c, x.Mg)
return k1, ok1
case *MINFO:
k1, ok1 := compressionLenSearch(c, x.Rmail)
k2, ok2 := compressionLenSearch(c, x.Email)
return k1 + k2, ok1 && ok2
case *MR:
k1, ok1 := compressionLenSearch(c, x.Mr)
return k1, ok1
case *PTR:
k1, ok1 := compressionLenSearch(c, x.Ptr)
return k1, ok1
case *AFSDB:
k1, ok1 := compressionLenSearch(c, x.Hostname)
return k1, ok1
case *CNAME:
k1, ok1 := compressionLenSearch(c, x.Target)
case *MB:
k1, ok1 := compressionLenSearch(c, x.Mb)
return k1, ok1
case *MD:
k1, ok1 := compressionLenSearch(c, x.Md)
return k1, ok1
case *MF:
k1, ok1 := compressionLenSearch(c, x.Mf)
return k1, ok1
case *NS:
k1, ok1 := compressionLenSearch(c, x.Ns)
return k1, ok1
case *RT:
k1, ok1 := compressionLenSearch(c, x.Host)
return k1, ok1
@@ -105,15 +101,19 @@ func compressionLenSearchType(c map[string]int, r RR) (int, bool) {
k1, ok1 := compressionLenSearch(c, x.Ns)
k2, ok2 := compressionLenSearch(c, x.Mbox)
return k1 + k2, ok1 && ok2
case *MB:
k1, ok1 := compressionLenSearch(c, x.Mb)
case *CNAME:
k1, ok1 := compressionLenSearch(c, x.Target)
return k1, ok1
case *MINFO:
k1, ok1 := compressionLenSearch(c, x.Rmail)
k2, ok2 := compressionLenSearch(c, x.Email)
return k1 + k2, ok1 && ok2
case *MR:
k1, ok1 := compressionLenSearch(c, x.Mr)
return k1, ok1
case *MX:
k1, ok1 := compressionLenSearch(c, x.Mx)
return k1, ok1
case *NS:
k1, ok1 := compressionLenSearch(c, x.Ns)
return k1, ok1
}
return 0, false
}

32
vendor/github.com/miekg/dns/zmsg.go сгенерированный поставляемый
Просмотреть файл

@@ -61,6 +61,20 @@ func (rr *ANY) pack(msg []byte, off int, compression map[string]int, compress bo
return off, nil
}
func (rr *AVC) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
off, err := rr.Hdr.pack(msg, off, compression, compress)
if err != nil {
return off, err
}
headerEnd := off
off, err = packStringTxt(rr.Txt, msg, off)
if err != nil {
return off, err
}
rr.Header().Rdlength = uint16(off - headerEnd)
return off, nil
}
func (rr *CAA) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
off, err := rr.Hdr.pack(msg, off, compression, compress)
if err != nil {
@@ -1528,6 +1542,23 @@ func unpackANY(h RR_Header, msg []byte, off int) (RR, int, error) {
return rr, off, err
}
func unpackAVC(h RR_Header, msg []byte, off int) (RR, int, error) {
rr := new(AVC)
rr.Hdr = h
if noRdata(h) {
return rr, off, nil
}
var err error
rdStart := off
_ = rdStart
rr.Txt, off, err = unpackStringTxt(msg, off)
if err != nil {
return rr, off, err
}
return rr, off, err
}
func unpackCAA(h RR_Header, msg []byte, off int) (RR, int, error) {
rr := new(CAA)
rr.Hdr = h
@@ -3467,6 +3498,7 @@ var typeToUnpack = map[uint16]func(RR_Header, []byte, int) (RR, int, error){
TypeAAAA: unpackAAAA,
TypeAFSDB: unpackAFSDB,
TypeANY: unpackANY,
TypeAVC: unpackAVC,
TypeCAA: unpackCAA,
TypeCDNSKEY: unpackCDNSKEY,
TypeCDS: unpackCDS,

15
vendor/github.com/miekg/dns/ztypes.go сгенерированный поставляемый
Просмотреть файл

@@ -14,6 +14,7 @@ var TypeToRR = map[uint16]func() RR{
TypeAAAA: func() RR { return new(AAAA) },
TypeAFSDB: func() RR { return new(AFSDB) },
TypeANY: func() RR { return new(ANY) },
TypeAVC: func() RR { return new(AVC) },
TypeCAA: func() RR { return new(CAA) },
TypeCDNSKEY: func() RR { return new(CDNSKEY) },
TypeCDS: func() RR { return new(CDS) },
@@ -86,6 +87,7 @@ var TypeToString = map[uint16]string{
TypeAFSDB: "AFSDB",
TypeANY: "ANY",
TypeATMA: "ATMA",
TypeAVC: "AVC",
TypeAXFR: "AXFR",
TypeCAA: "CAA",
TypeCDNSKEY: "CDNSKEY",
@@ -166,6 +168,7 @@ func (rr *A) Header() *RR_Header { return &rr.Hdr }
func (rr *AAAA) Header() *RR_Header { return &rr.Hdr }
func (rr *AFSDB) Header() *RR_Header { return &rr.Hdr }
func (rr *ANY) Header() *RR_Header { return &rr.Hdr }
func (rr *AVC) Header() *RR_Header { return &rr.Hdr }
func (rr *CAA) Header() *RR_Header { return &rr.Hdr }
func (rr *CDNSKEY) Header() *RR_Header { return &rr.Hdr }
func (rr *CDS) Header() *RR_Header { return &rr.Hdr }
@@ -252,6 +255,13 @@ func (rr *ANY) len() int {
l := rr.Hdr.len()
return l
}
func (rr *AVC) len() int {
l := rr.Hdr.len()
for _, x := range rr.Txt {
l += len(x) + 1
}
return l
}
func (rr *CAA) len() int {
l := rr.Hdr.len()
l++ // Flag
@@ -649,6 +659,11 @@ func (rr *AFSDB) copy() RR {
func (rr *ANY) copy() RR {
return &ANY{*rr.Hdr.copyHeader()}
}
func (rr *AVC) copy() RR {
Txt := make([]string, len(rr.Txt))
copy(Txt, rr.Txt)
return &AVC{*rr.Hdr.copyHeader(), Txt}
}
func (rr *CAA) copy() RR {
return &CAA{*rr.Hdr.copyHeader(), rr.Flag, rr.Tag, rr.Value}
}

3
vendor/github.com/minio/minio-go/README.md сгенерированный поставляемый
Просмотреть файл

@@ -1,4 +1,5 @@
# Minio Go Client SDK for Amazon S3 Compatible Cloud Storage [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Minio/minio?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
# Minio Go Client SDK for Amazon S3 Compatible Cloud Storage [![Slack](https://slack.minio.io/slack?type=svg)](https://slack.minio.io)
The Minio Go Client SDK provides simple APIs to access any Amazon S3 compatible object storage.
**Supported cloud storage providers:**

10
vendor/github.com/minio/minio-go/api-error-response.go сгенерированный поставляемый
Просмотреть файл

@@ -149,6 +149,16 @@ func httpRespToErrorResponse(resp *http.Response, bucketName, objectName string)
return errResp
}
// ErrTransferAccelerationBucket - bucket name is invalid to be used with transfer acceleration.
func ErrTransferAccelerationBucket(bucketName string) error {
msg := fmt.Sprintf("The name of the bucket used for Transfer Acceleration must be DNS-compliant and must not contain periods (\".\").")
return ErrorResponse{
Code: "InvalidArgument",
Message: msg,
BucketName: bucketName,
}
}
// ErrEntityTooLarge - Input size is larger than supported maximum.
func ErrEntityTooLarge(totalSize, maxObjectSize int64, bucketName, objectName string) error {
msg := fmt.Sprintf("Your proposed upload size %d exceeds the maximum allowed object size %d for single PUT operation.", totalSize, maxObjectSize)

37
vendor/github.com/minio/minio-go/api-get-object.go сгенерированный поставляемый
Просмотреть файл

@@ -212,10 +212,12 @@ type Object struct {
reqCh chan<- getRequest
resCh <-chan getResponse
doneCh chan<- struct{}
prevOffset int64
currOffset int64
objectInfo ObjectInfo
// Ask lower level to initiate data fetching based on currOffset
seekData bool
// Keeps track of closed call.
isClosed bool
@@ -258,6 +260,10 @@ func (o *Object) doGetRequest(request getRequest) (getResponse, error) {
if response.Error != nil {
return response, response.Error
}
// Data are ready on the wire, no need to reinitiate connection in lower level
o.seekData = false
return response, nil
}
@@ -266,8 +272,6 @@ func (o *Object) doGetRequest(request getRequest) (getResponse, error) {
func (o *Object) setOffset(bytesRead int64) error {
// Update the currentOffset.
o.currOffset += bytesRead
// Save the current offset as previous offset.
o.prevOffset = o.currOffset
if o.currOffset >= o.objectInfo.Size {
return io.EOF
@@ -303,22 +307,9 @@ func (o *Object) Read(b []byte) (n int, err error) {
readReq.isFirstReq = true
}
// Verify if offset has changed and currOffset is greater than
// previous offset. Perhaps due to Seek().
offsetChange := o.prevOffset - o.currOffset
if offsetChange < 0 {
offsetChange = -offsetChange
}
if offsetChange > 0 {
// Fetch the new reader at the current offset again.
readReq.Offset = o.currOffset
readReq.DidOffsetChange = true
} else {
// No offset changes no need to fetch new reader, continue
// reading.
readReq.DidOffsetChange = false
readReq.Offset = 0
}
// Ask to establish a new data fetch routine based on seekData flag
readReq.DidOffsetChange = o.seekData
readReq.Offset = o.currOffset
// Send and receive from the first request.
response, err := o.doGetRequest(readReq)
@@ -430,8 +421,6 @@ func (o *Object) ReadAt(b []byte, offset int64) (n int, err error) {
if !o.objectInfoSet {
// Update the currentOffset.
o.currOffset += bytesRead
// Save the current offset as previous offset.
o.prevOffset = o.currOffset
} else {
// If this was not the first request update
// the offsets and compare against objectInfo
@@ -492,8 +481,6 @@ func (o *Object) Seek(offset int64, whence int) (n int64, err error) {
return 0, err
}
}
// Save current offset as previous offset.
o.prevOffset = o.currOffset
// Switch through whence.
switch whence {
@@ -527,6 +514,10 @@ func (o *Object) Seek(offset int64, whence int) (n int64, err error) {
if o.prevErr == io.EOF {
o.prevErr = nil
}
// Ask lower level to fetch again from source
o.seekData = true
// Return the effective offset.
return o.currOffset, nil
}

43
vendor/github.com/minio/minio-go/api.go сгенерированный поставляемый
Просмотреть файл

@@ -71,6 +71,9 @@ type Client struct {
isTraceEnabled bool
traceOutput io.Writer
// S3 specific accelerated endpoint.
s3AccelerateEndpoint string
// Random seed.
random *rand.Rand
}
@@ -78,7 +81,7 @@ type Client struct {
// Global constants.
const (
libraryName = "minio-go"
libraryVersion = "2.0.3"
libraryVersion = "2.0.4"
)
// User Agent should always following the below style.
@@ -206,8 +209,7 @@ func privateNew(endpoint, accessKeyID, secretAccessKey string, secure bool) (*Cl
// SetAppInfo - add application details to user agent.
func (c *Client) SetAppInfo(appName string, appVersion string) {
// if app name and version is not set, we do not a new user
// agent.
// if app name and version not set, we do not set a new user agent.
if appName != "" && appVersion != "" {
c.appInfo = struct {
appName string
@@ -258,8 +260,18 @@ func (c *Client) TraceOff() {
c.isTraceEnabled = false
}
// requestMetadata - is container for all the values to make a
// request.
// SetS3TransferAccelerate - turns s3 accelerated endpoint on or off for all your
// requests. This feature is only specific to S3 for all other endpoints this
// function does nothing. To read further details on s3 transfer acceleration
// please vist -
// http://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html
func (c *Client) SetS3TransferAccelerate(accelerateEndpoint string) {
if s3utils.IsAmazonEndpoint(c.endpointURL) {
c.s3AccelerateEndpoint = accelerateEndpoint
}
}
// requestMetadata - is container for all the values to make a request.
type requestMetadata struct {
// If set newRequest presigns the URL.
presignURL bool
@@ -601,10 +613,10 @@ func (c Client) newRequest(method string, metadata requestMetadata) (req *http.R
req.Body = ioutil.NopCloser(metadata.contentBody)
}
// FIXEM: Enable this when Google Cloud Storage properly supports 100-continue.
// FIXME: Enable this when Google Cloud Storage properly supports 100-continue.
// Skip setting 'expect' header for Google Cloud Storage, there
// are some known issues - https://github.com/restic/restic/issues/520
if !s3utils.IsGoogleEndpoint(c.endpointURL) {
if !s3utils.IsGoogleEndpoint(c.endpointURL) && c.s3AccelerateEndpoint == "" {
// Set 'Expect' header for the request.
req.Header.Set("Expect", "100-continue")
}
@@ -672,9 +684,22 @@ func (c Client) makeTargetURL(bucketName, objectName, bucketLocation string, que
host := c.endpointURL.Host
// For Amazon S3 endpoint, try to fetch location based endpoint.
if s3utils.IsAmazonEndpoint(c.endpointURL) {
// Fetch new host based on the bucket location.
host = getS3Endpoint(bucketLocation)
if c.s3AccelerateEndpoint != "" && bucketName != "" {
// http://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html
// Disable transfer acceleration for non-compliant bucket names.
if strings.Contains(bucketName, ".") {
return nil, ErrTransferAccelerationBucket(bucketName)
}
// If transfer acceleration is requested set new host.
// For more details about enabling transfer acceleration read here.
// http://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html
host = c.s3AccelerateEndpoint
} else {
// Fetch new host based on the bucket location.
host = getS3Endpoint(bucketLocation)
}
}
// Save scheme.
scheme := c.endpointURL.Scheme

2
vendor/github.com/minio/minio-go/api_functional_v2_test.go сгенерированный поставляемый
Просмотреть файл

@@ -943,7 +943,7 @@ func TestCopyObjectV2(t *testing.T) {
}
// Set copy conditions.
copyConds := NewCopyConditions()
copyConds := CopyConditions{}
err = copyConds.SetModified(time.Date(2014, time.April, 0, 0, 0, 0, 0, time.UTC))
if err != nil {
t.Fatal("Error:", err)

151
vendor/github.com/minio/minio-go/api_functional_v4_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1255,6 +1255,7 @@ func TestGetObjectReadSeekFunctional(t *testing.T) {
// Generate data more than 32K
buf := bytes.Repeat([]byte("2"), rand.Intn(1<<20)+32*1024)
bufSize := len(buf)
// Save the data
objectName := randString(60, rand.NewSource(time.Now().UnixNano()), "")
@@ -1263,10 +1264,21 @@ func TestGetObjectReadSeekFunctional(t *testing.T) {
t.Fatal("Error:", err, bucketName, objectName)
}
if n != int64(len(buf)) {
if n != int64(bufSize) {
t.Fatalf("Error: number of bytes does not match, want %v, got %v\n", len(buf), n)
}
defer func() {
err = c.RemoveObject(bucketName, objectName)
if err != nil {
t.Fatal("Error: ", err)
}
err = c.RemoveBucket(bucketName)
if err != nil {
t.Fatal("Error:", err)
}
}()
// Read the data back
r, err := c.GetObject(bucketName, objectName)
if err != nil {
@@ -1277,77 +1289,86 @@ func TestGetObjectReadSeekFunctional(t *testing.T) {
if err != nil {
t.Fatal("Error:", err, bucketName, objectName)
}
if st.Size != int64(len(buf)) {
if st.Size != int64(bufSize) {
t.Fatalf("Error: number of bytes in stat does not match, want %v, got %v\n",
len(buf), st.Size)
}
offset := int64(2048)
n, err = r.Seek(offset, 0)
if err != nil {
t.Fatal("Error:", err, offset)
}
if n != offset {
t.Fatalf("Error: number of bytes seeked does not match, want %v, got %v\n",
offset, n)
}
n, err = r.Seek(0, 1)
if err != nil {
t.Fatal("Error:", err)
}
if n != offset {
t.Fatalf("Error: number of current seek does not match, want %v, got %v\n",
offset, n)
}
_, err = r.Seek(offset, 2)
if err == nil {
t.Fatal("Error: seek on positive offset for whence '2' should error out")
}
n, err = r.Seek(-offset, 2)
if err != nil {
t.Fatal("Error:", err)
}
if n != st.Size-offset {
t.Fatalf("Error: number of bytes seeked back does not match, want %d, got %v\n", st.Size-offset, n)
}
var buffer1 bytes.Buffer
if _, err = io.CopyN(&buffer1, r, st.Size); err != nil {
if err != io.EOF {
t.Fatal("Error:", err)
// This following function helps us to compare data from the reader after seek
// with the data from the original buffer
cmpData := func(r io.Reader, start, end int) {
if end-start == 0 {
return
}
buffer := bytes.NewBuffer([]byte{})
if _, err := io.CopyN(buffer, r, int64(bufSize)); err != nil {
if err != io.EOF {
t.Fatal("Error:", err)
}
}
if !bytes.Equal(buf[start:end], buffer.Bytes()) {
t.Fatal("Error: Incorrect read bytes v/s original buffer.")
}
}
if !bytes.Equal(buf[len(buf)-int(offset):], buffer1.Bytes()) {
t.Fatal("Error: Incorrect read bytes v/s original buffer.")
// Generic seek error for errors other than io.EOF
seekErr := errors.New("seek error")
testCases := []struct {
offset int64
whence int
pos int64
err error
shouldCmp bool
start int
end int
}{
// Start from offset 0, fetch data and compare
{0, 0, 0, nil, true, 0, 0},
// Start from offset 2048, fetch data and compare
{2048, 0, 2048, nil, true, 2048, bufSize},
// Start from offset larger than possible
{int64(bufSize) + 1024, 0, 0, seekErr, false, 0, 0},
// Move to offset 0 without comparing
{0, 0, 0, nil, false, 0, 0},
// Move one step forward and compare
{1, 1, 1, nil, true, 1, bufSize},
// Move larger than possible
{int64(bufSize), 1, 0, seekErr, false, 0, 0},
// Provide negative offset with CUR_SEEK
{int64(-1), 1, 0, seekErr, false, 0, 0},
// Test with whence SEEK_END and with positive offset
{1024, 2, int64(bufSize) - 1024, io.EOF, true, 0, 0},
// Test with whence SEEK_END and with negative offset
{-1024, 2, int64(bufSize) - 1024, nil, true, bufSize - 1024, bufSize},
// Test with whence SEEK_END and with large negative offset
{-int64(bufSize) * 2, 2, 0, seekErr, true, 0, 0},
}
// Seek again and read again.
n, err = r.Seek(offset-1, 0)
if err != nil {
t.Fatal("Error:", err)
}
if n != (offset - 1) {
t.Fatalf("Error: number of bytes seeked back does not match, want %v, got %v\n", offset-1, n)
}
var buffer2 bytes.Buffer
if _, err = io.CopyN(&buffer2, r, st.Size); err != nil {
if err != io.EOF {
t.Fatal("Error:", err)
for i, testCase := range testCases {
// Perform seek operation
n, err := r.Seek(testCase.offset, testCase.whence)
// We expect an error
if testCase.err == seekErr && err == nil {
t.Fatalf("Test %d, unexpected err value: expected: %v, found: %v", i+1, testCase.err, err)
}
// We expect a specific error
if testCase.err != seekErr && testCase.err != err {
t.Fatalf("Test %d, unexpected err value: expected: %v, found: %v", i+1, testCase.err, err)
}
// If we expect an error go to the next loop
if testCase.err != nil {
continue
}
// Check the returned seek pos
if n != testCase.pos {
t.Fatalf("Test %d, error: number of bytes seeked does not match, want %v, got %v\n", i+1,
testCase.pos, n)
}
// Compare only if shouldCmp is activated
if testCase.shouldCmp {
cmpData(r, testCase.start, testCase.end)
}
}
// Verify now lesser bytes.
if !bytes.Equal(buf[2047:], buffer2.Bytes()) {
t.Fatal("Error: Incorrect read bytes v/s original buffer.")
}
err = c.RemoveObject(bucketName, objectName)
if err != nil {
t.Fatal("Error: ", err)
}
err = c.RemoveBucket(bucketName)
if err != nil {
t.Fatal("Error:", err)
}
}
@@ -1662,7 +1683,7 @@ func TestCopyObject(t *testing.T) {
}
// Set copy conditions.
copyConds := NewCopyConditions()
copyConds := CopyConditions{}
// Start by setting wrong conditions
err = copyConds.SetModified(time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC))
@@ -1725,7 +1746,7 @@ func TestCopyObject(t *testing.T) {
}
// CopyObject again but with wrong conditions
copyConds = NewCopyConditions()
copyConds = CopyConditions{}
err = copyConds.SetUnmodified(time.Date(2014, time.April, 0, 0, 0, 0, 0, time.UTC))
if err != nil {
t.Fatal("Error:", err)

7
vendor/github.com/minio/minio-go/bucket-cache.go сгенерированный поставляемый
Просмотреть файл

@@ -164,13 +164,6 @@ func (c Client) getBucketLocationRequest(bucketName string) (*http.Request, erro
// Set get bucket location always as path style.
targetURL := c.endpointURL
// Requesting a bucket location from an accelerate endpoint returns a 400,
// so default to us-east-1 for the lookup
if s3utils.IsAmazonS3AccelerateEndpoint(c.endpointURL) {
targetURL.Host = getS3Endpoint("us-east-1")
}
targetURL.Path = path.Join(bucketName, "") + "/"
targetURL.RawQuery = urlValues.Encode()

10
vendor/github.com/minio/minio-go/copy-conditions.go сгенерированный поставляемый
Просмотреть файл

@@ -41,11 +41,13 @@ type CopyConditions struct {
conditions []copyCondition
}
// NewCopyConditions - Instantiate new list of conditions.
// NewCopyConditions - Instantiate new list of conditions. This
// function is left behind for backward compatibility. The idiomatic
// way to set an empty set of copy conditions is,
// ``copyConditions := CopyConditions{}``.
//
func NewCopyConditions() CopyConditions {
return CopyConditions{
conditions: make([]copyCondition, 0),
}
return CopyConditions{}
}
// SetMatchETag - set match etag.

89
vendor/github.com/minio/minio-go/docs/API.md сгенерированный поставляемый
Просмотреть файл

@@ -1,4 +1,4 @@
# Golang Client API Reference [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Minio/minio?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
# Minio Go Client API Reference [![Slack](https://slack.minio.io/slack?type=svg)](https://slack.minio.io)
## Initialize Minio Client object.
@@ -60,7 +60,7 @@ func main() {
|[`ListBuckets`](#ListBuckets) |[`PutObject`](#PutObject) |[`PresignedPutObject`](#PresignedPutObject) | [`GetBucketPolicy`](#GetBucketPolicy) | [`SetCustomTransport`](#SetCustomTransport) |
|[`BucketExists`](#BucketExists) |[`CopyObject`](#CopyObject) |[`PresignedPostPolicy`](#PresignedPostPolicy) | [`ListBucketPolicies`](#ListBucketPolicies) | [`TraceOn`](#TraceOn) |
| [`RemoveBucket`](#RemoveBucket) |[`StatObject`](#StatObject) | | [`SetBucketNotification`](#SetBucketNotification) | [`TraceOff`](#TraceOff) |
|[`ListObjects`](#ListObjects) |[`RemoveObject`](#RemoveObject) | | [`GetBucketNotification`](#GetBucketNotification) |
|[`ListObjects`](#ListObjects) |[`RemoveObject`](#RemoveObject) | | [`GetBucketNotification`](#GetBucketNotification) | [`SetS3TransferAccelerate`](#SetS3TransferAccelerate) |
|[`ListObjectsV2`](#ListObjectsV2) | [`RemoveObjects`](#RemoveObjects) | | [`RemoveAllBucketNotification`](#RemoveAllBucketNotification) |
|[`ListIncompleteUploads`](#ListIncompleteUploads) | [`RemoveIncompleteUpload`](#RemoveIncompleteUpload) | | [`ListenBucketNotification`](#ListenBucketNotification) |
| | [`FPutObject`](#FPutObject) | | |
@@ -69,7 +69,7 @@ func main() {
## 1. Constructor
<a name="Minio"></a>
### New(endpoint string, accessKeyID string, secretAccessKey string, ssl bool) (*Client, error)
### New(endpoint, accessKeyID, secretAccessKey string, ssl bool) (*Client, error)
Initializes a new client object.
__Parameters__
@@ -86,7 +86,7 @@ __Parameters__
## 2. Bucket operations
<a name="MakeBucket"></a>
### MakeBucket(bucketName string, location string) error
### MakeBucket(bucketName, location string) error
Creates a new bucket.
@@ -216,7 +216,7 @@ if err != nil {
```
<a name="ListObjects"></a>
### ListObjects(bucketName string, prefix string, recursive bool, doneCh chan struct{}) <-chan ObjectInfo
### ListObjects(bucketName, prefix string, recursive bool, doneCh chan struct{}) <-chan ObjectInfo
Lists objects in a bucket.
@@ -267,7 +267,7 @@ for object := range objectCh {
<a name="ListObjectsV2"></a>
### ListObjectsV2(bucketName string, prefix string, recursive bool, doneCh chan struct{}) <-chan ObjectInfo
### ListObjectsV2(bucketName, prefix string, recursive bool, doneCh chan struct{}) <-chan ObjectInfo
Lists objects in a bucket using the recommended listing API v2
@@ -317,7 +317,7 @@ for object := range objectCh {
```
<a name="ListIncompleteUploads"></a>
### ListIncompleteUploads(bucketName string, prefix string, recursive bool, doneCh chan struct{}) <- chan ObjectMultipartInfo
### ListIncompleteUploads(bucketName, prefix string, recursive bool, doneCh chan struct{}) <- chan ObjectMultipartInfo
Lists partially uploaded objects in a bucket.
@@ -373,7 +373,7 @@ for multiPartObject := range multiPartObjectCh {
## 3. Object operations
<a name="GetObject"></a>
### GetObject(bucketName string, objectName string) (*Object, error)
### GetObject(bucketName, objectName string) (*Object, error)
Downloads an object.
@@ -392,7 +392,7 @@ __Return Value__
|Param |Type |Description |
|:---|:---| :---|
|`object` | _*minio.Object_ |_minio.Object_ represents object reader |
|`object` | _*minio.Object_ |_minio.Object_ represents object reader. It implements io.Reader, io.Seeker, io.ReaderAt and io.Closer interfaces. |
__Example__
@@ -418,7 +418,7 @@ if _, err = io.Copy(localFile, object); err != nil {
```
<a name="FGetObject"></a>
### FGetObject(bucketName string, objectName string, filePath string) error
### FGetObject(bucketName, objectName, filePath string) error
Downloads and saves the object as a file in the local filesystem.
@@ -446,7 +446,7 @@ if err != nil {
```
<a name="PutObject"></a>
### PutObject(bucketName string, objectName string, reader io.Reader, contentType string) (n int, err error)
### PutObject(bucketName, objectName string, reader io.Reader, contentType string) (n int, err error)
Uploads an object.
@@ -489,7 +489,7 @@ if err != nil {
<a name="CopyObject"></a>
### CopyObject(bucketName string, objectName string, objectSource string, conditions CopyConditions) error
### CopyObject(bucketName, objectName, objectSource string, conditions CopyConditions) error
Copy a source object into a new object with the provided name in the provided bucket.
@@ -509,24 +509,34 @@ __Example__
```go
// Use-case-1
// To copy an existing object to a new object with _no_ copy conditions.
copyConditions := minio.CopyConditions{}
err := minioClient.CopyObject("mybucket", "myobject", "my-sourcebucketname/my-sourceobjectname", copyConds)
if err != nil {
fmt.Println(err)
return
}
// All following conditions are allowed and can be combined together.
// Use-case-2
// To copy an existing object to a new object with the following copy conditions
// 1. that matches a given ETag
// 2. and modified after 1st April 2014
// 3. but unmodified since 23rd April 2014
// Set copy conditions.
var copyConds = minio.NewCopyConditions()
// Set modified condition, copy object modified since 2014 April.
copyConds.SetModified(time.Date(2014, time.April, 0, 0, 0, 0, 0, time.UTC))
// Initialize empty copy conditions.
var copyConds = minio.CopyConditions{}
// Set unmodified condition, copy object unmodified since 2014 April.
// copyConds.SetUnmodified(time.Date(2014, time.April, 0, 0, 0, 0, 0, time.UTC))
// copy object that matches the given ETag.
copyConds.SetMatchETag("31624deb84149d2f8ef9c385918b653a")
// Set matching ETag condition, copy object which matches the following ETag.
// copyConds.SetMatchETag("31624deb84149d2f8ef9c385918b653a")
// and modified after 1st April 2014
copyConds.SetModified(time.Date(2014, time.April, 1, 0, 0, 0, 0, time.UTC))
// Set matching ETag except condition, copy object which does not match the following ETag.
// copyConds.SetMatchETagExcept("31624deb84149d2f8ef9c385918b653a")
// but unmodified since 23rd April 2014
copyConds.SetUnmodified(time.Date(2014, time.April, 23, 0, 0, 0, 0, time.UTC))
err := minioClient.CopyObject("mybucket", "myobject", "/my-sourcebucketname/my-sourceobjectname", copyConds)
err := minioClient.CopyObject("mybucket", "myobject", "my-sourcebucketname/my-sourceobjectname", copyConds)
if err != nil {
fmt.Println(err)
return
@@ -535,7 +545,7 @@ if err != nil {
```
<a name="FPutObject"></a>
### FPutObject(bucketName string, objectName string, filePath string, contentType string) error
### FPutObject(bucketName, objectName, filePath, contentType string) error
Uploads contents from a file to objectName.
@@ -569,7 +579,7 @@ if err != nil {
```
<a name="StatObject"></a>
### StatObject(bucketName string, objectName string) (ObjectInfo, error)
### StatObject(bucketName, objectName string) (ObjectInfo, error)
Gets metadata of an object.
@@ -613,7 +623,7 @@ fmt.Println(objInfo)
```
<a name="RemoveObject"></a>
### RemoveObject(bucketName string, objectName string) error
### RemoveObject(bucketName, objectName string) error
Removes an object.
@@ -670,7 +680,7 @@ for e := range errorCh {
<a name="RemoveIncompleteUpload"></a>
### RemoveIncompleteUpload(bucketName string, objectName string) error
### RemoveIncompleteUpload(bucketName, objectName string) error
Removes a partially uploaded object.
@@ -699,7 +709,7 @@ if err != nil {
<a name="PresignedGetObject"></a>
### PresignedGetObject(bucketName string, objectName string, expiry time.Duration, reqParams url.Values) (*url.URL, error)
### PresignedGetObject(bucketName, objectName string, expiry time.Duration, reqParams url.Values) (*url.URL, error)
Generates a presigned URL for HTTP GET operations. Browsers/Mobile clients may point to this URL to directly download objects even if the bucket is private. This presigned URL can have an associated expiration time in seconds after which it is no longer operational. The default expiry is set to 7 days.
@@ -733,7 +743,7 @@ if err != nil {
```
<a name="PresignedPutObject"></a>
### PresignedPutObject(bucketName string, objectName string, expiry time.Duration) (*url.URL, error)
### PresignedPutObject(bucketName, objectName string, expiry time.Duration) (*url.URL, error)
Generates a presigned URL for HTTP PUT operations. Browsers/Mobile clients may point to this URL to upload objects directly to a bucket even if it is private. This presigned URL can have an associated expiration time in seconds after which it is no longer operational. The default expiry is set to 7 days.
@@ -822,7 +832,7 @@ fmt.Printf("%s\n", url)
## 5. Bucket policy/notification operations
<a name="SetBucketPolicy"></a>
### SetBucketPolicy(bucketname string, objectPrefix string, policy policy.BucketPolicy) error
### SetBucketPolicy(bucketname, objectPrefix string, policy policy.BucketPolicy) error
Set access permissions on bucket or an object prefix.
@@ -864,7 +874,7 @@ if err != nil {
```
<a name="GetBucketPolicy"></a>
### GetBucketPolicy(bucketName string, objectPrefix string) (policy.BucketPolicy, error)
### GetBucketPolicy(bucketName, objectPrefix string) (policy.BucketPolicy, error)
Get access permissions on a bucket or a prefix.
@@ -901,7 +911,7 @@ fmt.Println("Access permissions for mybucket is", bucketPolicy)
```
<a name="ListBucketPolicies"></a>
### ListBucketPolicies(bucketName string, objectPrefix string) (map[string]BucketPolicy, error)
### ListBucketPolicies(bucketName, objectPrefix string) (map[string]BucketPolicy, error)
Get access permissions rules associated to the specified bucket and prefix.
@@ -1099,7 +1109,7 @@ for notificationInfo := range minioClient.ListenBucketNotification("YOUR-BUCKET"
## 6. Client custom settings
<a name="SetAppInfo"></a>
### SetAppInfo(appName string, appVersion string)
### SetAppInfo(appName, appVersion string)
Adds application details to User-Agent.
__Parameters__
@@ -1148,6 +1158,17 @@ __Parameters__
### TraceOff()
Disables HTTP tracing.
<a name="SetS3TransferAccelerate"></a>
### SetS3TransferAccelerate(acceleratedEndpoint string)
Set AWS S3 transfer acceleration endpoint for all API requests hereafter.
NOTE: This API applies only to AWS S3 and ignored with other S3 compatible object storage services.
__Parameters__
| Param | Type | Description |
|---|---|---|
|`acceleratedEndpoint` | _string_ | Set to new S3 transfer acceleration endpoint.|
## 7. Explore Further

2
vendor/github.com/minio/minio-go/examples/s3/copyobject.go сгенерированный поставляемый
Просмотреть файл

@@ -45,7 +45,7 @@ func main() {
// All following conditions are allowed and can be combined together.
// Set copy conditions.
var copyConds = minio.NewCopyConditions()
var copyConds = minio.CopyConditions{}
// Set modified condition, copy object modified since 2014 April.
copyConds.SetModified(time.Date(2014, time.April, 0, 0, 0, 0, 0, time.UTC))

56
vendor/github.com/minio/minio-go/examples/s3/putobject-s3-accelerate.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,56 @@
// +build ignore
/*
* Minio Go Library for Amazon S3 Compatible Cloud Storage (C) 2016 Minio, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package main
import (
"log"
"os"
"github.com/minio/minio-go"
)
func main() {
// Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY, my-testfile, my-bucketname and
// my-objectname are dummy values, please replace them with original values.
// Requests are always secure (HTTPS) by default. Set secure=false to enable insecure (HTTP) access.
// This boolean value is the last argument for New().
// New returns an Amazon S3 compatible client object. API compatibility (v2 or v4) is automatically
// determined based on the Endpoint value.
s3Client, err := minio.New("s3.amazonaws.com", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true)
if err != nil {
log.Fatalln(err)
}
// Enable S3 transfer accelerate endpoint.
s3Client.S3TransferAccelerate("s3-accelerate.amazonaws.com")
object, err := os.Open("my-testfile")
if err != nil {
log.Fatalln(err)
}
defer object.Close()
n, err := s3Client.PutObject("my-bucketname", "my-objectname", object, "application/octet-stream")
if err != nil {
log.Fatalln(err)
}
log.Println("Uploaded", "my-objectname", " of size: ", n, "Successfully.")
}

12
vendor/github.com/minio/minio-go/pkg/s3utils/utils.go сгенерированный поставляемый
Просмотреть файл

@@ -85,10 +85,6 @@ func IsAmazonEndpoint(endpointURL url.URL) bool {
return true
}
if IsAmazonS3AccelerateEndpoint(endpointURL) {
return true
}
return endpointURL.Host == "s3.amazonaws.com"
}
@@ -105,14 +101,6 @@ func IsAmazonChinaEndpoint(endpointURL url.URL) bool {
return endpointURL.Host == "s3.cn-north-1.amazonaws.com.cn"
}
// IsAmazonS3AccelerateEndpoint - Match if it is an Amazon S3 Accelerate
func IsAmazonS3AccelerateEndpoint(endpointURL url.URL) bool {
if endpointURL == sentinelURL {
return false
}
return endpointURL.Host == "s3-accelerate.amazonaws.com"
}
// IsGoogleEndpoint - Match if it is exactly Google cloud storage endpoint.
func IsGoogleEndpoint(endpointURL url.URL) bool {
if endpointURL == sentinelURL {

8
vendor/github.com/minio/minio-go/pkg/set/stringset.go сгенерированный поставляемый
Просмотреть файл

@@ -25,8 +25,8 @@ import (
// StringSet - uses map as set of strings.
type StringSet map[string]struct{}
// keys - returns StringSet keys.
func (set StringSet) keys() []string {
// ToSlice - returns StringSet as string slice.
func (set StringSet) ToSlice() []string {
keys := make([]string, 0, len(set))
for k := range set {
keys = append(keys, k)
@@ -141,7 +141,7 @@ func (set StringSet) Union(sset StringSet) StringSet {
// MarshalJSON - converts to JSON data.
func (set StringSet) MarshalJSON() ([]byte, error) {
return json.Marshal(set.keys())
return json.Marshal(set.ToSlice())
}
// UnmarshalJSON - parses JSON data and creates new set with it.
@@ -169,7 +169,7 @@ func (set *StringSet) UnmarshalJSON(data []byte) error {
// String - returns printable string of the set.
func (set StringSet) String() string {
return fmt.Sprintf("%s", set.keys())
return fmt.Sprintf("%s", set.ToSlice())
}
// NewStringSet - creates new string set.

25
vendor/github.com/minio/minio-go/pkg/set/stringset_test.go сгенерированный поставляемый
Просмотреть файл

@@ -17,6 +17,7 @@
package set
import (
"fmt"
"strings"
"testing"
)
@@ -320,3 +321,27 @@ func TestStringSetString(t *testing.T) {
}
}
}
// StringSet.ToSlice() is called with series of cases for valid and erroneous inputs and the result is validated.
func TestStringSetToSlice(t *testing.T) {
testCases := []struct {
set StringSet
expectedResult string
}{
// Test empty set.
{NewStringSet(), `[]`},
// Test set with empty value.
{CreateStringSet(""), `[]`},
// Test set with value.
{CreateStringSet("foo"), `[foo]`},
// Test set with value.
{CreateStringSet("foo", "bar"), `[bar foo]`},
}
for _, testCase := range testCases {
sslice := testCase.set.ToSlice()
if str := fmt.Sprintf("%s", sslice); str != testCase.expectedResult {
t.Fatalf("expected: %s, got: %s", testCase.expectedResult, str)
}
}
}

2
vendor/github.com/mitchellh/mapstructure/.travis.yml сгенерированный поставляемый
Просмотреть файл

@@ -1,7 +1,7 @@
language: go
go:
- 1.4
- 1.8.1
script:
- go test

8
vendor/github.com/mitchellh/mapstructure/decode_hooks.go сгенерированный поставляемый
Просмотреть файл

@@ -121,6 +121,11 @@ func StringToTimeDurationHookFunc() DecodeHookFunc {
}
}
// WeaklyTypedHook is a DecodeHookFunc which adds support for weak typing to
// the decoder.
//
// Note that this is significantly different from the WeaklyTypedInput option
// of the DecoderConfig.
func WeaklyTypedHook(
f reflect.Kind,
t reflect.Kind,
@@ -132,9 +137,8 @@ func WeaklyTypedHook(
case reflect.Bool:
if dataVal.Bool() {
return "1", nil
} else {
return "0", nil
}
return "0", nil
case reflect.Float32:
return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil
case reflect.Int:

11
vendor/github.com/mitchellh/mapstructure/mapstructure.go сгенерированный поставляемый
Просмотреть файл

@@ -1,5 +1,5 @@
// The mapstructure package exposes functionality to convert an
// arbitrary map[string]interface{} into a native Go structure.
// Package mapstructure exposes functionality to convert an arbitrary
// map[string]interface{} into a native Go structure.
//
// The Go structure can be arbitrarily complex, containing slices,
// other structs, etc. and the decoder will properly decode nested
@@ -32,7 +32,12 @@ import (
// both.
type DecodeHookFunc interface{}
// DecodeHookFuncType is a DecodeHookFunc which has complete information about
// the source and target types.
type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error)
// DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the
// source and target types.
type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error)
// DecoderConfig is the configuration that is used to create a new decoder
@@ -436,7 +441,7 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value)
case dataKind == reflect.Uint:
val.SetFloat(float64(dataVal.Uint()))
case dataKind == reflect.Float32:
val.SetFloat(float64(dataVal.Float()))
val.SetFloat(dataVal.Float())
case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
if dataVal.Bool() {
val.SetFloat(1)

2
vendor/github.com/mitchellh/mapstructure/mapstructure_test.go сгенерированный поставляемый
Просмотреть файл

@@ -437,7 +437,7 @@ func TestDecode_DecodeHookType(t *testing.T) {
func TestDecode_Nil(t *testing.T) {
t.Parallel()
var input interface{} = nil
var input interface{}
result := Basic{
Vstring: "foo",
}

1
vendor/github.com/nicksnyder/go-i18n/.travis.yml сгенерированный поставляемый
Просмотреть файл

@@ -7,4 +7,5 @@ go:
- 1.5
- 1.6
- 1.7
- 1.8
- tip

66
vendor/github.com/nicksnyder/go-i18n/README.md сгенерированный поставляемый
Просмотреть файл

@@ -1,19 +1,19 @@
go-i18n [![Build Status](https://secure.travis-ci.org/nicksnyder/go-i18n.png?branch=master)](http://travis-ci.org/nicksnyder/go-i18n)
go-i18n [![Build Status](https://travis-ci.org/nicksnyder/go-i18n.svg?branch=master)](http://travis-ci.org/nicksnyder/go-i18n) [![Sourcegraph](https://sourcegraph.com/github.com/nicksnyder/go-i18n/-/badge.svg)](https://sourcegraph.com/github.com/nicksnyder/go-i18n?badge)
=======
go-i18n is a Go [package](#i18n-package) and a [command](#goi18n-command) that helps you translate Go programs into multiple languages.
* Supports [pluralized strings](http://cldr.unicode.org/index/cldr-spec/plural-rules) for all 200+ languages in the [Unicode Common Locale Data Repository (CLDR)](http://www.unicode.org/cldr/charts/28/supplemental/language_plural_rules.html).
* Code and tests are [automatically generated](https://github.com/nicksnyder/go-i18n/tree/master/i18n/language/codegen) from [CLDR data](http://cldr.unicode.org/index/downloads)
* Supports strings with named variables using [text/template](http://golang.org/pkg/text/template/) syntax.
* Translation files are simple JSON or YAML.
* Translation files are simple JSON, TOML or YAML.
* [Documented](http://godoc.org/github.com/nicksnyder/go-i18n) and [tested](https://travis-ci.org/nicksnyder/go-i18n)!
Package i18n [![GoDoc](http://godoc.org/github.com/nicksnyder/go-i18n?status.png)](http://godoc.org/github.com/nicksnyder/go-i18n/i18n)
Package i18n [![GoDoc](http://godoc.org/github.com/nicksnyder/go-i18n?status.svg)](http://godoc.org/github.com/nicksnyder/go-i18n/i18n)
------------
The i18n package provides runtime APIs for fetching translated strings.
Command goi18n [![GoDoc](http://godoc.org/github.com/nicksnyder/go-i18n?status.png)](http://godoc.org/github.com/nicksnyder/go-i18n/goi18n)
Command goi18n [![GoDoc](http://godoc.org/github.com/nicksnyder/go-i18n?status.svg)](http://godoc.org/github.com/nicksnyder/go-i18n/goi18n)
--------------
The goi18n command provides functionality for managing the translation process.
@@ -66,7 +66,7 @@ Translation files
A translation file stores translated and untranslated strings.
Example:
Here is an example of the default file format that go-i18n supports:
```json
[
@@ -116,6 +116,62 @@ Example:
]
```
To use a different file format, write a parser for the format and add the parsed translations using [AddTranslation](https://godoc.org/github.com/nicksnyder/go-i18n/i18n#AddTranslation).
Note that TOML only supports the flat format, which is described below.
More examples of translation files: [JSON](https://github.com/nicksnyder/go-i18n/tree/master/goi18n/testdata/input), [TOML](https://github.com/nicksnyder/go-i18n/blob/master/goi18n/testdata/input/flat/ar-ar.one.toml), [YAML](https://github.com/nicksnyder/go-i18n/blob/master/goi18n/testdata/input/yaml/en-us.one.yaml).
Flat Format
-------------
You can also write shorter translation files with flat format.
E.g the example above can be written in this way:
```json
{
"d_days": {
"one": "{{.Count}} day.",
"other": "{{.Count}} days."
},
"my_height_in_meters": {
"one": "I am {{.Count}} meter tall.",
"other": "I am {{.Count}} meters tall."
},
"person_greeting": {
"other": "Hello {{.Person}}"
},
"person_unread_email_count": {
"one": "{{.Person}} has {{.Count}} unread email.",
"other": "{{.Person}} has {{.Count}} unread emails."
},
"person_unread_email_count_timeframe": {
"one": "{{.Person}} has {{.Count}} unread email in the past {{.Timeframe}}.",
"other": "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}."
},
"program_greeting": {
"other": "Hello world"
},
"your_unread_email_count": {
"one": "You have {{.Count}} unread email.",
"other": "You have {{.Count}} unread emails."
}
}
```
The logic of flat format is, what it is structure of structures
and name of substructures (ids) should be always a string.
If there is only one key in substructure and it is "other", then it's non-plural
translation, else plural.
More examples of flat format translation files can be found in [goi18n/testdata/input/flat](https://github.com/nicksnyder/go-i18n/tree/master/goi18n/testdata/input/flat).
Contributions
-------------

1
vendor/github.com/nicksnyder/go-i18n/goi18n/constants_command.go сгенерированный поставляемый
Просмотреть файл

@@ -139,7 +139,6 @@ Options:
Default: .
`)
os.Exit(1)
}
// commonInitialisms is a set of common initialisms.

97
vendor/github.com/nicksnyder/go-i18n/goi18n/merge_command.go сгенерированный поставляемый
Просмотреть файл

@@ -5,7 +5,6 @@ import (
"flag"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"sort"
@@ -15,6 +14,7 @@ import (
"github.com/nicksnyder/go-i18n/i18n/bundle"
"github.com/nicksnyder/go-i18n/i18n/language"
"github.com/nicksnyder/go-i18n/i18n/translation"
toml "github.com/pelletier/go-toml"
)
type mergeCommand struct {
@@ -22,6 +22,7 @@ type mergeCommand struct {
sourceLanguage string
outdir string
format string
flat bool
}
func (mc *mergeCommand) execute() error {
@@ -33,15 +34,10 @@ func (mc *mergeCommand) execute() error {
return fmt.Errorf("invalid source locale: %s", mc.sourceLanguage)
}
marshal, err := newMarshalFunc(mc.format)
if err != nil {
return err
}
bundle := bundle.New()
for _, tf := range mc.translationFiles {
if err := bundle.LoadTranslationFile(tf); err != nil {
return fmt.Errorf("failed to load translation file %s because %s\n", tf, err)
return fmt.Errorf("failed to load translation file %s: %s\n", tf, err)
}
}
@@ -64,7 +60,7 @@ func (mc *mergeCommand) execute() error {
all := filter(localeTranslations, func(t translation.Translation) translation.Translation {
return t.Normalize(lang)
})
if err := mc.writeFile("all", all, localeID, marshal); err != nil {
if err := mc.writeFile("all", all, localeID); err != nil {
return err
}
@@ -74,7 +70,7 @@ func (mc *mergeCommand) execute() error {
}
return nil
})
if err := mc.writeFile("untranslated", untranslated, localeID, marshal); err != nil {
if err := mc.writeFile("untranslated", untranslated, localeID); err != nil {
return err
}
}
@@ -88,6 +84,7 @@ func (mc *mergeCommand) parse(arguments []string) {
sourceLanguage := flags.String("sourceLanguage", "en-us", "")
outdir := flags.String("outdir", ".", "")
format := flags.String("format", "json", "")
flat := flags.Bool("flat", true, "")
flags.Parse(arguments)
@@ -95,31 +92,44 @@ func (mc *mergeCommand) parse(arguments []string) {
mc.sourceLanguage = *sourceLanguage
mc.outdir = *outdir
mc.format = *format
if *format == "toml" {
mc.flat = true
} else {
mc.flat = *flat
}
}
func (mc *mergeCommand) SetArgs(args []string) {
mc.translationFiles = args
}
type marshalFunc func(interface{}) ([]byte, error)
func (mc *mergeCommand) writeFile(label string, translations []translation.Translation, localeID string, marshal marshalFunc) error {
func (mc *mergeCommand) writeFile(label string, translations []translation.Translation, localeID string) error {
sort.Sort(translation.SortableByID(translations))
buf, err := marshal(marshalInterface(translations))
if err != nil {
return fmt.Errorf("failed to marshal %s strings to %s because %s", localeID, mc.format, err)
var convert func([]translation.Translation) interface{}
if mc.flat {
convert = marshalFlatInterface
} else {
convert = marshalInterface
}
buf, err := mc.marshal(convert(translations))
if err != nil {
return fmt.Errorf("failed to marshal %s strings to %s: %s", localeID, mc.format, err)
}
filename := filepath.Join(mc.outdir, fmt.Sprintf("%s.%s.%s", localeID, label, mc.format))
if err := ioutil.WriteFile(filename, buf, 0666); err != nil {
return fmt.Errorf("failed to write %s because %s", filename, err)
return fmt.Errorf("failed to write %s: %s", filename, err)
}
return nil
}
func filter(translations map[string]translation.Translation, filter func(translation.Translation) translation.Translation) []translation.Translation {
func filter(translations map[string]translation.Translation, f func(translation.Translation) translation.Translation) []translation.Translation {
filtered := make([]translation.Translation, 0, len(translations))
for _, translation := range translations {
if t := filter(translation); t != nil {
if t := f(translation); t != nil {
filtered = append(filtered, t)
}
}
@@ -127,21 +137,15 @@ func filter(translations map[string]translation.Translation, filter func(transla
}
func newMarshalFunc(format string) (marshalFunc, error) {
switch format {
case "json":
return func(v interface{}) ([]byte, error) {
return json.MarshalIndent(v, "", " ")
}, nil
case "yaml":
return func(v interface{}) ([]byte, error) {
return yaml.Marshal(v)
}, nil
func marshalFlatInterface(translations []translation.Translation) interface{} {
mi := make(map[string]interface{}, len(translations))
for _, translation := range translations {
mi[translation.ID()] = translation.MarshalFlatInterface()
}
return nil, fmt.Errorf("unsupported format: %s\n", format)
return mi
}
func marshalInterface(translations []translation.Translation) []interface{} {
func marshalInterface(translations []translation.Translation) interface{} {
mi := make([]interface{}, len(translations))
for i, translation := range translations {
mi[i] = translation.MarshalInterface()
@@ -149,6 +153,31 @@ func marshalInterface(translations []translation.Translation) []interface{} {
return mi
}
func (mc mergeCommand) marshal(v interface{}) ([]byte, error) {
switch mc.format {
case "json":
return json.MarshalIndent(v, "", " ")
case "toml":
return marshalTOML(v)
case "yaml":
return yaml.Marshal(v)
}
return nil, fmt.Errorf("unsupported format: %s\n", mc.format)
}
func marshalTOML(v interface{}) ([]byte, error) {
m, ok := v.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("invalid format for marshaling to TOML")
}
tree, err := toml.TreeFromMap(m)
if err != nil {
return nil, err
}
s, err := tree.ToTomlString()
return []byte(s), err
}
func usageMerge() {
fmt.Printf(`Merge translation files.
@@ -198,9 +227,13 @@ Options:
-format format
goi18n encodes the output translation files in this format.
Supported formats: json, yaml
Supported formats: json, toml, yaml
Default: json
-flat
goi18n writes the output translation files in flat format.
Usage of '-format toml' automitically sets this flag.
Default: true
`)
os.Exit(1)
}

36
vendor/github.com/nicksnyder/go-i18n/goi18n/merge_command_flat_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,36 @@
package main
import "testing"
func TestMergeExecuteFlat(t *testing.T) {
files := []string{
"testdata/input/flat/en-us.one.yaml",
"testdata/input/flat/en-us.two.json",
"testdata/input/flat/fr-fr.json",
"testdata/input/flat/ar-ar.one.toml",
"testdata/input/flat/ar-ar.two.json",
}
testFlatMergeExecute(t, files)
}
func testFlatMergeExecute(t *testing.T, files []string) {
resetDir(t, "testdata/output/flat")
mc := &mergeCommand{
translationFiles: files,
sourceLanguage: "en-us",
outdir: "testdata/output/flat",
format: "json",
flat: true,
}
if err := mc.execute(); err != nil {
t.Fatal(err)
}
expectEqualFiles(t, "testdata/output/flat/en-us.all.json", "testdata/expected/flat/en-us.all.json")
expectEqualFiles(t, "testdata/output/flat/ar-ar.all.json", "testdata/expected/flat/ar-ar.all.json")
expectEqualFiles(t, "testdata/output/flat/fr-fr.all.json", "testdata/expected/flat/fr-fr.all.json")
expectEqualFiles(t, "testdata/output/flat/en-us.untranslated.json", "testdata/expected/flat/en-us.untranslated.json")
expectEqualFiles(t, "testdata/output/flat/ar-ar.untranslated.json", "testdata/expected/flat/ar-ar.untranslated.json")
expectEqualFiles(t, "testdata/output/flat/fr-fr.untranslated.json", "testdata/expected/flat/fr-fr.untranslated.json")
}

3
vendor/github.com/nicksnyder/go-i18n/goi18n/merge_command_test.go сгенерированный поставляемый
Просмотреть файл

@@ -37,6 +37,7 @@ func testMergeExecute(t *testing.T, files []string) {
sourceLanguage: "en-us",
outdir: "testdata/output",
format: "json",
flat: false,
}
if err := mc.execute(); err != nil {
t.Fatal(err)
@@ -69,6 +70,6 @@ func expectEqualFiles(t *testing.T, expectedName, actualName string) {
t.Fatal(err)
}
if !bytes.Equal(actual, expected) {
t.Fatalf("contents of files did not match: %s, %s", expectedName, actualName)
t.Errorf("contents of files did not match: %s, %s", expectedName, actualName)
}
}

34
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/en-us.flat.json сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,34 @@
{
"program_greeting": {
"other": "Hello world"
},
"person_greeting": {
"other": "Hello {{.Person}}"
},
"my_height_in_meters": {
"one": "I am {{.Count}} meter tall.",
"other": "I am {{.Count}} meters tall."
},
"your_unread_email_count": {
"one": "You have {{.Count}} unread email.",
"other": "You have {{.Count}} unread emails."
},
"person_unread_email_count": {
"one": "{{.Person}} has {{.Count}} unread email.",
"other": "{{.Person}} has {{.Count}} unread emails."
},
"person_unread_email_count_timeframe": {
"one": "{{.Person}} has {{.Count}} unread email in the past {{.Timeframe}}.",
"other": "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}."
},
"d_days": {
"one": "{{.Count}} day.",
"other": "{{.Count}} days."
}
}

25
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/en-us.flat.toml сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,25 @@
[program_greeting]
other = "Hello world"
[person_greeting]
other = "Hello {{.Person}}"
[my_height_in_meters]
one = "I am {{.Count}} meter tall."
other = "I am {{.Count}} meters tall."
[your_unread_email_count]
one = "You have {{.Count}} unread email."
other = "You have {{.Count}} unread emails."
[person_unread_email_count]
one = "{{.Person}} has {{.Count}} unread email."
other = "{{.Person}} has {{.Count}} unread emails."
[person_unread_email_count_timeframe]
one = "{{.Person}} has {{.Count}} unread email in the past {{.Timeframe}}."
other = "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}."
[d_days]
one = "{{.Count}} day"
other = "{{.Count}} days"

25
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/en-us.flat.yaml сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,25 @@
program_greeting:
other: "Hello world"
person_greeting:
other: "Hello {{.Person}}"
my_height_in_meters:
one: "I am {{.Count}} meter tall."
other: "I am {{.Count}} meters tall."
your_unread_email_count:
one: "You have {{.Count}} unread email."
other: "You have {{.Count}} unread emails."
person_unread_email_count:
one: "{{.Person}} has {{.Count}} unread email."
other: "{{.Person}} has {{.Count}} unread emails."
person_unread_email_count_timeframe:
one: "{{.Person}} has {{.Count}} unread email in the past {{.Timeframe}}."
other: "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}."
d_days:
one: "{{.Count}} day"
other: "{{.Count}} days"

43
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/expected/flat/ar-ar.all.json сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,43 @@
{
"d_days": {
"few": "new arabic few translation of d_days",
"many": "arabic many translation of d_days",
"one": "arabic one translation of d_days",
"other": "",
"two": "",
"zero": ""
},
"my_height_in_meters": {
"few": "",
"many": "",
"one": "",
"other": "",
"two": "",
"zero": ""
},
"person_greeting": {
"other": "new arabic translation of person_greeting"
},
"person_unread_email_count": {
"few": "arabic few translation of person_unread_email_count",
"many": "arabic many translation of person_unread_email_count",
"one": "arabic one translation of person_unread_email_count",
"other": "arabic other translation of person_unread_email_count",
"two": "arabic two translation of person_unread_email_count",
"zero": "arabic zero translation of person_unread_email_count"
},
"person_unread_email_count_timeframe": {
"other": ""
},
"program_greeting": {
"other": ""
},
"your_unread_email_count": {
"few": "",
"many": "",
"one": "",
"other": "",
"two": "",
"zero": ""
}
}

32
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/expected/flat/ar-ar.untranslated.json сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,32 @@
{
"d_days": {
"few": "new arabic few translation of d_days",
"many": "arabic many translation of d_days",
"one": "arabic one translation of d_days",
"other": "{{.Count}} days",
"two": "{{.Count}} days",
"zero": "{{.Count}} days"
},
"my_height_in_meters": {
"few": "I am {{.Count}} meters tall.",
"many": "I am {{.Count}} meters tall.",
"one": "I am {{.Count}} meters tall.",
"other": "I am {{.Count}} meters tall.",
"two": "I am {{.Count}} meters tall.",
"zero": "I am {{.Count}} meters tall."
},
"person_unread_email_count_timeframe": {
"other": "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}."
},
"program_greeting": {
"other": "Hello world"
},
"your_unread_email_count": {
"few": "You have {{.Count}} unread emails.",
"many": "You have {{.Count}} unread emails.",
"one": "You have {{.Count}} unread emails.",
"other": "You have {{.Count}} unread emails.",
"two": "You have {{.Count}} unread emails.",
"zero": "You have {{.Count}} unread emails."
}
}

27
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/expected/flat/en-us.all.json сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,27 @@
{
"d_days": {
"one": "{{.Count}} day",
"other": "{{.Count}} days"
},
"my_height_in_meters": {
"one": "I am {{.Count}} meter tall.",
"other": "I am {{.Count}} meters tall."
},
"person_greeting": {
"other": "Hello {{.Person}}"
},
"person_unread_email_count": {
"one": "{{.Person}} has {{.Count}} unread email.",
"other": "{{.Person}} has {{.Count}} unread emails."
},
"person_unread_email_count_timeframe": {
"other": "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}."
},
"program_greeting": {
"other": "Hello world"
},
"your_unread_email_count": {
"one": "You have {{.Count}} unread email.",
"other": "You have {{.Count}} unread emails."
}
}

1
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/expected/flat/en-us.untranslated.json сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1 @@
{}

0
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/expected/flat/en-us.untranslated.json.json сгенерированный поставляемый Обычный файл
Просмотреть файл

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