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

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

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

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

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

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

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

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

@@ -4,6 +4,7 @@ import (
"bufio" "bufio"
"compress/gzip" "compress/gzip"
"fmt" "fmt"
"io"
"net" "net"
"net/http" "net/http"
"strconv" "strconv"
@@ -21,10 +22,16 @@ const (
type codings map[string]float64 type codings map[string]float64
// The default qvalue to assign to an encoding if no explicit qvalue is set. const (
// This is actually kind of ambiguous in RFC 2616, so hopefully it's correct. // DefaultQValue is the default qvalue to assign to an encoding if no explicit qvalue is set.
// The examples seem to indicate that it is. // This is actually kind of ambiguous in RFC 2616, so hopefully it's correct.
const DEFAULT_QVALUE = 1.0 // 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 // 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 // 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 // GzipResponseWriter provides an http.ResponseWriter interface, which gzips
// bytes before writing them to the underlying response. This doesn't close the // bytes before writing them to the underlying response. This doesn't close the
// writers, so don't forget to do that. // writers, so don't forget to do that.
// It can be configured to skip response smaller than minSize.
type GzipResponseWriter struct { type GzipResponseWriter struct {
http.ResponseWriter http.ResponseWriter
index int // Index for gzipWriterPools. index int // Index for gzipWriterPools.
gw *gzip.Writer 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. // Write appends data to the gzip writer.
func (w *GzipResponseWriter) Write(b []byte) (int, error) { func (w *GzipResponseWriter) Write(b []byte) (int, error) {
// Lazily create the gzip.Writer, this allows empty bodies to be actually // If content type is not set.
// empty, for example in the case of status code 204 (no content).
if w.gw == nil {
w.init()
}
if _, ok := w.Header()[contentType]; !ok { 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)) 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 // startGzip initialize any GZIP specific informations.
// then pass the code along to the underlying ResponseWriter. func (w *GzipResponseWriter) startGzip() error {
func (w *GzipResponseWriter) WriteHeader(code int) {
if w.gw == nil && // Set the GZIP header.
code != http.StatusNotModified && code != http.StatusNoContent { w.Header().Set(contentEncoding, "gzip")
w.init()
// 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 // 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 := gzipWriterPools[w.index].Get().(*gzip.Writer)
gzw.Reset(w.ResponseWriter) gzw.Reset(w.ResponseWriter)
w.gw = gzw 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. // Close will close the gzip.Writer and will put it back in the gzipWriterPool.
func (w *GzipResponseWriter) Close() error { 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 { if w.gw == nil {
return 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 // if an invalid gzip compression level is given, so if one can ensure the level
// is valid, the returned error can be safely ignored. // is valid, the returned error can be safely ignored.
func NewGzipLevelHandler(level int) (func(http.Handler) http.Handler, error) { 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) { if level != gzip.DefaultCompression && (level < gzip.BestSpeed || level > gzip.BestCompression) {
return nil, fmt.Errorf("invalid compression level requested: %d", level) 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 { return func(h http.Handler) http.Handler {
index := poolIndex(level) index := poolIndex(level)
@@ -176,6 +252,9 @@ func NewGzipLevelHandler(level int) (func(http.Handler) http.Handler, error) {
gw := &GzipResponseWriter{ gw := &GzipResponseWriter{
ResponseWriter: w, ResponseWriter: w,
index: index, index: index,
minSize: minSize,
buf: []byte{},
} }
defer gw.Close() defer gw.Close()
@@ -238,7 +317,7 @@ func parseEncodings(s string) (codings, error) {
func parseCoding(s string) (coding string, qvalue float64, err error) { func parseCoding(s string) (coding string, qvalue float64, err error) {
for n, part := range strings.Split(s, ";") { for n, part := range strings.Split(s, ";") {
part = strings.TrimSpace(part) part = strings.TrimSpace(part)
qvalue = DEFAULT_QVALUE qvalue = DefaultQValue
if n == 0 { if n == 0 {
coding = strings.ToLower(part) 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" "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 := map[string]codings{
// Examples from RFC 2616 // Examples from RFC 2616
@@ -39,8 +43,6 @@ func TestParseEncodings(t *testing.T) {
} }
func TestGzipHandler(t *testing.T) { func TestGzipHandler(t *testing.T) {
testBody := "aaabbbccc"
// This just exists to provide something for GzipHandler to wrap. // This just exists to provide something for GzipHandler to wrap.
handler := newTestHandler(testBody) handler := newTestHandler(testBody)
@@ -80,7 +82,6 @@ func TestGzipHandler(t *testing.T) {
} }
func TestNewGzipLevelHandler(t *testing.T) { func TestNewGzipLevelHandler(t *testing.T) {
testBody := "aaabbbccc"
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
io.WriteString(w, testBody) 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, "gzip", res.Header.Get("Content-Encoding"))
assert.Equal(t, "Accept-Encoding", res.Header.Get("Vary")) assert.Equal(t, "Accept-Encoding", res.Header.Get("Vary"))
assert.Equal(t, gzipStrLevel(testBody, lvl), resp.Body.Bytes()) assert.Equal(t, gzipStrLevel(testBody, lvl), resp.Body.Bytes())
} }
} }
@@ -135,7 +135,7 @@ func TestGzipHandlerNoBody(t *testing.T) {
{http.StatusNoContent, "", 0}, {http.StatusNoContent, "", 0},
{http.StatusNotModified, "", 0}, {http.StatusNotModified, "", 0},
// Body is going to get gzip'd no matter what. // Body is going to get gzip'd no matter what.
{http.StatusOK, "gzip", 23}, {http.StatusOK, "", 0},
} }
for num, test := range tests { for num, test := range tests {
@@ -170,7 +170,7 @@ func TestGzipHandlerNoBody(t *testing.T) {
} }
func TestGzipHandlerContentLength(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) { handler := GzipHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Length", strconv.Itoa(len(b))) w.Header().Set("Content-Length", strconv.Itoa(len(b)))
w.Write(b) w.Write(b)
@@ -215,6 +215,48 @@ func TestGzipHandlerContentLength(t *testing.T) {
assert.NotEqual(t, b, body) 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) { func TestGzipDoubleClose(t *testing.T) {
// reset the pool for the default compression so we can make sure duplicates // reset the pool for the default compression so we can make sure duplicates
// aren't added back by double close // aren't added back by double close
@@ -240,6 +282,19 @@ func TestGzipDoubleClose(t *testing.T) {
assert.False(t, w1 == w2) 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) } func BenchmarkGzipHandler_S2k(b *testing.B) { benchmark(b, false, 2048) }

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

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

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

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

@@ -1,8 +1,12 @@
# html2text # html2text
[![Documentation](https://godoc.org/github.com/jaytaylor/html2text?status.svg)](https://godoc.org/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/jaytaylor/html2text.svg?branch=master)](https://travis-ci.org/jaytaylor/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/jaytaylor/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 ### Converts HTML into text
@@ -23,7 +27,7 @@ It requires go 1.x or newer ;)
## Download the package ## Download the package
```bash ```bash
go get github.com/jaytaylor/html2text go get github.com/cpanato/html2text
``` ```
## Example usage ## Example usage
@@ -34,7 +38,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/jaytaylor/html2text" "github.com/cpanato/html2text"
) )
func main() { func main() {
@@ -102,15 +106,3 @@ go test
# License # License
Permissive MIT 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 ( import (
"bytes" "bytes"
"io" "io"
"io/ioutil"
"regexp" "regexp"
"strings" "strings"
"unicode" "unicode"
"github.com/ssor/bom" "github.com/dimchansky/utfbom"
"golang.org/x/net/html" "golang.org/x/net/html"
"golang.org/x/net/html/atom" "golang.org/x/net/html/atom"
@@ -291,10 +292,9 @@ func FromHtmlNode(doc *html.Node) (string, error) {
} }
func FromReader(reader io.Reader) (string, error) { func FromReader(reader io.Reader) (string, error) {
newReader, err := bom.NewReaderWithoutBom(reader) bs, err := ioutil.ReadAll(reader)
if err != nil { newReader, _ := utfbom.Skip(bytes.NewReader(bs))
return "", err
}
doc, err := html.Parse(newReader) doc, err := html.Parse(newReader)
if err != nil { if err != nil {
return "", err return "", err
@@ -303,8 +303,8 @@ func FromReader(reader io.Reader) (string, error) {
} }
func FromString(input string) (string, error) { func FromString(input string) (string, error) {
bs := bom.CleanBom([]byte(input)) bs := utfbom.SkipOnly(bytes.NewReader([]byte(input)))
text, err := FromReader(bytes.NewReader(bs)) text, err := FromReader(bs)
if err != nil { if err != nil {
return "", err return "", err
} }

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

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

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

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

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

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

@@ -1,6 +1,6 @@
The MIT License (MIT) 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 Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

179
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. A few usage examples can be found below. See the documentation for the full list of supported functions.
### Image resizing ### Image resizing
```go ```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) 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) 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) 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) 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** **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 The same image resized from 512x512px to 128x128px using different resampling filters.
---|--- From faster (lower quality) to slower (higher quality):
`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)
**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 ### Gaussian Blur
```go ```go
dstImage := imaging.Blur(srcImage, 0.5) dstImage := imaging.Blur(srcImage, 0.5)
``` ```
Sigma parameter allows to control the strength of the blurring effect. Sigma parameter allows to control the strength of the blurring effect.
Original image | Sigma = 0.5 | Sigma = 1.5 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) ![srcImage](testdata/lena_128.png) | ![dstImage](testdata/out_blur_0.5.png) | ![dstImage](testdata/out_blur_1.5.png)
### Sharpening ### Sharpening
```go ```go
dstImage := imaging.Sharpen(srcImage, 0.5) 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 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) ![srcImage](testdata/lena_128.png) | ![dstImage](testdata/out_sharpen_0.5.png) | ![dstImage](testdata/out_sharpen_1.5.png)
### Gamma correction ### Gamma correction
```go ```go
dstImage := imaging.AdjustGamma(srcImage, 0.75) dstImage := imaging.AdjustGamma(srcImage, 0.75)
``` ```
Original image | Gamma = 0.75 | Gamma = 1.25 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) ![srcImage](testdata/lena_128.png) | ![dstImage](testdata/out_gamma_0.75.png) | ![dstImage](testdata/out_gamma_1.25.png)
### Contrast adjustment ### Contrast adjustment
```go ```go
dstImage := imaging.AdjustContrast(srcImage, 20) dstImage := imaging.AdjustContrast(srcImage, 20)
``` ```
Original image | Contrast = 20 | Contrast = -20 Original image | Contrast = 10 | Contrast = -10
---|---|--- -----------------------------------|--------------------------------------------|-------------------------------------------
![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) ![srcImage](testdata/lena_128.png) | ![dstImage](testdata/out_contrast_p10.png) | ![dstImage](testdata/out_contrast_m10.png)
### Brightness adjustment ### Brightness adjustment
```go ```go
dstImage := imaging.AdjustBrightness(srcImage, 20) dstImage := imaging.AdjustBrightness(srcImage, 20)
``` ```
Original image | Brightness = 20 | Brightness = -20 Original image | Brightness = 10 | Brightness = -10
---|---|--- -----------------------------------|----------------------------------------------|---------------------------------------------
![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) ![srcImage](testdata/lena_128.png) | ![dstImage](testdata/out_brightness_p10.png) | ![dstImage](testdata/out_brightness_m10.png)
## Example code
### Complete code example
Here is the code example that loads several images, makes thumbnails of them
and combines them together side-by-side.
```go ```go
package main package main
import ( import (
"image" "image"
"image/color" "image/color"
"log"
"github.com/disintegration/imaging" "github.com/disintegration/imaging"
) )
func main() { 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 // Crop the original image to 350x350px size using the center anchor.
files := []string{"01.jpg", "02.jpg", "03.jpg"} src = imaging.CropAnchor(src, 350, 350, imaging.Center)
// load images and make 100x100 thumbnails of them // Resize the cropped image to width = 256px preserving the aspect ratio.
var thumbnails []image.Image src = imaging.Resize(src, 256, 0, imaging.Lanczos)
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)
}
// create a new blank image // Create a blurred version of the image.
dst := imaging.New(100*len(thumbnails), 100, color.NRGBA{0, 0, 0, 0}) img1 := imaging.Blur(src, 2)
// paste thumbnails into the new image side by side // Create a grayscale version of the image with higher contrast and sharpness.
for i, thumb := range thumbnails { img2 := imaging.Grayscale(src)
dst = imaging.Paste(dst, thumb, image.Pt(i*100, 0)) img2 = imaging.AdjustContrast(img2, 20)
} img2 = imaging.Sharpen(img2, 2)
// save the combined image to file // Create an inverted version of the image.
err := imaging.Save(dst, "dst.jpg") img3 := imaging.Invert(src)
if err != nil {
panic(err) // 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) { func TestAdjustBrightness(t *testing.T) {
td := []struct { td := []struct {
desc string 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) { func TestAdjustGamma(t *testing.T) {
td := []struct { td := []struct {
desc string 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) { func TestAdjustSigmoid(t *testing.T) {
td := []struct { td := []struct {
desc string 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++ { for y := 0; y < height; y++ {
var r, g, b, a float64
r, g, b, a := 0.0, 0.0, 0.0, 0.0
for ix := start; ix <= end; ix++ { for ix := start; ix <= end; ix++ {
weight := kernel[absint(x-ix)] weight := kernel[absint(x-ix)]
i := y*src.Stride + ix*4 i := y*src.Stride + ix*4
@@ -74,17 +73,11 @@ func blurHorizontal(src *image.NRGBA, kernel []float64) *image.NRGBA {
a += wa 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 j := y*dst.Stride + x*4
dst.Pix[j+0] = uint8(r + 0.5) dst.Pix[j+0] = clamp(r / a)
dst.Pix[j+1] = uint8(g + 0.5) dst.Pix[j+1] = clamp(g / a)
dst.Pix[j+2] = uint8(b + 0.5) dst.Pix[j+2] = clamp(b / a)
dst.Pix[j+3] = uint8(a + 0.5) 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++ { for x := 0; x < width; x++ {
var r, g, b, a float64
r, g, b, a := 0.0, 0.0, 0.0, 0.0
for iy := start; iy <= end; iy++ { for iy := start; iy <= end; iy++ {
weight := kernel[absint(y-iy)] weight := kernel[absint(y-iy)]
i := iy*src.Stride + x*4 i := iy*src.Stride + x*4
@@ -129,17 +121,11 @@ func blurVertical(src *image.NRGBA, kernel []float64) *image.NRGBA {
a += wa 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 j := y*dst.Stride + x*4
dst.Pix[j+0] = uint8(r + 0.5) dst.Pix[j+0] = clamp(r / a)
dst.Pix[j+1] = uint8(g + 0.5) dst.Pix[j+1] = clamp(g / a)
dst.Pix[j+2] = uint8(b + 0.5) dst.Pix[j+2] = clamp(b / a)
dst.Pix[j+3] = uint8(a + 0.5) 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 i := y*src.Stride + x*4
for j := 0; j < 4; j++ { for j := 0; j < 4; j++ {
k := i + 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 { if val < 0 {
val = 0 val = 0
} else if val > 255 { } 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) { func TestSharpen(t *testing.T) {
td := []struct { td := []struct {
desc string 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.).
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.
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
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
that implements `image.Image` interface as an input, and return a new image of // `*image.NRGBA` type (32bit RGBA colors, not premultiplied by alpha).
`*image.NRGBA` type (32bit RGBA colors, not premultiplied by alpha).
*/
package imaging package imaging
import ( import (
@@ -24,8 +22,10 @@ import (
"golang.org/x/image/tiff" "golang.org/x/image/tiff"
) )
// Format is an image file format.
type Format int type Format int
// Image file formats.
const ( const (
JPEG Format = iota JPEG Format = iota
PNG PNG
@@ -52,6 +52,7 @@ func (f Format) String() string {
} }
var ( var (
// ErrUnsupportedFormat means the given image format (or file extension) is unsupported.
ErrUnsupportedFormat = errors.New("imaging: unsupported image format") ErrUnsupportedFormat = errors.New("imaging: unsupported image format")
) )
@@ -194,15 +195,12 @@ func Clone(img image.Image) *image.NRGBA {
di := dst.PixOffset(0, dstY) di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY) si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ { for dstX := 0; dstX < dstW; dstX++ {
dst.Pix[di+0] = src.Pix[si+0] dst.Pix[di+0] = src.Pix[si+0]
dst.Pix[di+1] = src.Pix[si+2] dst.Pix[di+1] = src.Pix[si+2]
dst.Pix[di+2] = src.Pix[si+4] dst.Pix[di+2] = src.Pix[si+4]
dst.Pix[di+3] = src.Pix[si+6] dst.Pix[di+3] = src.Pix[si+6]
di += 4 di += 4
si += 8 si += 8
} }
} }
}) })
@@ -213,9 +211,9 @@ func Clone(img image.Image) *image.NRGBA {
di := dst.PixOffset(0, dstY) di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY) si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ { for dstX := 0; dstX < dstW; dstX++ {
a := src.Pix[si+3] a := src.Pix[si+3]
dst.Pix[di+3] = a dst.Pix[di+3] = a
switch a { switch a {
case 0: case 0:
dst.Pix[di+0] = 0 dst.Pix[di+0] = 0
@@ -237,7 +235,6 @@ func Clone(img image.Image) *image.NRGBA {
di += 4 di += 4
si += 4 si += 4
} }
} }
}) })
@@ -248,9 +245,9 @@ func Clone(img image.Image) *image.NRGBA {
di := dst.PixOffset(0, dstY) di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY) si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ { for dstX := 0; dstX < dstW; dstX++ {
a := src.Pix[si+6] a := src.Pix[si+6]
dst.Pix[di+3] = a dst.Pix[di+3] = a
switch a { switch a {
case 0: case 0:
dst.Pix[di+0] = 0 dst.Pix[di+0] = 0
@@ -272,7 +269,6 @@ func Clone(img image.Image) *image.NRGBA {
di += 4 di += 4
si += 8 si += 8
} }
} }
}) })
@@ -283,16 +279,13 @@ func Clone(img image.Image) *image.NRGBA {
di := dst.PixOffset(0, dstY) di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY) si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ { for dstX := 0; dstX < dstW; dstX++ {
c := src.Pix[si] c := src.Pix[si]
dst.Pix[di+0] = c dst.Pix[di+0] = c
dst.Pix[di+1] = c dst.Pix[di+1] = c
dst.Pix[di+2] = c dst.Pix[di+2] = c
dst.Pix[di+3] = 0xff dst.Pix[di+3] = 0xff
di += 4 di += 4
si += 1 si += 1
} }
} }
}) })
@@ -303,16 +296,13 @@ func Clone(img image.Image) *image.NRGBA {
di := dst.PixOffset(0, dstY) di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY) si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ { for dstX := 0; dstX < dstW; dstX++ {
c := src.Pix[si] c := src.Pix[si]
dst.Pix[di+0] = c dst.Pix[di+0] = c
dst.Pix[di+1] = c dst.Pix[di+1] = c
dst.Pix[di+2] = c dst.Pix[di+2] = c
dst.Pix[di+3] = 0xff dst.Pix[di+3] = 0xff
di += 4 di += 4
si += 2 si += 2
} }
} }
}) })
@@ -322,7 +312,6 @@ func Clone(img image.Image) *image.NRGBA {
for dstY := partStart; dstY < partEnd; dstY++ { for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY) di := dst.PixOffset(0, dstY)
for dstX := 0; dstX < dstW; dstX++ { for dstX := 0; dstX < dstW; dstX++ {
srcX := srcMinX + dstX srcX := srcMinX + dstX
srcY := srcMinY + dstY srcY := srcMinY + dstY
siy := src.YOffset(srcX, srcY) siy := src.YOffset(srcX, srcY)
@@ -332,9 +321,7 @@ func Clone(img image.Image) *image.NRGBA {
dst.Pix[di+1] = g dst.Pix[di+1] = g
dst.Pix[di+2] = b dst.Pix[di+2] = b
dst.Pix[di+3] = 0xff dst.Pix[di+3] = 0xff
di += 4 di += 4
} }
} }
}) })
@@ -345,22 +332,18 @@ func Clone(img image.Image) *image.NRGBA {
for i := 0; i < plen; i++ { for i := 0; i < plen; i++ {
pnew[i] = color.NRGBAModel.Convert(src.Palette[i]).(color.NRGBA) pnew[i] = color.NRGBAModel.Convert(src.Palette[i]).(color.NRGBA)
} }
parallel(dstH, func(partStart, partEnd int) { parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ { for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY) di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY) si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ { for dstX := 0; dstX < dstW; dstX++ {
c := pnew[src.Pix[si]] c := pnew[src.Pix[si]]
dst.Pix[di+0] = c.R dst.Pix[di+0] = c.R
dst.Pix[di+1] = c.G dst.Pix[di+1] = c.G
dst.Pix[di+2] = c.B dst.Pix[di+2] = c.B
dst.Pix[di+3] = c.A dst.Pix[di+3] = c.A
di += 4 di += 4
si += 1 si += 1
} }
} }
}) })
@@ -370,15 +353,12 @@ func Clone(img image.Image) *image.NRGBA {
for dstY := partStart; dstY < partEnd; dstY++ { for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY) di := dst.PixOffset(0, dstY)
for dstX := 0; dstX < dstW; dstX++ { for dstX := 0; dstX < dstW; dstX++ {
c := color.NRGBAModel.Convert(img.At(srcMinX+dstX, srcMinY+dstY)).(color.NRGBA) c := color.NRGBAModel.Convert(img.At(srcMinX+dstX, srcMinY+dstY)).(color.NRGBA)
dst.Pix[di+0] = c.R dst.Pix[di+0] = c.R
dst.Pix[di+1] = c.G dst.Pix[di+1] = c.G
dst.Pix[di+2] = c.B dst.Pix[di+2] = c.B
dst.Pix[di+3] = c.A dst.Pix[di+3] = c.A
di += 4 di += 4
} }
} }
}) })
@@ -388,7 +368,7 @@ func Clone(img image.Image) *image.NRGBA {
return dst 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 { func toNRGBA(img image.Image) *image.NRGBA {
srcBounds := img.Bounds() srcBounds := img.Bounds()
if srcBounds.Min.X == 0 && srcBounds.Min.Y == 0 { if srcBounds.Min.X == 0 && srcBounds.Min.Y == 0 {

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

@@ -5,17 +5,12 @@ import (
"math" "math"
) )
type iwpair struct { type indexWeight struct {
i int index int
w int32 weight float64
} }
type pweights struct { func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) [][]indexWeight {
iwpairs []iwpair
wsum int32
}
func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) []pweights {
du := float64(srcSize) / float64(dstSize) du := float64(srcSize) / float64(dstSize)
scale := du scale := du
if scale < 1.0 { if scale < 1.0 {
@@ -23,7 +18,7 @@ func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) []pweights {
} }
ru := math.Ceil(scale * filter.Support) ru := math.Ceil(scale * filter.Support)
out := make([]pweights, dstSize) out := make([][]indexWeight, dstSize)
for v := 0; v < dstSize; v++ { for v := 0; v < dstSize; v++ {
fu := (float64(v)+0.5)*du - 0.5 fu := (float64(v)+0.5)*du - 0.5
@@ -37,15 +32,19 @@ func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) []pweights {
endu = srcSize - 1 endu = srcSize - 1
} }
wsum := int32(0) var sum float64
for u := startu; u <= endu; u++ { 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 { if w != 0 {
wsum += w sum += w
out[v].iwpairs = append(out[v].iwpairs, iwpair{u, 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 return out
@@ -127,22 +126,26 @@ func resizeHorizontal(src *image.NRGBA, width int, filter ResampleFilter) *image
parallel(dstH, func(partStart, partEnd int) { parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ { for dstY := partStart; dstY < partEnd; dstY++ {
i0 := dstY * src.Stride
j0 := dstY * dst.Stride
for dstX := 0; dstX < dstW; dstX++ { for dstX := 0; dstX < dstW; dstX++ {
var c [4]int64 var r, g, b, a float64
for _, iw := range weights[dstX].iwpairs { for _, w := range weights[dstX] {
i := dstY*src.Stride + iw.i*4 i := i0 + w.index*4
a := int64(src.Pix[i+3]) * int64(iw.w) aw := float64(src.Pix[i+3]) * w.weight
c[0] += int64(src.Pix[i+0]) * a r += float64(src.Pix[i+0]) * aw
c[1] += int64(src.Pix[i+1]) * a g += float64(src.Pix[i+1]) * aw
c[2] += int64(src.Pix[i+2]) * a b += float64(src.Pix[i+2]) * aw
c[3] += a 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) weights := precomputeWeights(dstH, srcH, filter)
parallel(dstW, func(partStart, partEnd int) { parallel(dstW, func(partStart, partEnd int) {
for dstX := partStart; dstX < partEnd; dstX++ { for dstX := partStart; dstX < partEnd; dstX++ {
for dstY := 0; dstY < dstH; dstY++ { for dstY := 0; dstY < dstH; dstY++ {
var c [4]int64 var r, g, b, a float64
for _, iw := range weights[dstY].iwpairs { for _, w := range weights[dstY] {
i := iw.i*src.Stride + dstX*4 i := w.index*src.Stride + dstX*4
a := int64(src.Pix[i+3]) * int64(iw.w) aw := float64(src.Pix[i+3]) * w.weight
c[0] += int64(src.Pix[i+0]) * a r += float64(src.Pix[i+0]) * aw
c[1] += int64(src.Pix[i+1]) * a g += float64(src.Pix[i+1]) * aw
c[2] += int64(src.Pix[i+2]) * a b += float64(src.Pix[i+2]) * aw
c[3] += a 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 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 { func resizeNearest(src *image.NRGBA, width, height int) *image.NRGBA {
dstW, dstH := width, height dstW, dstH := width, height
@@ -205,13 +208,16 @@ func resizeNearest(src *image.NRGBA, width, height int) *image.NRGBA {
parallel(dstH, func(partStart, partEnd int) { parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ { 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++ { for dstX := 0; dstX < dstW; dstX++ {
fx := (float64(dstX)+0.5)*dx - 0.5 srcX := int((float64(dstX) + 0.5) * dx)
if srcX > srcW-1 {
srcX := int(math.Min(math.Max(math.Floor(fx+0.5), 0.0), float64(srcW))) srcX = srcW - 1
srcY := int(math.Min(math.Max(math.Floor(fy+0.5), 0.0), float64(srcH))) }
srcOff := srcY*src.Stride + srcX*4 srcOff := srcY*src.Stride + srcX*4
dstOff := dstY*dst.Stride + dstX*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) 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, // Supported resample filters: NearestNeighbor, Box, Linear, Hermite, MitchellNetravali,
// CatmullRom, BSpline, Gaussian, Lanczos, Hann, Hamming, Blackman, Bartlett, Welch, Cosine. // CatmullRom, BSpline, Gaussian, Lanczos, Hann, Hamming, Blackman, Bartlett, Welch, Cosine.
@@ -361,7 +367,7 @@ type ResampleFilter struct {
Kernel func(float64) float64 Kernel func(float64) float64
} }
// Nearest-neighbor filter, no anti-aliasing. // NearestNeighbor is a nearest-neighbor filter (no anti-aliasing).
var NearestNeighbor ResampleFilter var NearestNeighbor ResampleFilter
// Box filter (averaging pixels). // Box filter (averaging pixels).
@@ -373,37 +379,37 @@ var Linear ResampleFilter
// Hermite cubic spline filter (BC-spline; B=0; C=0). // Hermite cubic spline filter (BC-spline; B=0; C=0).
var Hermite ResampleFilter 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 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 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 var BSpline ResampleFilter
// Gaussian Blurring Filter. // Gaussian is a Gaussian blurring Filter.
var Gaussian ResampleFilter var Gaussian ResampleFilter
// Bartlett-windowed sinc filter (3 lobes). // Bartlett is a Bartlett-windowed sinc filter (3 lobes).
var Bartlett ResampleFilter var Bartlett ResampleFilter
// Lanczos filter (3 lobes). // Lanczos filter (3 lobes).
var Lanczos ResampleFilter var Lanczos ResampleFilter
// Hann-windowed sinc filter (3 lobes). // Hann is a Hann-windowed sinc filter (3 lobes).
var Hann ResampleFilter var Hann ResampleFilter
// Hamming-windowed sinc filter (3 lobes). // Hamming is a Hamming-windowed sinc filter (3 lobes).
var Hamming ResampleFilter var Hamming ResampleFilter
// Blackman-windowed sinc filter (3 lobes). // Blackman is a Blackman-windowed sinc filter (3 lobes).
var Blackman ResampleFilter 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 var Welch ResampleFilter
// Cosine-windowed sinc filter (3 lobes). // Cosine is a Cosine-windowed sinc filter (3 lobes).
var Cosine ResampleFilter var Cosine ResampleFilter
func bcspline(x, b, c float64) float64 { 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), Rect: image.Rect(0, 0, 4, 4),
Stride: 4 * 4, Stride: 4 * 4,
Pix: []uint8{ Pix: []uint8{
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x3f, 0xff, 0x00, 0x00, 0xc0, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x40, 0xff, 0x00, 0x00, 0xbf, 0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0x3f, 0x6d, 0x6e, 0x24, 0x6f, 0xb1, 0x13, 0x3a, 0xd0, 0xc0, 0x00, 0x3f, 0xff, 0x00, 0xff, 0x00, 0x40, 0x6e, 0x6d, 0x25, 0x70, 0xb0, 0x14, 0x3b, 0xcf, 0xbf, 0x00, 0x40, 0xff,
0x00, 0xff, 0x00, 0xc0, 0x13, 0xb2, 0x3a, 0xcf, 0x33, 0x32, 0x9a, 0xef, 0x3f, 0x00, 0xc0, 0xff, 0x00, 0xff, 0x00, 0xbf, 0x14, 0xb0, 0x3b, 0xcf, 0x33, 0x33, 0x99, 0xef, 0x40, 0x00, 0xbf, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0xc0, 0x3f, 0xff, 0x00, 0x3f, 0xc0, 0xff, 0x00, 0x00, 0xff, 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 { for _, d := range td {
got := Resize(d.src, d.w, d.h, d.f) got := Resize(d.src, d.w, d.h, d.f)
want := d.want want := d.want
if !compareNRGBA(got, want, 1) { if !compareNRGBA(got, want, 0) {
t.Errorf("test [%s] failed: %#v", d.desc, got) 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) { func TestFit(t *testing.T) {
td := []struct { td := []struct {
desc string 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. // Anchor is the anchor point for image alignment.
type Anchor int type Anchor int
// Anchor point positions.
const ( const (
Center Anchor = iota Center Anchor = iota
TopLeft TopLeft

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

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

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

@@ -1,28 +1,24 @@
package imaging package imaging
import ( import (
"math"
"runtime" "runtime"
"sync" "sync"
"sync/atomic" "sync/atomic"
) )
var parallelizationEnabled = true // parallel starts parallel image processing based on the current GOMAXPROCS value.
// If GOMAXPROCS = 1 it uses no parallelization.
// if GOMAXPROCS = 1: no goroutines used // If GOMAXPROCS > 1 it spawns N=GOMAXPROCS workers in separate goroutines.
// if GOMAXPROCS > 1: spawn N=GOMAXPROCS workers in separate goroutines
func parallel(dataSize int, fn func(partStart, partEnd int)) { func parallel(dataSize int, fn func(partStart, partEnd int)) {
numGoroutines := 1 numGoroutines := 1
partSize := dataSize partSize := dataSize
if parallelizationEnabled { numProcs := runtime.GOMAXPROCS(0)
numProcs := runtime.GOMAXPROCS(0) if numProcs > 1 {
if numProcs > 1 { numGoroutines = numProcs
numGoroutines = numProcs partSize = dataSize / (numGoroutines * 10)
partSize = dataSize / (numGoroutines * 10) if partSize < 1 {
if partSize < 1 { 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 { func absint(i int) int {
if i < 0 { if i < 0 {
return -i return -i
@@ -61,17 +58,14 @@ func absint(i int) int {
return i return i
} }
// clamp & round float64 to uint8 (0..255) // clamp rounds and clamps float64 value to fit into uint8.
func clamp(v float64) uint8 { func clamp(x float64) uint8 {
return uint8(math.Min(math.Max(v, 0.0), 255.0) + 0.5) v := int64(x + 0.5)
} if v > 255 {
// clamp int32 to uint8 (0..255)
func clampint32(v int32) uint8 {
if v < 0 {
return 0
} else if v > 255 {
return 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++ { for i := 0; i < n; i++ {
if data[i] != true { if !data[i] {
return false return false
} }
} }
@@ -27,7 +27,7 @@ func TestParallel(t *testing.T) {
for _, e := range []bool{true, false} { for _, e := range []bool{true, false} {
for _, n := range []int{1, 10, 100, 1000} { for _, n := range []int{1, 10, 100, 1000} {
for _, p := range []int{1, 2, 4, 8, 16, 100} { 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) 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 // 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 // least-significant 16-bit Platform Specific ID. The magic numbers are
// specified at https://www.microsoft.com/typography/otspec/name.htm // 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) microsoftSymbolEncoding = 0x00030000 // PID = 3 (Microsoft), PSID = 0 (Symbol)
microsoftUCS2Encoding = 0x00030001 // PID = 3 (Microsoft), PSID = 1 (UCS-2) microsoftUCS2Encoding = 0x00030001 // PID = 3 (Microsoft), PSID = 1 (UCS-2)
microsoftUCS4Encoding = 0x0003000a // PID = 3 (Microsoft), PSID = 10 (UCS-4) 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) pidPsid := u32(table, offset)
// We prefer the Unicode cmap encoding. Failing to find that, we fall // We prefer the Unicode cmap encoding. Failing to find that, we fall
// back onto the Microsoft cmap encoding. // back onto the Microsoft cmap encoding.
if pidPsid == unicodeEncoding { if pidPsid == unicodeEncodingBMPOnly || pidPsid == unicodeEncodingFull {
bestOffset, bestPID, ok = offset, pidPsid>>16, true bestOffset, bestPID, ok = offset, pidPsid>>16, true
break break
@@ -550,8 +551,7 @@ func parse(ttf []byte, offset int) (font *Font, err error) {
return return
} }
ttcVersion, offset := u32(ttf, offset), offset+4 ttcVersion, offset := u32(ttf, offset), offset+4
if ttcVersion != 0x00010000 { if ttcVersion != 0x00010000 && ttcVersion != 0x00020000 {
// TODO: support TTC version 2.0, once I have such a .ttc file to test with.
err = FormatError("bad TTC version") err = FormatError("bad TTC version")
return return
} }
@@ -578,14 +578,15 @@ func parse(ttf []byte, offset int) (font *Font, err error) {
return return
} }
n, offset := int(u16(ttf, offset)), offset+2 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") err = FormatError("TTF data is too short")
return return
} }
f := new(Font) f := new(Font)
// Assign the table slices. // Assign the table slices.
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
x := 16*i + 12 x := 16*i + offset
switch string(ttf[x : x+4]) { switch string(ttf[x : x+4]) {
case "cmap": case "cmap":
f.cmap, err = readTable(ttf, ttf[x+8:x+16]) 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 // Done
return keys, nil return keys, nil
case token.ILLEGAL: case token.ILLEGAL:
fmt.Println("illegal") return nil, errors.New("illegal")
default: default:
return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type) 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") 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) return Open(name)
} }
func init() { func init() {
sql.Register("postgres", &drv{}) sql.Register("postgres", &Driver{})
} }
type parameterStatus struct { 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; * KISS;
* Fast; * 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 # Users

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

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

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

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

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

@@ -33,6 +33,9 @@ func TestCompareDomainName(t *testing.T) {
if CompareDomainName(".", ".") != 0 { if CompareDomainName(".", ".") != 0 {
t.Errorf("%s with %s should be %d", ".", ".", 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) { func TestSplit(t *testing.T) {

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

@@ -14,13 +14,17 @@ package dns
import ( import (
crand "crypto/rand" crand "crypto/rand"
"encoding/binary" "encoding/binary"
"fmt"
"math/big" "math/big"
"math/rand" "math/rand"
"strconv" "strconv"
"sync" "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 ( var (
ErrAlg error = &Error{err: "bad algorithm"} // ErrAlg indicates an error with the (DNSSEC) algorithm. 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. ErrKeyAlg error = &Error{err: "bad key algorithm"} // ErrKeyAlg indicates that the algorithm in the key is not valid.
ErrKey error = &Error{err: "bad key"} ErrKey error = &Error{err: "bad key"}
ErrKeySize error = &Error{err: "bad key size"} 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"} ErrNoSig error = &Error{err: "no signature found"}
ErrPrivKey error = &Error{err: "bad private key"} ErrPrivKey error = &Error{err: "bad private key"}
ErrRcode error = &Error{err: "bad rcode"} ErrRcode error = &Error{err: "bad rcode"}
@@ -329,6 +334,7 @@ func UnpackDomainName(msg []byte, off int) (string, int, error) {
s := make([]byte, 0, 64) s := make([]byte, 0, 64)
off1 := 0 off1 := 0
lenmsg := len(msg) lenmsg := len(msg)
maxLen := maxDomainNameWireOctets
ptr := 0 // number of pointers followed ptr := 0 // number of pointers followed
Loop: Loop:
for { for {
@@ -353,8 +359,10 @@ Loop:
fallthrough fallthrough
case '"', '\\': case '"', '\\':
s = append(s, '\\', b) s = append(s, '\\', b)
// presentation-format \X escapes add an extra byte
maxLen += 1
default: default:
if b < 32 || b >= 127 { // unprintable use \DDD if b < 32 || b >= 127 { // unprintable, use \DDD
var buf [3]byte var buf [3]byte
bufs := strconv.AppendInt(buf[:0], int64(b), 10) bufs := strconv.AppendInt(buf[:0], int64(b), 10)
s = append(s, '\\') s = append(s, '\\')
@@ -364,6 +372,8 @@ Loop:
for _, r := range bufs { for _, r := range bufs {
s = append(s, r) s = append(s, r)
} }
// presentation-format \DDD escapes add 3 extra bytes
maxLen += 3
} else { } else {
s = append(s, b) s = append(s, b)
} }
@@ -388,6 +398,9 @@ Loop:
if ptr++; ptr > 10 { if ptr++; ptr > 10 {
return "", lenmsg, &Error{err: "too many compression pointers"} 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) off = (c^0xC0)<<8 | int(c1)
default: default:
// 0x80 and 0x40 are reserved // 0x80 and 0x40 are reserved
@@ -399,6 +412,9 @@ Loop:
} }
if len(s) == 0 { if len(s) == 0 {
s = []byte(".") 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 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) return toBase32(nsec3)
} }
// Denialer is an interface that should be implemented by types that are used to denial // Cover returns true if a name is covered by the NSEC3 record
// 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.
func (rr *NSEC3) Cover(name string) bool { func (rr *NSEC3) Cover(name string) bool {
// FIXME(miek): check if the zones match nameHash := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
// FIXME(miek): check if we're not dealing with parent nsec3 owner := strings.ToUpper(rr.Hdr.Name)
hname := HashName(name, rr.Hash, rr.Iterations, rr.Salt) labelIndices := Split(owner)
labels := Split(rr.Hdr.Name) if len(labelIndices) < 2 {
if len(labels) < 2 {
return false return false
} }
hash := strings.ToUpper(rr.Hdr.Name[labels[0] : labels[1]-1]) // -1 to remove the dot ownerHash := owner[:labelIndices[1]-1]
if hash == rr.NextDomain { ownerZone := owner[labelIndices[1]:]
return false // empty interval if !IsSubDomain(ownerZone, strings.ToUpper(name)) { // name is outside owner zone
}
if hash > rr.NextDomain { // last name, points to apex
// hname > hash
// hname > rr.NextDomain
// TODO(miek)
}
if hname <= hash {
return false return false
} }
if hname >= rr.NextDomain {
nextHash := rr.NextDomain
if ownerHash == nextHash { // empty interval
return false 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 { func (rr *NSEC3) Match(name string) bool {
// FIXME(miek): Check if we are in the same zone nameHash := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
hname := HashName(name, rr.Hash, rr.Iterations, rr.Salt) owner := strings.ToUpper(rr.Hdr.Name)
labels := Split(rr.Hdr.Name) labelIndices := Split(owner)
if len(labels) < 2 { if len(labelIndices) < 2 {
return false return false
} }
hash := strings.ToUpper(rr.Hdr.Name[labels[0] : labels[1]-1]) // -1 to remove the . ownerHash := owner[:labelIndices[1]-1]
if hash == hname { ownerZone := owner[labelIndices[1]:]
if !IsSubDomain(ownerZone, strings.ToUpper(name)) { // name is outside owner zone
return false
}
if ownerHash == nameHash {
return true return true
} }
return false return false

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

@@ -1,8 +1,6 @@
package dns package dns
import ( import "testing"
"testing"
)
func TestPackNsec3(t *testing.T) { func TestPackNsec3(t *testing.T) {
nsec3 := HashName("dnsex.nl.", SHA1, 0, "DEAD") nsec3 := HashName("dnsex.nl.", SHA1, 0, "DEAD")
@@ -17,13 +15,119 @@ func TestPackNsec3(t *testing.T) {
} }
func TestNsec3(t *testing.T) { func TestNsec3(t *testing.T) {
// examples taken from .nl nsec3, _ := NewRR("sk4e8fj94u78smusb40o1n0oltbblu2r.nl. IN NSEC3 1 1 5 F10E9F7EA83FC8F3 SK4F38CQ0ATIEI8MH3RGD0P5I4II6QAN NS SOA TXT RRSIG DNSKEY NSEC3PARAM")
nsec3, _ := NewRR("39p91242oslggest5e6a7cci4iaeqvnk.nl. IN NSEC3 1 1 5 F10E9F7EA83FC8F3 39P99DCGG0MDLARTCRMCF6OFLLUL7PR6 NS DS RRSIG") if !nsec3.(*NSEC3).Match("nl.") { // name hash = sk4e8fj94u78smusb40o1n0oltbblu2r
if !nsec3.(*NSEC3).Cover("snasajsksasasa.nl.") { // 39p94jrinub66hnpem8qdpstrec86pg3 t.Fatal("sk4e8fj94u78smusb40o1n0oltbblu2r.nl. should match sk4e8fj94u78smusb40o1n0oltbblu2r.nl.")
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
if !nsec3.(*NSEC3).Match("nl.") { // sk4e8fj94u78smusb40o1n0oltbblu2r.nl. t.Fatal("sk4e8fj94u78smusb40o1n0oltbblu2r.NL. should match sk4e8fj94u78smusb40o1n0oltbblu2r.nl.")
t.Error("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 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) { func setTXT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(TXT) rr := new(TXT)
rr.Hdr = h rr.Hdr = h
@@ -2158,6 +2170,7 @@ var typeToparserFunc = map[uint16]parserFunc{
TypeSMIMEA: {setSMIMEA, true}, TypeSMIMEA: {setSMIMEA, true},
TypeSOA: {setSOA, false}, TypeSOA: {setSOA, false},
TypeSPF: {setSPF, true}, TypeSPF: {setSPF, true},
TypeAVC: {setAVC, true},
TypeSRV: {setSRV, false}, TypeSRV: {setSRV, false},
TypeSSHFP: {setSSHFP, true}, TypeSSHFP: {setSSHFP, true},
TypeTALINK: {setTALINK, false}, TypeTALINK: {setTALINK, false},

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

@@ -91,6 +91,7 @@ const (
TypeEUI64 uint16 = 109 TypeEUI64 uint16 = 109
TypeURI uint16 = 256 TypeURI uint16 = 256
TypeCAA uint16 = 257 TypeCAA uint16 = 257
TypeAVC uint16 = 258
TypeTKEY uint16 = 249 TypeTKEY uint16 = 249
TypeTSIG uint16 = 250 TypeTSIG uint16 = 250
@@ -530,6 +531,13 @@ type SPF struct {
func (rr *SPF) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) } 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 { type SRV struct {
Hdr RR_Header Hdr RR_Header
Priority uint16 Priority uint16

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

@@ -5,99 +5,95 @@ package dns
func compressionLenHelperType(c map[string]int, r RR) { func compressionLenHelperType(c map[string]int, r RR) {
switch x := r.(type) { 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: case *PTR:
compressionLenHelper(c, x.Ptr) compressionLenHelper(c, x.Ptr)
case *SOA: case *SOA:
compressionLenHelper(c, x.Ns) compressionLenHelper(c, x.Ns)
compressionLenHelper(c, x.Mbox) compressionLenHelper(c, x.Mbox)
case *MD: case *AFSDB:
compressionLenHelper(c, x.Md) compressionLenHelper(c, x.Hostname)
case *NSAPPTR: case *HIP:
compressionLenHelper(c, x.Ptr) for i := range x.RendezvousServers {
case *MG: compressionLenHelper(c, x.RendezvousServers[i])
compressionLenHelper(c, x.Mg) }
case *LP:
compressionLenHelper(c, x.Fqdn)
case *CNAME:
compressionLenHelper(c, x.Target)
case *MB: case *MB:
compressionLenHelper(c, x.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) { func compressionLenSearchType(c map[string]int, r RR) (int, bool) {
switch x := r.(type) { switch x := r.(type) {
case *MF:
k1, ok1 := compressionLenSearch(c, x.Mf)
return k1, ok1
case *MG: case *MG:
k1, ok1 := compressionLenSearch(c, x.Mg) k1, ok1 := compressionLenSearch(c, x.Mg)
return k1, ok1 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: case *PTR:
k1, ok1 := compressionLenSearch(c, x.Ptr) k1, ok1 := compressionLenSearch(c, x.Ptr)
return k1, ok1 return k1, ok1
case *AFSDB: case *AFSDB:
k1, ok1 := compressionLenSearch(c, x.Hostname) k1, ok1 := compressionLenSearch(c, x.Hostname)
return k1, ok1 return k1, ok1
case *CNAME: case *MB:
k1, ok1 := compressionLenSearch(c, x.Target) k1, ok1 := compressionLenSearch(c, x.Mb)
return k1, ok1 return k1, ok1
case *MD: case *MD:
k1, ok1 := compressionLenSearch(c, x.Md) k1, ok1 := compressionLenSearch(c, x.Md)
return k1, ok1 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: case *RT:
k1, ok1 := compressionLenSearch(c, x.Host) k1, ok1 := compressionLenSearch(c, x.Host)
return k1, ok1 return k1, ok1
@@ -105,15 +101,19 @@ func compressionLenSearchType(c map[string]int, r RR) (int, bool) {
k1, ok1 := compressionLenSearch(c, x.Ns) k1, ok1 := compressionLenSearch(c, x.Ns)
k2, ok2 := compressionLenSearch(c, x.Mbox) k2, ok2 := compressionLenSearch(c, x.Mbox)
return k1 + k2, ok1 && ok2 return k1 + k2, ok1 && ok2
case *MB: case *CNAME:
k1, ok1 := compressionLenSearch(c, x.Mb) 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 return k1, ok1
case *MX: case *MX:
k1, ok1 := compressionLenSearch(c, x.Mx) k1, ok1 := compressionLenSearch(c, x.Mx)
return k1, ok1 return k1, ok1
case *NS:
k1, ok1 := compressionLenSearch(c, x.Ns)
return k1, ok1
} }
return 0, false 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 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) { 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) off, err := rr.Hdr.pack(msg, off, compression, compress)
if err != nil { if err != nil {
@@ -1528,6 +1542,23 @@ func unpackANY(h RR_Header, msg []byte, off int) (RR, int, error) {
return rr, off, err 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) { func unpackCAA(h RR_Header, msg []byte, off int) (RR, int, error) {
rr := new(CAA) rr := new(CAA)
rr.Hdr = h rr.Hdr = h
@@ -3467,6 +3498,7 @@ var typeToUnpack = map[uint16]func(RR_Header, []byte, int) (RR, int, error){
TypeAAAA: unpackAAAA, TypeAAAA: unpackAAAA,
TypeAFSDB: unpackAFSDB, TypeAFSDB: unpackAFSDB,
TypeANY: unpackANY, TypeANY: unpackANY,
TypeAVC: unpackAVC,
TypeCAA: unpackCAA, TypeCAA: unpackCAA,
TypeCDNSKEY: unpackCDNSKEY, TypeCDNSKEY: unpackCDNSKEY,
TypeCDS: unpackCDS, 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) }, TypeAAAA: func() RR { return new(AAAA) },
TypeAFSDB: func() RR { return new(AFSDB) }, TypeAFSDB: func() RR { return new(AFSDB) },
TypeANY: func() RR { return new(ANY) }, TypeANY: func() RR { return new(ANY) },
TypeAVC: func() RR { return new(AVC) },
TypeCAA: func() RR { return new(CAA) }, TypeCAA: func() RR { return new(CAA) },
TypeCDNSKEY: func() RR { return new(CDNSKEY) }, TypeCDNSKEY: func() RR { return new(CDNSKEY) },
TypeCDS: func() RR { return new(CDS) }, TypeCDS: func() RR { return new(CDS) },
@@ -86,6 +87,7 @@ var TypeToString = map[uint16]string{
TypeAFSDB: "AFSDB", TypeAFSDB: "AFSDB",
TypeANY: "ANY", TypeANY: "ANY",
TypeATMA: "ATMA", TypeATMA: "ATMA",
TypeAVC: "AVC",
TypeAXFR: "AXFR", TypeAXFR: "AXFR",
TypeCAA: "CAA", TypeCAA: "CAA",
TypeCDNSKEY: "CDNSKEY", 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 *AAAA) Header() *RR_Header { return &rr.Hdr }
func (rr *AFSDB) 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 *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 *CAA) Header() *RR_Header { return &rr.Hdr }
func (rr *CDNSKEY) Header() *RR_Header { return &rr.Hdr } func (rr *CDNSKEY) Header() *RR_Header { return &rr.Hdr }
func (rr *CDS) 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() l := rr.Hdr.len()
return l 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 { func (rr *CAA) len() int {
l := rr.Hdr.len() l := rr.Hdr.len()
l++ // Flag l++ // Flag
@@ -649,6 +659,11 @@ func (rr *AFSDB) copy() RR {
func (rr *ANY) copy() RR { func (rr *ANY) copy() RR {
return &ANY{*rr.Hdr.copyHeader()} 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 { func (rr *CAA) copy() RR {
return &CAA{*rr.Hdr.copyHeader(), rr.Flag, rr.Tag, rr.Value} 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. The Minio Go Client SDK provides simple APIs to access any Amazon S3 compatible object storage.
**Supported cloud storage providers:** **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 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. // ErrEntityTooLarge - Input size is larger than supported maximum.
func ErrEntityTooLarge(totalSize, maxObjectSize int64, bucketName, objectName string) error { 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) 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 reqCh chan<- getRequest
resCh <-chan getResponse resCh <-chan getResponse
doneCh chan<- struct{} doneCh chan<- struct{}
prevOffset int64
currOffset int64 currOffset int64
objectInfo ObjectInfo objectInfo ObjectInfo
// Ask lower level to initiate data fetching based on currOffset
seekData bool
// Keeps track of closed call. // Keeps track of closed call.
isClosed bool isClosed bool
@@ -258,6 +260,10 @@ func (o *Object) doGetRequest(request getRequest) (getResponse, error) {
if response.Error != nil { if response.Error != nil {
return response, response.Error return response, response.Error
} }
// Data are ready on the wire, no need to reinitiate connection in lower level
o.seekData = false
return response, nil return response, nil
} }
@@ -266,8 +272,6 @@ func (o *Object) doGetRequest(request getRequest) (getResponse, error) {
func (o *Object) setOffset(bytesRead int64) error { func (o *Object) setOffset(bytesRead int64) error {
// Update the currentOffset. // Update the currentOffset.
o.currOffset += bytesRead o.currOffset += bytesRead
// Save the current offset as previous offset.
o.prevOffset = o.currOffset
if o.currOffset >= o.objectInfo.Size { if o.currOffset >= o.objectInfo.Size {
return io.EOF return io.EOF
@@ -303,22 +307,9 @@ func (o *Object) Read(b []byte) (n int, err error) {
readReq.isFirstReq = true readReq.isFirstReq = true
} }
// Verify if offset has changed and currOffset is greater than // Ask to establish a new data fetch routine based on seekData flag
// previous offset. Perhaps due to Seek(). readReq.DidOffsetChange = o.seekData
offsetChange := o.prevOffset - o.currOffset readReq.Offset = 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
}
// Send and receive from the first request. // Send and receive from the first request.
response, err := o.doGetRequest(readReq) response, err := o.doGetRequest(readReq)
@@ -430,8 +421,6 @@ func (o *Object) ReadAt(b []byte, offset int64) (n int, err error) {
if !o.objectInfoSet { if !o.objectInfoSet {
// Update the currentOffset. // Update the currentOffset.
o.currOffset += bytesRead o.currOffset += bytesRead
// Save the current offset as previous offset.
o.prevOffset = o.currOffset
} else { } else {
// If this was not the first request update // If this was not the first request update
// the offsets and compare against objectInfo // 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 return 0, err
} }
} }
// Save current offset as previous offset.
o.prevOffset = o.currOffset
// Switch through whence. // Switch through whence.
switch whence { switch whence {
@@ -527,6 +514,10 @@ func (o *Object) Seek(offset int64, whence int) (n int64, err error) {
if o.prevErr == io.EOF { if o.prevErr == io.EOF {
o.prevErr = nil o.prevErr = nil
} }
// Ask lower level to fetch again from source
o.seekData = true
// Return the effective offset. // Return the effective offset.
return o.currOffset, nil return o.currOffset, nil
} }

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

@@ -71,6 +71,9 @@ type Client struct {
isTraceEnabled bool isTraceEnabled bool
traceOutput io.Writer traceOutput io.Writer
// S3 specific accelerated endpoint.
s3AccelerateEndpoint string
// Random seed. // Random seed.
random *rand.Rand random *rand.Rand
} }
@@ -78,7 +81,7 @@ type Client struct {
// Global constants. // Global constants.
const ( const (
libraryName = "minio-go" libraryName = "minio-go"
libraryVersion = "2.0.3" libraryVersion = "2.0.4"
) )
// User Agent should always following the below style. // 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. // SetAppInfo - add application details to user agent.
func (c *Client) SetAppInfo(appName string, appVersion string) { func (c *Client) SetAppInfo(appName string, appVersion string) {
// if app name and version is not set, we do not a new user // if app name and version not set, we do not set a new user agent.
// agent.
if appName != "" && appVersion != "" { if appName != "" && appVersion != "" {
c.appInfo = struct { c.appInfo = struct {
appName string appName string
@@ -258,8 +260,18 @@ func (c *Client) TraceOff() {
c.isTraceEnabled = false c.isTraceEnabled = false
} }
// requestMetadata - is container for all the values to make a // SetS3TransferAccelerate - turns s3 accelerated endpoint on or off for all your
// request. // 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 { type requestMetadata struct {
// If set newRequest presigns the URL. // If set newRequest presigns the URL.
presignURL bool presignURL bool
@@ -601,10 +613,10 @@ func (c Client) newRequest(method string, metadata requestMetadata) (req *http.R
req.Body = ioutil.NopCloser(metadata.contentBody) 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 // Skip setting 'expect' header for Google Cloud Storage, there
// are some known issues - https://github.com/restic/restic/issues/520 // 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. // Set 'Expect' header for the request.
req.Header.Set("Expect", "100-continue") req.Header.Set("Expect", "100-continue")
} }
@@ -672,9 +684,22 @@ func (c Client) makeTargetURL(bucketName, objectName, bucketLocation string, que
host := c.endpointURL.Host host := c.endpointURL.Host
// For Amazon S3 endpoint, try to fetch location based endpoint. // For Amazon S3 endpoint, try to fetch location based endpoint.
if s3utils.IsAmazonEndpoint(c.endpointURL) { if s3utils.IsAmazonEndpoint(c.endpointURL) {
// Fetch new host based on the bucket location. if c.s3AccelerateEndpoint != "" && bucketName != "" {
host = getS3Endpoint(bucketLocation) // 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. // Save scheme.
scheme := c.endpointURL.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. // Set copy conditions.
copyConds := NewCopyConditions() copyConds := CopyConditions{}
err = copyConds.SetModified(time.Date(2014, time.April, 0, 0, 0, 0, 0, time.UTC)) err = copyConds.SetModified(time.Date(2014, time.April, 0, 0, 0, 0, 0, time.UTC))
if err != nil { if err != nil {
t.Fatal("Error:", err) 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 // Generate data more than 32K
buf := bytes.Repeat([]byte("2"), rand.Intn(1<<20)+32*1024) buf := bytes.Repeat([]byte("2"), rand.Intn(1<<20)+32*1024)
bufSize := len(buf)
// Save the data // Save the data
objectName := randString(60, rand.NewSource(time.Now().UnixNano()), "") objectName := randString(60, rand.NewSource(time.Now().UnixNano()), "")
@@ -1263,10 +1264,21 @@ func TestGetObjectReadSeekFunctional(t *testing.T) {
t.Fatal("Error:", err, bucketName, objectName) 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) 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 // Read the data back
r, err := c.GetObject(bucketName, objectName) r, err := c.GetObject(bucketName, objectName)
if err != nil { if err != nil {
@@ -1277,77 +1289,86 @@ func TestGetObjectReadSeekFunctional(t *testing.T) {
if err != nil { if err != nil {
t.Fatal("Error:", err, bucketName, objectName) 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", t.Fatalf("Error: number of bytes in stat does not match, want %v, got %v\n",
len(buf), st.Size) len(buf), st.Size)
} }
offset := int64(2048) // This following function helps us to compare data from the reader after seek
n, err = r.Seek(offset, 0) // with the data from the original buffer
if err != nil { cmpData := func(r io.Reader, start, end int) {
t.Fatal("Error:", err, offset) if end-start == 0 {
} return
if n != offset { }
t.Fatalf("Error: number of bytes seeked does not match, want %v, got %v\n", buffer := bytes.NewBuffer([]byte{})
offset, n) if _, err := io.CopyN(buffer, r, int64(bufSize)); err != nil {
} if err != io.EOF {
n, err = r.Seek(0, 1) t.Fatal("Error:", err)
if err != nil { }
t.Fatal("Error:", err) }
} if !bytes.Equal(buf[start:end], buffer.Bytes()) {
if n != offset { t.Fatal("Error: Incorrect read bytes v/s original buffer.")
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)
} }
} }
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. for i, testCase := range testCases {
n, err = r.Seek(offset-1, 0) // Perform seek operation
if err != nil { n, err := r.Seek(testCase.offset, testCase.whence)
t.Fatal("Error:", err) // We expect an error
} if testCase.err == seekErr && err == nil {
if n != (offset - 1) { t.Fatalf("Test %d, unexpected err value: expected: %v, found: %v", i+1, testCase.err, err)
t.Fatalf("Error: number of bytes seeked back does not match, want %v, got %v\n", offset-1, n) }
} // We expect a specific error
if testCase.err != seekErr && testCase.err != err {
var buffer2 bytes.Buffer t.Fatalf("Test %d, unexpected err value: expected: %v, found: %v", i+1, testCase.err, err)
if _, err = io.CopyN(&buffer2, r, st.Size); err != nil { }
if err != io.EOF { // If we expect an error go to the next loop
t.Fatal("Error:", err) 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. // Set copy conditions.
copyConds := NewCopyConditions() copyConds := CopyConditions{}
// Start by setting wrong conditions // Start by setting wrong conditions
err = copyConds.SetModified(time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC)) 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 // 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)) err = copyConds.SetUnmodified(time.Date(2014, time.April, 0, 0, 0, 0, 0, time.UTC))
if err != nil { if err != nil {
t.Fatal("Error:", err) 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. // Set get bucket location always as path style.
targetURL := c.endpointURL 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.Path = path.Join(bucketName, "") + "/"
targetURL.RawQuery = urlValues.Encode() targetURL.RawQuery = urlValues.Encode()

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

@@ -41,11 +41,13 @@ type CopyConditions struct {
conditions []copyCondition 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 { func NewCopyConditions() CopyConditions {
return CopyConditions{ return CopyConditions{}
conditions: make([]copyCondition, 0),
}
} }
// SetMatchETag - set match etag. // 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. ## Initialize Minio Client object.
@@ -60,7 +60,7 @@ func main() {
|[`ListBuckets`](#ListBuckets) |[`PutObject`](#PutObject) |[`PresignedPutObject`](#PresignedPutObject) | [`GetBucketPolicy`](#GetBucketPolicy) | [`SetCustomTransport`](#SetCustomTransport) | |[`ListBuckets`](#ListBuckets) |[`PutObject`](#PutObject) |[`PresignedPutObject`](#PresignedPutObject) | [`GetBucketPolicy`](#GetBucketPolicy) | [`SetCustomTransport`](#SetCustomTransport) |
|[`BucketExists`](#BucketExists) |[`CopyObject`](#CopyObject) |[`PresignedPostPolicy`](#PresignedPostPolicy) | [`ListBucketPolicies`](#ListBucketPolicies) | [`TraceOn`](#TraceOn) | |[`BucketExists`](#BucketExists) |[`CopyObject`](#CopyObject) |[`PresignedPostPolicy`](#PresignedPostPolicy) | [`ListBucketPolicies`](#ListBucketPolicies) | [`TraceOn`](#TraceOn) |
| [`RemoveBucket`](#RemoveBucket) |[`StatObject`](#StatObject) | | [`SetBucketNotification`](#SetBucketNotification) | [`TraceOff`](#TraceOff) | | [`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) | |[`ListObjectsV2`](#ListObjectsV2) | [`RemoveObjects`](#RemoveObjects) | | [`RemoveAllBucketNotification`](#RemoveAllBucketNotification) |
|[`ListIncompleteUploads`](#ListIncompleteUploads) | [`RemoveIncompleteUpload`](#RemoveIncompleteUpload) | | [`ListenBucketNotification`](#ListenBucketNotification) | |[`ListIncompleteUploads`](#ListIncompleteUploads) | [`RemoveIncompleteUpload`](#RemoveIncompleteUpload) | | [`ListenBucketNotification`](#ListenBucketNotification) |
| | [`FPutObject`](#FPutObject) | | | | | [`FPutObject`](#FPutObject) | | |
@@ -69,7 +69,7 @@ func main() {
## 1. Constructor ## 1. Constructor
<a name="Minio"></a> <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. Initializes a new client object.
__Parameters__ __Parameters__
@@ -86,7 +86,7 @@ __Parameters__
## 2. Bucket operations ## 2. Bucket operations
<a name="MakeBucket"></a> <a name="MakeBucket"></a>
### MakeBucket(bucketName string, location string) error ### MakeBucket(bucketName, location string) error
Creates a new bucket. Creates a new bucket.
@@ -216,7 +216,7 @@ if err != nil {
``` ```
<a name="ListObjects"></a> <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. Lists objects in a bucket.
@@ -267,7 +267,7 @@ for object := range objectCh {
<a name="ListObjectsV2"></a> <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 Lists objects in a bucket using the recommended listing API v2
@@ -317,7 +317,7 @@ for object := range objectCh {
``` ```
<a name="ListIncompleteUploads"></a> <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. Lists partially uploaded objects in a bucket.
@@ -373,7 +373,7 @@ for multiPartObject := range multiPartObjectCh {
## 3. Object operations ## 3. Object operations
<a name="GetObject"></a> <a name="GetObject"></a>
### GetObject(bucketName string, objectName string) (*Object, error) ### GetObject(bucketName, objectName string) (*Object, error)
Downloads an object. Downloads an object.
@@ -392,7 +392,7 @@ __Return Value__
|Param |Type |Description | |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__ __Example__
@@ -418,7 +418,7 @@ if _, err = io.Copy(localFile, object); err != nil {
``` ```
<a name="FGetObject"></a> <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. Downloads and saves the object as a file in the local filesystem.
@@ -446,7 +446,7 @@ if err != nil {
``` ```
<a name="PutObject"></a> <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. Uploads an object.
@@ -489,7 +489,7 @@ if err != nil {
<a name="CopyObject"></a> <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. Copy a source object into a new object with the provided name in the provided bucket.
@@ -509,24 +509,34 @@ __Example__
```go ```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. // Initialize empty 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))
// Set unmodified condition, copy object unmodified since 2014 April. // copy object that matches the given ETag.
// copyConds.SetUnmodified(time.Date(2014, time.April, 0, 0, 0, 0, 0, time.UTC)) copyConds.SetMatchETag("31624deb84149d2f8ef9c385918b653a")
// Set matching ETag condition, copy object which matches the following ETag. // and modified after 1st April 2014
// copyConds.SetMatchETag("31624deb84149d2f8ef9c385918b653a") 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. // but unmodified since 23rd April 2014
// copyConds.SetMatchETagExcept("31624deb84149d2f8ef9c385918b653a") 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 { if err != nil {
fmt.Println(err) fmt.Println(err)
return return
@@ -535,7 +545,7 @@ if err != nil {
``` ```
<a name="FPutObject"></a> <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. Uploads contents from a file to objectName.
@@ -569,7 +579,7 @@ if err != nil {
``` ```
<a name="StatObject"></a> <a name="StatObject"></a>
### StatObject(bucketName string, objectName string) (ObjectInfo, error) ### StatObject(bucketName, objectName string) (ObjectInfo, error)
Gets metadata of an object. Gets metadata of an object.
@@ -613,7 +623,7 @@ fmt.Println(objInfo)
``` ```
<a name="RemoveObject"></a> <a name="RemoveObject"></a>
### RemoveObject(bucketName string, objectName string) error ### RemoveObject(bucketName, objectName string) error
Removes an object. Removes an object.
@@ -670,7 +680,7 @@ for e := range errorCh {
<a name="RemoveIncompleteUpload"></a> <a name="RemoveIncompleteUpload"></a>
### RemoveIncompleteUpload(bucketName string, objectName string) error ### RemoveIncompleteUpload(bucketName, objectName string) error
Removes a partially uploaded object. Removes a partially uploaded object.
@@ -699,7 +709,7 @@ if err != nil {
<a name="PresignedGetObject"></a> <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. 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> <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. 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 ## 5. Bucket policy/notification operations
<a name="SetBucketPolicy"></a> <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. Set access permissions on bucket or an object prefix.
@@ -864,7 +874,7 @@ if err != nil {
``` ```
<a name="GetBucketPolicy"></a> <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. 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> <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. 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 ## 6. Client custom settings
<a name="SetAppInfo"></a> <a name="SetAppInfo"></a>
### SetAppInfo(appName string, appVersion string) ### SetAppInfo(appName, appVersion string)
Adds application details to User-Agent. Adds application details to User-Agent.
__Parameters__ __Parameters__
@@ -1148,6 +1158,17 @@ __Parameters__
### TraceOff() ### TraceOff()
Disables HTTP tracing. 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 ## 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. // All following conditions are allowed and can be combined together.
// Set copy conditions. // Set copy conditions.
var copyConds = minio.NewCopyConditions() var copyConds = minio.CopyConditions{}
// Set modified condition, copy object modified since 2014 April. // Set modified condition, copy object modified since 2014 April.
copyConds.SetModified(time.Date(2014, time.April, 0, 0, 0, 0, 0, time.UTC)) 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 return true
} }
if IsAmazonS3AccelerateEndpoint(endpointURL) {
return true
}
return endpointURL.Host == "s3.amazonaws.com" 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" 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. // IsGoogleEndpoint - Match if it is exactly Google cloud storage endpoint.
func IsGoogleEndpoint(endpointURL url.URL) bool { func IsGoogleEndpoint(endpointURL url.URL) bool {
if endpointURL == sentinelURL { 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. // StringSet - uses map as set of strings.
type StringSet map[string]struct{} type StringSet map[string]struct{}
// keys - returns StringSet keys. // ToSlice - returns StringSet as string slice.
func (set StringSet) keys() []string { func (set StringSet) ToSlice() []string {
keys := make([]string, 0, len(set)) keys := make([]string, 0, len(set))
for k := range set { for k := range set {
keys = append(keys, k) keys = append(keys, k)
@@ -141,7 +141,7 @@ func (set StringSet) Union(sset StringSet) StringSet {
// MarshalJSON - converts to JSON data. // MarshalJSON - converts to JSON data.
func (set StringSet) MarshalJSON() ([]byte, error) { 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. // 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. // String - returns printable string of the set.
func (set StringSet) String() string { func (set StringSet) String() string {
return fmt.Sprintf("%s", set.keys()) return fmt.Sprintf("%s", set.ToSlice())
} }
// NewStringSet - creates new string set. // NewStringSet - creates new string set.

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

@@ -17,6 +17,7 @@
package set package set
import ( import (
"fmt"
"strings" "strings"
"testing" "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 language: go
go: go:
- 1.4 - 1.8.1
script: script:
- go test - 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( func WeaklyTypedHook(
f reflect.Kind, f reflect.Kind,
t reflect.Kind, t reflect.Kind,
@@ -132,9 +137,8 @@ func WeaklyTypedHook(
case reflect.Bool: case reflect.Bool:
if dataVal.Bool() { if dataVal.Bool() {
return "1", nil return "1", nil
} else {
return "0", nil
} }
return "0", nil
case reflect.Float32: case reflect.Float32:
return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil
case reflect.Int: case reflect.Int:

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

@@ -1,5 +1,5 @@
// The mapstructure package exposes functionality to convert an // Package mapstructure exposes functionality to convert an arbitrary
// arbitrary map[string]interface{} into a native Go structure. // map[string]interface{} into a native Go structure.
// //
// The Go structure can be arbitrarily complex, containing slices, // The Go structure can be arbitrarily complex, containing slices,
// other structs, etc. and the decoder will properly decode nested // other structs, etc. and the decoder will properly decode nested
@@ -32,7 +32,12 @@ import (
// both. // both.
type DecodeHookFunc interface{} 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) 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) type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error)
// DecoderConfig is the configuration that is used to create a new decoder // 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: case dataKind == reflect.Uint:
val.SetFloat(float64(dataVal.Uint())) val.SetFloat(float64(dataVal.Uint()))
case dataKind == reflect.Float32: case dataKind == reflect.Float32:
val.SetFloat(float64(dataVal.Float())) val.SetFloat(dataVal.Float())
case dataKind == reflect.Bool && d.config.WeaklyTypedInput: case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
if dataVal.Bool() { if dataVal.Bool() {
val.SetFloat(1) 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) { func TestDecode_Nil(t *testing.T) {
t.Parallel() t.Parallel()
var input interface{} = nil var input interface{}
result := Basic{ result := Basic{
Vstring: "foo", Vstring: "foo",
} }

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

@@ -7,4 +7,5 @@ go:
- 1.5 - 1.5
- 1.6 - 1.6
- 1.7 - 1.7
- 1.8
- tip - 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. 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). * 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) * 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. * 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)! * [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. 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. The goi18n command provides functionality for managing the translation process.
@@ -66,7 +66,7 @@ Translation files
A translation file stores translated and untranslated strings. A translation file stores translated and untranslated strings.
Example: Here is an example of the default file format that go-i18n supports:
```json ```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 Contributions
------------- -------------

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

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

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

@@ -5,7 +5,6 @@ import (
"flag" "flag"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os"
"path/filepath" "path/filepath"
"reflect" "reflect"
"sort" "sort"
@@ -15,6 +14,7 @@ import (
"github.com/nicksnyder/go-i18n/i18n/bundle" "github.com/nicksnyder/go-i18n/i18n/bundle"
"github.com/nicksnyder/go-i18n/i18n/language" "github.com/nicksnyder/go-i18n/i18n/language"
"github.com/nicksnyder/go-i18n/i18n/translation" "github.com/nicksnyder/go-i18n/i18n/translation"
toml "github.com/pelletier/go-toml"
) )
type mergeCommand struct { type mergeCommand struct {
@@ -22,6 +22,7 @@ type mergeCommand struct {
sourceLanguage string sourceLanguage string
outdir string outdir string
format string format string
flat bool
} }
func (mc *mergeCommand) execute() error { func (mc *mergeCommand) execute() error {
@@ -33,15 +34,10 @@ func (mc *mergeCommand) execute() error {
return fmt.Errorf("invalid source locale: %s", mc.sourceLanguage) return fmt.Errorf("invalid source locale: %s", mc.sourceLanguage)
} }
marshal, err := newMarshalFunc(mc.format)
if err != nil {
return err
}
bundle := bundle.New() bundle := bundle.New()
for _, tf := range mc.translationFiles { for _, tf := range mc.translationFiles {
if err := bundle.LoadTranslationFile(tf); err != nil { 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 { all := filter(localeTranslations, func(t translation.Translation) translation.Translation {
return t.Normalize(lang) 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 return err
} }
@@ -74,7 +70,7 @@ func (mc *mergeCommand) execute() error {
} }
return nil return nil
}) })
if err := mc.writeFile("untranslated", untranslated, localeID, marshal); err != nil { if err := mc.writeFile("untranslated", untranslated, localeID); err != nil {
return err return err
} }
} }
@@ -88,6 +84,7 @@ func (mc *mergeCommand) parse(arguments []string) {
sourceLanguage := flags.String("sourceLanguage", "en-us", "") sourceLanguage := flags.String("sourceLanguage", "en-us", "")
outdir := flags.String("outdir", ".", "") outdir := flags.String("outdir", ".", "")
format := flags.String("format", "json", "") format := flags.String("format", "json", "")
flat := flags.Bool("flat", true, "")
flags.Parse(arguments) flags.Parse(arguments)
@@ -95,31 +92,44 @@ func (mc *mergeCommand) parse(arguments []string) {
mc.sourceLanguage = *sourceLanguage mc.sourceLanguage = *sourceLanguage
mc.outdir = *outdir mc.outdir = *outdir
mc.format = *format mc.format = *format
if *format == "toml" {
mc.flat = true
} else {
mc.flat = *flat
}
} }
func (mc *mergeCommand) SetArgs(args []string) { func (mc *mergeCommand) SetArgs(args []string) {
mc.translationFiles = args mc.translationFiles = args
} }
type marshalFunc func(interface{}) ([]byte, error) func (mc *mergeCommand) writeFile(label string, translations []translation.Translation, localeID string) error {
func (mc *mergeCommand) writeFile(label string, translations []translation.Translation, localeID string, marshal marshalFunc) error {
sort.Sort(translation.SortableByID(translations)) sort.Sort(translation.SortableByID(translations))
buf, err := marshal(marshalInterface(translations))
if err != nil { var convert func([]translation.Translation) interface{}
return fmt.Errorf("failed to marshal %s strings to %s because %s", localeID, mc.format, err) 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)) filename := filepath.Join(mc.outdir, fmt.Sprintf("%s.%s.%s", localeID, label, mc.format))
if err := ioutil.WriteFile(filename, buf, 0666); err != nil { 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 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)) filtered := make([]translation.Translation, 0, len(translations))
for _, translation := range translations { for _, translation := range translations {
if t := filter(translation); t != nil { if t := f(translation); t != nil {
filtered = append(filtered, t) filtered = append(filtered, t)
} }
} }
@@ -127,21 +137,15 @@ func filter(translations map[string]translation.Translation, filter func(transla
} }
func newMarshalFunc(format string) (marshalFunc, error) { func marshalFlatInterface(translations []translation.Translation) interface{} {
switch format { mi := make(map[string]interface{}, len(translations))
case "json": for _, translation := range translations {
return func(v interface{}) ([]byte, error) { mi[translation.ID()] = translation.MarshalFlatInterface()
return json.MarshalIndent(v, "", " ")
}, nil
case "yaml":
return func(v interface{}) ([]byte, error) {
return yaml.Marshal(v)
}, nil
} }
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)) mi := make([]interface{}, len(translations))
for i, translation := range translations { for i, translation := range translations {
mi[i] = translation.MarshalInterface() mi[i] = translation.MarshalInterface()
@@ -149,6 +153,31 @@ func marshalInterface(translations []translation.Translation) []interface{} {
return mi 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() { func usageMerge() {
fmt.Printf(`Merge translation files. fmt.Printf(`Merge translation files.
@@ -198,9 +227,13 @@ Options:
-format format -format format
goi18n encodes the output translation files in this format. goi18n encodes the output translation files in this format.
Supported formats: json, yaml Supported formats: json, toml, yaml
Default: json 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", sourceLanguage: "en-us",
outdir: "testdata/output", outdir: "testdata/output",
format: "json", format: "json",
flat: false,
} }
if err := mc.execute(); err != nil { if err := mc.execute(); err != nil {
t.Fatal(err) t.Fatal(err)
@@ -69,6 +70,6 @@ func expectEqualFiles(t *testing.T, expectedName, actualName string) {
t.Fatal(err) t.Fatal(err)
} }
if !bytes.Equal(actual, expected) { 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 сгенерированный поставляемый Обычный файл
Просмотреть файл

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

@@ -0,0 +1,27 @@
{
"d_days": {
"one": "",
"other": ""
},
"my_height_in_meters": {
"one": "",
"other": ""
},
"person_greeting": {
"other": ""
},
"person_unread_email_count": {
"one": "",
"other": ""
},
"person_unread_email_count_timeframe": {
"other": ""
},
"program_greeting": {
"other": ""
},
"your_unread_email_count": {
"one": "",
"other": ""
}
}

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

@@ -0,0 +1,27 @@
{
"d_days": {
"one": "{{.Count}} days",
"other": "{{.Count}} days"
},
"my_height_in_meters": {
"one": "I am {{.Count}} meters tall.",
"other": "I am {{.Count}} meters tall."
},
"person_greeting": {
"other": "Hello {{.Person}}"
},
"person_unread_email_count": {
"one": "{{.Person}} has {{.Count}} unread emails.",
"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 emails.",
"other": "You have {{.Count}} unread emails."
}
}

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