Upgrading server dependancies (#6215)
63
glide.lock
сгенерированный
@@ -1,5 +1,5 @@
|
||||
hash: 193ce14426dc6d4ae2da1c1aad08389a157529f829ed12948095239e18e045a5
|
||||
updated: 2017-03-30T22:26:27.084209918-07:00
|
||||
hash: 024025a74451af061cc996e2b9192bad74cfd0952515fab332e3ad2968606909
|
||||
updated: 2017-04-24T11:23:43.046980248-04:00
|
||||
imports:
|
||||
- name: github.com/alecthomas/log4go
|
||||
version: 3fbce08846379ec7f4f6bc7fce6dd01ce28fae4c
|
||||
@@ -8,10 +8,12 @@ imports:
|
||||
version: 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
|
||||
subpackages:
|
||||
- quantile
|
||||
- name: github.com/cpanato/html2text
|
||||
version: d788b7d6dc58bea298b318059332a25442583880
|
||||
- name: github.com/dgryski/dgoogauth
|
||||
version: 96977cbd42e27be71f9f731db6634123de7e861a
|
||||
- name: github.com/disintegration/imaging
|
||||
version: 243d2d8673c1225a6afceeb9b3b4423d485dc8df
|
||||
version: ac27d1805a555e1754fa177216ee07f4e63c30b5
|
||||
- name: github.com/dyatlov/go-opengraph
|
||||
version: 41a3523719dfbe7e8f853fbd4061867543db5270
|
||||
subpackages:
|
||||
@@ -25,12 +27,12 @@ imports:
|
||||
- name: github.com/go-sql-driver/mysql
|
||||
version: a0583e0143b1624142adab07e0e97fe106d99561
|
||||
- name: github.com/golang/freetype
|
||||
version: d9be45aaf7452cc30c0ceb1b1bf7efe1d17b7c87
|
||||
version: b12e98108289d6367ecd1a819deee597b2c3fa57
|
||||
subpackages:
|
||||
- raster
|
||||
- truetype
|
||||
- name: github.com/golang/protobuf
|
||||
version: c9c7427a2a70d2eb3bafa0ab2dc163e45f143317
|
||||
version: 2bba0603135d7d7f5cb73b2125beeda19c09f4ef
|
||||
subpackages:
|
||||
- proto
|
||||
- name: github.com/gorilla/context
|
||||
@@ -46,7 +48,7 @@ imports:
|
||||
subpackages:
|
||||
- simplelru
|
||||
- name: github.com/hashicorp/hcl
|
||||
version: 630949a3c5fa3c613328e1b8256052cbc2327c9b
|
||||
version: 7fa7fff964d035e8a162cce3a164b3ad02ad651b
|
||||
subpackages:
|
||||
- hcl/ast
|
||||
- hcl/parser
|
||||
@@ -58,12 +60,10 @@ imports:
|
||||
- json/token
|
||||
- name: github.com/inconshreveable/mousetrap
|
||||
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
|
||||
- name: github.com/jaytaylor/html2text
|
||||
version: f3b8a7ca0a23f0a806b2e1ad1247de39ecde54bf
|
||||
- name: github.com/jehiah/go-strftime
|
||||
version: 834e15c05a45371503440cc195bbd05c9a0968d9
|
||||
- name: github.com/lib/pq
|
||||
version: 472a0745531a17dbac346e828b4c60e73ddff30c
|
||||
version: 2704adc878c21e1329f46f6e56a1c387d788ff94
|
||||
subpackages:
|
||||
- oid
|
||||
- name: github.com/magiconair/properties
|
||||
@@ -79,33 +79,33 @@ imports:
|
||||
subpackages:
|
||||
- pbutil
|
||||
- name: github.com/miekg/dns
|
||||
version: b54e1be39a9c14cd0bcea6df97eb15b3ec5e8cde
|
||||
version: 6ebcb714d36901126ee2807031543b38c56de963
|
||||
- name: github.com/minio/minio-go
|
||||
version: 52cc94e879db78c2e2c6e160869df943137ec4cd
|
||||
version: dcaae9ec4d0b0a81d17f22f6d7a186491f6a55ec
|
||||
subpackages:
|
||||
- pkg/policy
|
||||
- pkg/s3signer
|
||||
- pkg/s3utils
|
||||
- pkg/set
|
||||
- name: github.com/mitchellh/mapstructure
|
||||
version: 53818660ed4955e899c0bcafa97299a388bd7c8e
|
||||
version: cc8532a8e9a55ea36402aa21efdf403a60d34096
|
||||
- name: github.com/mssola/user_agent
|
||||
version: 85b2f5798558a46fc23443c596e781712f4b7792
|
||||
- name: github.com/nicksnyder/go-i18n
|
||||
version: f757c9f9b69c16ff69d38dbf224be28a7b6537bb
|
||||
version: fed5740db6b83ee8ba7c1b07ff063115bc6f4b96
|
||||
subpackages:
|
||||
- i18n
|
||||
- i18n/bundle
|
||||
- i18n/language
|
||||
- i18n/translation
|
||||
- name: github.com/NYTimes/gziphandler
|
||||
version: 3b0c4852c5b9710340f1ed7b1a529c46a3bc0fc1
|
||||
version: 22d4470af89e09998fc16b35029df973932df4ae
|
||||
- name: github.com/pborman/uuid
|
||||
version: a97ce2ca70fa5a848076093f05e639a89ca34d06
|
||||
- name: github.com/pelletier/go-buffruneio
|
||||
version: c37440a7cf42ac63b919c752ca73a85067e05992
|
||||
- name: github.com/pelletier/go-toml
|
||||
version: e32a2e04744250647a72bf17da1b09befc03b6b1
|
||||
version: fe206efb84b2bc8e8cfafe6b4c1826622be969e3
|
||||
- name: github.com/prometheus/client_golang
|
||||
version: c5b7fccd204277076155f10851dad72b76a49317
|
||||
subpackages:
|
||||
@@ -115,11 +115,11 @@ imports:
|
||||
subpackages:
|
||||
- go
|
||||
- name: github.com/prometheus/common
|
||||
version: 49fee292b27bfff7f354ee0f64e1bc4850462edf
|
||||
version: 9e0844febd9e2856f839c9cb974fbd676d1755a8
|
||||
subpackages:
|
||||
- expfmt
|
||||
- name: github.com/prometheus/procfs
|
||||
version: a1dba9ce8baed984a2495b658c82687f8157b98f
|
||||
version: 332f6238064950a97bc3ed3f5421f6418537e707
|
||||
- name: github.com/rsc/letsencrypt
|
||||
version: 76104d26167d38b6a0010f42bfc8ec5487742e8b
|
||||
- name: github.com/rwcarlsen/goexif
|
||||
@@ -136,31 +136,31 @@ imports:
|
||||
subpackages:
|
||||
- mem
|
||||
- name: github.com/spf13/cast
|
||||
version: ce135a4ebeee6cfe9a26c93ee0d37825f26113c7
|
||||
version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4
|
||||
- name: github.com/spf13/cobra
|
||||
version: 7be4beda01ec05d0b93d80b3facd2b6f44080d94
|
||||
version: f4f10f6873175e78bb1503da7e78c260a7f3ef63
|
||||
- name: github.com/spf13/jwalterweatherman
|
||||
version: fa7ca7e836cf3a8bb4ebf799f472c12d7e903d66
|
||||
- name: github.com/spf13/pflag
|
||||
version: 9ff6c6923cfffbcd502984b8e0c80539a94968b7
|
||||
version: 2300d0f8576fe575f71aaa5b9bbe4e1b0dc2eb51
|
||||
- name: github.com/spf13/viper
|
||||
version: 84f94806c67f59dd7ae87bc5351f7a9c94a4558d
|
||||
version: 0967fc9aceab2ce9da34061253ac10fb99bba5b2
|
||||
- name: github.com/tylerb/graceful
|
||||
version: d72b0151351a13d0421b763b88f791469c4f5dc7
|
||||
version: 4654dfbb6ad53cb5e27f37d99b02e16c1872fbbb
|
||||
- name: github.com/xenolf/lego
|
||||
version: 0e2937900b224325f4476745a9b53aef246b7410
|
||||
version: 5dfe609afb1ebe9da97c9846d97a55415e5a5ccd
|
||||
subpackages:
|
||||
- acme
|
||||
- name: github.com/xtgo/uuid
|
||||
version: a0b114877d4caeffbd7f87e3757c17fce570fea7
|
||||
- name: golang.org/x/crypto
|
||||
version: 459e26527287adbc2adcc5d0d49abff9a5f315a7
|
||||
version: 3543873453996aaab2fc6b3928a35fc5ca2b5afb
|
||||
subpackages:
|
||||
- bcrypt
|
||||
- blowfish
|
||||
- ocsp
|
||||
- name: golang.org/x/image
|
||||
version: c0851fbc5b9272dd7d08a021e9e3d2a21027b51f
|
||||
version: 3210c0296b49a552ad9668ede9c61008df821b94
|
||||
subpackages:
|
||||
- bmp
|
||||
- font
|
||||
@@ -168,29 +168,27 @@ imports:
|
||||
- tiff
|
||||
- tiff/lzw
|
||||
- name: golang.org/x/net
|
||||
version: 78ebe5c8b6a27ec13109c73c22193d618270e1e1
|
||||
version: d212a1ef2de2f5d441c327b8f26cf3ea3ea9f265
|
||||
subpackages:
|
||||
- context
|
||||
- html
|
||||
- html/atom
|
||||
- publicsuffix
|
||||
- name: golang.org/x/sys
|
||||
version: 8fd966b47dbdd4faa03de0d06e3d733baeb9a1a9
|
||||
version: ea9bcade75cb975a0b9738936568ab388b845617
|
||||
subpackages:
|
||||
- unix
|
||||
- name: golang.org/x/text
|
||||
version: 65f4f820a7954b82e5c9325e1e088a4fda098f36
|
||||
version: a9a820217f98f7c8a207ec1e45a874e1fe12c478
|
||||
subpackages:
|
||||
- transform
|
||||
- unicode/norm
|
||||
- name: golang.org/x/time
|
||||
version: f51c12702a4d776e4c1fa9b0fabab841babae631
|
||||
version: c06e80d9300e4443158a03817b8a8cb37d230320
|
||||
subpackages:
|
||||
- rate
|
||||
- name: gopkg.in/asn1-ber.v1
|
||||
version: 4e86f4367175e39f69d9358a5f17b4dda270378d
|
||||
- name: gopkg.in/gomail.v2
|
||||
version: 41f3572897373c5538c50a2402db15db079fa4fd
|
||||
- name: gopkg.in/square/go-jose.v1
|
||||
version: aa2e30fdd1fe9dd3394119af66451ae790d50e0d
|
||||
subpackages:
|
||||
@@ -199,8 +197,7 @@ imports:
|
||||
- name: gopkg.in/throttled/throttled.v2
|
||||
version: b5675e93f9d999b22f92d859a5bf2138d3641af4
|
||||
subpackages:
|
||||
- store
|
||||
- store/memstore
|
||||
- name: gopkg.in/yaml.v2
|
||||
version: a3f3340b5840cee44f372bddb5880fcbc419b46a
|
||||
version: cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b
|
||||
testImports: []
|
||||
|
||||
31
glide.yaml
@@ -5,7 +5,12 @@ import:
|
||||
repo: https://github.com/mattermost/log4go.git
|
||||
- package: github.com/dgryski/dgoogauth
|
||||
- package: github.com/disintegration/imaging
|
||||
version: v1.0.0
|
||||
version: v1.1.0
|
||||
- package: github.com/dyatlov/go-opengraph
|
||||
subpackages:
|
||||
- opengraph
|
||||
- package: github.com/fsnotify/fsnotify
|
||||
version: v1.4.2
|
||||
- package: github.com/go-gorp/gorp
|
||||
version: 0c9bc0918534d133cedb439a24adc7cbe66e4a9d
|
||||
- package: github.com/go-ldap/ldap
|
||||
@@ -23,17 +28,27 @@ import:
|
||||
- package: github.com/mattermost/rsc
|
||||
subpackages:
|
||||
- qr
|
||||
- package: github.com/minio/minio-go
|
||||
version: v2.0.4
|
||||
- package: github.com/mssola/user_agent
|
||||
version: v0.4.1
|
||||
- package: github.com/nicksnyder/go-i18n
|
||||
version: v1.7.0
|
||||
version: v1.8.0
|
||||
subpackages:
|
||||
- i18n
|
||||
- package: github.com/pborman/uuid
|
||||
version: v1.0
|
||||
- package: github.com/rsc/letsencrypt
|
||||
- package: github.com/rwcarlsen/goexif
|
||||
subpackages:
|
||||
- exif
|
||||
- package: github.com/segmentio/analytics-go
|
||||
version: 2.1.1
|
||||
- package: github.com/spf13/cobra
|
||||
- package: github.com/spf13/pflag
|
||||
- package: github.com/spf13/viper
|
||||
- package: github.com/tylerb/graceful
|
||||
version: v1.2.15
|
||||
- package: golang.org/x/crypto
|
||||
subpackages:
|
||||
- bcrypt
|
||||
@@ -43,12 +58,10 @@ import:
|
||||
- package: gopkg.in/throttled/throttled.v2
|
||||
version: v2.0.3
|
||||
subpackages:
|
||||
- store
|
||||
- store/memstore
|
||||
- package: github.com/segmentio/analytics-go
|
||||
version: 2.1.1
|
||||
- package: github.com/rsc/letsencrypt
|
||||
- package: github.com/minio/minio-go
|
||||
version: v2.0.3
|
||||
- package: github.com/prometheus/client_golang
|
||||
version: v0.8.0
|
||||
subpackages:
|
||||
@@ -75,9 +88,5 @@ import:
|
||||
- package: github.com/dyatlov/go-opengraph
|
||||
subpackages:
|
||||
- opengraph
|
||||
- package: github.com/jaytaylor/html2text
|
||||
- package: gopkg.in/gomail.v2
|
||||
version: 2.0.0
|
||||
- package: github.com/spf13/viper
|
||||
- package: github.com/fsnotify/fsnotify
|
||||
version: v1.4.2
|
||||
- package: github.com/cpanato/html2text
|
||||
|
||||
|
||||
1
vendor/github.com/NYTimes/gziphandler/.travis.yml
сгенерированный
поставляемый
@@ -2,4 +2,5 @@ language: go
|
||||
|
||||
go:
|
||||
- 1.7
|
||||
- 1.8
|
||||
- tip
|
||||
|
||||
4
vendor/github.com/NYTimes/gziphandler/README.md
сгенерированный
поставляемый
@@ -38,12 +38,12 @@ func main() {
|
||||
|
||||
## Documentation
|
||||
|
||||
The docs can be found at [godoc.org] [docs], as usual.
|
||||
The docs can be found at [godoc.org][docs], as usual.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
[Apache 2.0] [license].
|
||||
[Apache 2.0][license].
|
||||
|
||||
|
||||
|
||||
|
||||
129
vendor/github.com/NYTimes/gziphandler/gzip.go
сгенерированный
поставляемый
@@ -4,6 +4,7 @@ import (
|
||||
"bufio"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
@@ -21,10 +22,16 @@ const (
|
||||
|
||||
type codings map[string]float64
|
||||
|
||||
// The default qvalue to assign to an encoding if no explicit qvalue is set.
|
||||
// This is actually kind of ambiguous in RFC 2616, so hopefully it's correct.
|
||||
// The examples seem to indicate that it is.
|
||||
const DEFAULT_QVALUE = 1.0
|
||||
const (
|
||||
// DefaultQValue is the default qvalue to assign to an encoding if no explicit qvalue is set.
|
||||
// This is actually kind of ambiguous in RFC 2616, so hopefully it's correct.
|
||||
// The examples seem to indicate that it is.
|
||||
DefaultQValue = 1.0
|
||||
|
||||
// DefaultMinSize defines the minimum size to reach to enable compression.
|
||||
// It's 512 bytes.
|
||||
DefaultMinSize = 512
|
||||
)
|
||||
|
||||
// gzipWriterPools stores a sync.Pool for each compression level for reuse of
|
||||
// gzip.Writers. Use poolIndex to covert a compression level to an index into
|
||||
@@ -63,35 +70,88 @@ func addLevelPool(level int) {
|
||||
// GzipResponseWriter provides an http.ResponseWriter interface, which gzips
|
||||
// bytes before writing them to the underlying response. This doesn't close the
|
||||
// writers, so don't forget to do that.
|
||||
// It can be configured to skip response smaller than minSize.
|
||||
type GzipResponseWriter struct {
|
||||
http.ResponseWriter
|
||||
index int // Index for gzipWriterPools.
|
||||
gw *gzip.Writer
|
||||
|
||||
code int // Saves the WriteHeader value.
|
||||
|
||||
minSize int // Specifed the minimum response size to gzip. If the response length is bigger than this value, it is compressed.
|
||||
buf []byte // Holds the first part of the write before reaching the minSize or the end of the write.
|
||||
}
|
||||
|
||||
// Write appends data to the gzip writer.
|
||||
func (w *GzipResponseWriter) Write(b []byte) (int, error) {
|
||||
// Lazily create the gzip.Writer, this allows empty bodies to be actually
|
||||
// empty, for example in the case of status code 204 (no content).
|
||||
if w.gw == nil {
|
||||
w.init()
|
||||
}
|
||||
|
||||
// If content type is not set.
|
||||
if _, ok := w.Header()[contentType]; !ok {
|
||||
// If content type is not set, infer it from the uncompressed body.
|
||||
// It infer it from the uncompressed body.
|
||||
w.Header().Set(contentType, http.DetectContentType(b))
|
||||
}
|
||||
return w.gw.Write(b)
|
||||
|
||||
// GZIP responseWriter is initialized. Use the GZIP responseWriter.
|
||||
if w.gw != nil {
|
||||
n, err := w.gw.Write(b)
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Save the write into a buffer for later use in GZIP responseWriter (if content is long enough) or at close with regular responseWriter.
|
||||
w.buf = append(w.buf, b...)
|
||||
|
||||
// If the global writes are bigger than the minSize, compression is enable.
|
||||
if len(w.buf) >= w.minSize {
|
||||
err := w.startGzip()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
// WriteHeader will check if the gzip writer needs to be lazily initiated and
|
||||
// then pass the code along to the underlying ResponseWriter.
|
||||
func (w *GzipResponseWriter) WriteHeader(code int) {
|
||||
if w.gw == nil &&
|
||||
code != http.StatusNotModified && code != http.StatusNoContent {
|
||||
w.init()
|
||||
// startGzip initialize any GZIP specific informations.
|
||||
func (w *GzipResponseWriter) startGzip() error {
|
||||
|
||||
// Set the GZIP header.
|
||||
w.Header().Set(contentEncoding, "gzip")
|
||||
|
||||
// if the Content-Length is already set, then calls to Write on gzip
|
||||
// will fail to set the Content-Length header since its already set
|
||||
// See: https://github.com/golang/go/issues/14975.
|
||||
w.Header().Del(contentLength)
|
||||
|
||||
// Write the header to gzip response.
|
||||
w.writeHeader()
|
||||
|
||||
// Initialize the GZIP response.
|
||||
w.init()
|
||||
|
||||
// Flush the buffer into the gzip reponse.
|
||||
n, err := w.gw.Write(w.buf)
|
||||
|
||||
// This should never happen (per io.Writer docs), but if the write didn't
|
||||
// accept the entire buffer but returned no specific error, we have no clue
|
||||
// what's going on, so abort just to be safe.
|
||||
if err == nil && n < len(w.buf) {
|
||||
return io.ErrShortWrite
|
||||
}
|
||||
w.ResponseWriter.WriteHeader(code)
|
||||
|
||||
w.buf = nil
|
||||
return err
|
||||
}
|
||||
|
||||
// WriteHeader just saves the response code until close or GZIP effective writes.
|
||||
func (w *GzipResponseWriter) WriteHeader(code int) {
|
||||
w.code = code
|
||||
}
|
||||
|
||||
// writeHeader uses the saved code to send it to the ResponseWriter.
|
||||
func (w *GzipResponseWriter) writeHeader() {
|
||||
if w.code == 0 {
|
||||
w.code = http.StatusOK
|
||||
}
|
||||
w.ResponseWriter.WriteHeader(w.code)
|
||||
}
|
||||
|
||||
// init graps a new gzip writer from the gzipWriterPool and writes the correct
|
||||
@@ -102,15 +162,22 @@ func (w *GzipResponseWriter) init() {
|
||||
gzw := gzipWriterPools[w.index].Get().(*gzip.Writer)
|
||||
gzw.Reset(w.ResponseWriter)
|
||||
w.gw = gzw
|
||||
w.ResponseWriter.Header().Set(contentEncoding, "gzip")
|
||||
// if the Content-Length is already set, then calls to Write on gzip
|
||||
// will fail to set the Content-Length header since its already set
|
||||
// See: https://github.com/golang/go/issues/14975
|
||||
w.ResponseWriter.Header().Del(contentLength)
|
||||
}
|
||||
|
||||
// Close will close the gzip.Writer and will put it back in the gzipWriterPool.
|
||||
func (w *GzipResponseWriter) Close() error {
|
||||
// Buffer not nil means the regular response must be returned.
|
||||
if w.buf != nil {
|
||||
w.writeHeader()
|
||||
// Make the write into the regular response.
|
||||
_, writeErr := w.ResponseWriter.Write(w.buf)
|
||||
// Returns the error if any at write.
|
||||
if writeErr != nil {
|
||||
return fmt.Errorf("gziphandler: write to regular responseWriter at close gets error: %q", writeErr.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// If the GZIP responseWriter is not set no needs to close it.
|
||||
if w.gw == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -163,9 +230,18 @@ func MustNewGzipLevelHandler(level int) func(http.Handler) http.Handler {
|
||||
// if an invalid gzip compression level is given, so if one can ensure the level
|
||||
// is valid, the returned error can be safely ignored.
|
||||
func NewGzipLevelHandler(level int) (func(http.Handler) http.Handler, error) {
|
||||
return NewGzipLevelAndMinSize(level, DefaultMinSize)
|
||||
}
|
||||
|
||||
// NewGzipLevelAndMinSize behave as NewGzipLevelHandler except it let the caller
|
||||
// specify the minimum size before compression.
|
||||
func NewGzipLevelAndMinSize(level, minSize int) (func(http.Handler) http.Handler, error) {
|
||||
if level != gzip.DefaultCompression && (level < gzip.BestSpeed || level > gzip.BestCompression) {
|
||||
return nil, fmt.Errorf("invalid compression level requested: %d", level)
|
||||
}
|
||||
if minSize < 0 {
|
||||
return nil, fmt.Errorf("minimum size must be more than zero")
|
||||
}
|
||||
return func(h http.Handler) http.Handler {
|
||||
index := poolIndex(level)
|
||||
|
||||
@@ -176,6 +252,9 @@ func NewGzipLevelHandler(level int) (func(http.Handler) http.Handler, error) {
|
||||
gw := &GzipResponseWriter{
|
||||
ResponseWriter: w,
|
||||
index: index,
|
||||
minSize: minSize,
|
||||
|
||||
buf: []byte{},
|
||||
}
|
||||
defer gw.Close()
|
||||
|
||||
@@ -238,7 +317,7 @@ func parseEncodings(s string) (codings, error) {
|
||||
func parseCoding(s string) (coding string, qvalue float64, err error) {
|
||||
for n, part := range strings.Split(s, ";") {
|
||||
part = strings.TrimSpace(part)
|
||||
qvalue = DEFAULT_QVALUE
|
||||
qvalue = DefaultQValue
|
||||
|
||||
if n == 0 {
|
||||
coding = strings.ToLower(part)
|
||||
|
||||
43
vendor/github.com/NYTimes/gziphandler/gzip_go18.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,43 @@
|
||||
// +build go1.8
|
||||
|
||||
package gziphandler
|
||||
|
||||
import "net/http"
|
||||
|
||||
// Push initiates an HTTP/2 server push.
|
||||
// Push returns ErrNotSupported if the client has disabled push or if push
|
||||
// is not supported on the underlying connection.
|
||||
func (w *GzipResponseWriter) Push(target string, opts *http.PushOptions) error {
|
||||
pusher, ok := w.ResponseWriter.(http.Pusher)
|
||||
if ok && pusher != nil {
|
||||
return pusher.Push(target, setAcceptEncodingForPushOptions(opts))
|
||||
}
|
||||
return http.ErrNotSupported
|
||||
}
|
||||
|
||||
// setAcceptEncodingForPushOptions sets "Accept-Encoding" : "gzip" for PushOptions without overriding existing headers.
|
||||
func setAcceptEncodingForPushOptions(opts *http.PushOptions) *http.PushOptions {
|
||||
|
||||
if opts == nil {
|
||||
opts = &http.PushOptions{
|
||||
Header: http.Header{
|
||||
acceptEncoding: []string{"gzip"},
|
||||
},
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
if opts.Header == nil {
|
||||
opts.Header = http.Header{
|
||||
acceptEncoding: []string{"gzip"},
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
if encoding := opts.Header.Get(acceptEncoding); encoding == "" {
|
||||
opts.Header.Add(acceptEncoding, "gzip")
|
||||
return opts
|
||||
}
|
||||
|
||||
return opts
|
||||
}
|
||||
70
vendor/github.com/NYTimes/gziphandler/gzip_go18_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,70 @@
|
||||
// +build go1.8
|
||||
|
||||
package gziphandler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSetAcceptEncodingForPushOptionsWithoutHeaders(t *testing.T) {
|
||||
var opts *http.PushOptions
|
||||
opts = setAcceptEncodingForPushOptions(opts)
|
||||
|
||||
assert.NotNil(t, opts)
|
||||
assert.NotNil(t, opts.Header)
|
||||
|
||||
for k, v := range opts.Header {
|
||||
assert.Equal(t, "Accept-Encoding", k)
|
||||
assert.Len(t, v, 1)
|
||||
assert.Equal(t, "gzip", v[0])
|
||||
}
|
||||
|
||||
opts = &http.PushOptions{}
|
||||
opts = setAcceptEncodingForPushOptions(opts)
|
||||
|
||||
assert.NotNil(t, opts)
|
||||
assert.NotNil(t, opts.Header)
|
||||
|
||||
for k, v := range opts.Header {
|
||||
assert.Equal(t, "Accept-Encoding", k)
|
||||
assert.Len(t, v, 1)
|
||||
assert.Equal(t, "gzip", v[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetAcceptEncodingForPushOptionsWithHeaders(t *testing.T) {
|
||||
opts := &http.PushOptions{
|
||||
Header: http.Header{
|
||||
"User-Agent": []string{"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36"},
|
||||
},
|
||||
}
|
||||
opts = setAcceptEncodingForPushOptions(opts)
|
||||
|
||||
assert.NotNil(t, opts)
|
||||
assert.NotNil(t, opts.Header)
|
||||
|
||||
assert.Equal(t, "gzip", opts.Header.Get("Accept-Encoding"))
|
||||
assert.Equal(t, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36", opts.Header.Get("User-Agent"))
|
||||
|
||||
opts = &http.PushOptions{
|
||||
Header: http.Header{
|
||||
"User-Agent": []string{"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36"},
|
||||
acceptEncoding: []string{"deflate"},
|
||||
},
|
||||
}
|
||||
opts = setAcceptEncodingForPushOptions(opts)
|
||||
|
||||
assert.NotNil(t, opts)
|
||||
assert.NotNil(t, opts.Header)
|
||||
|
||||
e, found := opts.Header["Accept-Encoding"]
|
||||
if !found {
|
||||
assert.Fail(t, "Missing Accept-Encoding header value")
|
||||
}
|
||||
assert.Len(t, e, 1)
|
||||
assert.Equal(t, "deflate", e[0])
|
||||
assert.Equal(t, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36", opts.Header.Get("User-Agent"))
|
||||
}
|
||||
69
vendor/github.com/NYTimes/gziphandler/gzip_test.go
сгенерированный
поставляемый
@@ -16,8 +16,12 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestParseEncodings(t *testing.T) {
|
||||
const (
|
||||
smallTestBody = "aaabbcaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbccc"
|
||||
testBody = "aaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbcccaaabbbccc"
|
||||
)
|
||||
|
||||
func TestParseEncodings(t *testing.T) {
|
||||
examples := map[string]codings{
|
||||
|
||||
// Examples from RFC 2616
|
||||
@@ -39,8 +43,6 @@ func TestParseEncodings(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGzipHandler(t *testing.T) {
|
||||
testBody := "aaabbbccc"
|
||||
|
||||
// This just exists to provide something for GzipHandler to wrap.
|
||||
handler := newTestHandler(testBody)
|
||||
|
||||
@@ -80,7 +82,6 @@ func TestGzipHandler(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewGzipLevelHandler(t *testing.T) {
|
||||
testBody := "aaabbbccc"
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
io.WriteString(w, testBody)
|
||||
@@ -102,7 +103,6 @@ func TestNewGzipLevelHandler(t *testing.T) {
|
||||
assert.Equal(t, "gzip", res.Header.Get("Content-Encoding"))
|
||||
assert.Equal(t, "Accept-Encoding", res.Header.Get("Vary"))
|
||||
assert.Equal(t, gzipStrLevel(testBody, lvl), resp.Body.Bytes())
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ func TestGzipHandlerNoBody(t *testing.T) {
|
||||
{http.StatusNoContent, "", 0},
|
||||
{http.StatusNotModified, "", 0},
|
||||
// Body is going to get gzip'd no matter what.
|
||||
{http.StatusOK, "gzip", 23},
|
||||
{http.StatusOK, "", 0},
|
||||
}
|
||||
|
||||
for num, test := range tests {
|
||||
@@ -170,7 +170,7 @@ func TestGzipHandlerNoBody(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGzipHandlerContentLength(t *testing.T) {
|
||||
b := []byte("testtesttesttesttesttesttesttesttesttesttesttesttest")
|
||||
b := []byte(testBody)
|
||||
handler := GzipHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(b)))
|
||||
w.Write(b)
|
||||
@@ -215,6 +215,48 @@ func TestGzipHandlerContentLength(t *testing.T) {
|
||||
assert.NotEqual(t, b, body)
|
||||
}
|
||||
|
||||
func TestGzipHandlerMinSizeMustBePositive(t *testing.T) {
|
||||
_, err := NewGzipLevelAndMinSize(gzip.DefaultCompression, -1)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestGzipHandlerMinSize(t *testing.T) {
|
||||
responseLength := 0
|
||||
b := []byte{'x'}
|
||||
|
||||
wrapper, _ := NewGzipLevelAndMinSize(gzip.DefaultCompression, 128)
|
||||
handler := wrapper(http.HandlerFunc(
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
// Write responses one byte at a time to ensure that the flush
|
||||
// mechanism, if used, is working properly.
|
||||
for i := 0; i < responseLength; i++ {
|
||||
n, err := w.Write(b)
|
||||
assert.Equal(t, 1, n)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
},
|
||||
))
|
||||
|
||||
r, _ := http.NewRequest("GET", "/whatever", &bytes.Buffer{})
|
||||
r.Header.Add("Accept-Encoding", "gzip")
|
||||
|
||||
// Short response is not compressed
|
||||
responseLength = 127
|
||||
w := httptest.NewRecorder()
|
||||
handler.ServeHTTP(w, r)
|
||||
if w.Result().Header.Get(contentEncoding) == "gzip" {
|
||||
t.Error("Expected uncompressed response, got compressed")
|
||||
}
|
||||
|
||||
// Long response is not compressed
|
||||
responseLength = 128
|
||||
w = httptest.NewRecorder()
|
||||
handler.ServeHTTP(w, r)
|
||||
if w.Result().Header.Get(contentEncoding) != "gzip" {
|
||||
t.Error("Expected compressed response, got uncompressed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGzipDoubleClose(t *testing.T) {
|
||||
// reset the pool for the default compression so we can make sure duplicates
|
||||
// aren't added back by double close
|
||||
@@ -240,6 +282,19 @@ func TestGzipDoubleClose(t *testing.T) {
|
||||
assert.False(t, w1 == w2)
|
||||
}
|
||||
|
||||
func TestStatusCodes(t *testing.T) {
|
||||
handler := GzipHandler(http.NotFoundHandler())
|
||||
r := httptest.NewRequest("GET", "/", nil)
|
||||
r.Header.Set("Accept-Encoding", "gzip")
|
||||
w := httptest.NewRecorder()
|
||||
handler.ServeHTTP(w, r)
|
||||
|
||||
result := w.Result()
|
||||
if result.StatusCode != 404 {
|
||||
t.Errorf("StatusCode should have been 404 but was %d", result.StatusCode)
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
func BenchmarkGzipHandler_S2k(b *testing.B) { benchmark(b, false, 2048) }
|
||||
|
||||
0
vendor/github.com/jaytaylor/html2text/.gitignore → vendor/github.com/cpanato/html2text/.gitignore
сгенерированный
поставляемый
0
vendor/github.com/jaytaylor/html2text/.travis.yml → vendor/github.com/cpanato/html2text/.travis.yml
сгенерированный
поставляемый
0
vendor/github.com/jaytaylor/html2text/LICENSE → vendor/github.com/cpanato/html2text/LICENSE
сгенерированный
поставляемый
34
vendor/github.com/jaytaylor/html2text/README.md → vendor/github.com/cpanato/html2text/README.md
сгенерированный
поставляемый
@@ -1,8 +1,12 @@
|
||||
# html2text
|
||||
|
||||
[](https://godoc.org/github.com/jaytaylor/html2text)
|
||||
[](https://travis-ci.org/jaytaylor/html2text)
|
||||
[](https://goreportcard.com/report/github.com/jaytaylor/html2text)
|
||||
[](https://godoc.org/github.com/cpanato/html2text)
|
||||
[](https://travis-ci.org/cpanato/html2text)
|
||||
[](https://goreportcard.com/report/github.com/cpanato/html2text)
|
||||
|
||||
### Initial information
|
||||
This project was forked from [github.com/jaytaylor/html2text](https://github.com/jaytaylor/html2text) in order to use another clean bom library due the original one has no license.
|
||||
|
||||
|
||||
### Converts HTML into text
|
||||
|
||||
@@ -23,7 +27,7 @@ It requires go 1.x or newer ;)
|
||||
## Download the package
|
||||
|
||||
```bash
|
||||
go get github.com/jaytaylor/html2text
|
||||
go get github.com/cpanato/html2text
|
||||
```
|
||||
|
||||
## Example usage
|
||||
@@ -34,7 +38,7 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/jaytaylor/html2text"
|
||||
"github.com/cpanato/html2text"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -45,17 +49,17 @@ func main() {
|
||||
<link rel=\"stylesheet\" href=\"main.css\">
|
||||
<style type=\"text/css\">body { color: #fff; }</style>
|
||||
</head>
|
||||
|
||||
|
||||
<body>
|
||||
<div class="logo">
|
||||
<a href="http://mymegaservice.com/"><img src="/logo-image.jpg" alt="Mega Service"/></a>
|
||||
</div>
|
||||
|
||||
|
||||
<h1>Welcome to your new account on my service!</h1>
|
||||
|
||||
|
||||
<p>
|
||||
Here is some more information:
|
||||
|
||||
|
||||
<ul>
|
||||
<li>Link 1: <a href="https://example.com">Example.com</a></li>
|
||||
<li>Link 2: <a href="https://example2.com">Example2.com</a></li>
|
||||
@@ -102,15 +106,3 @@ go test
|
||||
# License
|
||||
|
||||
Permissive MIT license.
|
||||
|
||||
|
||||
## Contact
|
||||
|
||||
You are more than welcome to open issues and send pull requests if you find a bug or want a new feature.
|
||||
|
||||
If you appreciate this library please feel free to drop me a line and tell me! It's always nice to hear from people who have benefitted from my work.
|
||||
|
||||
Email: jay at (my github username).com
|
||||
|
||||
Twitter: [@jtaylor](https://twitter.com/jtaylor)
|
||||
|
||||
14
vendor/github.com/jaytaylor/html2text/html2text.go → vendor/github.com/cpanato/html2text/html2text.go
сгенерированный
поставляемый
@@ -3,11 +3,12 @@ package html2text
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/ssor/bom"
|
||||
"github.com/dimchansky/utfbom"
|
||||
|
||||
"golang.org/x/net/html"
|
||||
"golang.org/x/net/html/atom"
|
||||
@@ -291,10 +292,9 @@ func FromHtmlNode(doc *html.Node) (string, error) {
|
||||
}
|
||||
|
||||
func FromReader(reader io.Reader) (string, error) {
|
||||
newReader, err := bom.NewReaderWithoutBom(reader)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
bs, err := ioutil.ReadAll(reader)
|
||||
newReader, _ := utfbom.Skip(bytes.NewReader(bs))
|
||||
|
||||
doc, err := html.Parse(newReader)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -303,8 +303,8 @@ func FromReader(reader io.Reader) (string, error) {
|
||||
}
|
||||
|
||||
func FromString(input string) (string, error) {
|
||||
bs := bom.CleanBom([]byte(input))
|
||||
text, err := FromReader(bytes.NewReader(bs))
|
||||
bs := utfbom.SkipOnly(bytes.NewReader([]byte(input)))
|
||||
text, err := FromReader(bs)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
0
vendor/github.com/jaytaylor/html2text/html2text_test.go → vendor/github.com/cpanato/html2text/html2text_test.go
сгенерированный
поставляемый
0
vendor/github.com/jaytaylor/html2text/testdata/utf8.html → vendor/github.com/cpanato/html2text/testdata/utf8.html
сгенерированный
поставляемый
1
vendor/github.com/disintegration/imaging/.travis.yml
сгенерированный
поставляемый
@@ -9,6 +9,7 @@ go:
|
||||
- 1.5
|
||||
- 1.6
|
||||
- 1.7
|
||||
- 1.8
|
||||
|
||||
before_install:
|
||||
- go get golang.org/x/tools/cmd/cover
|
||||
|
||||
2
vendor/github.com/disintegration/imaging/LICENSE
сгенерированный
поставляемый
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2012-2014 Grigory Dryapak
|
||||
Copyright (c) 2012-2017 Grigory Dryapak
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
181
vendor/github.com/disintegration/imaging/README.md
сгенерированный
поставляемый
@@ -26,17 +26,18 @@ http://godoc.org/github.com/disintegration/imaging
|
||||
A few usage examples can be found below. See the documentation for the full list of supported functions.
|
||||
|
||||
### Image resizing
|
||||
|
||||
```go
|
||||
// resize srcImage to size = 128x128px using the Lanczos filter
|
||||
// Resize srcImage to size = 128x128px using the Lanczos filter.
|
||||
dstImage128 := imaging.Resize(srcImage, 128, 128, imaging.Lanczos)
|
||||
|
||||
// resize srcImage to width = 800px preserving the aspect ratio
|
||||
// Resize srcImage to width = 800px preserving the aspect ratio.
|
||||
dstImage800 := imaging.Resize(srcImage, 800, 0, imaging.Lanczos)
|
||||
|
||||
// scale down srcImage to fit the 800x600px bounding box
|
||||
// Scale down srcImage to fit the 800x600px bounding box.
|
||||
dstImageFit := imaging.Fit(srcImage, 800, 600, imaging.Lanczos)
|
||||
|
||||
// resize and crop the srcImage to fill the 100x100px area
|
||||
// Resize and crop the srcImage to fill the 100x100px area.
|
||||
dstImageFill := imaging.Fill(srcImage, 100, 100, imaging.Center, imaging.Lanczos)
|
||||
```
|
||||
|
||||
@@ -53,146 +54,138 @@ The full list of supported filters: NearestNeighbor, Box, Linear, Hermite, Mitc
|
||||
|
||||
**Resampling filters comparison**
|
||||
|
||||
Original image. Will be resized from 512x512px to 128x128px.
|
||||
The original image.
|
||||
|
||||

|
||||

|
||||
|
||||
Filter | Resize result
|
||||
---|---
|
||||
`imaging.NearestNeighbor` | 
|
||||
`imaging.Box` | 
|
||||
`imaging.Linear` | 
|
||||
`imaging.MitchellNetravali` | 
|
||||
`imaging.CatmullRom` | 
|
||||
`imaging.Gaussian` | 
|
||||
`imaging.Lanczos` | 
|
||||
The same image resized from 512x512px to 128x128px using different resampling filters.
|
||||
From faster (lower quality) to slower (higher quality):
|
||||
|
||||
**Resize functions comparison**
|
||||
Filter | Resize result
|
||||
--------------------------|---------------------------------------------
|
||||
`imaging.NearestNeighbor` | 
|
||||
`imaging.Linear` | 
|
||||
`imaging.CatmullRom` | 
|
||||
`imaging.Lanczos` | 
|
||||
|
||||
Original image:
|
||||
|
||||

|
||||
|
||||
Resize the image to width=100px and height=100px:
|
||||
|
||||
```go
|
||||
dstImage := imaging.Resize(srcImage, 100, 100, imaging.Lanczos)
|
||||
```
|
||||

|
||||
|
||||
Resize the image to width=100px preserving the aspect ratio:
|
||||
|
||||
```go
|
||||
dstImage := imaging.Resize(srcImage, 100, 0, imaging.Lanczos)
|
||||
```
|
||||

|
||||
|
||||
Resize the image to fit the 100x100px boundng box preserving the aspect ratio:
|
||||
|
||||
```go
|
||||
dstImage := imaging.Fit(srcImage, 100, 100, imaging.Lanczos)
|
||||
```
|
||||

|
||||
|
||||
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)
|
||||
```
|
||||

|
||||
|
||||
### Gaussian Blur
|
||||
|
||||
```go
|
||||
dstImage := imaging.Blur(srcImage, 0.5)
|
||||
```
|
||||
|
||||
Sigma parameter allows to control the strength of the blurring effect.
|
||||
|
||||
Original image | Sigma = 0.5 | Sigma = 1.5
|
||||
---|---|---
|
||||
 |  | 
|
||||
Original image | Sigma = 0.5 | Sigma = 1.5
|
||||
-----------------------------------|----------------------------------------|---------------------------------------
|
||||
 |  | 
|
||||
|
||||
### Sharpening
|
||||
|
||||
```go
|
||||
dstImage := imaging.Sharpen(srcImage, 0.5)
|
||||
```
|
||||
|
||||
Uses gaussian function internally. Sigma parameter allows to control the strength of the sharpening effect.
|
||||
`Sharpen` uses gaussian function internally. Sigma parameter allows to control the strength of the sharpening effect.
|
||||
|
||||
Original image | Sigma = 0.5 | Sigma = 1.5
|
||||
---|---|---
|
||||
 |  | 
|
||||
Original image | Sigma = 0.5 | Sigma = 1.5
|
||||
-----------------------------------|-------------------------------------------|------------------------------------------
|
||||
 |  | 
|
||||
|
||||
### Gamma correction
|
||||
|
||||
```go
|
||||
dstImage := imaging.AdjustGamma(srcImage, 0.75)
|
||||
```
|
||||
|
||||
Original image | Gamma = 0.75 | Gamma = 1.25
|
||||
---|---|---
|
||||
 |  | 
|
||||
Original image | Gamma = 0.75 | Gamma = 1.25
|
||||
-----------------------------------|------------------------------------------|-----------------------------------------
|
||||
 |  | 
|
||||
|
||||
### Contrast adjustment
|
||||
|
||||
```go
|
||||
dstImage := imaging.AdjustContrast(srcImage, 20)
|
||||
```
|
||||
|
||||
Original image | Contrast = 20 | Contrast = -20
|
||||
---|---|---
|
||||
 |  | 
|
||||
Original image | Contrast = 10 | Contrast = -10
|
||||
-----------------------------------|--------------------------------------------|-------------------------------------------
|
||||
 |  | 
|
||||
|
||||
### Brightness adjustment
|
||||
|
||||
```go
|
||||
dstImage := imaging.AdjustBrightness(srcImage, 20)
|
||||
```
|
||||
|
||||
Original image | Brightness = 20 | Brightness = -20
|
||||
---|---|---
|
||||
 |  | 
|
||||
Original image | Brightness = 10 | Brightness = -10
|
||||
-----------------------------------|----------------------------------------------|---------------------------------------------
|
||||
 |  | 
|
||||
|
||||
|
||||
### Complete code example
|
||||
Here is the code example that loads several images, makes thumbnails of them
|
||||
and combines them together side-by-side.
|
||||
## Example code
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
|
||||
"github.com/disintegration/imaging"
|
||||
"image"
|
||||
"image/color"
|
||||
"log"
|
||||
|
||||
"github.com/disintegration/imaging"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Open the test image.
|
||||
src, err := imaging.Open("testdata/lena_512.png")
|
||||
if err != nil {
|
||||
log.Fatalf("Open failed: %v", err)
|
||||
}
|
||||
|
||||
// input files
|
||||
files := []string{"01.jpg", "02.jpg", "03.jpg"}
|
||||
// Crop the original image to 350x350px size using the center anchor.
|
||||
src = imaging.CropAnchor(src, 350, 350, imaging.Center)
|
||||
|
||||
// load images and make 100x100 thumbnails of them
|
||||
var thumbnails []image.Image
|
||||
for _, file := range files {
|
||||
img, err := imaging.Open(file)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
thumb := imaging.Thumbnail(img, 100, 100, imaging.CatmullRom)
|
||||
thumbnails = append(thumbnails, thumb)
|
||||
}
|
||||
// Resize the cropped image to width = 256px preserving the aspect ratio.
|
||||
src = imaging.Resize(src, 256, 0, imaging.Lanczos)
|
||||
|
||||
// create a new blank image
|
||||
dst := imaging.New(100*len(thumbnails), 100, color.NRGBA{0, 0, 0, 0})
|
||||
// Create a blurred version of the image.
|
||||
img1 := imaging.Blur(src, 2)
|
||||
|
||||
// paste thumbnails into the new image side by side
|
||||
for i, thumb := range thumbnails {
|
||||
dst = imaging.Paste(dst, thumb, image.Pt(i*100, 0))
|
||||
}
|
||||
// Create a grayscale version of the image with higher contrast and sharpness.
|
||||
img2 := imaging.Grayscale(src)
|
||||
img2 = imaging.AdjustContrast(img2, 20)
|
||||
img2 = imaging.Sharpen(img2, 2)
|
||||
|
||||
// save the combined image to file
|
||||
err := imaging.Save(dst, "dst.jpg")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// Create an inverted version of the image.
|
||||
img3 := imaging.Invert(src)
|
||||
|
||||
// Create an embossed version of the image using a convolution filter.
|
||||
img4 := imaging.Convolve3x3(
|
||||
src,
|
||||
[9]float64{
|
||||
-1, -1, 0,
|
||||
-1, 1, 1,
|
||||
0, 1, 1,
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
// Create a new image and paste the four produced images into it.
|
||||
dst := imaging.New(512, 512, color.NRGBA{0, 0, 0, 0})
|
||||
dst = imaging.Paste(dst, img1, image.Pt(0, 0))
|
||||
dst = imaging.Paste(dst, img2, image.Pt(0, 256))
|
||||
dst = imaging.Paste(dst, img3, image.Pt(256, 0))
|
||||
dst = imaging.Paste(dst, img4, image.Pt(256, 256))
|
||||
|
||||
// Save the resulting image using JPEG format.
|
||||
err = imaging.Save(dst, "testdata/out_example.jpg")
|
||||
if err != nil {
|
||||
log.Fatalf("Save failed: %v", err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||

|
||||
60
vendor/github.com/disintegration/imaging/adjust_test.go
сгенерированный
поставляемый
@@ -206,6 +206,26 @@ func TestAdjustContrast(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAdjustContrastGolden(t *testing.T) {
|
||||
src, err := Open("testdata/lena_128.png")
|
||||
if err != nil {
|
||||
t.Errorf("Open: %v", err)
|
||||
}
|
||||
for name, p := range map[string]float64{
|
||||
"out_contrast_m10.png": -10,
|
||||
"out_contrast_p10.png": 10,
|
||||
} {
|
||||
got := AdjustContrast(src, p)
|
||||
want, err := Open("testdata/" + name)
|
||||
if err != nil {
|
||||
t.Errorf("Open: %v", err)
|
||||
}
|
||||
if !compareNRGBA(got, toNRGBA(want), 0) {
|
||||
t.Errorf("resulting image differs from golden: %s", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAdjustBrightness(t *testing.T) {
|
||||
td := []struct {
|
||||
desc string
|
||||
@@ -333,6 +353,26 @@ func TestAdjustBrightness(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAdjustBrightnessGolden(t *testing.T) {
|
||||
src, err := Open("testdata/lena_128.png")
|
||||
if err != nil {
|
||||
t.Errorf("Open: %v", err)
|
||||
}
|
||||
for name, p := range map[string]float64{
|
||||
"out_brightness_m10.png": -10,
|
||||
"out_brightness_p10.png": 10,
|
||||
} {
|
||||
got := AdjustBrightness(src, p)
|
||||
want, err := Open("testdata/" + name)
|
||||
if err != nil {
|
||||
t.Errorf("Open: %v", err)
|
||||
}
|
||||
if !compareNRGBA(got, toNRGBA(want), 0) {
|
||||
t.Errorf("resulting image differs from golden: %s", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAdjustGamma(t *testing.T) {
|
||||
td := []struct {
|
||||
desc string
|
||||
@@ -416,6 +456,26 @@ func TestAdjustGamma(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAdjustGammaGolden(t *testing.T) {
|
||||
src, err := Open("testdata/lena_128.png")
|
||||
if err != nil {
|
||||
t.Errorf("Open: %v", err)
|
||||
}
|
||||
for name, g := range map[string]float64{
|
||||
"out_gamma_0.75.png": 0.75,
|
||||
"out_gamma_1.25.png": 1.25,
|
||||
} {
|
||||
got := AdjustGamma(src, g)
|
||||
want, err := Open("testdata/" + name)
|
||||
if err != nil {
|
||||
t.Errorf("Open: %v", err)
|
||||
}
|
||||
if !compareNRGBA(got, toNRGBA(want), 0) {
|
||||
t.Errorf("resulting image differs from golden: %s", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAdjustSigmoid(t *testing.T) {
|
||||
td := []struct {
|
||||
desc string
|
||||
|
||||
148
vendor/github.com/disintegration/imaging/convolution.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,148 @@
|
||||
package imaging
|
||||
|
||||
import (
|
||||
"image"
|
||||
)
|
||||
|
||||
// ConvolveOptions are convolution parameters.
|
||||
type ConvolveOptions struct {
|
||||
// If Normalize is true the kernel is normalized before convolution.
|
||||
Normalize bool
|
||||
|
||||
// If Abs is true the absolute value of each color channel is taken after convolution.
|
||||
Abs bool
|
||||
|
||||
// Bias is added to each color channel value after convolution.
|
||||
Bias int
|
||||
}
|
||||
|
||||
// Convolve3x3 convolves the image with the specified 3x3 convolution kernel.
|
||||
// Default parameters are used if a nil *ConvolveOptions is passed.
|
||||
func Convolve3x3(img image.Image, kernel [9]float64, options *ConvolveOptions) *image.NRGBA {
|
||||
return convolve(img, kernel[:], options)
|
||||
}
|
||||
|
||||
// Convolve5x5 convolves the image with the specified 5x5 convolution kernel.
|
||||
// Default parameters are used if a nil *ConvolveOptions is passed.
|
||||
func Convolve5x5(img image.Image, kernel [25]float64, options *ConvolveOptions) *image.NRGBA {
|
||||
return convolve(img, kernel[:], options)
|
||||
}
|
||||
|
||||
func convolve(img image.Image, kernel []float64, options *ConvolveOptions) *image.NRGBA {
|
||||
src := toNRGBA(img)
|
||||
w := src.Bounds().Max.X
|
||||
h := src.Bounds().Max.Y
|
||||
dst := image.NewNRGBA(image.Rect(0, 0, w, h))
|
||||
|
||||
if w < 1 || h < 1 {
|
||||
return dst
|
||||
}
|
||||
|
||||
if options == nil {
|
||||
options = &ConvolveOptions{}
|
||||
}
|
||||
|
||||
if options.Normalize {
|
||||
normalizeKernel(kernel)
|
||||
}
|
||||
|
||||
type coef struct {
|
||||
x, y int
|
||||
k float64
|
||||
}
|
||||
var coefs []coef
|
||||
var m int
|
||||
|
||||
switch len(kernel) {
|
||||
case 9:
|
||||
m = 1
|
||||
case 25:
|
||||
m = 2
|
||||
default:
|
||||
return dst
|
||||
}
|
||||
|
||||
i := 0
|
||||
for y := -m; y <= m; y++ {
|
||||
for x := -m; x <= m; x++ {
|
||||
if kernel[i] != 0 {
|
||||
coefs = append(coefs, coef{x: x, y: y, k: kernel[i]})
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
parallel(h, func(partStart, partEnd int) {
|
||||
for y := partStart; y < partEnd; y++ {
|
||||
for x := 0; x < w; x++ {
|
||||
var r, g, b float64
|
||||
for _, c := range coefs {
|
||||
ix := x + c.x
|
||||
if ix < 0 {
|
||||
ix = 0
|
||||
} else if ix >= w {
|
||||
ix = w - 1
|
||||
}
|
||||
|
||||
iy := y + c.y
|
||||
if iy < 0 {
|
||||
iy = 0
|
||||
} else if iy >= h {
|
||||
iy = h - 1
|
||||
}
|
||||
|
||||
off := iy*src.Stride + ix*4
|
||||
r += float64(src.Pix[off+0]) * c.k
|
||||
g += float64(src.Pix[off+1]) * c.k
|
||||
b += float64(src.Pix[off+2]) * c.k
|
||||
}
|
||||
|
||||
if options.Abs {
|
||||
if r < 0 {
|
||||
r = -r
|
||||
}
|
||||
if g < 0 {
|
||||
g = -g
|
||||
}
|
||||
if b < 0 {
|
||||
b = -b
|
||||
}
|
||||
}
|
||||
|
||||
if options.Bias != 0 {
|
||||
r += float64(options.Bias)
|
||||
g += float64(options.Bias)
|
||||
b += float64(options.Bias)
|
||||
}
|
||||
|
||||
srcOff := y*src.Stride + x*4
|
||||
dstOff := y*dst.Stride + x*4
|
||||
dst.Pix[dstOff+0] = clamp(r)
|
||||
dst.Pix[dstOff+1] = clamp(g)
|
||||
dst.Pix[dstOff+2] = clamp(b)
|
||||
dst.Pix[dstOff+3] = src.Pix[srcOff+3]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
func normalizeKernel(kernel []float64) {
|
||||
var sum, sumpos float64
|
||||
for i := range kernel {
|
||||
sum += kernel[i]
|
||||
if kernel[i] > 0 {
|
||||
sumpos += kernel[i]
|
||||
}
|
||||
}
|
||||
if sum != 0 {
|
||||
for i := range kernel {
|
||||
kernel[i] /= sum
|
||||
}
|
||||
} else if sumpos != 0 {
|
||||
for i := range kernel {
|
||||
kernel[i] /= sumpos
|
||||
}
|
||||
}
|
||||
}
|
||||
275
vendor/github.com/disintegration/imaging/convolution_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,275 @@
|
||||
package imaging
|
||||
|
||||
import (
|
||||
"image"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestConvolve3x3(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
src image.Image
|
||||
kernel [9]float64
|
||||
options *ConvolveOptions
|
||||
want *image.NRGBA
|
||||
}{
|
||||
{
|
||||
"Convolve3x3 0x0",
|
||||
&image.NRGBA{
|
||||
Rect: image.Rect(0, 0, 0, 0),
|
||||
Stride: 0,
|
||||
Pix: []uint8{},
|
||||
},
|
||||
[9]float64{
|
||||
0, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 0,
|
||||
},
|
||||
nil,
|
||||
&image.NRGBA{Rect: image.Rect(0, 0, 0, 0)},
|
||||
},
|
||||
{
|
||||
"Convolve3x3 4x4 identity",
|
||||
&image.NRGBA{
|
||||
Rect: image.Rect(-1, -1, 3, 3),
|
||||
Stride: 4 * 4,
|
||||
Pix: []uint8{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
},
|
||||
},
|
||||
[9]float64{
|
||||
0, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 0,
|
||||
},
|
||||
nil,
|
||||
&image.NRGBA{
|
||||
Rect: image.Rect(0, 0, 4, 4),
|
||||
Stride: 4 * 4,
|
||||
Pix: []uint8{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"Convolve3x3 4x4 abs",
|
||||
&image.NRGBA{
|
||||
Rect: image.Rect(-1, -1, 3, 3),
|
||||
Stride: 4 * 4,
|
||||
Pix: []uint8{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
},
|
||||
},
|
||||
[9]float64{
|
||||
0, 0, 0,
|
||||
0, -1, 0,
|
||||
0, 0, 0,
|
||||
},
|
||||
&ConvolveOptions{Abs: true},
|
||||
&image.NRGBA{
|
||||
Rect: image.Rect(0, 0, 4, 4),
|
||||
Stride: 4 * 4,
|
||||
Pix: []uint8{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"Convolve3x3 4x4 bias",
|
||||
&image.NRGBA{
|
||||
Rect: image.Rect(-1, -1, 3, 3),
|
||||
Stride: 4 * 4,
|
||||
Pix: []uint8{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
},
|
||||
},
|
||||
[9]float64{
|
||||
0, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 0,
|
||||
},
|
||||
&ConvolveOptions{Bias: 0x10},
|
||||
&image.NRGBA{
|
||||
Rect: image.Rect(0, 0, 4, 4),
|
||||
Stride: 4 * 4,
|
||||
Pix: []uint8{
|
||||
0x10, 0x11, 0x12, 0x03, 0x14, 0x15, 0x16, 0x07, 0x18, 0x19, 0x1a, 0x0b, 0x1c, 0x1d, 0x1e, 0x0f,
|
||||
0x20, 0x21, 0x22, 0x13, 0x24, 0x25, 0x26, 0x17, 0x28, 0x29, 0x2a, 0x1b, 0x2c, 0x2d, 0x2e, 0x1f,
|
||||
0x30, 0x31, 0x32, 0x23, 0x34, 0x35, 0x36, 0x27, 0x38, 0x39, 0x3a, 0x2b, 0x3c, 0x3d, 0x3e, 0x2f,
|
||||
0x40, 0x41, 0x42, 0x33, 0x44, 0x45, 0x46, 0x37, 0x48, 0x49, 0x4a, 0x3b, 0x4c, 0x4d, 0x4e, 0x3f,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"Convolve3x3 4x4 norm",
|
||||
&image.NRGBA{
|
||||
Rect: image.Rect(-1, -1, 3, 3),
|
||||
Stride: 4 * 4,
|
||||
Pix: []uint8{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
},
|
||||
},
|
||||
[9]float64{
|
||||
1, 1, 1,
|
||||
1, 1, 1,
|
||||
1, 1, 1,
|
||||
},
|
||||
&ConvolveOptions{Normalize: true},
|
||||
&image.NRGBA{
|
||||
Rect: image.Rect(0, 0, 4, 4),
|
||||
Stride: 4 * 4,
|
||||
Pix: []uint8{
|
||||
0x07, 0x08, 0x09, 0x03, 0x09, 0x0a, 0x0b, 0x07, 0x0d, 0x0e, 0x0f, 0x0b, 0x10, 0x11, 0x12, 0x0f,
|
||||
0x11, 0x12, 0x13, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1b, 0x1c, 0x1d, 0x1f,
|
||||
0x21, 0x22, 0x23, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2b, 0x2c, 0x2d, 0x2f,
|
||||
0x2c, 0x2d, 0x2e, 0x33, 0x2f, 0x30, 0x31, 0x37, 0x33, 0x34, 0x35, 0x3b, 0x35, 0x36, 0x37, 0x3f,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"Convolve3x3 3x3 laplacian",
|
||||
&image.NRGBA{
|
||||
Rect: image.Rect(-1, -1, 2, 2),
|
||||
Stride: 3 * 4,
|
||||
Pix: []uint8{
|
||||
0x00, 0x01, 0x01, 0xff, 0x00, 0x01, 0x02, 0xff, 0x00, 0x01, 0x03, 0xff,
|
||||
0x00, 0x01, 0x04, 0xff, 0x10, 0x10, 0x10, 0xff, 0x00, 0x01, 0x05, 0xff,
|
||||
0x00, 0x01, 0x06, 0xff, 0x00, 0x01, 0x07, 0xff, 0x00, 0x01, 0x08, 0xff,
|
||||
},
|
||||
},
|
||||
[9]float64{
|
||||
-1, -1, -1,
|
||||
-1, 8, -1,
|
||||
-1, -1, -1,
|
||||
},
|
||||
nil,
|
||||
&image.NRGBA{
|
||||
Rect: image.Rect(0, 0, 3, 3),
|
||||
Stride: 3 * 4,
|
||||
Pix: []uint8{
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x80, 0x78, 0x5c, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
got := Convolve3x3(tc.src, tc.kernel, tc.options)
|
||||
want := tc.want
|
||||
if !compareNRGBA(got, want, 0) {
|
||||
t.Errorf("test [%s] failed: want %#v got %#v", tc.desc, want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvolve5x5(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
src image.Image
|
||||
kernel [25]float64
|
||||
options *ConvolveOptions
|
||||
want *image.NRGBA
|
||||
}{
|
||||
{
|
||||
"Convolve5x5 4x4 translate",
|
||||
&image.NRGBA{
|
||||
Rect: image.Rect(-1, -1, 3, 3),
|
||||
Stride: 4 * 4,
|
||||
Pix: []uint8{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
},
|
||||
},
|
||||
[25]float64{
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1,
|
||||
},
|
||||
nil,
|
||||
&image.NRGBA{
|
||||
Rect: image.Rect(0, 0, 4, 4),
|
||||
Stride: 4 * 4,
|
||||
Pix: []uint8{
|
||||
0x28, 0x29, 0x2a, 0x03, 0x2c, 0x2d, 0x2e, 0x07, 0x2c, 0x2d, 0x2e, 0x0b, 0x2c, 0x2d, 0x2e, 0x0f,
|
||||
0x38, 0x39, 0x3a, 0x13, 0x3c, 0x3d, 0x3e, 0x17, 0x3c, 0x3d, 0x3e, 0x1b, 0x3c, 0x3d, 0x3e, 0x1f,
|
||||
0x38, 0x39, 0x3a, 0x23, 0x3c, 0x3d, 0x3e, 0x27, 0x3c, 0x3d, 0x3e, 0x2b, 0x3c, 0x3d, 0x3e, 0x2f,
|
||||
0x38, 0x39, 0x3a, 0x33, 0x3c, 0x3d, 0x3e, 0x37, 0x3c, 0x3d, 0x3e, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
got := Convolve5x5(tc.src, tc.kernel, tc.options)
|
||||
want := tc.want
|
||||
if !compareNRGBA(got, want, 0) {
|
||||
t.Errorf("test [%s] failed: want %#v got %#v", tc.desc, want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkConvolve3x3(b *testing.B) {
|
||||
b.StopTimer()
|
||||
img, err := Open("testdata/lena_512.png")
|
||||
if err != nil {
|
||||
b.Fatalf("Open: %v", err)
|
||||
}
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
Convolve3x3(
|
||||
img,
|
||||
[9]float64{
|
||||
-1, -1, 0,
|
||||
-1, 0, 1,
|
||||
0, 1, 1,
|
||||
},
|
||||
nil,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkConvolve5x5(b *testing.B) {
|
||||
b.StopTimer()
|
||||
img, err := Open("testdata/lena_512.png")
|
||||
if err != nil {
|
||||
b.Fatalf("Open: %v", err)
|
||||
}
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
Convolve5x5(
|
||||
img,
|
||||
[25]float64{
|
||||
-1, -1, -1, -1, 0,
|
||||
-1, -1, -1, 0, 1,
|
||||
-1, -1, 0, 1, 1,
|
||||
-1, 0, 1, 1, 1,
|
||||
0, 1, 1, 1, 1,
|
||||
},
|
||||
nil,
|
||||
)
|
||||
}
|
||||
}
|
||||
36
vendor/github.com/disintegration/imaging/effects.go
сгенерированный
поставляемый
@@ -62,8 +62,7 @@ func blurHorizontal(src *image.NRGBA, kernel []float64) *image.NRGBA {
|
||||
}
|
||||
|
||||
for y := 0; y < height; y++ {
|
||||
|
||||
r, g, b, a := 0.0, 0.0, 0.0, 0.0
|
||||
var r, g, b, a float64
|
||||
for ix := start; ix <= end; ix++ {
|
||||
weight := kernel[absint(x-ix)]
|
||||
i := y*src.Stride + ix*4
|
||||
@@ -74,17 +73,11 @@ func blurHorizontal(src *image.NRGBA, kernel []float64) *image.NRGBA {
|
||||
a += wa
|
||||
}
|
||||
|
||||
r = math.Min(math.Max(r/a, 0.0), 255.0)
|
||||
g = math.Min(math.Max(g/a, 0.0), 255.0)
|
||||
b = math.Min(math.Max(b/a, 0.0), 255.0)
|
||||
a = math.Min(math.Max(a/weightSum, 0.0), 255.0)
|
||||
|
||||
j := y*dst.Stride + x*4
|
||||
dst.Pix[j+0] = uint8(r + 0.5)
|
||||
dst.Pix[j+1] = uint8(g + 0.5)
|
||||
dst.Pix[j+2] = uint8(b + 0.5)
|
||||
dst.Pix[j+3] = uint8(a + 0.5)
|
||||
|
||||
dst.Pix[j+0] = clamp(r / a)
|
||||
dst.Pix[j+1] = clamp(g / a)
|
||||
dst.Pix[j+2] = clamp(b / a)
|
||||
dst.Pix[j+3] = clamp(a / weightSum)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -117,8 +110,7 @@ func blurVertical(src *image.NRGBA, kernel []float64) *image.NRGBA {
|
||||
}
|
||||
|
||||
for x := 0; x < width; x++ {
|
||||
|
||||
r, g, b, a := 0.0, 0.0, 0.0, 0.0
|
||||
var r, g, b, a float64
|
||||
for iy := start; iy <= end; iy++ {
|
||||
weight := kernel[absint(y-iy)]
|
||||
i := iy*src.Stride + x*4
|
||||
@@ -129,17 +121,11 @@ func blurVertical(src *image.NRGBA, kernel []float64) *image.NRGBA {
|
||||
a += wa
|
||||
}
|
||||
|
||||
r = math.Min(math.Max(r/a, 0.0), 255.0)
|
||||
g = math.Min(math.Max(g/a, 0.0), 255.0)
|
||||
b = math.Min(math.Max(b/a, 0.0), 255.0)
|
||||
a = math.Min(math.Max(a/weightSum, 0.0), 255.0)
|
||||
|
||||
j := y*dst.Stride + x*4
|
||||
dst.Pix[j+0] = uint8(r + 0.5)
|
||||
dst.Pix[j+1] = uint8(g + 0.5)
|
||||
dst.Pix[j+2] = uint8(b + 0.5)
|
||||
dst.Pix[j+3] = uint8(a + 0.5)
|
||||
|
||||
dst.Pix[j+0] = clamp(r / a)
|
||||
dst.Pix[j+1] = clamp(g / a)
|
||||
dst.Pix[j+2] = clamp(b / a)
|
||||
dst.Pix[j+3] = clamp(a / weightSum)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -173,7 +159,7 @@ func Sharpen(img image.Image, sigma float64) *image.NRGBA {
|
||||
i := y*src.Stride + x*4
|
||||
for j := 0; j < 4; j++ {
|
||||
k := i + j
|
||||
val := int(src.Pix[k]) + (int(src.Pix[k]) - int(blurred.Pix[k]))
|
||||
val := int(src.Pix[k])<<1 - int(blurred.Pix[k])
|
||||
if val < 0 {
|
||||
val = 0
|
||||
} else if val > 255 {
|
||||
|
||||
64
vendor/github.com/disintegration/imaging/effects_test.go
сгенерированный
поставляемый
@@ -88,6 +88,38 @@ func TestBlur(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlurGolden(t *testing.T) {
|
||||
src, err := Open("testdata/lena_128.png")
|
||||
if err != nil {
|
||||
t.Errorf("Open: %v", err)
|
||||
}
|
||||
for name, sigma := range map[string]float64{
|
||||
"out_blur_0.5.png": 0.5,
|
||||
"out_blur_1.5.png": 1.5,
|
||||
} {
|
||||
got := Blur(src, sigma)
|
||||
want, err := Open("testdata/" + name)
|
||||
if err != nil {
|
||||
t.Errorf("Open: %v", err)
|
||||
}
|
||||
if !compareNRGBA(got, toNRGBA(want), 0) {
|
||||
t.Errorf("resulting image differs from golden: %s", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkBlur(b *testing.B) {
|
||||
b.StopTimer()
|
||||
img, err := Open("testdata/lena_512.png")
|
||||
if err != nil {
|
||||
b.Fatalf("Open: %v", err)
|
||||
}
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
Blur(img, 3)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSharpen(t *testing.T) {
|
||||
td := []struct {
|
||||
desc string
|
||||
@@ -188,3 +220,35 @@ func TestSharpen(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSharpenGolden(t *testing.T) {
|
||||
src, err := Open("testdata/lena_128.png")
|
||||
if err != nil {
|
||||
t.Errorf("Open: %v", err)
|
||||
}
|
||||
for name, sigma := range map[string]float64{
|
||||
"out_sharpen_0.5.png": 0.5,
|
||||
"out_sharpen_1.5.png": 1.5,
|
||||
} {
|
||||
got := Sharpen(src, sigma)
|
||||
want, err := Open("testdata/" + name)
|
||||
if err != nil {
|
||||
t.Errorf("Open: %v", err)
|
||||
}
|
||||
if !compareNRGBA(got, toNRGBA(want), 0) {
|
||||
t.Errorf("resulting image differs from golden: %s", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSharpen(b *testing.B) {
|
||||
b.StopTimer()
|
||||
img, err := Open("testdata/lena_512.png")
|
||||
if err != nil {
|
||||
b.Fatalf("Open: %v", err)
|
||||
}
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
Sharpen(img, 3)
|
||||
}
|
||||
}
|
||||
|
||||
58
vendor/github.com/disintegration/imaging/example_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,58 @@
|
||||
package imaging_test
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"log"
|
||||
|
||||
"github.com/disintegration/imaging"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
// Open the test image.
|
||||
src, err := imaging.Open("testdata/lena_512.png")
|
||||
if err != nil {
|
||||
log.Fatalf("Open failed: %v", err)
|
||||
}
|
||||
|
||||
// Crop the original image to 350x350px size using the center anchor.
|
||||
src = imaging.CropAnchor(src, 350, 350, imaging.Center)
|
||||
|
||||
// Resize the cropped image to width = 256px preserving the aspect ratio.
|
||||
src = imaging.Resize(src, 256, 0, imaging.Lanczos)
|
||||
|
||||
// Create a blurred version of the image.
|
||||
img1 := imaging.Blur(src, 2)
|
||||
|
||||
// Create a grayscale version of the image with higher contrast and sharpness.
|
||||
img2 := imaging.Grayscale(src)
|
||||
img2 = imaging.AdjustContrast(img2, 20)
|
||||
img2 = imaging.Sharpen(img2, 2)
|
||||
|
||||
// Create an inverted version of the image.
|
||||
img3 := imaging.Invert(src)
|
||||
|
||||
// Create an embossed version of the image using a convolution filter.
|
||||
img4 := imaging.Convolve3x3(
|
||||
src,
|
||||
[9]float64{
|
||||
-1, -1, 0,
|
||||
-1, 1, 1,
|
||||
0, 1, 1,
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
// Create a new image and paste the four produced images into it.
|
||||
dst := imaging.New(512, 512, color.NRGBA{0, 0, 0, 0})
|
||||
dst = imaging.Paste(dst, img1, image.Pt(0, 0))
|
||||
dst = imaging.Paste(dst, img2, image.Pt(0, 256))
|
||||
dst = imaging.Paste(dst, img3, image.Pt(256, 0))
|
||||
dst = imaging.Paste(dst, img4, image.Pt(256, 256))
|
||||
|
||||
// Save the resulting image using JPEG format.
|
||||
err = imaging.Save(dst, "testdata/out_example.jpg")
|
||||
if err != nil {
|
||||
log.Fatalf("Save failed: %v", err)
|
||||
}
|
||||
}
|
||||
44
vendor/github.com/disintegration/imaging/helpers.go
сгенерированный
поставляемый
@@ -1,11 +1,9 @@
|
||||
/*
|
||||
Package imaging provides basic image manipulation functions (resize, rotate, flip, crop, etc.).
|
||||
This package is based on the standard Go image package and works best along with it.
|
||||
|
||||
Image manipulation functions provided by the package take any image type
|
||||
that implements `image.Image` interface as an input, and return a new image of
|
||||
`*image.NRGBA` type (32bit RGBA colors, not premultiplied by alpha).
|
||||
*/
|
||||
// Package imaging provides basic image manipulation functions (resize, rotate, flip, crop, etc.).
|
||||
// This package is based on the standard Go image package and works best along with it.
|
||||
//
|
||||
// Image manipulation functions provided by the package take any image type
|
||||
// that implements `image.Image` interface as an input, and return a new image of
|
||||
// `*image.NRGBA` type (32bit RGBA colors, not premultiplied by alpha).
|
||||
package imaging
|
||||
|
||||
import (
|
||||
@@ -24,8 +22,10 @@ import (
|
||||
"golang.org/x/image/tiff"
|
||||
)
|
||||
|
||||
// Format is an image file format.
|
||||
type Format int
|
||||
|
||||
// Image file formats.
|
||||
const (
|
||||
JPEG Format = iota
|
||||
PNG
|
||||
@@ -52,6 +52,7 @@ func (f Format) String() string {
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrUnsupportedFormat means the given image format (or file extension) is unsupported.
|
||||
ErrUnsupportedFormat = errors.New("imaging: unsupported image format")
|
||||
)
|
||||
|
||||
@@ -194,15 +195,12 @@ func Clone(img image.Image) *image.NRGBA {
|
||||
di := dst.PixOffset(0, dstY)
|
||||
si := src.PixOffset(srcMinX, srcMinY+dstY)
|
||||
for dstX := 0; dstX < dstW; dstX++ {
|
||||
|
||||
dst.Pix[di+0] = src.Pix[si+0]
|
||||
dst.Pix[di+1] = src.Pix[si+2]
|
||||
dst.Pix[di+2] = src.Pix[si+4]
|
||||
dst.Pix[di+3] = src.Pix[si+6]
|
||||
|
||||
di += 4
|
||||
si += 8
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -213,9 +211,9 @@ func Clone(img image.Image) *image.NRGBA {
|
||||
di := dst.PixOffset(0, dstY)
|
||||
si := src.PixOffset(srcMinX, srcMinY+dstY)
|
||||
for dstX := 0; dstX < dstW; dstX++ {
|
||||
|
||||
a := src.Pix[si+3]
|
||||
dst.Pix[di+3] = a
|
||||
|
||||
switch a {
|
||||
case 0:
|
||||
dst.Pix[di+0] = 0
|
||||
@@ -237,7 +235,6 @@ func Clone(img image.Image) *image.NRGBA {
|
||||
|
||||
di += 4
|
||||
si += 4
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -248,9 +245,9 @@ func Clone(img image.Image) *image.NRGBA {
|
||||
di := dst.PixOffset(0, dstY)
|
||||
si := src.PixOffset(srcMinX, srcMinY+dstY)
|
||||
for dstX := 0; dstX < dstW; dstX++ {
|
||||
|
||||
a := src.Pix[si+6]
|
||||
dst.Pix[di+3] = a
|
||||
|
||||
switch a {
|
||||
case 0:
|
||||
dst.Pix[di+0] = 0
|
||||
@@ -272,7 +269,6 @@ func Clone(img image.Image) *image.NRGBA {
|
||||
|
||||
di += 4
|
||||
si += 8
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -283,16 +279,13 @@ func Clone(img image.Image) *image.NRGBA {
|
||||
di := dst.PixOffset(0, dstY)
|
||||
si := src.PixOffset(srcMinX, srcMinY+dstY)
|
||||
for dstX := 0; dstX < dstW; dstX++ {
|
||||
|
||||
c := src.Pix[si]
|
||||
dst.Pix[di+0] = c
|
||||
dst.Pix[di+1] = c
|
||||
dst.Pix[di+2] = c
|
||||
dst.Pix[di+3] = 0xff
|
||||
|
||||
di += 4
|
||||
si += 1
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -303,16 +296,13 @@ func Clone(img image.Image) *image.NRGBA {
|
||||
di := dst.PixOffset(0, dstY)
|
||||
si := src.PixOffset(srcMinX, srcMinY+dstY)
|
||||
for dstX := 0; dstX < dstW; dstX++ {
|
||||
|
||||
c := src.Pix[si]
|
||||
dst.Pix[di+0] = c
|
||||
dst.Pix[di+1] = c
|
||||
dst.Pix[di+2] = c
|
||||
dst.Pix[di+3] = 0xff
|
||||
|
||||
di += 4
|
||||
si += 2
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -322,7 +312,6 @@ func Clone(img image.Image) *image.NRGBA {
|
||||
for dstY := partStart; dstY < partEnd; dstY++ {
|
||||
di := dst.PixOffset(0, dstY)
|
||||
for dstX := 0; dstX < dstW; dstX++ {
|
||||
|
||||
srcX := srcMinX + dstX
|
||||
srcY := srcMinY + dstY
|
||||
siy := src.YOffset(srcX, srcY)
|
||||
@@ -332,9 +321,7 @@ func Clone(img image.Image) *image.NRGBA {
|
||||
dst.Pix[di+1] = g
|
||||
dst.Pix[di+2] = b
|
||||
dst.Pix[di+3] = 0xff
|
||||
|
||||
di += 4
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -345,22 +332,18 @@ func Clone(img image.Image) *image.NRGBA {
|
||||
for i := 0; i < plen; i++ {
|
||||
pnew[i] = color.NRGBAModel.Convert(src.Palette[i]).(color.NRGBA)
|
||||
}
|
||||
|
||||
parallel(dstH, func(partStart, partEnd int) {
|
||||
for dstY := partStart; dstY < partEnd; dstY++ {
|
||||
di := dst.PixOffset(0, dstY)
|
||||
si := src.PixOffset(srcMinX, srcMinY+dstY)
|
||||
for dstX := 0; dstX < dstW; dstX++ {
|
||||
|
||||
c := pnew[src.Pix[si]]
|
||||
dst.Pix[di+0] = c.R
|
||||
dst.Pix[di+1] = c.G
|
||||
dst.Pix[di+2] = c.B
|
||||
dst.Pix[di+3] = c.A
|
||||
|
||||
di += 4
|
||||
si += 1
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -370,15 +353,12 @@ func Clone(img image.Image) *image.NRGBA {
|
||||
for dstY := partStart; dstY < partEnd; dstY++ {
|
||||
di := dst.PixOffset(0, dstY)
|
||||
for dstX := 0; dstX < dstW; dstX++ {
|
||||
|
||||
c := color.NRGBAModel.Convert(img.At(srcMinX+dstX, srcMinY+dstY)).(color.NRGBA)
|
||||
dst.Pix[di+0] = c.R
|
||||
dst.Pix[di+1] = c.G
|
||||
dst.Pix[di+2] = c.B
|
||||
dst.Pix[di+3] = c.A
|
||||
|
||||
di += 4
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -388,7 +368,7 @@ func Clone(img image.Image) *image.NRGBA {
|
||||
return dst
|
||||
}
|
||||
|
||||
// This function used internally to convert any image type to NRGBA if needed.
|
||||
// toNRGBA converts any image type to *image.NRGBA with min-point at (0, 0).
|
||||
func toNRGBA(img image.Image) *image.NRGBA {
|
||||
srcBounds := img.Bounds()
|
||||
if srcBounds.Min.X == 0 && srcBounds.Min.Y == 0 {
|
||||
|
||||
2
vendor/github.com/disintegration/imaging/histogram.go
сгенерированный
поставляемый
@@ -17,7 +17,7 @@ func Histogram(img image.Image) [256]float64 {
|
||||
var total float64
|
||||
|
||||
if width == 0 || height == 0 {
|
||||
return histogram
|
||||
return histogram
|
||||
}
|
||||
|
||||
for y := 0; y < height; y++ {
|
||||
|
||||
2
vendor/github.com/disintegration/imaging/histogram_test.go
сгенерированный
поставляемый
@@ -36,7 +36,7 @@ func TestHistogram(t *testing.T) {
|
||||
for _, val := range h {
|
||||
if val != 0 {
|
||||
t.Errorf("Histogram for an empty image should be a zero histogram.")
|
||||
return
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
132
vendor/github.com/disintegration/imaging/resize.go
сгенерированный
поставляемый
@@ -5,17 +5,12 @@ import (
|
||||
"math"
|
||||
)
|
||||
|
||||
type iwpair struct {
|
||||
i int
|
||||
w int32
|
||||
type indexWeight struct {
|
||||
index int
|
||||
weight float64
|
||||
}
|
||||
|
||||
type pweights struct {
|
||||
iwpairs []iwpair
|
||||
wsum int32
|
||||
}
|
||||
|
||||
func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) []pweights {
|
||||
func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) [][]indexWeight {
|
||||
du := float64(srcSize) / float64(dstSize)
|
||||
scale := du
|
||||
if scale < 1.0 {
|
||||
@@ -23,7 +18,7 @@ func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) []pweights {
|
||||
}
|
||||
ru := math.Ceil(scale * filter.Support)
|
||||
|
||||
out := make([]pweights, dstSize)
|
||||
out := make([][]indexWeight, dstSize)
|
||||
|
||||
for v := 0; v < dstSize; v++ {
|
||||
fu := (float64(v)+0.5)*du - 0.5
|
||||
@@ -37,15 +32,19 @@ func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) []pweights {
|
||||
endu = srcSize - 1
|
||||
}
|
||||
|
||||
wsum := int32(0)
|
||||
var sum float64
|
||||
for u := startu; u <= endu; u++ {
|
||||
w := int32(0xff * filter.Kernel((float64(u)-fu)/scale))
|
||||
w := filter.Kernel((float64(u) - fu) / scale)
|
||||
if w != 0 {
|
||||
wsum += w
|
||||
out[v].iwpairs = append(out[v].iwpairs, iwpair{u, w})
|
||||
sum += w
|
||||
out[v] = append(out[v], indexWeight{index: u, weight: w})
|
||||
}
|
||||
}
|
||||
if sum != 0 {
|
||||
for i := range out[v] {
|
||||
out[v][i].weight /= sum
|
||||
}
|
||||
}
|
||||
out[v].wsum = wsum
|
||||
}
|
||||
|
||||
return out
|
||||
@@ -127,22 +126,26 @@ func resizeHorizontal(src *image.NRGBA, width int, filter ResampleFilter) *image
|
||||
|
||||
parallel(dstH, func(partStart, partEnd int) {
|
||||
for dstY := partStart; dstY < partEnd; dstY++ {
|
||||
i0 := dstY * src.Stride
|
||||
j0 := dstY * dst.Stride
|
||||
for dstX := 0; dstX < dstW; dstX++ {
|
||||
var c [4]int64
|
||||
for _, iw := range weights[dstX].iwpairs {
|
||||
i := dstY*src.Stride + iw.i*4
|
||||
a := int64(src.Pix[i+3]) * int64(iw.w)
|
||||
c[0] += int64(src.Pix[i+0]) * a
|
||||
c[1] += int64(src.Pix[i+1]) * a
|
||||
c[2] += int64(src.Pix[i+2]) * a
|
||||
c[3] += a
|
||||
var r, g, b, a float64
|
||||
for _, w := range weights[dstX] {
|
||||
i := i0 + w.index*4
|
||||
aw := float64(src.Pix[i+3]) * w.weight
|
||||
r += float64(src.Pix[i+0]) * aw
|
||||
g += float64(src.Pix[i+1]) * aw
|
||||
b += float64(src.Pix[i+2]) * aw
|
||||
a += aw
|
||||
}
|
||||
if a != 0 {
|
||||
aInv := 1 / a
|
||||
j := j0 + dstX*4
|
||||
dst.Pix[j+0] = clamp(r * aInv)
|
||||
dst.Pix[j+1] = clamp(g * aInv)
|
||||
dst.Pix[j+2] = clamp(b * aInv)
|
||||
dst.Pix[j+3] = clamp(a)
|
||||
}
|
||||
j := dstY*dst.Stride + dstX*4
|
||||
sum := weights[dstX].wsum
|
||||
dst.Pix[j+0] = clampint32(int32(float64(c[0])/float64(c[3]) + 0.5))
|
||||
dst.Pix[j+1] = clampint32(int32(float64(c[1])/float64(c[3]) + 0.5))
|
||||
dst.Pix[j+2] = clampint32(int32(float64(c[2])/float64(c[3]) + 0.5))
|
||||
dst.Pix[j+3] = clampint32(int32(float64(c[3])/float64(sum) + 0.5))
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -163,33 +166,33 @@ func resizeVertical(src *image.NRGBA, height int, filter ResampleFilter) *image.
|
||||
weights := precomputeWeights(dstH, srcH, filter)
|
||||
|
||||
parallel(dstW, func(partStart, partEnd int) {
|
||||
|
||||
for dstX := partStart; dstX < partEnd; dstX++ {
|
||||
for dstY := 0; dstY < dstH; dstY++ {
|
||||
var c [4]int64
|
||||
for _, iw := range weights[dstY].iwpairs {
|
||||
i := iw.i*src.Stride + dstX*4
|
||||
a := int64(src.Pix[i+3]) * int64(iw.w)
|
||||
c[0] += int64(src.Pix[i+0]) * a
|
||||
c[1] += int64(src.Pix[i+1]) * a
|
||||
c[2] += int64(src.Pix[i+2]) * a
|
||||
c[3] += a
|
||||
var r, g, b, a float64
|
||||
for _, w := range weights[dstY] {
|
||||
i := w.index*src.Stride + dstX*4
|
||||
aw := float64(src.Pix[i+3]) * w.weight
|
||||
r += float64(src.Pix[i+0]) * aw
|
||||
g += float64(src.Pix[i+1]) * aw
|
||||
b += float64(src.Pix[i+2]) * aw
|
||||
a += aw
|
||||
}
|
||||
if a != 0 {
|
||||
aInv := 1 / a
|
||||
j := dstY*dst.Stride + dstX*4
|
||||
dst.Pix[j+0] = clamp(r * aInv)
|
||||
dst.Pix[j+1] = clamp(g * aInv)
|
||||
dst.Pix[j+2] = clamp(b * aInv)
|
||||
dst.Pix[j+3] = clamp(a)
|
||||
}
|
||||
j := dstY*dst.Stride + dstX*4
|
||||
sum := weights[dstY].wsum
|
||||
dst.Pix[j+0] = clampint32(int32(float64(c[0])/float64(c[3]) + 0.5))
|
||||
dst.Pix[j+1] = clampint32(int32(float64(c[1])/float64(c[3]) + 0.5))
|
||||
dst.Pix[j+2] = clampint32(int32(float64(c[2])/float64(c[3]) + 0.5))
|
||||
dst.Pix[j+3] = clampint32(int32(float64(c[3])/float64(sum) + 0.5))
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// fast nearest-neighbor resize, no filtering
|
||||
// resizeNearest is a fast nearest-neighbor resize, no filtering.
|
||||
func resizeNearest(src *image.NRGBA, width, height int) *image.NRGBA {
|
||||
dstW, dstH := width, height
|
||||
|
||||
@@ -205,13 +208,16 @@ func resizeNearest(src *image.NRGBA, width, height int) *image.NRGBA {
|
||||
parallel(dstH, func(partStart, partEnd int) {
|
||||
|
||||
for dstY := partStart; dstY < partEnd; dstY++ {
|
||||
fy := (float64(dstY)+0.5)*dy - 0.5
|
||||
srcY := int((float64(dstY) + 0.5) * dy)
|
||||
if srcY > srcH-1 {
|
||||
srcY = srcH - 1
|
||||
}
|
||||
|
||||
for dstX := 0; dstX < dstW; dstX++ {
|
||||
fx := (float64(dstX)+0.5)*dx - 0.5
|
||||
|
||||
srcX := int(math.Min(math.Max(math.Floor(fx+0.5), 0.0), float64(srcW)))
|
||||
srcY := int(math.Min(math.Max(math.Floor(fy+0.5), 0.0), float64(srcH)))
|
||||
srcX := int((float64(dstX) + 0.5) * dx)
|
||||
if srcX > srcW-1 {
|
||||
srcX = srcW - 1
|
||||
}
|
||||
|
||||
srcOff := srcY*src.Stride + srcX*4
|
||||
dstOff := dstY*dst.Stride + dstX*4
|
||||
@@ -326,7 +332,7 @@ func Thumbnail(img image.Image, width, height int, filter ResampleFilter) *image
|
||||
return Fill(img, width, height, Center, filter)
|
||||
}
|
||||
|
||||
// Resample filter struct. It can be used to make custom filters.
|
||||
// ResampleFilter is a resampling filter struct. It can be used to define custom filters.
|
||||
//
|
||||
// Supported resample filters: NearestNeighbor, Box, Linear, Hermite, MitchellNetravali,
|
||||
// CatmullRom, BSpline, Gaussian, Lanczos, Hann, Hamming, Blackman, Bartlett, Welch, Cosine.
|
||||
@@ -361,7 +367,7 @@ type ResampleFilter struct {
|
||||
Kernel func(float64) float64
|
||||
}
|
||||
|
||||
// Nearest-neighbor filter, no anti-aliasing.
|
||||
// NearestNeighbor is a nearest-neighbor filter (no anti-aliasing).
|
||||
var NearestNeighbor ResampleFilter
|
||||
|
||||
// Box filter (averaging pixels).
|
||||
@@ -373,37 +379,37 @@ var Linear ResampleFilter
|
||||
// Hermite cubic spline filter (BC-spline; B=0; C=0).
|
||||
var Hermite ResampleFilter
|
||||
|
||||
// Mitchell-Netravali cubic filter (BC-spline; B=1/3; C=1/3).
|
||||
// MitchellNetravali is Mitchell-Netravali cubic filter (BC-spline; B=1/3; C=1/3).
|
||||
var MitchellNetravali ResampleFilter
|
||||
|
||||
// Catmull-Rom - sharp cubic filter (BC-spline; B=0; C=0.5).
|
||||
// CatmullRom is a Catmull-Rom - sharp cubic filter (BC-spline; B=0; C=0.5).
|
||||
var CatmullRom ResampleFilter
|
||||
|
||||
// Cubic B-spline - smooth cubic filter (BC-spline; B=1; C=0).
|
||||
// BSpline is a smooth cubic filter (BC-spline; B=1; C=0).
|
||||
var BSpline ResampleFilter
|
||||
|
||||
// Gaussian Blurring Filter.
|
||||
// Gaussian is a Gaussian blurring Filter.
|
||||
var Gaussian ResampleFilter
|
||||
|
||||
// Bartlett-windowed sinc filter (3 lobes).
|
||||
// Bartlett is a Bartlett-windowed sinc filter (3 lobes).
|
||||
var Bartlett ResampleFilter
|
||||
|
||||
// Lanczos filter (3 lobes).
|
||||
var Lanczos ResampleFilter
|
||||
|
||||
// Hann-windowed sinc filter (3 lobes).
|
||||
// Hann is a Hann-windowed sinc filter (3 lobes).
|
||||
var Hann ResampleFilter
|
||||
|
||||
// Hamming-windowed sinc filter (3 lobes).
|
||||
// Hamming is a Hamming-windowed sinc filter (3 lobes).
|
||||
var Hamming ResampleFilter
|
||||
|
||||
// Blackman-windowed sinc filter (3 lobes).
|
||||
// Blackman is a Blackman-windowed sinc filter (3 lobes).
|
||||
var Blackman ResampleFilter
|
||||
|
||||
// Welch-windowed sinc filter (parabolic window, 3 lobes).
|
||||
// Welch is a Welch-windowed sinc filter (parabolic window, 3 lobes).
|
||||
var Welch ResampleFilter
|
||||
|
||||
// Cosine-windowed sinc filter (3 lobes).
|
||||
// Cosine is a Cosine-windowed sinc filter (3 lobes).
|
||||
var Cosine ResampleFilter
|
||||
|
||||
func bcspline(x, b, c float64) float64 {
|
||||
|
||||
68
vendor/github.com/disintegration/imaging/resize_test.go
сгенерированный
поставляемый
@@ -108,10 +108,10 @@ func TestResize(t *testing.T) {
|
||||
Rect: image.Rect(0, 0, 4, 4),
|
||||
Stride: 4 * 4,
|
||||
Pix: []uint8{
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x3f, 0xff, 0x00, 0x00, 0xc0, 0xff, 0x00, 0x00, 0xff,
|
||||
0x00, 0xff, 0x00, 0x3f, 0x6d, 0x6e, 0x24, 0x6f, 0xb1, 0x13, 0x3a, 0xd0, 0xc0, 0x00, 0x3f, 0xff,
|
||||
0x00, 0xff, 0x00, 0xc0, 0x13, 0xb2, 0x3a, 0xcf, 0x33, 0x32, 0x9a, 0xef, 0x3f, 0x00, 0xc0, 0xff,
|
||||
0x00, 0xff, 0x00, 0xff, 0x00, 0xc0, 0x3f, 0xff, 0x00, 0x3f, 0xc0, 0xff, 0x00, 0x00, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x40, 0xff, 0x00, 0x00, 0xbf, 0xff, 0x00, 0x00, 0xff,
|
||||
0x00, 0xff, 0x00, 0x40, 0x6e, 0x6d, 0x25, 0x70, 0xb0, 0x14, 0x3b, 0xcf, 0xbf, 0x00, 0x40, 0xff,
|
||||
0x00, 0xff, 0x00, 0xbf, 0x14, 0xb0, 0x3b, 0xcf, 0x33, 0x33, 0x99, 0xef, 0x40, 0x00, 0xbf, 0xff,
|
||||
0x00, 0xff, 0x00, 0xff, 0x00, 0xbf, 0x40, 0xff, 0x00, 0x40, 0xbf, 0xff, 0x00, 0x00, 0xff, 0xff,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -158,7 +158,7 @@ func TestResize(t *testing.T) {
|
||||
for _, d := range td {
|
||||
got := Resize(d.src, d.w, d.h, d.f)
|
||||
want := d.want
|
||||
if !compareNRGBA(got, want, 1) {
|
||||
if !compareNRGBA(got, want, 0) {
|
||||
t.Errorf("test [%s] failed: %#v", d.desc, got)
|
||||
}
|
||||
}
|
||||
@@ -201,6 +201,28 @@ func TestResize(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestResizeGolden(t *testing.T) {
|
||||
src, err := Open("testdata/lena_512.png")
|
||||
if err != nil {
|
||||
t.Errorf("Open: %v", err)
|
||||
}
|
||||
for name, filter := range map[string]ResampleFilter{
|
||||
"out_resize_nearest.png": NearestNeighbor,
|
||||
"out_resize_linear.png": Linear,
|
||||
"out_resize_catrom.png": CatmullRom,
|
||||
"out_resize_lanczos.png": Lanczos,
|
||||
} {
|
||||
got := Resize(src, 128, 0, filter)
|
||||
want, err := Open("testdata/" + name)
|
||||
if err != nil {
|
||||
t.Errorf("Open: %v", err)
|
||||
}
|
||||
if !compareNRGBA(got, toNRGBA(want), 0) {
|
||||
t.Errorf("resulting image differs from golden: %s", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFit(t *testing.T) {
|
||||
td := []struct {
|
||||
desc string
|
||||
@@ -568,3 +590,39 @@ func TestThumbnail(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkResizeLanczosUp(b *testing.B) {
|
||||
benchmarkResize(b, "testdata/lena_128.png", 512, Lanczos)
|
||||
}
|
||||
|
||||
func BenchmarkResizeLinearUp(b *testing.B) {
|
||||
benchmarkResize(b, "testdata/lena_128.png", 512, Linear)
|
||||
}
|
||||
|
||||
func BenchmarkResizeNearestNeighborUp(b *testing.B) {
|
||||
benchmarkResize(b, "testdata/lena_128.png", 512, NearestNeighbor)
|
||||
}
|
||||
|
||||
func BenchmarkResizeLanczosDown(b *testing.B) {
|
||||
benchmarkResize(b, "testdata/lena_512.png", 128, Lanczos)
|
||||
}
|
||||
|
||||
func BenchmarkResizeLinearDown(b *testing.B) {
|
||||
benchmarkResize(b, "testdata/lena_512.png", 128, Linear)
|
||||
}
|
||||
|
||||
func BenchmarkResizeNearestNeighborDown(b *testing.B) {
|
||||
benchmarkResize(b, "testdata/lena_512.png", 128, NearestNeighbor)
|
||||
}
|
||||
|
||||
func benchmarkResize(b *testing.B, filename string, size int, f ResampleFilter) {
|
||||
b.StopTimer()
|
||||
img, err := Open(filename)
|
||||
if err != nil {
|
||||
b.Fatalf("Open: %v", err)
|
||||
}
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
Resize(img, size, size, f)
|
||||
}
|
||||
}
|
||||
|
||||
Двоичные данные
vendor/github.com/disintegration/imaging/testdata/lena_128.png
сгенерированный
поставляемый
Обычный файл
|
После Ширина: | Высота: | Размер: 49 KiB |
Двоичные данные
vendor/github.com/disintegration/imaging/testdata/lena_512.png
сгенерированный
поставляемый
Обычный файл
|
После Ширина: | Высота: | Размер: 465 KiB |
Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_blur_0.5.png
сгенерированный
поставляемый
Обычный файл
|
После Ширина: | Высота: | Размер: 28 KiB |
Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_blur_1.5.png
сгенерированный
поставляемый
Обычный файл
|
После Ширина: | Высота: | Размер: 21 KiB |
Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_brightness_m10.png
сгенерированный
поставляемый
Обычный файл
|
После Ширина: | Высота: | Размер: 31 KiB |
Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_brightness_p10.png
сгенерированный
поставляемый
Обычный файл
|
После Ширина: | Высота: | Размер: 31 KiB |
Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_contrast_m10.png
сгенерированный
поставляемый
Обычный файл
|
После Ширина: | Высота: | Размер: 30 KiB |
Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_contrast_p10.png
сгенерированный
поставляемый
Обычный файл
|
После Ширина: | Высота: | Размер: 32 KiB |
Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_example.jpg
сгенерированный
поставляемый
Обычный файл
|
После Ширина: | Высота: | Размер: 134 KiB |
Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_gamma_0.75.png
сгенерированный
поставляемый
Обычный файл
|
После Ширина: | Высота: | Размер: 31 KiB |
Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_gamma_1.25.png
сгенерированный
поставляемый
Обычный файл
|
После Ширина: | Высота: | Размер: 31 KiB |
Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_resize_catrom.png
сгенерированный
поставляемый
Обычный файл
|
После Ширина: | Высота: | Размер: 30 KiB |
Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_resize_lanczos.png
сгенерированный
поставляемый
Обычный файл
|
После Ширина: | Высота: | Размер: 31 KiB |
Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_resize_linear.png
сгенерированный
поставляемый
Обычный файл
|
После Ширина: | Высота: | Размер: 29 KiB |
Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_resize_nearest.png
сгенерированный
поставляемый
Обычный файл
|
После Ширина: | Высота: | Размер: 35 KiB |
Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_sharpen_0.5.png
сгенерированный
поставляемый
Обычный файл
|
После Ширина: | Высота: | Размер: 33 KiB |
Двоичные данные
vendor/github.com/disintegration/imaging/testdata/out_sharpen_1.5.png
сгенерированный
поставляемый
Обычный файл
|
После Ширина: | Высота: | Размер: 36 KiB |
1
vendor/github.com/disintegration/imaging/tools.go
сгенерированный
поставляемый
@@ -8,6 +8,7 @@ import (
|
||||
// Anchor is the anchor point for image alignment.
|
||||
type Anchor int
|
||||
|
||||
// Anchor point positions.
|
||||
const (
|
||||
Center Anchor = iota
|
||||
TopLeft
|
||||
|
||||
2
vendor/github.com/disintegration/imaging/tools_test.go
сгенерированный
поставляемый
@@ -598,7 +598,7 @@ func TestOverlay(t *testing.T) {
|
||||
for _, d := range td {
|
||||
got := Overlay(d.src1, d.src2, d.p, d.a)
|
||||
want := d.want
|
||||
if !compareNRGBA(got, want, 1) {
|
||||
if !compareNRGBA(got, want, 0) {
|
||||
t.Errorf("test [%s] failed: %#v", d.desc, got)
|
||||
}
|
||||
}
|
||||
|
||||
42
vendor/github.com/disintegration/imaging/utils.go
сгенерированный
поставляемый
@@ -1,28 +1,24 @@
|
||||
package imaging
|
||||
|
||||
import (
|
||||
"math"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
var parallelizationEnabled = true
|
||||
|
||||
// if GOMAXPROCS = 1: no goroutines used
|
||||
// if GOMAXPROCS > 1: spawn N=GOMAXPROCS workers in separate goroutines
|
||||
// parallel starts parallel image processing based on the current GOMAXPROCS value.
|
||||
// If GOMAXPROCS = 1 it uses no parallelization.
|
||||
// If GOMAXPROCS > 1 it spawns N=GOMAXPROCS workers in separate goroutines.
|
||||
func parallel(dataSize int, fn func(partStart, partEnd int)) {
|
||||
numGoroutines := 1
|
||||
partSize := dataSize
|
||||
|
||||
if parallelizationEnabled {
|
||||
numProcs := runtime.GOMAXPROCS(0)
|
||||
if numProcs > 1 {
|
||||
numGoroutines = numProcs
|
||||
partSize = dataSize / (numGoroutines * 10)
|
||||
if partSize < 1 {
|
||||
partSize = 1
|
||||
}
|
||||
numProcs := runtime.GOMAXPROCS(0)
|
||||
if numProcs > 1 {
|
||||
numGoroutines = numProcs
|
||||
partSize = dataSize / (numGoroutines * 10)
|
||||
if partSize < 1 {
|
||||
partSize = 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +50,7 @@ func parallel(dataSize int, fn func(partStart, partEnd int)) {
|
||||
}
|
||||
}
|
||||
|
||||
// absint returns the absolute value of i.
|
||||
func absint(i int) int {
|
||||
if i < 0 {
|
||||
return -i
|
||||
@@ -61,17 +58,14 @@ func absint(i int) int {
|
||||
return i
|
||||
}
|
||||
|
||||
// clamp & round float64 to uint8 (0..255)
|
||||
func clamp(v float64) uint8 {
|
||||
return uint8(math.Min(math.Max(v, 0.0), 255.0) + 0.5)
|
||||
}
|
||||
|
||||
// clamp int32 to uint8 (0..255)
|
||||
func clampint32(v int32) uint8 {
|
||||
if v < 0 {
|
||||
return 0
|
||||
} else if v > 255 {
|
||||
// clamp rounds and clamps float64 value to fit into uint8.
|
||||
func clamp(x float64) uint8 {
|
||||
v := int64(x + 0.5)
|
||||
if v > 255 {
|
||||
return 255
|
||||
}
|
||||
return uint8(v)
|
||||
if v > 0 {
|
||||
return uint8(v)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
24
vendor/github.com/disintegration/imaging/utils_test.go
сгенерированный
поставляемый
@@ -15,7 +15,7 @@ func testParallelN(enabled bool, n, procs int) bool {
|
||||
}
|
||||
})
|
||||
for i := 0; i < n; i++ {
|
||||
if data[i] != true {
|
||||
if !data[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ func TestParallel(t *testing.T) {
|
||||
for _, e := range []bool{true, false} {
|
||||
for _, n := range []int{1, 10, 100, 1000} {
|
||||
for _, p := range []int{1, 2, 4, 8, 16, 100} {
|
||||
if testParallelN(e, n, p) != true {
|
||||
if !testParallelN(e, n, p) {
|
||||
t.Errorf("test [parallel %v %d %d] failed", e, n, p)
|
||||
}
|
||||
}
|
||||
@@ -59,23 +59,3 @@ func TestClamp(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestClampint32(t *testing.T) {
|
||||
td := []struct {
|
||||
i int32
|
||||
u uint8
|
||||
}{
|
||||
{0, 0},
|
||||
{255, 255},
|
||||
{128, 128},
|
||||
{256, 255},
|
||||
{2500, 255},
|
||||
{-10, 0},
|
||||
}
|
||||
|
||||
for _, d := range td {
|
||||
if clampint32(d.i) != d.u {
|
||||
t.Errorf("test [clampint32 %v %v] failed: %v", d.i, d.u, clampint32(d.i))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
13
vendor/github.com/golang/freetype/truetype/truetype.go
сгенерированный
поставляемый
@@ -57,7 +57,8 @@ const (
|
||||
// A 32-bit encoding consists of a most-significant 16-bit Platform ID and a
|
||||
// least-significant 16-bit Platform Specific ID. The magic numbers are
|
||||
// specified at https://www.microsoft.com/typography/otspec/name.htm
|
||||
unicodeEncoding = 0x00000003 // PID = 0 (Unicode), PSID = 3 (Unicode 2.0)
|
||||
unicodeEncodingBMPOnly = 0x00000003 // PID = 0 (Unicode), PSID = 3 (Unicode 2.0 BMP Only)
|
||||
unicodeEncodingFull = 0x00000004 // PID = 0 (Unicode), PSID = 4 (Unicode 2.0 Full Repertoire)
|
||||
microsoftSymbolEncoding = 0x00030000 // PID = 3 (Microsoft), PSID = 0 (Symbol)
|
||||
microsoftUCS2Encoding = 0x00030001 // PID = 3 (Microsoft), PSID = 1 (UCS-2)
|
||||
microsoftUCS4Encoding = 0x0003000a // PID = 3 (Microsoft), PSID = 10 (UCS-4)
|
||||
@@ -142,7 +143,7 @@ func parseSubtables(table []byte, name string, offset, size int, pred func([]byt
|
||||
pidPsid := u32(table, offset)
|
||||
// We prefer the Unicode cmap encoding. Failing to find that, we fall
|
||||
// back onto the Microsoft cmap encoding.
|
||||
if pidPsid == unicodeEncoding {
|
||||
if pidPsid == unicodeEncodingBMPOnly || pidPsid == unicodeEncodingFull {
|
||||
bestOffset, bestPID, ok = offset, pidPsid>>16, true
|
||||
break
|
||||
|
||||
@@ -550,8 +551,7 @@ func parse(ttf []byte, offset int) (font *Font, err error) {
|
||||
return
|
||||
}
|
||||
ttcVersion, offset := u32(ttf, offset), offset+4
|
||||
if ttcVersion != 0x00010000 {
|
||||
// TODO: support TTC version 2.0, once I have such a .ttc file to test with.
|
||||
if ttcVersion != 0x00010000 && ttcVersion != 0x00020000 {
|
||||
err = FormatError("bad TTC version")
|
||||
return
|
||||
}
|
||||
@@ -578,14 +578,15 @@ func parse(ttf []byte, offset int) (font *Font, err error) {
|
||||
return
|
||||
}
|
||||
n, offset := int(u16(ttf, offset)), offset+2
|
||||
if len(ttf) < 16*n+12 {
|
||||
offset += 6 // Skip the searchRange, entrySelector and rangeShift.
|
||||
if len(ttf) < 16*n+offset {
|
||||
err = FormatError("TTF data is too short")
|
||||
return
|
||||
}
|
||||
f := new(Font)
|
||||
// Assign the table slices.
|
||||
for i := 0; i < n; i++ {
|
||||
x := 16*i + 12
|
||||
x := 16*i + offset
|
||||
switch string(ttf[x : x+4]) {
|
||||
case "cmap":
|
||||
f.cmap, err = readTable(ttf, ttf[x+8:x+16])
|
||||
|
||||
2
vendor/github.com/hashicorp/hcl/json/parser/parser.go
сгенерированный
поставляемый
@@ -147,7 +147,7 @@ func (p *Parser) objectKey() ([]*ast.ObjectKey, error) {
|
||||
// Done
|
||||
return keys, nil
|
||||
case token.ILLEGAL:
|
||||
fmt.Println("illegal")
|
||||
return nil, errors.New("illegal")
|
||||
default:
|
||||
return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type)
|
||||
}
|
||||
|
||||
6
vendor/github.com/lib/pq/conn.go
сгенерированный
поставляемый
@@ -35,14 +35,14 @@ var (
|
||||
errNoLastInsertId = errors.New("no LastInsertId available after the empty statement")
|
||||
)
|
||||
|
||||
type drv struct{}
|
||||
type Driver struct{}
|
||||
|
||||
func (d *drv) Open(name string) (driver.Conn, error) {
|
||||
func (d *Driver) Open(name string) (driver.Conn, error) {
|
||||
return Open(name)
|
||||
}
|
||||
|
||||
func init() {
|
||||
sql.Register("postgres", &drv{})
|
||||
sql.Register("postgres", &Driver{})
|
||||
}
|
||||
|
||||
type parameterStatus struct {
|
||||
|
||||
2
vendor/github.com/miekg/dns/README.md
сгенерированный
поставляемый
@@ -19,7 +19,7 @@ two versions of Go, currently: 1.6 and 1.7.
|
||||
|
||||
* KISS;
|
||||
* Fast;
|
||||
* Small API, if its easy to code in Go, don't make a function for it.
|
||||
* Small API. If it's easy to code in Go, don't make a function for it.
|
||||
|
||||
# Users
|
||||
|
||||
|
||||
2
vendor/github.com/miekg/dns/dnssec.go
сгенерированный
поставляемый
@@ -515,7 +515,7 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
|
||||
}
|
||||
// Remainder
|
||||
expo += uint64(keybuf[keyoff])
|
||||
if expo > 2<<31 {
|
||||
if expo > (2<<31)+1 {
|
||||
// Larger expo than supported.
|
||||
// println("dns: F5 primes (or larger) are not supported")
|
||||
return nil
|
||||
|
||||
3
vendor/github.com/miekg/dns/labels.go
сгенерированный
поставляемый
@@ -1,5 +1,7 @@
|
||||
package dns
|
||||
|
||||
import "strings"
|
||||
|
||||
// Holds a bunch of helper functions for dealing with labels.
|
||||
|
||||
// SplitDomainName splits a name string into it's labels.
|
||||
@@ -50,6 +52,7 @@ func SplitDomainName(s string) (labels []string) {
|
||||
//
|
||||
// s1 and s2 must be syntactically valid domain names.
|
||||
func CompareDomainName(s1, s2 string) (n int) {
|
||||
s1, s2 = strings.ToLower(s1), strings.ToLower(s2)
|
||||
s1 = Fqdn(s1)
|
||||
s2 = Fqdn(s2)
|
||||
l1 := Split(s1)
|
||||
|
||||
3
vendor/github.com/miekg/dns/labels_test.go
сгенерированный
поставляемый
@@ -33,6 +33,9 @@ func TestCompareDomainName(t *testing.T) {
|
||||
if CompareDomainName(".", ".") != 0 {
|
||||
t.Errorf("%s with %s should be %d", ".", ".", 0)
|
||||
}
|
||||
if CompareDomainName("test.com.", "TEST.COM.") != 2 {
|
||||
t.Errorf("test.com. and TEST.COM. should be an exact match")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplit(t *testing.T) {
|
||||
|
||||
20
vendor/github.com/miekg/dns/msg.go
сгенерированный
поставляемый
@@ -14,13 +14,17 @@ package dns
|
||||
import (
|
||||
crand "crypto/rand"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const maxCompressionOffset = 2 << 13 // We have 14 bits for the compression pointer
|
||||
const (
|
||||
maxCompressionOffset = 2 << 13 // We have 14 bits for the compression pointer
|
||||
maxDomainNameWireOctets = 255 // See RFC 1035 section 2.3.4
|
||||
)
|
||||
|
||||
var (
|
||||
ErrAlg error = &Error{err: "bad algorithm"} // ErrAlg indicates an error with the (DNSSEC) algorithm.
|
||||
@@ -33,6 +37,7 @@ var (
|
||||
ErrKeyAlg error = &Error{err: "bad key algorithm"} // ErrKeyAlg indicates that the algorithm in the key is not valid.
|
||||
ErrKey error = &Error{err: "bad key"}
|
||||
ErrKeySize error = &Error{err: "bad key size"}
|
||||
ErrLongDomain error = &Error{err: fmt.Sprintf("domain name exceeded %d wire-format octets", maxDomainNameWireOctets)}
|
||||
ErrNoSig error = &Error{err: "no signature found"}
|
||||
ErrPrivKey error = &Error{err: "bad private key"}
|
||||
ErrRcode error = &Error{err: "bad rcode"}
|
||||
@@ -329,6 +334,7 @@ func UnpackDomainName(msg []byte, off int) (string, int, error) {
|
||||
s := make([]byte, 0, 64)
|
||||
off1 := 0
|
||||
lenmsg := len(msg)
|
||||
maxLen := maxDomainNameWireOctets
|
||||
ptr := 0 // number of pointers followed
|
||||
Loop:
|
||||
for {
|
||||
@@ -353,8 +359,10 @@ Loop:
|
||||
fallthrough
|
||||
case '"', '\\':
|
||||
s = append(s, '\\', b)
|
||||
// presentation-format \X escapes add an extra byte
|
||||
maxLen += 1
|
||||
default:
|
||||
if b < 32 || b >= 127 { // unprintable use \DDD
|
||||
if b < 32 || b >= 127 { // unprintable, use \DDD
|
||||
var buf [3]byte
|
||||
bufs := strconv.AppendInt(buf[:0], int64(b), 10)
|
||||
s = append(s, '\\')
|
||||
@@ -364,6 +372,8 @@ Loop:
|
||||
for _, r := range bufs {
|
||||
s = append(s, r)
|
||||
}
|
||||
// presentation-format \DDD escapes add 3 extra bytes
|
||||
maxLen += 3
|
||||
} else {
|
||||
s = append(s, b)
|
||||
}
|
||||
@@ -388,6 +398,9 @@ Loop:
|
||||
if ptr++; ptr > 10 {
|
||||
return "", lenmsg, &Error{err: "too many compression pointers"}
|
||||
}
|
||||
// pointer should guarantee that it advances and points forwards at least
|
||||
// but the condition on previous three lines guarantees that it's
|
||||
// at least loop-free
|
||||
off = (c^0xC0)<<8 | int(c1)
|
||||
default:
|
||||
// 0x80 and 0x40 are reserved
|
||||
@@ -399,6 +412,9 @@ Loop:
|
||||
}
|
||||
if len(s) == 0 {
|
||||
s = []byte(".")
|
||||
} else if len(s) >= maxLen {
|
||||
// error if the name is too long, but don't throw it away
|
||||
return string(s), lenmsg, ErrLongDomain
|
||||
}
|
||||
return string(s), off1, nil
|
||||
}
|
||||
|
||||
124
vendor/github.com/miekg/dns/msg_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,124 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const (
|
||||
maxPrintableLabel = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789x"
|
||||
tooLongLabel = maxPrintableLabel + "x"
|
||||
)
|
||||
|
||||
var (
|
||||
longDomain = maxPrintableLabel[:53] + strings.TrimSuffix(
|
||||
strings.Join([]string{".", ".", ".", ".", "."}, maxPrintableLabel[:49]), ".")
|
||||
reChar = regexp.MustCompile(`.`)
|
||||
i = -1
|
||||
maxUnprintableLabel = reChar.ReplaceAllStringFunc(maxPrintableLabel, func(ch string) string {
|
||||
if i++; i >= 32 {
|
||||
i = 0
|
||||
}
|
||||
return fmt.Sprintf("\\%03d", i)
|
||||
})
|
||||
)
|
||||
|
||||
func TestUnpackDomainName(t *testing.T) {
|
||||
var cases = []struct {
|
||||
label string
|
||||
input string
|
||||
expectedOutput string
|
||||
expectedError string
|
||||
}{
|
||||
{"empty domain",
|
||||
"\x00",
|
||||
".",
|
||||
""},
|
||||
{"long label",
|
||||
string(63) + maxPrintableLabel + "\x00",
|
||||
maxPrintableLabel + ".",
|
||||
""},
|
||||
{"unprintable label",
|
||||
string(63) + regexp.MustCompile(`\\[0-9]+`).ReplaceAllStringFunc(maxUnprintableLabel,
|
||||
func(escape string) string {
|
||||
n, _ := strconv.ParseInt(escape[1:], 10, 8)
|
||||
return string(n)
|
||||
}) + "\x00",
|
||||
maxUnprintableLabel + ".",
|
||||
""},
|
||||
{"long domain",
|
||||
string(53) + strings.Replace(longDomain, ".", string(49), -1) + "\x00",
|
||||
longDomain + ".",
|
||||
""},
|
||||
{"compression pointer",
|
||||
// an unrealistic but functional test referencing an offset _inside_ a label
|
||||
"\x03foo" + "\x05\x03com\x00" + "\x07example" + "\xC0\x05",
|
||||
"foo.\\003com\\000.example.com.",
|
||||
""},
|
||||
|
||||
{"too long domain",
|
||||
string(54) + "x" + strings.Replace(longDomain, ".", string(49), -1) + "\x00",
|
||||
"x" + longDomain + ".",
|
||||
ErrLongDomain.Error()},
|
||||
{"too long by pointer",
|
||||
// a matryoshka doll name to get over 255 octets after expansion via internal pointers
|
||||
string([]byte{
|
||||
// 11 length values, first to last
|
||||
40, 37, 34, 31, 28, 25, 22, 19, 16, 13, 0,
|
||||
// 12 filler values
|
||||
120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120,
|
||||
// 10 pointers, last to first
|
||||
192, 10, 192, 9, 192, 8, 192, 7, 192, 6, 192, 5, 192, 4, 192, 3, 192, 2, 192, 1,
|
||||
}),
|
||||
"",
|
||||
ErrLongDomain.Error()},
|
||||
{"long by pointer",
|
||||
// a matryoshka doll name _not_ exceeding 255 octets after expansion
|
||||
string([]byte{
|
||||
// 11 length values, first to last
|
||||
37, 34, 31, 28, 25, 22, 19, 16, 13, 10, 0,
|
||||
// 9 filler values
|
||||
120, 120, 120, 120, 120, 120, 120, 120, 120,
|
||||
// 10 pointers, last to first
|
||||
192, 10, 192, 9, 192, 8, 192, 7, 192, 6, 192, 5, 192, 4, 192, 3, 192, 2, 192, 1,
|
||||
}),
|
||||
"" +
|
||||
(`\"\031\028\025\022\019\016\013\010\000xxxxxxxxx` +
|
||||
`\192\010\192\009\192\008\192\007\192\006\192\005\192\004\192\003\192\002.`) +
|
||||
(`\031\028\025\022\019\016\013\010\000xxxxxxxxx` +
|
||||
`\192\010\192\009\192\008\192\007\192\006\192\005\192\004\192\003.`) +
|
||||
(`\028\025\022\019\016\013\010\000xxxxxxxxx` +
|
||||
`\192\010\192\009\192\008\192\007\192\006\192\005\192\004.`) +
|
||||
(`\025\022\019\016\013\010\000xxxxxxxxx` +
|
||||
`\192\010\192\009\192\008\192\007\192\006\192\005.`) +
|
||||
`\022\019\016\013\010\000xxxxxxxxx\192\010\192\009\192\008\192\007\192\006.` +
|
||||
`\019\016\013\010\000xxxxxxxxx\192\010\192\009\192\008\192\007.` +
|
||||
`\016\013\010\000xxxxxxxxx\192\010\192\009\192\008.` +
|
||||
`\013\010\000xxxxxxxxx\192\010\192\009.` +
|
||||
`\010\000xxxxxxxxx\192\010.` +
|
||||
`\000xxxxxxxxx.`,
|
||||
""},
|
||||
{"truncated name", "\x07example\x03", "", "dns: buffer size too small"},
|
||||
{"non-absolute name", "\x07example\x03com", "", "dns: buffer size too small"},
|
||||
{"compression pointer cycle",
|
||||
"\x03foo" + "\x03bar" + "\x07example" + "\xC0\x04",
|
||||
"",
|
||||
"dns: too many compression pointers"},
|
||||
{"reserved compression pointer 0b10", "\x07example\x80", "", "dns: bad rdata"},
|
||||
{"reserved compression pointer 0b01", "\x07example\x40", "", "dns: bad rdata"},
|
||||
}
|
||||
for _, test := range cases {
|
||||
output, idx, err := UnpackDomainName([]byte(test.input), 0)
|
||||
if test.expectedOutput != "" && output != test.expectedOutput {
|
||||
t.Errorf("%s: expected %s, got %s", test.label, test.expectedOutput, output)
|
||||
}
|
||||
if test.expectedError == "" && err != nil {
|
||||
t.Errorf("%s: expected no error, got %d %v", test.label, idx, err)
|
||||
} else if test.expectedError != "" && (err == nil || err.Error() != test.expectedError) {
|
||||
t.Errorf("%s: expected error %s, got %d %v", test.label, test.expectedError, idx, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
76
vendor/github.com/miekg/dns/nsecx.go
сгенерированный
поставляемый
@@ -48,62 +48,50 @@ func HashName(label string, ha uint8, iter uint16, salt string) string {
|
||||
return toBase32(nsec3)
|
||||
}
|
||||
|
||||
// Denialer is an interface that should be implemented by types that are used to denial
|
||||
// answers in DNSSEC.
|
||||
type Denialer interface {
|
||||
// Cover will check if the (unhashed) name is being covered by this NSEC or NSEC3.
|
||||
Cover(name string) bool
|
||||
// Match will check if the ownername matches the (unhashed) name for this NSEC3 or NSEC3.
|
||||
Match(name string) bool
|
||||
}
|
||||
|
||||
// Cover implements the Denialer interface.
|
||||
func (rr *NSEC) Cover(name string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Match implements the Denialer interface.
|
||||
func (rr *NSEC) Match(name string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Cover implements the Denialer interface.
|
||||
// Cover returns true if a name is covered by the NSEC3 record
|
||||
func (rr *NSEC3) Cover(name string) bool {
|
||||
// FIXME(miek): check if the zones match
|
||||
// FIXME(miek): check if we're not dealing with parent nsec3
|
||||
hname := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
|
||||
labels := Split(rr.Hdr.Name)
|
||||
if len(labels) < 2 {
|
||||
nameHash := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
|
||||
owner := strings.ToUpper(rr.Hdr.Name)
|
||||
labelIndices := Split(owner)
|
||||
if len(labelIndices) < 2 {
|
||||
return false
|
||||
}
|
||||
hash := strings.ToUpper(rr.Hdr.Name[labels[0] : labels[1]-1]) // -1 to remove the dot
|
||||
if hash == rr.NextDomain {
|
||||
return false // empty interval
|
||||
}
|
||||
if hash > rr.NextDomain { // last name, points to apex
|
||||
// hname > hash
|
||||
// hname > rr.NextDomain
|
||||
// TODO(miek)
|
||||
}
|
||||
if hname <= hash {
|
||||
ownerHash := owner[:labelIndices[1]-1]
|
||||
ownerZone := owner[labelIndices[1]:]
|
||||
if !IsSubDomain(ownerZone, strings.ToUpper(name)) { // name is outside owner zone
|
||||
return false
|
||||
}
|
||||
if hname >= rr.NextDomain {
|
||||
|
||||
nextHash := rr.NextDomain
|
||||
if ownerHash == nextHash { // empty interval
|
||||
return false
|
||||
}
|
||||
return true
|
||||
if ownerHash > nextHash { // end of zone
|
||||
if nameHash > ownerHash { // covered since there is nothing after ownerHash
|
||||
return true
|
||||
}
|
||||
return nameHash < nextHash // if nameHash is before beginning of zone it is covered
|
||||
}
|
||||
if nameHash < ownerHash { // nameHash is before ownerHash, not covered
|
||||
return false
|
||||
}
|
||||
return nameHash < nextHash // if nameHash is before nextHash is it covered (between ownerHash and nextHash)
|
||||
}
|
||||
|
||||
// Match implements the Denialer interface.
|
||||
// Match returns true if a name matches the NSEC3 record
|
||||
func (rr *NSEC3) Match(name string) bool {
|
||||
// FIXME(miek): Check if we are in the same zone
|
||||
hname := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
|
||||
labels := Split(rr.Hdr.Name)
|
||||
if len(labels) < 2 {
|
||||
nameHash := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
|
||||
owner := strings.ToUpper(rr.Hdr.Name)
|
||||
labelIndices := Split(owner)
|
||||
if len(labelIndices) < 2 {
|
||||
return false
|
||||
}
|
||||
hash := strings.ToUpper(rr.Hdr.Name[labels[0] : labels[1]-1]) // -1 to remove the .
|
||||
if hash == hname {
|
||||
ownerHash := owner[:labelIndices[1]-1]
|
||||
ownerZone := owner[labelIndices[1]:]
|
||||
if !IsSubDomain(ownerZone, strings.ToUpper(name)) { // name is outside owner zone
|
||||
return false
|
||||
}
|
||||
if ownerHash == nameHash {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
124
vendor/github.com/miekg/dns/nsecx_test.go
сгенерированный
поставляемый
@@ -1,8 +1,6 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
import "testing"
|
||||
|
||||
func TestPackNsec3(t *testing.T) {
|
||||
nsec3 := HashName("dnsex.nl.", SHA1, 0, "DEAD")
|
||||
@@ -17,13 +15,119 @@ func TestPackNsec3(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNsec3(t *testing.T) {
|
||||
// examples taken from .nl
|
||||
nsec3, _ := NewRR("39p91242oslggest5e6a7cci4iaeqvnk.nl. IN NSEC3 1 1 5 F10E9F7EA83FC8F3 39P99DCGG0MDLARTCRMCF6OFLLUL7PR6 NS DS RRSIG")
|
||||
if !nsec3.(*NSEC3).Cover("snasajsksasasa.nl.") { // 39p94jrinub66hnpem8qdpstrec86pg3
|
||||
t.Error("39p94jrinub66hnpem8qdpstrec86pg3. should be covered by 39p91242oslggest5e6a7cci4iaeqvnk.nl. - 39P99DCGG0MDLARTCRMCF6OFLLUL7PR6")
|
||||
nsec3, _ := NewRR("sk4e8fj94u78smusb40o1n0oltbblu2r.nl. IN NSEC3 1 1 5 F10E9F7EA83FC8F3 SK4F38CQ0ATIEI8MH3RGD0P5I4II6QAN NS SOA TXT RRSIG DNSKEY NSEC3PARAM")
|
||||
if !nsec3.(*NSEC3).Match("nl.") { // name hash = sk4e8fj94u78smusb40o1n0oltbblu2r
|
||||
t.Fatal("sk4e8fj94u78smusb40o1n0oltbblu2r.nl. should match sk4e8fj94u78smusb40o1n0oltbblu2r.nl.")
|
||||
}
|
||||
nsec3, _ = NewRR("sk4e8fj94u78smusb40o1n0oltbblu2r.nl. IN NSEC3 1 1 5 F10E9F7EA83FC8F3 SK4F38CQ0ATIEI8MH3RGD0P5I4II6QAN NS SOA TXT RRSIG DNSKEY NSEC3PARAM")
|
||||
if !nsec3.(*NSEC3).Match("nl.") { // sk4e8fj94u78smusb40o1n0oltbblu2r.nl.
|
||||
t.Error("sk4e8fj94u78smusb40o1n0oltbblu2r.nl. should match sk4e8fj94u78smusb40o1n0oltbblu2r.nl.")
|
||||
if !nsec3.(*NSEC3).Match("NL.") { // name hash = sk4e8fj94u78smusb40o1n0oltbblu2r
|
||||
t.Fatal("sk4e8fj94u78smusb40o1n0oltbblu2r.NL. should match sk4e8fj94u78smusb40o1n0oltbblu2r.nl.")
|
||||
}
|
||||
if nsec3.(*NSEC3).Match("com.") { //
|
||||
t.Fatal("com. is not in the zone nl.")
|
||||
}
|
||||
if nsec3.(*NSEC3).Match("test.nl.") { // name hash = gd0ptr5bnfpimpu2d3v6gd4n0bai7s0q
|
||||
t.Fatal("gd0ptr5bnfpimpu2d3v6gd4n0bai7s0q.nl. should not match sk4e8fj94u78smusb40o1n0oltbblu2r.nl.")
|
||||
}
|
||||
nsec3, _ = NewRR("nl. IN NSEC3 1 1 5 F10E9F7EA83FC8F3 SK4F38CQ0ATIEI8MH3RGD0P5I4II6QAN NS SOA TXT RRSIG DNSKEY NSEC3PARAM")
|
||||
if nsec3.(*NSEC3).Match("nl.") {
|
||||
t.Fatal("sk4e8fj94u78smusb40o1n0oltbblu2r.nl. should not match a record without a owner hash")
|
||||
}
|
||||
|
||||
for _, tc := range []struct {
|
||||
rr *NSEC3
|
||||
name string
|
||||
covers bool
|
||||
}{
|
||||
// positive tests
|
||||
{ // name hash between owner hash and next hash
|
||||
rr: &NSEC3{
|
||||
Hdr: RR_Header{Name: "2N1TB3VAIRUOBL6RKDVII42N9TFMIALP.com."},
|
||||
Hash: 1,
|
||||
Flags: 1,
|
||||
Iterations: 5,
|
||||
Salt: "F10E9F7EA83FC8F3",
|
||||
NextDomain: "PT3RON8N7PM3A0OE989IB84OOSADP7O8",
|
||||
},
|
||||
name: "bsd.com.",
|
||||
covers: true,
|
||||
},
|
||||
{ // end of zone, name hash is after owner hash
|
||||
rr: &NSEC3{
|
||||
Hdr: RR_Header{Name: "3v62ulr0nre83v0rja2vjgtlif9v6rab.com."},
|
||||
Hash: 1,
|
||||
Flags: 1,
|
||||
Iterations: 5,
|
||||
Salt: "F10E9F7EA83FC8F3",
|
||||
NextDomain: "2N1TB3VAIRUOBL6RKDVII42N9TFMIALP",
|
||||
},
|
||||
name: "csd.com.",
|
||||
covers: true,
|
||||
},
|
||||
{ // end of zone, name hash is before beginning of zone
|
||||
rr: &NSEC3{
|
||||
Hdr: RR_Header{Name: "PT3RON8N7PM3A0OE989IB84OOSADP7O8.com."},
|
||||
Hash: 1,
|
||||
Flags: 1,
|
||||
Iterations: 5,
|
||||
Salt: "F10E9F7EA83FC8F3",
|
||||
NextDomain: "3V62ULR0NRE83V0RJA2VJGTLIF9V6RAB",
|
||||
},
|
||||
name: "asd.com.",
|
||||
covers: true,
|
||||
},
|
||||
// negative tests
|
||||
{ // too short owner name
|
||||
rr: &NSEC3{
|
||||
Hdr: RR_Header{Name: "nl."},
|
||||
Hash: 1,
|
||||
Flags: 1,
|
||||
Iterations: 5,
|
||||
Salt: "F10E9F7EA83FC8F3",
|
||||
NextDomain: "39P99DCGG0MDLARTCRMCF6OFLLUL7PR6",
|
||||
},
|
||||
name: "asd.com.",
|
||||
covers: false,
|
||||
},
|
||||
{ // outside of zone
|
||||
rr: &NSEC3{
|
||||
Hdr: RR_Header{Name: "39p91242oslggest5e6a7cci4iaeqvnk.nl."},
|
||||
Hash: 1,
|
||||
Flags: 1,
|
||||
Iterations: 5,
|
||||
Salt: "F10E9F7EA83FC8F3",
|
||||
NextDomain: "39P99DCGG0MDLARTCRMCF6OFLLUL7PR6",
|
||||
},
|
||||
name: "asd.com.",
|
||||
covers: false,
|
||||
},
|
||||
{ // empty interval
|
||||
rr: &NSEC3{
|
||||
Hdr: RR_Header{Name: "2n1tb3vairuobl6rkdvii42n9tfmialp.com."},
|
||||
Hash: 1,
|
||||
Flags: 1,
|
||||
Iterations: 5,
|
||||
Salt: "F10E9F7EA83FC8F3",
|
||||
NextDomain: "2N1TB3VAIRUOBL6RKDVII42N9TFMIALP",
|
||||
},
|
||||
name: "asd.com.",
|
||||
covers: false,
|
||||
},
|
||||
{ // name hash is before owner hash, not covered
|
||||
rr: &NSEC3{
|
||||
Hdr: RR_Header{Name: "3V62ULR0NRE83V0RJA2VJGTLIF9V6RAB.com."},
|
||||
Hash: 1,
|
||||
Flags: 1,
|
||||
Iterations: 5,
|
||||
Salt: "F10E9F7EA83FC8F3",
|
||||
NextDomain: "PT3RON8N7PM3A0OE989IB84OOSADP7O8",
|
||||
},
|
||||
name: "asd.com.",
|
||||
covers: false,
|
||||
},
|
||||
} {
|
||||
covers := tc.rr.Cover(tc.name)
|
||||
if tc.covers != covers {
|
||||
t.Fatalf("Cover failed for %s: expected %t, got %t [record: %s]", tc.name, tc.covers, covers, tc.rr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
18
vendor/github.com/miekg/dns/parse_test.go
сгенерированный
поставляемый
@@ -1509,3 +1509,21 @@ func TestParseURI(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseAVC(t *testing.T) {
|
||||
avcs := map[string]string{
|
||||
`example.org. IN AVC "app-name:WOLFGANG|app-class:OAM|business=yes"`: `example.org. 3600 IN AVC "app-name:WOLFGANG|app-class:OAM|business=yes"`,
|
||||
}
|
||||
for avc, o := range avcs {
|
||||
rr, err := NewRR(avc)
|
||||
if err != nil {
|
||||
t.Error("failed to parse RR: ", err)
|
||||
continue
|
||||
}
|
||||
if rr.String() != o {
|
||||
t.Errorf("`%s' should be equal to\n`%s', but is `%s'", avc, o, rr.String())
|
||||
} else {
|
||||
t.Logf("RR is OK: `%s'", rr.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
13
vendor/github.com/miekg/dns/scan_rr.go
сгенерированный
поставляемый
@@ -1807,6 +1807,18 @@ func setSPF(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
|
||||
return rr, nil, c1
|
||||
}
|
||||
|
||||
func setAVC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
|
||||
rr := new(AVC)
|
||||
rr.Hdr = h
|
||||
|
||||
s, e, c1 := endingToTxtSlice(c, "bad AVC Txt", f)
|
||||
if e != nil {
|
||||
return nil, e, ""
|
||||
}
|
||||
rr.Txt = s
|
||||
return rr, nil, c1
|
||||
}
|
||||
|
||||
func setTXT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
|
||||
rr := new(TXT)
|
||||
rr.Hdr = h
|
||||
@@ -2158,6 +2170,7 @@ var typeToparserFunc = map[uint16]parserFunc{
|
||||
TypeSMIMEA: {setSMIMEA, true},
|
||||
TypeSOA: {setSOA, false},
|
||||
TypeSPF: {setSPF, true},
|
||||
TypeAVC: {setAVC, true},
|
||||
TypeSRV: {setSRV, false},
|
||||
TypeSSHFP: {setSSHFP, true},
|
||||
TypeTALINK: {setTALINK, false},
|
||||
|
||||
8
vendor/github.com/miekg/dns/types.go
сгенерированный
поставляемый
@@ -91,6 +91,7 @@ const (
|
||||
TypeEUI64 uint16 = 109
|
||||
TypeURI uint16 = 256
|
||||
TypeCAA uint16 = 257
|
||||
TypeAVC uint16 = 258
|
||||
|
||||
TypeTKEY uint16 = 249
|
||||
TypeTSIG uint16 = 250
|
||||
@@ -530,6 +531,13 @@ type SPF struct {
|
||||
|
||||
func (rr *SPF) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
|
||||
|
||||
type AVC struct {
|
||||
Hdr RR_Header
|
||||
Txt []string `dns:"txt"`
|
||||
}
|
||||
|
||||
func (rr *AVC) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
|
||||
|
||||
type SRV struct {
|
||||
Hdr RR_Header
|
||||
Priority uint16
|
||||
|
||||
146
vendor/github.com/miekg/dns/zcompress.go
сгенерированный
поставляемый
@@ -5,99 +5,95 @@ package dns
|
||||
|
||||
func compressionLenHelperType(c map[string]int, r RR) {
|
||||
switch x := r.(type) {
|
||||
case *KX:
|
||||
compressionLenHelper(c, x.Exchanger)
|
||||
case *MX:
|
||||
compressionLenHelper(c, x.Mx)
|
||||
case *NSEC:
|
||||
compressionLenHelper(c, x.NextDomain)
|
||||
case *DNAME:
|
||||
compressionLenHelper(c, x.Target)
|
||||
case *HIP:
|
||||
for i := range x.RendezvousServers {
|
||||
compressionLenHelper(c, x.RendezvousServers[i])
|
||||
}
|
||||
case *CNAME:
|
||||
compressionLenHelper(c, x.Target)
|
||||
case *MR:
|
||||
compressionLenHelper(c, x.Mr)
|
||||
case *PX:
|
||||
compressionLenHelper(c, x.Map822)
|
||||
compressionLenHelper(c, x.Mapx400)
|
||||
case *SIG:
|
||||
compressionLenHelper(c, x.SignerName)
|
||||
case *SRV:
|
||||
compressionLenHelper(c, x.Target)
|
||||
case *TALINK:
|
||||
compressionLenHelper(c, x.PreviousName)
|
||||
compressionLenHelper(c, x.NextName)
|
||||
case *LP:
|
||||
compressionLenHelper(c, x.Fqdn)
|
||||
case *NAPTR:
|
||||
compressionLenHelper(c, x.Replacement)
|
||||
case *NS:
|
||||
compressionLenHelper(c, x.Ns)
|
||||
case *RP:
|
||||
compressionLenHelper(c, x.Mbox)
|
||||
compressionLenHelper(c, x.Txt)
|
||||
case *RRSIG:
|
||||
compressionLenHelper(c, x.SignerName)
|
||||
case *TKEY:
|
||||
compressionLenHelper(c, x.Algorithm)
|
||||
case *TSIG:
|
||||
compressionLenHelper(c, x.Algorithm)
|
||||
case *AFSDB:
|
||||
compressionLenHelper(c, x.Hostname)
|
||||
case *MF:
|
||||
compressionLenHelper(c, x.Mf)
|
||||
case *RT:
|
||||
compressionLenHelper(c, x.Host)
|
||||
case *MINFO:
|
||||
compressionLenHelper(c, x.Rmail)
|
||||
compressionLenHelper(c, x.Email)
|
||||
case *PTR:
|
||||
compressionLenHelper(c, x.Ptr)
|
||||
case *SOA:
|
||||
compressionLenHelper(c, x.Ns)
|
||||
compressionLenHelper(c, x.Mbox)
|
||||
case *MD:
|
||||
compressionLenHelper(c, x.Md)
|
||||
case *NSAPPTR:
|
||||
compressionLenHelper(c, x.Ptr)
|
||||
case *MG:
|
||||
compressionLenHelper(c, x.Mg)
|
||||
case *AFSDB:
|
||||
compressionLenHelper(c, x.Hostname)
|
||||
case *HIP:
|
||||
for i := range x.RendezvousServers {
|
||||
compressionLenHelper(c, x.RendezvousServers[i])
|
||||
}
|
||||
case *LP:
|
||||
compressionLenHelper(c, x.Fqdn)
|
||||
case *CNAME:
|
||||
compressionLenHelper(c, x.Target)
|
||||
case *MB:
|
||||
compressionLenHelper(c, x.Mb)
|
||||
case *RP:
|
||||
compressionLenHelper(c, x.Mbox)
|
||||
compressionLenHelper(c, x.Txt)
|
||||
case *RRSIG:
|
||||
compressionLenHelper(c, x.SignerName)
|
||||
case *MF:
|
||||
compressionLenHelper(c, x.Mf)
|
||||
case *MINFO:
|
||||
compressionLenHelper(c, x.Rmail)
|
||||
compressionLenHelper(c, x.Email)
|
||||
case *SIG:
|
||||
compressionLenHelper(c, x.SignerName)
|
||||
case *SRV:
|
||||
compressionLenHelper(c, x.Target)
|
||||
case *TSIG:
|
||||
compressionLenHelper(c, x.Algorithm)
|
||||
case *KX:
|
||||
compressionLenHelper(c, x.Exchanger)
|
||||
case *MG:
|
||||
compressionLenHelper(c, x.Mg)
|
||||
case *NSAPPTR:
|
||||
compressionLenHelper(c, x.Ptr)
|
||||
case *PX:
|
||||
compressionLenHelper(c, x.Map822)
|
||||
compressionLenHelper(c, x.Mapx400)
|
||||
case *DNAME:
|
||||
compressionLenHelper(c, x.Target)
|
||||
case *MR:
|
||||
compressionLenHelper(c, x.Mr)
|
||||
case *MX:
|
||||
compressionLenHelper(c, x.Mx)
|
||||
case *TKEY:
|
||||
compressionLenHelper(c, x.Algorithm)
|
||||
case *NSEC:
|
||||
compressionLenHelper(c, x.NextDomain)
|
||||
case *TALINK:
|
||||
compressionLenHelper(c, x.PreviousName)
|
||||
compressionLenHelper(c, x.NextName)
|
||||
case *MD:
|
||||
compressionLenHelper(c, x.Md)
|
||||
case *NAPTR:
|
||||
compressionLenHelper(c, x.Replacement)
|
||||
case *NS:
|
||||
compressionLenHelper(c, x.Ns)
|
||||
case *RT:
|
||||
compressionLenHelper(c, x.Host)
|
||||
}
|
||||
}
|
||||
|
||||
func compressionLenSearchType(c map[string]int, r RR) (int, bool) {
|
||||
switch x := r.(type) {
|
||||
case *MF:
|
||||
k1, ok1 := compressionLenSearch(c, x.Mf)
|
||||
return k1, ok1
|
||||
case *MG:
|
||||
k1, ok1 := compressionLenSearch(c, x.Mg)
|
||||
return k1, ok1
|
||||
case *MINFO:
|
||||
k1, ok1 := compressionLenSearch(c, x.Rmail)
|
||||
k2, ok2 := compressionLenSearch(c, x.Email)
|
||||
return k1 + k2, ok1 && ok2
|
||||
case *MR:
|
||||
k1, ok1 := compressionLenSearch(c, x.Mr)
|
||||
return k1, ok1
|
||||
case *PTR:
|
||||
k1, ok1 := compressionLenSearch(c, x.Ptr)
|
||||
return k1, ok1
|
||||
case *AFSDB:
|
||||
k1, ok1 := compressionLenSearch(c, x.Hostname)
|
||||
return k1, ok1
|
||||
case *CNAME:
|
||||
k1, ok1 := compressionLenSearch(c, x.Target)
|
||||
case *MB:
|
||||
k1, ok1 := compressionLenSearch(c, x.Mb)
|
||||
return k1, ok1
|
||||
case *MD:
|
||||
k1, ok1 := compressionLenSearch(c, x.Md)
|
||||
return k1, ok1
|
||||
case *MF:
|
||||
k1, ok1 := compressionLenSearch(c, x.Mf)
|
||||
return k1, ok1
|
||||
case *NS:
|
||||
k1, ok1 := compressionLenSearch(c, x.Ns)
|
||||
return k1, ok1
|
||||
case *RT:
|
||||
k1, ok1 := compressionLenSearch(c, x.Host)
|
||||
return k1, ok1
|
||||
@@ -105,15 +101,19 @@ func compressionLenSearchType(c map[string]int, r RR) (int, bool) {
|
||||
k1, ok1 := compressionLenSearch(c, x.Ns)
|
||||
k2, ok2 := compressionLenSearch(c, x.Mbox)
|
||||
return k1 + k2, ok1 && ok2
|
||||
case *MB:
|
||||
k1, ok1 := compressionLenSearch(c, x.Mb)
|
||||
case *CNAME:
|
||||
k1, ok1 := compressionLenSearch(c, x.Target)
|
||||
return k1, ok1
|
||||
case *MINFO:
|
||||
k1, ok1 := compressionLenSearch(c, x.Rmail)
|
||||
k2, ok2 := compressionLenSearch(c, x.Email)
|
||||
return k1 + k2, ok1 && ok2
|
||||
case *MR:
|
||||
k1, ok1 := compressionLenSearch(c, x.Mr)
|
||||
return k1, ok1
|
||||
case *MX:
|
||||
k1, ok1 := compressionLenSearch(c, x.Mx)
|
||||
return k1, ok1
|
||||
case *NS:
|
||||
k1, ok1 := compressionLenSearch(c, x.Ns)
|
||||
return k1, ok1
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
32
vendor/github.com/miekg/dns/zmsg.go
сгенерированный
поставляемый
@@ -61,6 +61,20 @@ func (rr *ANY) pack(msg []byte, off int, compression map[string]int, compress bo
|
||||
return off, nil
|
||||
}
|
||||
|
||||
func (rr *AVC) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
|
||||
off, err := rr.Hdr.pack(msg, off, compression, compress)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
headerEnd := off
|
||||
off, err = packStringTxt(rr.Txt, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
rr.Header().Rdlength = uint16(off - headerEnd)
|
||||
return off, nil
|
||||
}
|
||||
|
||||
func (rr *CAA) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
|
||||
off, err := rr.Hdr.pack(msg, off, compression, compress)
|
||||
if err != nil {
|
||||
@@ -1528,6 +1542,23 @@ func unpackANY(h RR_Header, msg []byte, off int) (RR, int, error) {
|
||||
return rr, off, err
|
||||
}
|
||||
|
||||
func unpackAVC(h RR_Header, msg []byte, off int) (RR, int, error) {
|
||||
rr := new(AVC)
|
||||
rr.Hdr = h
|
||||
if noRdata(h) {
|
||||
return rr, off, nil
|
||||
}
|
||||
var err error
|
||||
rdStart := off
|
||||
_ = rdStart
|
||||
|
||||
rr.Txt, off, err = unpackStringTxt(msg, off)
|
||||
if err != nil {
|
||||
return rr, off, err
|
||||
}
|
||||
return rr, off, err
|
||||
}
|
||||
|
||||
func unpackCAA(h RR_Header, msg []byte, off int) (RR, int, error) {
|
||||
rr := new(CAA)
|
||||
rr.Hdr = h
|
||||
@@ -3467,6 +3498,7 @@ var typeToUnpack = map[uint16]func(RR_Header, []byte, int) (RR, int, error){
|
||||
TypeAAAA: unpackAAAA,
|
||||
TypeAFSDB: unpackAFSDB,
|
||||
TypeANY: unpackANY,
|
||||
TypeAVC: unpackAVC,
|
||||
TypeCAA: unpackCAA,
|
||||
TypeCDNSKEY: unpackCDNSKEY,
|
||||
TypeCDS: unpackCDS,
|
||||
|
||||
15
vendor/github.com/miekg/dns/ztypes.go
сгенерированный
поставляемый
@@ -14,6 +14,7 @@ var TypeToRR = map[uint16]func() RR{
|
||||
TypeAAAA: func() RR { return new(AAAA) },
|
||||
TypeAFSDB: func() RR { return new(AFSDB) },
|
||||
TypeANY: func() RR { return new(ANY) },
|
||||
TypeAVC: func() RR { return new(AVC) },
|
||||
TypeCAA: func() RR { return new(CAA) },
|
||||
TypeCDNSKEY: func() RR { return new(CDNSKEY) },
|
||||
TypeCDS: func() RR { return new(CDS) },
|
||||
@@ -86,6 +87,7 @@ var TypeToString = map[uint16]string{
|
||||
TypeAFSDB: "AFSDB",
|
||||
TypeANY: "ANY",
|
||||
TypeATMA: "ATMA",
|
||||
TypeAVC: "AVC",
|
||||
TypeAXFR: "AXFR",
|
||||
TypeCAA: "CAA",
|
||||
TypeCDNSKEY: "CDNSKEY",
|
||||
@@ -166,6 +168,7 @@ func (rr *A) Header() *RR_Header { return &rr.Hdr }
|
||||
func (rr *AAAA) Header() *RR_Header { return &rr.Hdr }
|
||||
func (rr *AFSDB) Header() *RR_Header { return &rr.Hdr }
|
||||
func (rr *ANY) Header() *RR_Header { return &rr.Hdr }
|
||||
func (rr *AVC) Header() *RR_Header { return &rr.Hdr }
|
||||
func (rr *CAA) Header() *RR_Header { return &rr.Hdr }
|
||||
func (rr *CDNSKEY) Header() *RR_Header { return &rr.Hdr }
|
||||
func (rr *CDS) Header() *RR_Header { return &rr.Hdr }
|
||||
@@ -252,6 +255,13 @@ func (rr *ANY) len() int {
|
||||
l := rr.Hdr.len()
|
||||
return l
|
||||
}
|
||||
func (rr *AVC) len() int {
|
||||
l := rr.Hdr.len()
|
||||
for _, x := range rr.Txt {
|
||||
l += len(x) + 1
|
||||
}
|
||||
return l
|
||||
}
|
||||
func (rr *CAA) len() int {
|
||||
l := rr.Hdr.len()
|
||||
l++ // Flag
|
||||
@@ -649,6 +659,11 @@ func (rr *AFSDB) copy() RR {
|
||||
func (rr *ANY) copy() RR {
|
||||
return &ANY{*rr.Hdr.copyHeader()}
|
||||
}
|
||||
func (rr *AVC) copy() RR {
|
||||
Txt := make([]string, len(rr.Txt))
|
||||
copy(Txt, rr.Txt)
|
||||
return &AVC{*rr.Hdr.copyHeader(), Txt}
|
||||
}
|
||||
func (rr *CAA) copy() RR {
|
||||
return &CAA{*rr.Hdr.copyHeader(), rr.Flag, rr.Tag, rr.Value}
|
||||
}
|
||||
|
||||
3
vendor/github.com/minio/minio-go/README.md
сгенерированный
поставляемый
@@ -1,4 +1,5 @@
|
||||
# Minio Go Client SDK for Amazon S3 Compatible Cloud Storage [](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 [](https://slack.minio.io)
|
||||
|
||||
The Minio Go Client SDK provides simple APIs to access any Amazon S3 compatible object storage.
|
||||
|
||||
**Supported cloud storage providers:**
|
||||
|
||||
10
vendor/github.com/minio/minio-go/api-error-response.go
сгенерированный
поставляемый
@@ -149,6 +149,16 @@ func httpRespToErrorResponse(resp *http.Response, bucketName, objectName string)
|
||||
return errResp
|
||||
}
|
||||
|
||||
// ErrTransferAccelerationBucket - bucket name is invalid to be used with transfer acceleration.
|
||||
func ErrTransferAccelerationBucket(bucketName string) error {
|
||||
msg := fmt.Sprintf("The name of the bucket used for Transfer Acceleration must be DNS-compliant and must not contain periods (\".\").")
|
||||
return ErrorResponse{
|
||||
Code: "InvalidArgument",
|
||||
Message: msg,
|
||||
BucketName: bucketName,
|
||||
}
|
||||
}
|
||||
|
||||
// ErrEntityTooLarge - Input size is larger than supported maximum.
|
||||
func ErrEntityTooLarge(totalSize, maxObjectSize int64, bucketName, objectName string) error {
|
||||
msg := fmt.Sprintf("Your proposed upload size ‘%d’ exceeds the maximum allowed object size ‘%d’ for single PUT operation.", totalSize, maxObjectSize)
|
||||
|
||||
37
vendor/github.com/minio/minio-go/api-get-object.go
сгенерированный
поставляемый
@@ -212,10 +212,12 @@ type Object struct {
|
||||
reqCh chan<- getRequest
|
||||
resCh <-chan getResponse
|
||||
doneCh chan<- struct{}
|
||||
prevOffset int64
|
||||
currOffset int64
|
||||
objectInfo ObjectInfo
|
||||
|
||||
// Ask lower level to initiate data fetching based on currOffset
|
||||
seekData bool
|
||||
|
||||
// Keeps track of closed call.
|
||||
isClosed bool
|
||||
|
||||
@@ -258,6 +260,10 @@ func (o *Object) doGetRequest(request getRequest) (getResponse, error) {
|
||||
if response.Error != nil {
|
||||
return response, response.Error
|
||||
}
|
||||
|
||||
// Data are ready on the wire, no need to reinitiate connection in lower level
|
||||
o.seekData = false
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
@@ -266,8 +272,6 @@ func (o *Object) doGetRequest(request getRequest) (getResponse, error) {
|
||||
func (o *Object) setOffset(bytesRead int64) error {
|
||||
// Update the currentOffset.
|
||||
o.currOffset += bytesRead
|
||||
// Save the current offset as previous offset.
|
||||
o.prevOffset = o.currOffset
|
||||
|
||||
if o.currOffset >= o.objectInfo.Size {
|
||||
return io.EOF
|
||||
@@ -303,22 +307,9 @@ func (o *Object) Read(b []byte) (n int, err error) {
|
||||
readReq.isFirstReq = true
|
||||
}
|
||||
|
||||
// Verify if offset has changed and currOffset is greater than
|
||||
// previous offset. Perhaps due to Seek().
|
||||
offsetChange := o.prevOffset - o.currOffset
|
||||
if offsetChange < 0 {
|
||||
offsetChange = -offsetChange
|
||||
}
|
||||
if offsetChange > 0 {
|
||||
// Fetch the new reader at the current offset again.
|
||||
readReq.Offset = o.currOffset
|
||||
readReq.DidOffsetChange = true
|
||||
} else {
|
||||
// No offset changes no need to fetch new reader, continue
|
||||
// reading.
|
||||
readReq.DidOffsetChange = false
|
||||
readReq.Offset = 0
|
||||
}
|
||||
// Ask to establish a new data fetch routine based on seekData flag
|
||||
readReq.DidOffsetChange = o.seekData
|
||||
readReq.Offset = o.currOffset
|
||||
|
||||
// Send and receive from the first request.
|
||||
response, err := o.doGetRequest(readReq)
|
||||
@@ -430,8 +421,6 @@ func (o *Object) ReadAt(b []byte, offset int64) (n int, err error) {
|
||||
if !o.objectInfoSet {
|
||||
// Update the currentOffset.
|
||||
o.currOffset += bytesRead
|
||||
// Save the current offset as previous offset.
|
||||
o.prevOffset = o.currOffset
|
||||
} else {
|
||||
// If this was not the first request update
|
||||
// the offsets and compare against objectInfo
|
||||
@@ -492,8 +481,6 @@ func (o *Object) Seek(offset int64, whence int) (n int64, err error) {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
// Save current offset as previous offset.
|
||||
o.prevOffset = o.currOffset
|
||||
|
||||
// Switch through whence.
|
||||
switch whence {
|
||||
@@ -527,6 +514,10 @@ func (o *Object) Seek(offset int64, whence int) (n int64, err error) {
|
||||
if o.prevErr == io.EOF {
|
||||
o.prevErr = nil
|
||||
}
|
||||
|
||||
// Ask lower level to fetch again from source
|
||||
o.seekData = true
|
||||
|
||||
// Return the effective offset.
|
||||
return o.currOffset, nil
|
||||
}
|
||||
|
||||
43
vendor/github.com/minio/minio-go/api.go
сгенерированный
поставляемый
@@ -71,6 +71,9 @@ type Client struct {
|
||||
isTraceEnabled bool
|
||||
traceOutput io.Writer
|
||||
|
||||
// S3 specific accelerated endpoint.
|
||||
s3AccelerateEndpoint string
|
||||
|
||||
// Random seed.
|
||||
random *rand.Rand
|
||||
}
|
||||
@@ -78,7 +81,7 @@ type Client struct {
|
||||
// Global constants.
|
||||
const (
|
||||
libraryName = "minio-go"
|
||||
libraryVersion = "2.0.3"
|
||||
libraryVersion = "2.0.4"
|
||||
)
|
||||
|
||||
// User Agent should always following the below style.
|
||||
@@ -206,8 +209,7 @@ func privateNew(endpoint, accessKeyID, secretAccessKey string, secure bool) (*Cl
|
||||
|
||||
// SetAppInfo - add application details to user agent.
|
||||
func (c *Client) SetAppInfo(appName string, appVersion string) {
|
||||
// if app name and version is not set, we do not a new user
|
||||
// agent.
|
||||
// if app name and version not set, we do not set a new user agent.
|
||||
if appName != "" && appVersion != "" {
|
||||
c.appInfo = struct {
|
||||
appName string
|
||||
@@ -258,8 +260,18 @@ func (c *Client) TraceOff() {
|
||||
c.isTraceEnabled = false
|
||||
}
|
||||
|
||||
// requestMetadata - is container for all the values to make a
|
||||
// request.
|
||||
// SetS3TransferAccelerate - turns s3 accelerated endpoint on or off for all your
|
||||
// requests. This feature is only specific to S3 for all other endpoints this
|
||||
// function does nothing. To read further details on s3 transfer acceleration
|
||||
// please vist -
|
||||
// http://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html
|
||||
func (c *Client) SetS3TransferAccelerate(accelerateEndpoint string) {
|
||||
if s3utils.IsAmazonEndpoint(c.endpointURL) {
|
||||
c.s3AccelerateEndpoint = accelerateEndpoint
|
||||
}
|
||||
}
|
||||
|
||||
// requestMetadata - is container for all the values to make a request.
|
||||
type requestMetadata struct {
|
||||
// If set newRequest presigns the URL.
|
||||
presignURL bool
|
||||
@@ -601,10 +613,10 @@ func (c Client) newRequest(method string, metadata requestMetadata) (req *http.R
|
||||
req.Body = ioutil.NopCloser(metadata.contentBody)
|
||||
}
|
||||
|
||||
// FIXEM: Enable this when Google Cloud Storage properly supports 100-continue.
|
||||
// FIXME: Enable this when Google Cloud Storage properly supports 100-continue.
|
||||
// Skip setting 'expect' header for Google Cloud Storage, there
|
||||
// are some known issues - https://github.com/restic/restic/issues/520
|
||||
if !s3utils.IsGoogleEndpoint(c.endpointURL) {
|
||||
if !s3utils.IsGoogleEndpoint(c.endpointURL) && c.s3AccelerateEndpoint == "" {
|
||||
// Set 'Expect' header for the request.
|
||||
req.Header.Set("Expect", "100-continue")
|
||||
}
|
||||
@@ -672,9 +684,22 @@ func (c Client) makeTargetURL(bucketName, objectName, bucketLocation string, que
|
||||
host := c.endpointURL.Host
|
||||
// For Amazon S3 endpoint, try to fetch location based endpoint.
|
||||
if s3utils.IsAmazonEndpoint(c.endpointURL) {
|
||||
// Fetch new host based on the bucket location.
|
||||
host = getS3Endpoint(bucketLocation)
|
||||
if c.s3AccelerateEndpoint != "" && bucketName != "" {
|
||||
// http://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html
|
||||
// Disable transfer acceleration for non-compliant bucket names.
|
||||
if strings.Contains(bucketName, ".") {
|
||||
return nil, ErrTransferAccelerationBucket(bucketName)
|
||||
}
|
||||
// If transfer acceleration is requested set new host.
|
||||
// For more details about enabling transfer acceleration read here.
|
||||
// http://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html
|
||||
host = c.s3AccelerateEndpoint
|
||||
} else {
|
||||
// Fetch new host based on the bucket location.
|
||||
host = getS3Endpoint(bucketLocation)
|
||||
}
|
||||
}
|
||||
|
||||
// Save scheme.
|
||||
scheme := c.endpointURL.Scheme
|
||||
|
||||
|
||||
2
vendor/github.com/minio/minio-go/api_functional_v2_test.go
сгенерированный
поставляемый
@@ -943,7 +943,7 @@ func TestCopyObjectV2(t *testing.T) {
|
||||
}
|
||||
|
||||
// Set copy conditions.
|
||||
copyConds := NewCopyConditions()
|
||||
copyConds := CopyConditions{}
|
||||
err = copyConds.SetModified(time.Date(2014, time.April, 0, 0, 0, 0, 0, time.UTC))
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
|
||||
151
vendor/github.com/minio/minio-go/api_functional_v4_test.go
сгенерированный
поставляемый
@@ -1255,6 +1255,7 @@ func TestGetObjectReadSeekFunctional(t *testing.T) {
|
||||
|
||||
// Generate data more than 32K
|
||||
buf := bytes.Repeat([]byte("2"), rand.Intn(1<<20)+32*1024)
|
||||
bufSize := len(buf)
|
||||
|
||||
// Save the data
|
||||
objectName := randString(60, rand.NewSource(time.Now().UnixNano()), "")
|
||||
@@ -1263,10 +1264,21 @@ func TestGetObjectReadSeekFunctional(t *testing.T) {
|
||||
t.Fatal("Error:", err, bucketName, objectName)
|
||||
}
|
||||
|
||||
if n != int64(len(buf)) {
|
||||
if n != int64(bufSize) {
|
||||
t.Fatalf("Error: number of bytes does not match, want %v, got %v\n", len(buf), n)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
err = c.RemoveObject(bucketName, objectName)
|
||||
if err != nil {
|
||||
t.Fatal("Error: ", err)
|
||||
}
|
||||
err = c.RemoveBucket(bucketName)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Read the data back
|
||||
r, err := c.GetObject(bucketName, objectName)
|
||||
if err != nil {
|
||||
@@ -1277,77 +1289,86 @@ func TestGetObjectReadSeekFunctional(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err, bucketName, objectName)
|
||||
}
|
||||
if st.Size != int64(len(buf)) {
|
||||
if st.Size != int64(bufSize) {
|
||||
t.Fatalf("Error: number of bytes in stat does not match, want %v, got %v\n",
|
||||
len(buf), st.Size)
|
||||
}
|
||||
|
||||
offset := int64(2048)
|
||||
n, err = r.Seek(offset, 0)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err, offset)
|
||||
}
|
||||
if n != offset {
|
||||
t.Fatalf("Error: number of bytes seeked does not match, want %v, got %v\n",
|
||||
offset, n)
|
||||
}
|
||||
n, err = r.Seek(0, 1)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
if n != offset {
|
||||
t.Fatalf("Error: number of current seek does not match, want %v, got %v\n",
|
||||
offset, n)
|
||||
}
|
||||
_, err = r.Seek(offset, 2)
|
||||
if err == nil {
|
||||
t.Fatal("Error: seek on positive offset for whence '2' should error out")
|
||||
}
|
||||
n, err = r.Seek(-offset, 2)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
if n != st.Size-offset {
|
||||
t.Fatalf("Error: number of bytes seeked back does not match, want %d, got %v\n", st.Size-offset, n)
|
||||
}
|
||||
|
||||
var buffer1 bytes.Buffer
|
||||
if _, err = io.CopyN(&buffer1, r, st.Size); err != nil {
|
||||
if err != io.EOF {
|
||||
t.Fatal("Error:", err)
|
||||
// This following function helps us to compare data from the reader after seek
|
||||
// with the data from the original buffer
|
||||
cmpData := func(r io.Reader, start, end int) {
|
||||
if end-start == 0 {
|
||||
return
|
||||
}
|
||||
buffer := bytes.NewBuffer([]byte{})
|
||||
if _, err := io.CopyN(buffer, r, int64(bufSize)); err != nil {
|
||||
if err != io.EOF {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
}
|
||||
if !bytes.Equal(buf[start:end], buffer.Bytes()) {
|
||||
t.Fatal("Error: Incorrect read bytes v/s original buffer.")
|
||||
}
|
||||
}
|
||||
if !bytes.Equal(buf[len(buf)-int(offset):], buffer1.Bytes()) {
|
||||
t.Fatal("Error: Incorrect read bytes v/s original buffer.")
|
||||
|
||||
// Generic seek error for errors other than io.EOF
|
||||
seekErr := errors.New("seek error")
|
||||
|
||||
testCases := []struct {
|
||||
offset int64
|
||||
whence int
|
||||
pos int64
|
||||
err error
|
||||
shouldCmp bool
|
||||
start int
|
||||
end int
|
||||
}{
|
||||
// Start from offset 0, fetch data and compare
|
||||
{0, 0, 0, nil, true, 0, 0},
|
||||
// Start from offset 2048, fetch data and compare
|
||||
{2048, 0, 2048, nil, true, 2048, bufSize},
|
||||
// Start from offset larger than possible
|
||||
{int64(bufSize) + 1024, 0, 0, seekErr, false, 0, 0},
|
||||
// Move to offset 0 without comparing
|
||||
{0, 0, 0, nil, false, 0, 0},
|
||||
// Move one step forward and compare
|
||||
{1, 1, 1, nil, true, 1, bufSize},
|
||||
// Move larger than possible
|
||||
{int64(bufSize), 1, 0, seekErr, false, 0, 0},
|
||||
// Provide negative offset with CUR_SEEK
|
||||
{int64(-1), 1, 0, seekErr, false, 0, 0},
|
||||
// Test with whence SEEK_END and with positive offset
|
||||
{1024, 2, int64(bufSize) - 1024, io.EOF, true, 0, 0},
|
||||
// Test with whence SEEK_END and with negative offset
|
||||
{-1024, 2, int64(bufSize) - 1024, nil, true, bufSize - 1024, bufSize},
|
||||
// Test with whence SEEK_END and with large negative offset
|
||||
{-int64(bufSize) * 2, 2, 0, seekErr, true, 0, 0},
|
||||
}
|
||||
|
||||
// Seek again and read again.
|
||||
n, err = r.Seek(offset-1, 0)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
if n != (offset - 1) {
|
||||
t.Fatalf("Error: number of bytes seeked back does not match, want %v, got %v\n", offset-1, n)
|
||||
}
|
||||
|
||||
var buffer2 bytes.Buffer
|
||||
if _, err = io.CopyN(&buffer2, r, st.Size); err != nil {
|
||||
if err != io.EOF {
|
||||
t.Fatal("Error:", err)
|
||||
for i, testCase := range testCases {
|
||||
// Perform seek operation
|
||||
n, err := r.Seek(testCase.offset, testCase.whence)
|
||||
// We expect an error
|
||||
if testCase.err == seekErr && err == nil {
|
||||
t.Fatalf("Test %d, unexpected err value: expected: %v, found: %v", i+1, testCase.err, err)
|
||||
}
|
||||
// We expect a specific error
|
||||
if testCase.err != seekErr && testCase.err != err {
|
||||
t.Fatalf("Test %d, unexpected err value: expected: %v, found: %v", i+1, testCase.err, err)
|
||||
}
|
||||
// If we expect an error go to the next loop
|
||||
if testCase.err != nil {
|
||||
continue
|
||||
}
|
||||
// Check the returned seek pos
|
||||
if n != testCase.pos {
|
||||
t.Fatalf("Test %d, error: number of bytes seeked does not match, want %v, got %v\n", i+1,
|
||||
testCase.pos, n)
|
||||
}
|
||||
// Compare only if shouldCmp is activated
|
||||
if testCase.shouldCmp {
|
||||
cmpData(r, testCase.start, testCase.end)
|
||||
}
|
||||
}
|
||||
// Verify now lesser bytes.
|
||||
if !bytes.Equal(buf[2047:], buffer2.Bytes()) {
|
||||
t.Fatal("Error: Incorrect read bytes v/s original buffer.")
|
||||
}
|
||||
|
||||
err = c.RemoveObject(bucketName, objectName)
|
||||
if err != nil {
|
||||
t.Fatal("Error: ", err)
|
||||
}
|
||||
err = c.RemoveBucket(bucketName)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1662,7 +1683,7 @@ func TestCopyObject(t *testing.T) {
|
||||
}
|
||||
|
||||
// Set copy conditions.
|
||||
copyConds := NewCopyConditions()
|
||||
copyConds := CopyConditions{}
|
||||
|
||||
// Start by setting wrong conditions
|
||||
err = copyConds.SetModified(time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC))
|
||||
@@ -1725,7 +1746,7 @@ func TestCopyObject(t *testing.T) {
|
||||
}
|
||||
|
||||
// CopyObject again but with wrong conditions
|
||||
copyConds = NewCopyConditions()
|
||||
copyConds = CopyConditions{}
|
||||
err = copyConds.SetUnmodified(time.Date(2014, time.April, 0, 0, 0, 0, 0, time.UTC))
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
|
||||
7
vendor/github.com/minio/minio-go/bucket-cache.go
сгенерированный
поставляемый
@@ -164,13 +164,6 @@ func (c Client) getBucketLocationRequest(bucketName string) (*http.Request, erro
|
||||
|
||||
// Set get bucket location always as path style.
|
||||
targetURL := c.endpointURL
|
||||
|
||||
// Requesting a bucket location from an accelerate endpoint returns a 400,
|
||||
// so default to us-east-1 for the lookup
|
||||
if s3utils.IsAmazonS3AccelerateEndpoint(c.endpointURL) {
|
||||
targetURL.Host = getS3Endpoint("us-east-1")
|
||||
}
|
||||
|
||||
targetURL.Path = path.Join(bucketName, "") + "/"
|
||||
targetURL.RawQuery = urlValues.Encode()
|
||||
|
||||
|
||||
10
vendor/github.com/minio/minio-go/copy-conditions.go
сгенерированный
поставляемый
@@ -41,11 +41,13 @@ type CopyConditions struct {
|
||||
conditions []copyCondition
|
||||
}
|
||||
|
||||
// NewCopyConditions - Instantiate new list of conditions.
|
||||
// NewCopyConditions - Instantiate new list of conditions. This
|
||||
// function is left behind for backward compatibility. The idiomatic
|
||||
// way to set an empty set of copy conditions is,
|
||||
// ``copyConditions := CopyConditions{}``.
|
||||
//
|
||||
func NewCopyConditions() CopyConditions {
|
||||
return CopyConditions{
|
||||
conditions: make([]copyCondition, 0),
|
||||
}
|
||||
return CopyConditions{}
|
||||
}
|
||||
|
||||
// SetMatchETag - set match etag.
|
||||
|
||||
89
vendor/github.com/minio/minio-go/docs/API.md
сгенерированный
поставляемый
@@ -1,4 +1,4 @@
|
||||
# Golang Client API Reference [](https://gitter.im/Minio/minio?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
# Minio Go Client API Reference [](https://slack.minio.io)
|
||||
|
||||
## Initialize Minio Client object.
|
||||
|
||||
@@ -60,7 +60,7 @@ func main() {
|
||||
|[`ListBuckets`](#ListBuckets) |[`PutObject`](#PutObject) |[`PresignedPutObject`](#PresignedPutObject) | [`GetBucketPolicy`](#GetBucketPolicy) | [`SetCustomTransport`](#SetCustomTransport) |
|
||||
|[`BucketExists`](#BucketExists) |[`CopyObject`](#CopyObject) |[`PresignedPostPolicy`](#PresignedPostPolicy) | [`ListBucketPolicies`](#ListBucketPolicies) | [`TraceOn`](#TraceOn) |
|
||||
| [`RemoveBucket`](#RemoveBucket) |[`StatObject`](#StatObject) | | [`SetBucketNotification`](#SetBucketNotification) | [`TraceOff`](#TraceOff) |
|
||||
|[`ListObjects`](#ListObjects) |[`RemoveObject`](#RemoveObject) | | [`GetBucketNotification`](#GetBucketNotification) |
|
||||
|[`ListObjects`](#ListObjects) |[`RemoveObject`](#RemoveObject) | | [`GetBucketNotification`](#GetBucketNotification) | [`SetS3TransferAccelerate`](#SetS3TransferAccelerate) |
|
||||
|[`ListObjectsV2`](#ListObjectsV2) | [`RemoveObjects`](#RemoveObjects) | | [`RemoveAllBucketNotification`](#RemoveAllBucketNotification) |
|
||||
|[`ListIncompleteUploads`](#ListIncompleteUploads) | [`RemoveIncompleteUpload`](#RemoveIncompleteUpload) | | [`ListenBucketNotification`](#ListenBucketNotification) |
|
||||
| | [`FPutObject`](#FPutObject) | | |
|
||||
@@ -69,7 +69,7 @@ func main() {
|
||||
## 1. Constructor
|
||||
<a name="Minio"></a>
|
||||
|
||||
### New(endpoint string, accessKeyID string, secretAccessKey string, ssl bool) (*Client, error)
|
||||
### New(endpoint, accessKeyID, secretAccessKey string, ssl bool) (*Client, error)
|
||||
Initializes a new client object.
|
||||
|
||||
__Parameters__
|
||||
@@ -86,7 +86,7 @@ __Parameters__
|
||||
## 2. Bucket operations
|
||||
|
||||
<a name="MakeBucket"></a>
|
||||
### MakeBucket(bucketName string, location string) error
|
||||
### MakeBucket(bucketName, location string) error
|
||||
Creates a new bucket.
|
||||
|
||||
|
||||
@@ -216,7 +216,7 @@ if err != nil {
|
||||
```
|
||||
|
||||
<a name="ListObjects"></a>
|
||||
### ListObjects(bucketName string, prefix string, recursive bool, doneCh chan struct{}) <-chan ObjectInfo
|
||||
### ListObjects(bucketName, prefix string, recursive bool, doneCh chan struct{}) <-chan ObjectInfo
|
||||
|
||||
Lists objects in a bucket.
|
||||
|
||||
@@ -267,7 +267,7 @@ for object := range objectCh {
|
||||
|
||||
|
||||
<a name="ListObjectsV2"></a>
|
||||
### ListObjectsV2(bucketName string, prefix string, recursive bool, doneCh chan struct{}) <-chan ObjectInfo
|
||||
### ListObjectsV2(bucketName, prefix string, recursive bool, doneCh chan struct{}) <-chan ObjectInfo
|
||||
|
||||
Lists objects in a bucket using the recommended listing API v2
|
||||
|
||||
@@ -317,7 +317,7 @@ for object := range objectCh {
|
||||
```
|
||||
|
||||
<a name="ListIncompleteUploads"></a>
|
||||
### ListIncompleteUploads(bucketName string, prefix string, recursive bool, doneCh chan struct{}) <- chan ObjectMultipartInfo
|
||||
### ListIncompleteUploads(bucketName, prefix string, recursive bool, doneCh chan struct{}) <- chan ObjectMultipartInfo
|
||||
|
||||
Lists partially uploaded objects in a bucket.
|
||||
|
||||
@@ -373,7 +373,7 @@ for multiPartObject := range multiPartObjectCh {
|
||||
## 3. Object operations
|
||||
|
||||
<a name="GetObject"></a>
|
||||
### GetObject(bucketName string, objectName string) (*Object, error)
|
||||
### GetObject(bucketName, objectName string) (*Object, error)
|
||||
|
||||
Downloads an object.
|
||||
|
||||
@@ -392,7 +392,7 @@ __Return Value__
|
||||
|
||||
|Param |Type |Description |
|
||||
|:---|:---| :---|
|
||||
|`object` | _*minio.Object_ |_minio.Object_ represents object reader |
|
||||
|`object` | _*minio.Object_ |_minio.Object_ represents object reader. It implements io.Reader, io.Seeker, io.ReaderAt and io.Closer interfaces. |
|
||||
|
||||
|
||||
__Example__
|
||||
@@ -418,7 +418,7 @@ if _, err = io.Copy(localFile, object); err != nil {
|
||||
```
|
||||
|
||||
<a name="FGetObject"></a>
|
||||
### FGetObject(bucketName string, objectName string, filePath string) error
|
||||
### FGetObject(bucketName, objectName, filePath string) error
|
||||
Downloads and saves the object as a file in the local filesystem.
|
||||
|
||||
|
||||
@@ -446,7 +446,7 @@ if err != nil {
|
||||
```
|
||||
|
||||
<a name="PutObject"></a>
|
||||
### PutObject(bucketName string, objectName string, reader io.Reader, contentType string) (n int, err error)
|
||||
### PutObject(bucketName, objectName string, reader io.Reader, contentType string) (n int, err error)
|
||||
|
||||
Uploads an object.
|
||||
|
||||
@@ -489,7 +489,7 @@ if err != nil {
|
||||
|
||||
|
||||
<a name="CopyObject"></a>
|
||||
### CopyObject(bucketName string, objectName string, objectSource string, conditions CopyConditions) error
|
||||
### CopyObject(bucketName, objectName, objectSource string, conditions CopyConditions) error
|
||||
|
||||
Copy a source object into a new object with the provided name in the provided bucket.
|
||||
|
||||
@@ -509,24 +509,34 @@ __Example__
|
||||
|
||||
|
||||
```go
|
||||
// Use-case-1
|
||||
// To copy an existing object to a new object with _no_ copy conditions.
|
||||
copyConditions := minio.CopyConditions{}
|
||||
err := minioClient.CopyObject("mybucket", "myobject", "my-sourcebucketname/my-sourceobjectname", copyConds)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
// All following conditions are allowed and can be combined together.
|
||||
// Use-case-2
|
||||
// To copy an existing object to a new object with the following copy conditions
|
||||
// 1. that matches a given ETag
|
||||
// 2. and modified after 1st April 2014
|
||||
// 3. but unmodified since 23rd April 2014
|
||||
|
||||
// Set copy conditions.
|
||||
var copyConds = minio.NewCopyConditions()
|
||||
// Set modified condition, copy object modified since 2014 April.
|
||||
copyConds.SetModified(time.Date(2014, time.April, 0, 0, 0, 0, 0, time.UTC))
|
||||
// Initialize empty copy conditions.
|
||||
var copyConds = minio.CopyConditions{}
|
||||
|
||||
// Set unmodified condition, copy object unmodified since 2014 April.
|
||||
// copyConds.SetUnmodified(time.Date(2014, time.April, 0, 0, 0, 0, 0, time.UTC))
|
||||
// copy object that matches the given ETag.
|
||||
copyConds.SetMatchETag("31624deb84149d2f8ef9c385918b653a")
|
||||
|
||||
// Set matching ETag condition, copy object which matches the following ETag.
|
||||
// copyConds.SetMatchETag("31624deb84149d2f8ef9c385918b653a")
|
||||
// and modified after 1st April 2014
|
||||
copyConds.SetModified(time.Date(2014, time.April, 1, 0, 0, 0, 0, time.UTC))
|
||||
|
||||
// Set matching ETag except condition, copy object which does not match the following ETag.
|
||||
// copyConds.SetMatchETagExcept("31624deb84149d2f8ef9c385918b653a")
|
||||
// but unmodified since 23rd April 2014
|
||||
copyConds.SetUnmodified(time.Date(2014, time.April, 23, 0, 0, 0, 0, time.UTC))
|
||||
|
||||
err := minioClient.CopyObject("mybucket", "myobject", "/my-sourcebucketname/my-sourceobjectname", copyConds)
|
||||
err := minioClient.CopyObject("mybucket", "myobject", "my-sourcebucketname/my-sourceobjectname", copyConds)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
@@ -535,7 +545,7 @@ if err != nil {
|
||||
```
|
||||
|
||||
<a name="FPutObject"></a>
|
||||
### FPutObject(bucketName string, objectName string, filePath string, contentType string) error
|
||||
### FPutObject(bucketName, objectName, filePath, contentType string) error
|
||||
|
||||
Uploads contents from a file to objectName.
|
||||
|
||||
@@ -569,7 +579,7 @@ if err != nil {
|
||||
```
|
||||
|
||||
<a name="StatObject"></a>
|
||||
### StatObject(bucketName string, objectName string) (ObjectInfo, error)
|
||||
### StatObject(bucketName, objectName string) (ObjectInfo, error)
|
||||
|
||||
Gets metadata of an object.
|
||||
|
||||
@@ -613,7 +623,7 @@ fmt.Println(objInfo)
|
||||
```
|
||||
|
||||
<a name="RemoveObject"></a>
|
||||
### RemoveObject(bucketName string, objectName string) error
|
||||
### RemoveObject(bucketName, objectName string) error
|
||||
|
||||
Removes an object.
|
||||
|
||||
@@ -670,7 +680,7 @@ for e := range errorCh {
|
||||
|
||||
|
||||
<a name="RemoveIncompleteUpload"></a>
|
||||
### RemoveIncompleteUpload(bucketName string, objectName string) error
|
||||
### RemoveIncompleteUpload(bucketName, objectName string) error
|
||||
|
||||
Removes a partially uploaded object.
|
||||
|
||||
@@ -699,7 +709,7 @@ if err != nil {
|
||||
|
||||
|
||||
<a name="PresignedGetObject"></a>
|
||||
### PresignedGetObject(bucketName string, objectName string, expiry time.Duration, reqParams url.Values) (*url.URL, error)
|
||||
### PresignedGetObject(bucketName, objectName string, expiry time.Duration, reqParams url.Values) (*url.URL, error)
|
||||
|
||||
Generates a presigned URL for HTTP GET operations. Browsers/Mobile clients may point to this URL to directly download objects even if the bucket is private. This presigned URL can have an associated expiration time in seconds after which it is no longer operational. The default expiry is set to 7 days.
|
||||
|
||||
@@ -733,7 +743,7 @@ if err != nil {
|
||||
```
|
||||
|
||||
<a name="PresignedPutObject"></a>
|
||||
### PresignedPutObject(bucketName string, objectName string, expiry time.Duration) (*url.URL, error)
|
||||
### PresignedPutObject(bucketName, objectName string, expiry time.Duration) (*url.URL, error)
|
||||
|
||||
Generates a presigned URL for HTTP PUT operations. Browsers/Mobile clients may point to this URL to upload objects directly to a bucket even if it is private. This presigned URL can have an associated expiration time in seconds after which it is no longer operational. The default expiry is set to 7 days.
|
||||
|
||||
@@ -822,7 +832,7 @@ fmt.Printf("%s\n", url)
|
||||
## 5. Bucket policy/notification operations
|
||||
|
||||
<a name="SetBucketPolicy"></a>
|
||||
### SetBucketPolicy(bucketname string, objectPrefix string, policy policy.BucketPolicy) error
|
||||
### SetBucketPolicy(bucketname, objectPrefix string, policy policy.BucketPolicy) error
|
||||
|
||||
Set access permissions on bucket or an object prefix.
|
||||
|
||||
@@ -864,7 +874,7 @@ if err != nil {
|
||||
```
|
||||
|
||||
<a name="GetBucketPolicy"></a>
|
||||
### GetBucketPolicy(bucketName string, objectPrefix string) (policy.BucketPolicy, error)
|
||||
### GetBucketPolicy(bucketName, objectPrefix string) (policy.BucketPolicy, error)
|
||||
|
||||
Get access permissions on a bucket or a prefix.
|
||||
|
||||
@@ -901,7 +911,7 @@ fmt.Println("Access permissions for mybucket is", bucketPolicy)
|
||||
```
|
||||
|
||||
<a name="ListBucketPolicies"></a>
|
||||
### ListBucketPolicies(bucketName string, objectPrefix string) (map[string]BucketPolicy, error)
|
||||
### ListBucketPolicies(bucketName, objectPrefix string) (map[string]BucketPolicy, error)
|
||||
|
||||
Get access permissions rules associated to the specified bucket and prefix.
|
||||
|
||||
@@ -1099,7 +1109,7 @@ for notificationInfo := range minioClient.ListenBucketNotification("YOUR-BUCKET"
|
||||
## 6. Client custom settings
|
||||
|
||||
<a name="SetAppInfo"></a>
|
||||
### SetAppInfo(appName string, appVersion string)
|
||||
### SetAppInfo(appName, appVersion string)
|
||||
Adds application details to User-Agent.
|
||||
|
||||
__Parameters__
|
||||
@@ -1148,6 +1158,17 @@ __Parameters__
|
||||
### TraceOff()
|
||||
Disables HTTP tracing.
|
||||
|
||||
<a name="SetS3TransferAccelerate"></a>
|
||||
### SetS3TransferAccelerate(acceleratedEndpoint string)
|
||||
Set AWS S3 transfer acceleration endpoint for all API requests hereafter.
|
||||
NOTE: This API applies only to AWS S3 and ignored with other S3 compatible object storage services.
|
||||
|
||||
__Parameters__
|
||||
|
||||
| Param | Type | Description |
|
||||
|---|---|---|
|
||||
|`acceleratedEndpoint` | _string_ | Set to new S3 transfer acceleration endpoint.|
|
||||
|
||||
|
||||
## 7. Explore Further
|
||||
|
||||
|
||||
2
vendor/github.com/minio/minio-go/examples/s3/copyobject.go
сгенерированный
поставляемый
@@ -45,7 +45,7 @@ func main() {
|
||||
// All following conditions are allowed and can be combined together.
|
||||
|
||||
// Set copy conditions.
|
||||
var copyConds = minio.NewCopyConditions()
|
||||
var copyConds = minio.CopyConditions{}
|
||||
// Set modified condition, copy object modified since 2014 April.
|
||||
copyConds.SetModified(time.Date(2014, time.April, 0, 0, 0, 0, 0, time.UTC))
|
||||
|
||||
|
||||
56
vendor/github.com/minio/minio-go/examples/s3/putobject-s3-accelerate.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,56 @@
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
* Minio Go Library for Amazon S3 Compatible Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/minio/minio-go"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY, my-testfile, my-bucketname and
|
||||
// my-objectname are dummy values, please replace them with original values.
|
||||
|
||||
// Requests are always secure (HTTPS) by default. Set secure=false to enable insecure (HTTP) access.
|
||||
// This boolean value is the last argument for New().
|
||||
|
||||
// New returns an Amazon S3 compatible client object. API compatibility (v2 or v4) is automatically
|
||||
// determined based on the Endpoint value.
|
||||
s3Client, err := minio.New("s3.amazonaws.com", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
// Enable S3 transfer accelerate endpoint.
|
||||
s3Client.S3TransferAccelerate("s3-accelerate.amazonaws.com")
|
||||
|
||||
object, err := os.Open("my-testfile")
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
defer object.Close()
|
||||
|
||||
n, err := s3Client.PutObject("my-bucketname", "my-objectname", object, "application/octet-stream")
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
log.Println("Uploaded", "my-objectname", " of size: ", n, "Successfully.")
|
||||
}
|
||||
12
vendor/github.com/minio/minio-go/pkg/s3utils/utils.go
сгенерированный
поставляемый
@@ -85,10 +85,6 @@ func IsAmazonEndpoint(endpointURL url.URL) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
if IsAmazonS3AccelerateEndpoint(endpointURL) {
|
||||
return true
|
||||
}
|
||||
|
||||
return endpointURL.Host == "s3.amazonaws.com"
|
||||
}
|
||||
|
||||
@@ -105,14 +101,6 @@ func IsAmazonChinaEndpoint(endpointURL url.URL) bool {
|
||||
return endpointURL.Host == "s3.cn-north-1.amazonaws.com.cn"
|
||||
}
|
||||
|
||||
// IsAmazonS3AccelerateEndpoint - Match if it is an Amazon S3 Accelerate
|
||||
func IsAmazonS3AccelerateEndpoint(endpointURL url.URL) bool {
|
||||
if endpointURL == sentinelURL {
|
||||
return false
|
||||
}
|
||||
return endpointURL.Host == "s3-accelerate.amazonaws.com"
|
||||
}
|
||||
|
||||
// IsGoogleEndpoint - Match if it is exactly Google cloud storage endpoint.
|
||||
func IsGoogleEndpoint(endpointURL url.URL) bool {
|
||||
if endpointURL == sentinelURL {
|
||||
|
||||
8
vendor/github.com/minio/minio-go/pkg/set/stringset.go
сгенерированный
поставляемый
@@ -25,8 +25,8 @@ import (
|
||||
// StringSet - uses map as set of strings.
|
||||
type StringSet map[string]struct{}
|
||||
|
||||
// keys - returns StringSet keys.
|
||||
func (set StringSet) keys() []string {
|
||||
// ToSlice - returns StringSet as string slice.
|
||||
func (set StringSet) ToSlice() []string {
|
||||
keys := make([]string, 0, len(set))
|
||||
for k := range set {
|
||||
keys = append(keys, k)
|
||||
@@ -141,7 +141,7 @@ func (set StringSet) Union(sset StringSet) StringSet {
|
||||
|
||||
// MarshalJSON - converts to JSON data.
|
||||
func (set StringSet) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(set.keys())
|
||||
return json.Marshal(set.ToSlice())
|
||||
}
|
||||
|
||||
// UnmarshalJSON - parses JSON data and creates new set with it.
|
||||
@@ -169,7 +169,7 @@ func (set *StringSet) UnmarshalJSON(data []byte) error {
|
||||
|
||||
// String - returns printable string of the set.
|
||||
func (set StringSet) String() string {
|
||||
return fmt.Sprintf("%s", set.keys())
|
||||
return fmt.Sprintf("%s", set.ToSlice())
|
||||
}
|
||||
|
||||
// NewStringSet - creates new string set.
|
||||
|
||||
25
vendor/github.com/minio/minio-go/pkg/set/stringset_test.go
сгенерированный
поставляемый
@@ -17,6 +17,7 @@
|
||||
package set
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
@@ -320,3 +321,27 @@ func TestStringSetString(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// StringSet.ToSlice() is called with series of cases for valid and erroneous inputs and the result is validated.
|
||||
func TestStringSetToSlice(t *testing.T) {
|
||||
testCases := []struct {
|
||||
set StringSet
|
||||
expectedResult string
|
||||
}{
|
||||
// Test empty set.
|
||||
{NewStringSet(), `[]`},
|
||||
// Test set with empty value.
|
||||
{CreateStringSet(""), `[]`},
|
||||
// Test set with value.
|
||||
{CreateStringSet("foo"), `[foo]`},
|
||||
// Test set with value.
|
||||
{CreateStringSet("foo", "bar"), `[bar foo]`},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
sslice := testCase.set.ToSlice()
|
||||
if str := fmt.Sprintf("%s", sslice); str != testCase.expectedResult {
|
||||
t.Fatalf("expected: %s, got: %s", testCase.expectedResult, str)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2
vendor/github.com/mitchellh/mapstructure/.travis.yml
сгенерированный
поставляемый
@@ -1,7 +1,7 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.4
|
||||
- 1.8.1
|
||||
|
||||
script:
|
||||
- go test
|
||||
|
||||
8
vendor/github.com/mitchellh/mapstructure/decode_hooks.go
сгенерированный
поставляемый
@@ -121,6 +121,11 @@ func StringToTimeDurationHookFunc() DecodeHookFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// WeaklyTypedHook is a DecodeHookFunc which adds support for weak typing to
|
||||
// the decoder.
|
||||
//
|
||||
// Note that this is significantly different from the WeaklyTypedInput option
|
||||
// of the DecoderConfig.
|
||||
func WeaklyTypedHook(
|
||||
f reflect.Kind,
|
||||
t reflect.Kind,
|
||||
@@ -132,9 +137,8 @@ func WeaklyTypedHook(
|
||||
case reflect.Bool:
|
||||
if dataVal.Bool() {
|
||||
return "1", nil
|
||||
} else {
|
||||
return "0", nil
|
||||
}
|
||||
return "0", nil
|
||||
case reflect.Float32:
|
||||
return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil
|
||||
case reflect.Int:
|
||||
|
||||
11
vendor/github.com/mitchellh/mapstructure/mapstructure.go
сгенерированный
поставляемый
@@ -1,5 +1,5 @@
|
||||
// The mapstructure package exposes functionality to convert an
|
||||
// arbitrary map[string]interface{} into a native Go structure.
|
||||
// Package mapstructure exposes functionality to convert an arbitrary
|
||||
// map[string]interface{} into a native Go structure.
|
||||
//
|
||||
// The Go structure can be arbitrarily complex, containing slices,
|
||||
// other structs, etc. and the decoder will properly decode nested
|
||||
@@ -32,7 +32,12 @@ import (
|
||||
// both.
|
||||
type DecodeHookFunc interface{}
|
||||
|
||||
// DecodeHookFuncType is a DecodeHookFunc which has complete information about
|
||||
// the source and target types.
|
||||
type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error)
|
||||
|
||||
// DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the
|
||||
// source and target types.
|
||||
type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error)
|
||||
|
||||
// DecoderConfig is the configuration that is used to create a new decoder
|
||||
@@ -436,7 +441,7 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value)
|
||||
case dataKind == reflect.Uint:
|
||||
val.SetFloat(float64(dataVal.Uint()))
|
||||
case dataKind == reflect.Float32:
|
||||
val.SetFloat(float64(dataVal.Float()))
|
||||
val.SetFloat(dataVal.Float())
|
||||
case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
|
||||
if dataVal.Bool() {
|
||||
val.SetFloat(1)
|
||||
|
||||
2
vendor/github.com/mitchellh/mapstructure/mapstructure_test.go
сгенерированный
поставляемый
@@ -437,7 +437,7 @@ func TestDecode_DecodeHookType(t *testing.T) {
|
||||
func TestDecode_Nil(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var input interface{} = nil
|
||||
var input interface{}
|
||||
result := Basic{
|
||||
Vstring: "foo",
|
||||
}
|
||||
|
||||
1
vendor/github.com/nicksnyder/go-i18n/.travis.yml
сгенерированный
поставляемый
@@ -7,4 +7,5 @@ go:
|
||||
- 1.5
|
||||
- 1.6
|
||||
- 1.7
|
||||
- 1.8
|
||||
- tip
|
||||
|
||||
66
vendor/github.com/nicksnyder/go-i18n/README.md
сгенерированный
поставляемый
@@ -1,19 +1,19 @@
|
||||
go-i18n [](http://travis-ci.org/nicksnyder/go-i18n)
|
||||
go-i18n [](http://travis-ci.org/nicksnyder/go-i18n) [](https://sourcegraph.com/github.com/nicksnyder/go-i18n?badge)
|
||||
=======
|
||||
|
||||
go-i18n is a Go [package](#i18n-package) and a [command](#goi18n-command) that helps you translate Go programs into multiple languages.
|
||||
* Supports [pluralized strings](http://cldr.unicode.org/index/cldr-spec/plural-rules) for all 200+ languages in the [Unicode Common Locale Data Repository (CLDR)](http://www.unicode.org/cldr/charts/28/supplemental/language_plural_rules.html).
|
||||
* Code and tests are [automatically generated](https://github.com/nicksnyder/go-i18n/tree/master/i18n/language/codegen) from [CLDR data](http://cldr.unicode.org/index/downloads)
|
||||
* Supports strings with named variables using [text/template](http://golang.org/pkg/text/template/) syntax.
|
||||
* Translation files are simple JSON or YAML.
|
||||
* Translation files are simple JSON, TOML or YAML.
|
||||
* [Documented](http://godoc.org/github.com/nicksnyder/go-i18n) and [tested](https://travis-ci.org/nicksnyder/go-i18n)!
|
||||
|
||||
Package i18n [](http://godoc.org/github.com/nicksnyder/go-i18n/i18n)
|
||||
Package i18n [](http://godoc.org/github.com/nicksnyder/go-i18n/i18n)
|
||||
------------
|
||||
|
||||
The i18n package provides runtime APIs for fetching translated strings.
|
||||
|
||||
Command goi18n [](http://godoc.org/github.com/nicksnyder/go-i18n/goi18n)
|
||||
Command goi18n [](http://godoc.org/github.com/nicksnyder/go-i18n/goi18n)
|
||||
--------------
|
||||
|
||||
The goi18n command provides functionality for managing the translation process.
|
||||
@@ -66,7 +66,7 @@ Translation files
|
||||
|
||||
A translation file stores translated and untranslated strings.
|
||||
|
||||
Example:
|
||||
Here is an example of the default file format that go-i18n supports:
|
||||
|
||||
```json
|
||||
[
|
||||
@@ -116,6 +116,62 @@ Example:
|
||||
]
|
||||
```
|
||||
|
||||
To use a different file format, write a parser for the format and add the parsed translations using [AddTranslation](https://godoc.org/github.com/nicksnyder/go-i18n/i18n#AddTranslation).
|
||||
|
||||
Note that TOML only supports the flat format, which is described below.
|
||||
|
||||
More examples of translation files: [JSON](https://github.com/nicksnyder/go-i18n/tree/master/goi18n/testdata/input), [TOML](https://github.com/nicksnyder/go-i18n/blob/master/goi18n/testdata/input/flat/ar-ar.one.toml), [YAML](https://github.com/nicksnyder/go-i18n/blob/master/goi18n/testdata/input/yaml/en-us.one.yaml).
|
||||
|
||||
Flat Format
|
||||
-------------
|
||||
|
||||
You can also write shorter translation files with flat format.
|
||||
E.g the example above can be written in this way:
|
||||
|
||||
```json
|
||||
{
|
||||
"d_days": {
|
||||
"one": "{{.Count}} day.",
|
||||
"other": "{{.Count}} days."
|
||||
},
|
||||
|
||||
"my_height_in_meters": {
|
||||
"one": "I am {{.Count}} meter tall.",
|
||||
"other": "I am {{.Count}} meters tall."
|
||||
},
|
||||
|
||||
"person_greeting": {
|
||||
"other": "Hello {{.Person}}"
|
||||
},
|
||||
|
||||
"person_unread_email_count": {
|
||||
"one": "{{.Person}} has {{.Count}} unread email.",
|
||||
"other": "{{.Person}} has {{.Count}} unread emails."
|
||||
},
|
||||
|
||||
"person_unread_email_count_timeframe": {
|
||||
"one": "{{.Person}} has {{.Count}} unread email in the past {{.Timeframe}}.",
|
||||
"other": "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}."
|
||||
},
|
||||
|
||||
"program_greeting": {
|
||||
"other": "Hello world"
|
||||
},
|
||||
|
||||
"your_unread_email_count": {
|
||||
"one": "You have {{.Count}} unread email.",
|
||||
"other": "You have {{.Count}} unread emails."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The logic of flat format is, what it is structure of structures
|
||||
and name of substructures (ids) should be always a string.
|
||||
If there is only one key in substructure and it is "other", then it's non-plural
|
||||
translation, else plural.
|
||||
|
||||
More examples of flat format translation files can be found in [goi18n/testdata/input/flat](https://github.com/nicksnyder/go-i18n/tree/master/goi18n/testdata/input/flat).
|
||||
|
||||
Contributions
|
||||
-------------
|
||||
|
||||
|
||||
1
vendor/github.com/nicksnyder/go-i18n/goi18n/constants_command.go
сгенерированный
поставляемый
@@ -139,7 +139,6 @@ Options:
|
||||
Default: .
|
||||
|
||||
`)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// commonInitialisms is a set of common initialisms.
|
||||
|
||||
97
vendor/github.com/nicksnyder/go-i18n/goi18n/merge_command.go
сгенерированный
поставляемый
@@ -5,7 +5,6 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
@@ -15,6 +14,7 @@ import (
|
||||
"github.com/nicksnyder/go-i18n/i18n/bundle"
|
||||
"github.com/nicksnyder/go-i18n/i18n/language"
|
||||
"github.com/nicksnyder/go-i18n/i18n/translation"
|
||||
toml "github.com/pelletier/go-toml"
|
||||
)
|
||||
|
||||
type mergeCommand struct {
|
||||
@@ -22,6 +22,7 @@ type mergeCommand struct {
|
||||
sourceLanguage string
|
||||
outdir string
|
||||
format string
|
||||
flat bool
|
||||
}
|
||||
|
||||
func (mc *mergeCommand) execute() error {
|
||||
@@ -33,15 +34,10 @@ func (mc *mergeCommand) execute() error {
|
||||
return fmt.Errorf("invalid source locale: %s", mc.sourceLanguage)
|
||||
}
|
||||
|
||||
marshal, err := newMarshalFunc(mc.format)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bundle := bundle.New()
|
||||
for _, tf := range mc.translationFiles {
|
||||
if err := bundle.LoadTranslationFile(tf); err != nil {
|
||||
return fmt.Errorf("failed to load translation file %s because %s\n", tf, err)
|
||||
return fmt.Errorf("failed to load translation file %s: %s\n", tf, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +60,7 @@ func (mc *mergeCommand) execute() error {
|
||||
all := filter(localeTranslations, func(t translation.Translation) translation.Translation {
|
||||
return t.Normalize(lang)
|
||||
})
|
||||
if err := mc.writeFile("all", all, localeID, marshal); err != nil {
|
||||
if err := mc.writeFile("all", all, localeID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -74,7 +70,7 @@ func (mc *mergeCommand) execute() error {
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err := mc.writeFile("untranslated", untranslated, localeID, marshal); err != nil {
|
||||
if err := mc.writeFile("untranslated", untranslated, localeID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -88,6 +84,7 @@ func (mc *mergeCommand) parse(arguments []string) {
|
||||
sourceLanguage := flags.String("sourceLanguage", "en-us", "")
|
||||
outdir := flags.String("outdir", ".", "")
|
||||
format := flags.String("format", "json", "")
|
||||
flat := flags.Bool("flat", true, "")
|
||||
|
||||
flags.Parse(arguments)
|
||||
|
||||
@@ -95,31 +92,44 @@ func (mc *mergeCommand) parse(arguments []string) {
|
||||
mc.sourceLanguage = *sourceLanguage
|
||||
mc.outdir = *outdir
|
||||
mc.format = *format
|
||||
if *format == "toml" {
|
||||
mc.flat = true
|
||||
} else {
|
||||
mc.flat = *flat
|
||||
}
|
||||
}
|
||||
|
||||
func (mc *mergeCommand) SetArgs(args []string) {
|
||||
mc.translationFiles = args
|
||||
}
|
||||
|
||||
type marshalFunc func(interface{}) ([]byte, error)
|
||||
|
||||
func (mc *mergeCommand) writeFile(label string, translations []translation.Translation, localeID string, marshal marshalFunc) error {
|
||||
func (mc *mergeCommand) writeFile(label string, translations []translation.Translation, localeID string) error {
|
||||
sort.Sort(translation.SortableByID(translations))
|
||||
buf, err := marshal(marshalInterface(translations))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal %s strings to %s because %s", localeID, mc.format, err)
|
||||
|
||||
var convert func([]translation.Translation) interface{}
|
||||
if mc.flat {
|
||||
convert = marshalFlatInterface
|
||||
} else {
|
||||
convert = marshalInterface
|
||||
}
|
||||
|
||||
buf, err := mc.marshal(convert(translations))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal %s strings to %s: %s", localeID, mc.format, err)
|
||||
}
|
||||
|
||||
filename := filepath.Join(mc.outdir, fmt.Sprintf("%s.%s.%s", localeID, label, mc.format))
|
||||
|
||||
if err := ioutil.WriteFile(filename, buf, 0666); err != nil {
|
||||
return fmt.Errorf("failed to write %s because %s", filename, err)
|
||||
return fmt.Errorf("failed to write %s: %s", filename, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func filter(translations map[string]translation.Translation, filter func(translation.Translation) translation.Translation) []translation.Translation {
|
||||
func filter(translations map[string]translation.Translation, f func(translation.Translation) translation.Translation) []translation.Translation {
|
||||
filtered := make([]translation.Translation, 0, len(translations))
|
||||
for _, translation := range translations {
|
||||
if t := filter(translation); t != nil {
|
||||
if t := f(translation); t != nil {
|
||||
filtered = append(filtered, t)
|
||||
}
|
||||
}
|
||||
@@ -127,21 +137,15 @@ func filter(translations map[string]translation.Translation, filter func(transla
|
||||
|
||||
}
|
||||
|
||||
func newMarshalFunc(format string) (marshalFunc, error) {
|
||||
switch format {
|
||||
case "json":
|
||||
return func(v interface{}) ([]byte, error) {
|
||||
return json.MarshalIndent(v, "", " ")
|
||||
}, nil
|
||||
case "yaml":
|
||||
return func(v interface{}) ([]byte, error) {
|
||||
return yaml.Marshal(v)
|
||||
}, nil
|
||||
func marshalFlatInterface(translations []translation.Translation) interface{} {
|
||||
mi := make(map[string]interface{}, len(translations))
|
||||
for _, translation := range translations {
|
||||
mi[translation.ID()] = translation.MarshalFlatInterface()
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported format: %s\n", format)
|
||||
return mi
|
||||
}
|
||||
|
||||
func marshalInterface(translations []translation.Translation) []interface{} {
|
||||
func marshalInterface(translations []translation.Translation) interface{} {
|
||||
mi := make([]interface{}, len(translations))
|
||||
for i, translation := range translations {
|
||||
mi[i] = translation.MarshalInterface()
|
||||
@@ -149,6 +153,31 @@ func marshalInterface(translations []translation.Translation) []interface{} {
|
||||
return mi
|
||||
}
|
||||
|
||||
func (mc mergeCommand) marshal(v interface{}) ([]byte, error) {
|
||||
switch mc.format {
|
||||
case "json":
|
||||
return json.MarshalIndent(v, "", " ")
|
||||
case "toml":
|
||||
return marshalTOML(v)
|
||||
case "yaml":
|
||||
return yaml.Marshal(v)
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported format: %s\n", mc.format)
|
||||
}
|
||||
|
||||
func marshalTOML(v interface{}) ([]byte, error) {
|
||||
m, ok := v.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid format for marshaling to TOML")
|
||||
}
|
||||
tree, err := toml.TreeFromMap(m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s, err := tree.ToTomlString()
|
||||
return []byte(s), err
|
||||
}
|
||||
|
||||
func usageMerge() {
|
||||
fmt.Printf(`Merge translation files.
|
||||
|
||||
@@ -198,9 +227,13 @@ Options:
|
||||
|
||||
-format format
|
||||
goi18n encodes the output translation files in this format.
|
||||
Supported formats: json, yaml
|
||||
Supported formats: json, toml, yaml
|
||||
Default: json
|
||||
|
||||
-flat
|
||||
goi18n writes the output translation files in flat format.
|
||||
Usage of '-format toml' automitically sets this flag.
|
||||
Default: true
|
||||
|
||||
`)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
36
vendor/github.com/nicksnyder/go-i18n/goi18n/merge_command_flat_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,36 @@
|
||||
package main
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestMergeExecuteFlat(t *testing.T) {
|
||||
files := []string{
|
||||
"testdata/input/flat/en-us.one.yaml",
|
||||
"testdata/input/flat/en-us.two.json",
|
||||
"testdata/input/flat/fr-fr.json",
|
||||
"testdata/input/flat/ar-ar.one.toml",
|
||||
"testdata/input/flat/ar-ar.two.json",
|
||||
}
|
||||
testFlatMergeExecute(t, files)
|
||||
}
|
||||
|
||||
func testFlatMergeExecute(t *testing.T, files []string) {
|
||||
resetDir(t, "testdata/output/flat")
|
||||
|
||||
mc := &mergeCommand{
|
||||
translationFiles: files,
|
||||
sourceLanguage: "en-us",
|
||||
outdir: "testdata/output/flat",
|
||||
format: "json",
|
||||
flat: true,
|
||||
}
|
||||
if err := mc.execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
expectEqualFiles(t, "testdata/output/flat/en-us.all.json", "testdata/expected/flat/en-us.all.json")
|
||||
expectEqualFiles(t, "testdata/output/flat/ar-ar.all.json", "testdata/expected/flat/ar-ar.all.json")
|
||||
expectEqualFiles(t, "testdata/output/flat/fr-fr.all.json", "testdata/expected/flat/fr-fr.all.json")
|
||||
expectEqualFiles(t, "testdata/output/flat/en-us.untranslated.json", "testdata/expected/flat/en-us.untranslated.json")
|
||||
expectEqualFiles(t, "testdata/output/flat/ar-ar.untranslated.json", "testdata/expected/flat/ar-ar.untranslated.json")
|
||||
expectEqualFiles(t, "testdata/output/flat/fr-fr.untranslated.json", "testdata/expected/flat/fr-fr.untranslated.json")
|
||||
}
|
||||
3
vendor/github.com/nicksnyder/go-i18n/goi18n/merge_command_test.go
сгенерированный
поставляемый
@@ -37,6 +37,7 @@ func testMergeExecute(t *testing.T, files []string) {
|
||||
sourceLanguage: "en-us",
|
||||
outdir: "testdata/output",
|
||||
format: "json",
|
||||
flat: false,
|
||||
}
|
||||
if err := mc.execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -69,6 +70,6 @@ func expectEqualFiles(t *testing.T, expectedName, actualName string) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(actual, expected) {
|
||||
t.Fatalf("contents of files did not match: %s, %s", expectedName, actualName)
|
||||
t.Errorf("contents of files did not match: %s, %s", expectedName, actualName)
|
||||
}
|
||||
}
|
||||
|
||||
34
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/en-us.flat.json
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"program_greeting": {
|
||||
"other": "Hello world"
|
||||
},
|
||||
|
||||
"person_greeting": {
|
||||
"other": "Hello {{.Person}}"
|
||||
},
|
||||
|
||||
"my_height_in_meters": {
|
||||
"one": "I am {{.Count}} meter tall.",
|
||||
"other": "I am {{.Count}} meters tall."
|
||||
},
|
||||
|
||||
"your_unread_email_count": {
|
||||
"one": "You have {{.Count}} unread email.",
|
||||
"other": "You have {{.Count}} unread emails."
|
||||
},
|
||||
|
||||
"person_unread_email_count": {
|
||||
"one": "{{.Person}} has {{.Count}} unread email.",
|
||||
"other": "{{.Person}} has {{.Count}} unread emails."
|
||||
},
|
||||
|
||||
"person_unread_email_count_timeframe": {
|
||||
"one": "{{.Person}} has {{.Count}} unread email in the past {{.Timeframe}}.",
|
||||
"other": "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}."
|
||||
},
|
||||
|
||||
"d_days": {
|
||||
"one": "{{.Count}} day.",
|
||||
"other": "{{.Count}} days."
|
||||
}
|
||||
}
|
||||
25
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/en-us.flat.toml
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,25 @@
|
||||
[program_greeting]
|
||||
other = "Hello world"
|
||||
|
||||
[person_greeting]
|
||||
other = "Hello {{.Person}}"
|
||||
|
||||
[my_height_in_meters]
|
||||
one = "I am {{.Count}} meter tall."
|
||||
other = "I am {{.Count}} meters tall."
|
||||
|
||||
[your_unread_email_count]
|
||||
one = "You have {{.Count}} unread email."
|
||||
other = "You have {{.Count}} unread emails."
|
||||
|
||||
[person_unread_email_count]
|
||||
one = "{{.Person}} has {{.Count}} unread email."
|
||||
other = "{{.Person}} has {{.Count}} unread emails."
|
||||
|
||||
[person_unread_email_count_timeframe]
|
||||
one = "{{.Person}} has {{.Count}} unread email in the past {{.Timeframe}}."
|
||||
other = "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}."
|
||||
|
||||
[d_days]
|
||||
one = "{{.Count}} day"
|
||||
other = "{{.Count}} days"
|
||||
25
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/en-us.flat.yaml
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,25 @@
|
||||
program_greeting:
|
||||
other: "Hello world"
|
||||
|
||||
person_greeting:
|
||||
other: "Hello {{.Person}}"
|
||||
|
||||
my_height_in_meters:
|
||||
one: "I am {{.Count}} meter tall."
|
||||
other: "I am {{.Count}} meters tall."
|
||||
|
||||
your_unread_email_count:
|
||||
one: "You have {{.Count}} unread email."
|
||||
other: "You have {{.Count}} unread emails."
|
||||
|
||||
person_unread_email_count:
|
||||
one: "{{.Person}} has {{.Count}} unread email."
|
||||
other: "{{.Person}} has {{.Count}} unread emails."
|
||||
|
||||
person_unread_email_count_timeframe:
|
||||
one: "{{.Person}} has {{.Count}} unread email in the past {{.Timeframe}}."
|
||||
other: "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}."
|
||||
|
||||
d_days:
|
||||
one: "{{.Count}} day"
|
||||
other: "{{.Count}} days"
|
||||
43
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/expected/flat/ar-ar.all.json
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"d_days": {
|
||||
"few": "new arabic few translation of d_days",
|
||||
"many": "arabic many translation of d_days",
|
||||
"one": "arabic one translation of d_days",
|
||||
"other": "",
|
||||
"two": "",
|
||||
"zero": ""
|
||||
},
|
||||
"my_height_in_meters": {
|
||||
"few": "",
|
||||
"many": "",
|
||||
"one": "",
|
||||
"other": "",
|
||||
"two": "",
|
||||
"zero": ""
|
||||
},
|
||||
"person_greeting": {
|
||||
"other": "new arabic translation of person_greeting"
|
||||
},
|
||||
"person_unread_email_count": {
|
||||
"few": "arabic few translation of person_unread_email_count",
|
||||
"many": "arabic many translation of person_unread_email_count",
|
||||
"one": "arabic one translation of person_unread_email_count",
|
||||
"other": "arabic other translation of person_unread_email_count",
|
||||
"two": "arabic two translation of person_unread_email_count",
|
||||
"zero": "arabic zero translation of person_unread_email_count"
|
||||
},
|
||||
"person_unread_email_count_timeframe": {
|
||||
"other": ""
|
||||
},
|
||||
"program_greeting": {
|
||||
"other": ""
|
||||
},
|
||||
"your_unread_email_count": {
|
||||
"few": "",
|
||||
"many": "",
|
||||
"one": "",
|
||||
"other": "",
|
||||
"two": "",
|
||||
"zero": ""
|
||||
}
|
||||
}
|
||||
32
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/expected/flat/ar-ar.untranslated.json
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"d_days": {
|
||||
"few": "new arabic few translation of d_days",
|
||||
"many": "arabic many translation of d_days",
|
||||
"one": "arabic one translation of d_days",
|
||||
"other": "{{.Count}} days",
|
||||
"two": "{{.Count}} days",
|
||||
"zero": "{{.Count}} days"
|
||||
},
|
||||
"my_height_in_meters": {
|
||||
"few": "I am {{.Count}} meters tall.",
|
||||
"many": "I am {{.Count}} meters tall.",
|
||||
"one": "I am {{.Count}} meters tall.",
|
||||
"other": "I am {{.Count}} meters tall.",
|
||||
"two": "I am {{.Count}} meters tall.",
|
||||
"zero": "I am {{.Count}} meters tall."
|
||||
},
|
||||
"person_unread_email_count_timeframe": {
|
||||
"other": "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}."
|
||||
},
|
||||
"program_greeting": {
|
||||
"other": "Hello world"
|
||||
},
|
||||
"your_unread_email_count": {
|
||||
"few": "You have {{.Count}} unread emails.",
|
||||
"many": "You have {{.Count}} unread emails.",
|
||||
"one": "You have {{.Count}} unread emails.",
|
||||
"other": "You have {{.Count}} unread emails.",
|
||||
"two": "You have {{.Count}} unread emails.",
|
||||
"zero": "You have {{.Count}} unread emails."
|
||||
}
|
||||
}
|
||||
27
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/expected/flat/en-us.all.json
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"d_days": {
|
||||
"one": "{{.Count}} day",
|
||||
"other": "{{.Count}} days"
|
||||
},
|
||||
"my_height_in_meters": {
|
||||
"one": "I am {{.Count}} meter tall.",
|
||||
"other": "I am {{.Count}} meters tall."
|
||||
},
|
||||
"person_greeting": {
|
||||
"other": "Hello {{.Person}}"
|
||||
},
|
||||
"person_unread_email_count": {
|
||||
"one": "{{.Person}} has {{.Count}} unread email.",
|
||||
"other": "{{.Person}} has {{.Count}} unread emails."
|
||||
},
|
||||
"person_unread_email_count_timeframe": {
|
||||
"other": "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}."
|
||||
},
|
||||
"program_greeting": {
|
||||
"other": "Hello world"
|
||||
},
|
||||
"your_unread_email_count": {
|
||||
"one": "You have {{.Count}} unread email.",
|
||||
"other": "You have {{.Count}} unread emails."
|
||||
}
|
||||
}
|
||||
1
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/expected/flat/en-us.untranslated.json
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1 @@
|
||||
{}
|
||||