Update kubernetes/client-go to v7.0.0 (#1808)

This fix updates k8s' client-go to v7.0.0, which matches k8s 1.10.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
This commit is contained in:
Yong Tang
2018-05-16 23:10:28 -07:00
committed by Miek Gieben
parent 9a82fa0374
commit b109a79cb5
730 changed files with 17431 additions and 43251 deletions

View File

@@ -1,92 +0,0 @@
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
package width
// This code is shared between the main code generator and the test code.
import (
"flag"
"log"
"strconv"
"strings"
"golang.org/x/text/internal/gen"
"golang.org/x/text/internal/ucd"
)
var (
outputFile = flag.String("out", "tables.go", "output file")
)
var typeMap = map[string]elem{
"A": tagAmbiguous,
"N": tagNeutral,
"Na": tagNarrow,
"W": tagWide,
"F": tagFullwidth,
"H": tagHalfwidth,
}
// getWidthData calls f for every entry for which it is defined.
//
// f may be called multiple times for the same rune. The last call to f is the
// correct value. f is not called for all runes. The default tag type is
// Neutral.
func getWidthData(f func(r rune, tag elem, alt rune)) {
// Set the default values for Unified Ideographs. In line with Annex 11,
// we encode full ranges instead of the defined runes in Unified_Ideograph.
for _, b := range []struct{ lo, hi rune }{
{0x4E00, 0x9FFF}, // the CJK Unified Ideographs block,
{0x3400, 0x4DBF}, // the CJK Unified Ideographs Externsion A block,
{0xF900, 0xFAFF}, // the CJK Compatibility Ideographs block,
{0x20000, 0x2FFFF}, // the Supplementary Ideographic Plane,
{0x30000, 0x3FFFF}, // the Tertiary Ideographic Plane,
} {
for r := b.lo; r <= b.hi; r++ {
f(r, tagWide, 0)
}
}
inverse := map[rune]rune{}
maps := map[string]bool{
"<wide>": true,
"<narrow>": true,
}
// We cannot reuse package norm's decomposition, as we need an unexpanded
// decomposition. We make use of the opportunity to verify that the
// decomposition type is as expected.
ucd.Parse(gen.OpenUCDFile("UnicodeData.txt"), func(p *ucd.Parser) {
r := p.Rune(0)
s := strings.SplitN(p.String(ucd.DecompMapping), " ", 2)
if !maps[s[0]] {
return
}
x, err := strconv.ParseUint(s[1], 16, 32)
if err != nil {
log.Fatalf("Error parsing rune %q", s[1])
}
if inverse[r] != 0 || inverse[rune(x)] != 0 {
log.Fatalf("Circular dependency in mapping between %U and %U", r, x)
}
inverse[r] = rune(x)
inverse[rune(x)] = r
})
// <rune range>;<type>
ucd.Parse(gen.OpenUCDFile("EastAsianWidth.txt"), func(p *ucd.Parser) {
tag, ok := typeMap[p.String(1)]
if !ok {
log.Fatalf("Unknown width type %q", p.String(1))
}
r := p.Rune(0)
alt, ok := inverse[r]
if tag == tagFullwidth || tag == tagHalfwidth && r != wonSign {
tag |= tagNeedsFold
if !ok {
log.Fatalf("Narrow or wide rune %U has no decomposition", r)
}
}
f(r, tag, alt)
})
}

View File

@@ -1,52 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package width_test
import (
"fmt"
"golang.org/x/text/width"
)
func ExampleTransformer_fold() {
s := "abヲ₩○¥"
f := width.Fold.String(s)
fmt.Printf("%U: %s\n", []rune(s), s)
fmt.Printf("%U: %s\n", []rune(f), f)
// Output:
// [U+0061 U+0062 U+FF66 U+FFE6 U+FFEE U+FFE5 U+FF21]: abヲ₩○¥
// [U+0061 U+0062 U+30F2 U+20A9 U+25CB U+00A5 U+0041]: abヲ₩○¥A
}
func ExampleTransformer_widen() {
s := "ab¥ヲ₩○"
w := width.Widen.String(s)
fmt.Printf("%U: %s\n", []rune(s), s)
fmt.Printf("%U: %s\n", []rune(w), w)
// Output:
// [U+0061 U+0062 U+00A5 U+FF66 U+20A9 U+FFEE]: ab¥ヲ₩○
// [U+FF41 U+FF42 U+FFE5 U+30F2 U+FFE6 U+25CB]: ab¥ヲ₩○
}
func ExampleTransformer_narrow() {
s := "abヲ₩○¥"
n := width.Narrow.String(s)
fmt.Printf("%U: %s\n", []rune(s), s)
fmt.Printf("%U: %s\n", []rune(n), n)
// Ambiguous characters with a halfwidth equivalent get mapped as well.
s = "←"
n = width.Narrow.String(s)
fmt.Printf("%U: %s\n", []rune(s), s)
fmt.Printf("%U: %s\n", []rune(n), n)
// Output:
// [U+0061 U+0062 U+30F2 U+FFE6 U+25CB U+FFE5 U+FF21]: abヲ₩○¥
// [U+0061 U+0062 U+FF66 U+20A9 U+FFEE U+00A5 U+0041]: abヲ₩○¥A
// [U+2190]: ←
// [U+FFE9]: ←
}

115
vendor/golang.org/x/text/width/gen.go generated vendored
View File

@@ -1,115 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
// This program generates the trie for width operations. The generated table
// includes width category information as well as the normalization mappings.
package main
import (
"bytes"
"fmt"
"io"
"log"
"math"
"unicode/utf8"
"golang.org/x/text/internal/gen"
"golang.org/x/text/internal/triegen"
)
// See gen_common.go for flags.
func main() {
gen.Init()
genTables()
genTests()
gen.Repackage("gen_trieval.go", "trieval.go", "width")
gen.Repackage("gen_common.go", "common_test.go", "width")
}
func genTables() {
t := triegen.NewTrie("width")
// fold and inverse mappings. See mapComment for a description of the format
// of each entry. Add dummy value to make an index of 0 mean no mapping.
inverse := [][4]byte{{}}
mapping := map[[4]byte]int{[4]byte{}: 0}
getWidthData(func(r rune, tag elem, alt rune) {
idx := 0
if alt != 0 {
var buf [4]byte
buf[0] = byte(utf8.EncodeRune(buf[1:], alt))
s := string(r)
buf[buf[0]] ^= s[len(s)-1]
var ok bool
if idx, ok = mapping[buf]; !ok {
idx = len(mapping)
if idx > math.MaxUint8 {
log.Fatalf("Index %d does not fit in a byte.", idx)
}
mapping[buf] = idx
inverse = append(inverse, buf)
}
}
t.Insert(r, uint64(tag|elem(idx)))
})
w := &bytes.Buffer{}
gen.WriteUnicodeVersion(w)
sz, err := t.Gen(w)
if err != nil {
log.Fatal(err)
}
sz += writeMappings(w, inverse)
fmt.Fprintf(w, "// Total table size %d bytes (%dKiB)\n", sz, sz/1024)
gen.WriteVersionedGoFile(*outputFile, "width", w.Bytes())
}
const inverseDataComment = `
// inverseData contains 4-byte entries of the following format:
// <length> <modified UTF-8-encoded rune> <0 padding>
// The last byte of the UTF-8-encoded rune is xor-ed with the last byte of the
// UTF-8 encoding of the original rune. Mappings often have the following
// pattern:
// -> A (U+FF21 -> U+0041)
// -> B (U+FF22 -> U+0042)
// ...
// By xor-ing the last byte the same entry can be shared by many mappings. This
// reduces the total number of distinct entries by about two thirds.
// The resulting entry for the aforementioned mappings is
// { 0x01, 0xE0, 0x00, 0x00 }
// Using this entry to map U+FF21 (UTF-8 [EF BC A1]), we get
// E0 ^ A1 = 41.
// Similarly, for U+FF22 (UTF-8 [EF BC A2]), we get
// E0 ^ A2 = 42.
// Note that because of the xor-ing, the byte sequence stored in the entry is
// not valid UTF-8.`
func writeMappings(w io.Writer, data [][4]byte) int {
fmt.Fprintln(w, inverseDataComment)
fmt.Fprintf(w, "var inverseData = [%d][4]byte{\n", len(data))
for _, x := range data {
fmt.Fprintf(w, "{ 0x%02x, 0x%02x, 0x%02x, 0x%02x },\n", x[0], x[1], x[2], x[3])
}
fmt.Fprintln(w, "}")
return len(data) * 4
}
func genTests() {
w := &bytes.Buffer{}
fmt.Fprintf(w, "\nvar mapRunes = map[rune]struct{r rune; e elem}{\n")
getWidthData(func(r rune, tag elem, alt rune) {
if alt != 0 {
fmt.Fprintf(w, "\t0x%X: {0x%X, 0x%X},\n", r, alt, tag)
}
})
fmt.Fprintln(w, "}")
gen.WriteGoFile("runes_test.go", "width", w.Bytes())
}

View File

@@ -1,96 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
package main
// This code is shared between the main code generator and the test code.
import (
"flag"
"log"
"strconv"
"strings"
"golang.org/x/text/internal/gen"
"golang.org/x/text/internal/ucd"
)
var (
outputFile = flag.String("out", "tables.go", "output file")
)
var typeMap = map[string]elem{
"A": tagAmbiguous,
"N": tagNeutral,
"Na": tagNarrow,
"W": tagWide,
"F": tagFullwidth,
"H": tagHalfwidth,
}
// getWidthData calls f for every entry for which it is defined.
//
// f may be called multiple times for the same rune. The last call to f is the
// correct value. f is not called for all runes. The default tag type is
// Neutral.
func getWidthData(f func(r rune, tag elem, alt rune)) {
// Set the default values for Unified Ideographs. In line with Annex 11,
// we encode full ranges instead of the defined runes in Unified_Ideograph.
for _, b := range []struct{ lo, hi rune }{
{0x4E00, 0x9FFF}, // the CJK Unified Ideographs block,
{0x3400, 0x4DBF}, // the CJK Unified Ideographs Externsion A block,
{0xF900, 0xFAFF}, // the CJK Compatibility Ideographs block,
{0x20000, 0x2FFFF}, // the Supplementary Ideographic Plane,
{0x30000, 0x3FFFF}, // the Tertiary Ideographic Plane,
} {
for r := b.lo; r <= b.hi; r++ {
f(r, tagWide, 0)
}
}
inverse := map[rune]rune{}
maps := map[string]bool{
"<wide>": true,
"<narrow>": true,
}
// We cannot reuse package norm's decomposition, as we need an unexpanded
// decomposition. We make use of the opportunity to verify that the
// decomposition type is as expected.
ucd.Parse(gen.OpenUCDFile("UnicodeData.txt"), func(p *ucd.Parser) {
r := p.Rune(0)
s := strings.SplitN(p.String(ucd.DecompMapping), " ", 2)
if !maps[s[0]] {
return
}
x, err := strconv.ParseUint(s[1], 16, 32)
if err != nil {
log.Fatalf("Error parsing rune %q", s[1])
}
if inverse[r] != 0 || inverse[rune(x)] != 0 {
log.Fatalf("Circular dependency in mapping between %U and %U", r, x)
}
inverse[r] = rune(x)
inverse[rune(x)] = r
})
// <rune range>;<type>
ucd.Parse(gen.OpenUCDFile("EastAsianWidth.txt"), func(p *ucd.Parser) {
tag, ok := typeMap[p.String(1)]
if !ok {
log.Fatalf("Unknown width type %q", p.String(1))
}
r := p.Rune(0)
alt, ok := inverse[r]
if tag == tagFullwidth || tag == tagHalfwidth && r != wonSign {
tag |= tagNeedsFold
if !ok {
log.Fatalf("Narrow or wide rune %U has no decomposition", r)
}
}
f(r, tag, alt)
})
}

View File

@@ -1,34 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
package main
// elem is an entry of the width trie. The high byte is used to encode the type
// of the rune. The low byte is used to store the index to a mapping entry in
// the inverseData array.
type elem uint16
const (
tagNeutral elem = iota << typeShift
tagAmbiguous
tagWide
tagNarrow
tagFullwidth
tagHalfwidth
)
const (
numTypeBits = 3
typeShift = 16 - numTypeBits
// tagNeedsFold is true for all fullwidth and halfwidth runes except for
// the Won sign U+20A9.
tagNeedsFold = 0x1000
// The Korean Won sign is halfwidth, but SHOULD NOT be mapped to a wide
// variant.
wonSign rune = 0x20A9
)

View File

@@ -1,16 +0,0 @@
// Code generated by "stringer -type=Kind"; DO NOT EDIT.
package width
import "fmt"
const _Kind_name = "NeutralEastAsianAmbiguousEastAsianWideEastAsianNarrowEastAsianFullwidthEastAsianHalfwidth"
var _Kind_index = [...]uint8{0, 7, 25, 38, 53, 71, 89}
func (i Kind) String() string {
if i < 0 || i >= Kind(len(_Kind_index)-1) {
return fmt.Sprintf("Kind(%d)", i)
}
return _Kind_name[_Kind_index[i]:_Kind_index[i+1]]
}

View File

@@ -1,461 +0,0 @@
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
package width
var mapRunes = map[rune]struct {
r rune
e elem
}{
0x20: {0x3000, 0x6000},
0x21: {0xFF01, 0x6000},
0x22: {0xFF02, 0x6000},
0x23: {0xFF03, 0x6000},
0x24: {0xFF04, 0x6000},
0x25: {0xFF05, 0x6000},
0x26: {0xFF06, 0x6000},
0x27: {0xFF07, 0x6000},
0x28: {0xFF08, 0x6000},
0x29: {0xFF09, 0x6000},
0x2A: {0xFF0A, 0x6000},
0x2B: {0xFF0B, 0x6000},
0x2C: {0xFF0C, 0x6000},
0x2D: {0xFF0D, 0x6000},
0x2E: {0xFF0E, 0x6000},
0x2F: {0xFF0F, 0x6000},
0x30: {0xFF10, 0x6000},
0x31: {0xFF11, 0x6000},
0x32: {0xFF12, 0x6000},
0x33: {0xFF13, 0x6000},
0x34: {0xFF14, 0x6000},
0x35: {0xFF15, 0x6000},
0x36: {0xFF16, 0x6000},
0x37: {0xFF17, 0x6000},
0x38: {0xFF18, 0x6000},
0x39: {0xFF19, 0x6000},
0x3A: {0xFF1A, 0x6000},
0x3B: {0xFF1B, 0x6000},
0x3C: {0xFF1C, 0x6000},
0x3D: {0xFF1D, 0x6000},
0x3E: {0xFF1E, 0x6000},
0x3F: {0xFF1F, 0x6000},
0x40: {0xFF20, 0x6000},
0x41: {0xFF21, 0x6000},
0x42: {0xFF22, 0x6000},
0x43: {0xFF23, 0x6000},
0x44: {0xFF24, 0x6000},
0x45: {0xFF25, 0x6000},
0x46: {0xFF26, 0x6000},
0x47: {0xFF27, 0x6000},
0x48: {0xFF28, 0x6000},
0x49: {0xFF29, 0x6000},
0x4A: {0xFF2A, 0x6000},
0x4B: {0xFF2B, 0x6000},
0x4C: {0xFF2C, 0x6000},
0x4D: {0xFF2D, 0x6000},
0x4E: {0xFF2E, 0x6000},
0x4F: {0xFF2F, 0x6000},
0x50: {0xFF30, 0x6000},
0x51: {0xFF31, 0x6000},
0x52: {0xFF32, 0x6000},
0x53: {0xFF33, 0x6000},
0x54: {0xFF34, 0x6000},
0x55: {0xFF35, 0x6000},
0x56: {0xFF36, 0x6000},
0x57: {0xFF37, 0x6000},
0x58: {0xFF38, 0x6000},
0x59: {0xFF39, 0x6000},
0x5A: {0xFF3A, 0x6000},
0x5B: {0xFF3B, 0x6000},
0x5C: {0xFF3C, 0x6000},
0x5D: {0xFF3D, 0x6000},
0x5E: {0xFF3E, 0x6000},
0x5F: {0xFF3F, 0x6000},
0x60: {0xFF40, 0x6000},
0x61: {0xFF41, 0x6000},
0x62: {0xFF42, 0x6000},
0x63: {0xFF43, 0x6000},
0x64: {0xFF44, 0x6000},
0x65: {0xFF45, 0x6000},
0x66: {0xFF46, 0x6000},
0x67: {0xFF47, 0x6000},
0x68: {0xFF48, 0x6000},
0x69: {0xFF49, 0x6000},
0x6A: {0xFF4A, 0x6000},
0x6B: {0xFF4B, 0x6000},
0x6C: {0xFF4C, 0x6000},
0x6D: {0xFF4D, 0x6000},
0x6E: {0xFF4E, 0x6000},
0x6F: {0xFF4F, 0x6000},
0x70: {0xFF50, 0x6000},
0x71: {0xFF51, 0x6000},
0x72: {0xFF52, 0x6000},
0x73: {0xFF53, 0x6000},
0x74: {0xFF54, 0x6000},
0x75: {0xFF55, 0x6000},
0x76: {0xFF56, 0x6000},
0x77: {0xFF57, 0x6000},
0x78: {0xFF58, 0x6000},
0x79: {0xFF59, 0x6000},
0x7A: {0xFF5A, 0x6000},
0x7B: {0xFF5B, 0x6000},
0x7C: {0xFF5C, 0x6000},
0x7D: {0xFF5D, 0x6000},
0x7E: {0xFF5E, 0x6000},
0xA2: {0xFFE0, 0x6000},
0xA3: {0xFFE1, 0x6000},
0xA5: {0xFFE5, 0x6000},
0xA6: {0xFFE4, 0x6000},
0xAC: {0xFFE2, 0x6000},
0xAF: {0xFFE3, 0x6000},
0x20A9: {0xFFE6, 0xA000},
0x2190: {0xFFE9, 0x2000},
0x2191: {0xFFEA, 0x2000},
0x2192: {0xFFEB, 0x2000},
0x2193: {0xFFEC, 0x2000},
0x2502: {0xFFE8, 0x2000},
0x25A0: {0xFFED, 0x2000},
0x25CB: {0xFFEE, 0x2000},
0x2985: {0xFF5F, 0x6000},
0x2986: {0xFF60, 0x6000},
0x3000: {0x20, 0x9000},
0x3001: {0xFF64, 0x4000},
0x3002: {0xFF61, 0x4000},
0x300C: {0xFF62, 0x4000},
0x300D: {0xFF63, 0x4000},
0x3099: {0xFF9E, 0x4000},
0x309A: {0xFF9F, 0x4000},
0x30A1: {0xFF67, 0x4000},
0x30A2: {0xFF71, 0x4000},
0x30A3: {0xFF68, 0x4000},
0x30A4: {0xFF72, 0x4000},
0x30A5: {0xFF69, 0x4000},
0x30A6: {0xFF73, 0x4000},
0x30A7: {0xFF6A, 0x4000},
0x30A8: {0xFF74, 0x4000},
0x30A9: {0xFF6B, 0x4000},
0x30AA: {0xFF75, 0x4000},
0x30AB: {0xFF76, 0x4000},
0x30AD: {0xFF77, 0x4000},
0x30AF: {0xFF78, 0x4000},
0x30B1: {0xFF79, 0x4000},
0x30B3: {0xFF7A, 0x4000},
0x30B5: {0xFF7B, 0x4000},
0x30B7: {0xFF7C, 0x4000},
0x30B9: {0xFF7D, 0x4000},
0x30BB: {0xFF7E, 0x4000},
0x30BD: {0xFF7F, 0x4000},
0x30BF: {0xFF80, 0x4000},
0x30C1: {0xFF81, 0x4000},
0x30C3: {0xFF6F, 0x4000},
0x30C4: {0xFF82, 0x4000},
0x30C6: {0xFF83, 0x4000},
0x30C8: {0xFF84, 0x4000},
0x30CA: {0xFF85, 0x4000},
0x30CB: {0xFF86, 0x4000},
0x30CC: {0xFF87, 0x4000},
0x30CD: {0xFF88, 0x4000},
0x30CE: {0xFF89, 0x4000},
0x30CF: {0xFF8A, 0x4000},
0x30D2: {0xFF8B, 0x4000},
0x30D5: {0xFF8C, 0x4000},
0x30D8: {0xFF8D, 0x4000},
0x30DB: {0xFF8E, 0x4000},
0x30DE: {0xFF8F, 0x4000},
0x30DF: {0xFF90, 0x4000},
0x30E0: {0xFF91, 0x4000},
0x30E1: {0xFF92, 0x4000},
0x30E2: {0xFF93, 0x4000},
0x30E3: {0xFF6C, 0x4000},
0x30E4: {0xFF94, 0x4000},
0x30E5: {0xFF6D, 0x4000},
0x30E6: {0xFF95, 0x4000},
0x30E7: {0xFF6E, 0x4000},
0x30E8: {0xFF96, 0x4000},
0x30E9: {0xFF97, 0x4000},
0x30EA: {0xFF98, 0x4000},
0x30EB: {0xFF99, 0x4000},
0x30EC: {0xFF9A, 0x4000},
0x30ED: {0xFF9B, 0x4000},
0x30EF: {0xFF9C, 0x4000},
0x30F2: {0xFF66, 0x4000},
0x30F3: {0xFF9D, 0x4000},
0x30FB: {0xFF65, 0x4000},
0x30FC: {0xFF70, 0x4000},
0x3131: {0xFFA1, 0x4000},
0x3132: {0xFFA2, 0x4000},
0x3133: {0xFFA3, 0x4000},
0x3134: {0xFFA4, 0x4000},
0x3135: {0xFFA5, 0x4000},
0x3136: {0xFFA6, 0x4000},
0x3137: {0xFFA7, 0x4000},
0x3138: {0xFFA8, 0x4000},
0x3139: {0xFFA9, 0x4000},
0x313A: {0xFFAA, 0x4000},
0x313B: {0xFFAB, 0x4000},
0x313C: {0xFFAC, 0x4000},
0x313D: {0xFFAD, 0x4000},
0x313E: {0xFFAE, 0x4000},
0x313F: {0xFFAF, 0x4000},
0x3140: {0xFFB0, 0x4000},
0x3141: {0xFFB1, 0x4000},
0x3142: {0xFFB2, 0x4000},
0x3143: {0xFFB3, 0x4000},
0x3144: {0xFFB4, 0x4000},
0x3145: {0xFFB5, 0x4000},
0x3146: {0xFFB6, 0x4000},
0x3147: {0xFFB7, 0x4000},
0x3148: {0xFFB8, 0x4000},
0x3149: {0xFFB9, 0x4000},
0x314A: {0xFFBA, 0x4000},
0x314B: {0xFFBB, 0x4000},
0x314C: {0xFFBC, 0x4000},
0x314D: {0xFFBD, 0x4000},
0x314E: {0xFFBE, 0x4000},
0x314F: {0xFFC2, 0x4000},
0x3150: {0xFFC3, 0x4000},
0x3151: {0xFFC4, 0x4000},
0x3152: {0xFFC5, 0x4000},
0x3153: {0xFFC6, 0x4000},
0x3154: {0xFFC7, 0x4000},
0x3155: {0xFFCA, 0x4000},
0x3156: {0xFFCB, 0x4000},
0x3157: {0xFFCC, 0x4000},
0x3158: {0xFFCD, 0x4000},
0x3159: {0xFFCE, 0x4000},
0x315A: {0xFFCF, 0x4000},
0x315B: {0xFFD2, 0x4000},
0x315C: {0xFFD3, 0x4000},
0x315D: {0xFFD4, 0x4000},
0x315E: {0xFFD5, 0x4000},
0x315F: {0xFFD6, 0x4000},
0x3160: {0xFFD7, 0x4000},
0x3161: {0xFFDA, 0x4000},
0x3162: {0xFFDB, 0x4000},
0x3163: {0xFFDC, 0x4000},
0x3164: {0xFFA0, 0x4000},
0xFF01: {0x21, 0x9000},
0xFF02: {0x22, 0x9000},
0xFF03: {0x23, 0x9000},
0xFF04: {0x24, 0x9000},
0xFF05: {0x25, 0x9000},
0xFF06: {0x26, 0x9000},
0xFF07: {0x27, 0x9000},
0xFF08: {0x28, 0x9000},
0xFF09: {0x29, 0x9000},
0xFF0A: {0x2A, 0x9000},
0xFF0B: {0x2B, 0x9000},
0xFF0C: {0x2C, 0x9000},
0xFF0D: {0x2D, 0x9000},
0xFF0E: {0x2E, 0x9000},
0xFF0F: {0x2F, 0x9000},
0xFF10: {0x30, 0x9000},
0xFF11: {0x31, 0x9000},
0xFF12: {0x32, 0x9000},
0xFF13: {0x33, 0x9000},
0xFF14: {0x34, 0x9000},
0xFF15: {0x35, 0x9000},
0xFF16: {0x36, 0x9000},
0xFF17: {0x37, 0x9000},
0xFF18: {0x38, 0x9000},
0xFF19: {0x39, 0x9000},
0xFF1A: {0x3A, 0x9000},
0xFF1B: {0x3B, 0x9000},
0xFF1C: {0x3C, 0x9000},
0xFF1D: {0x3D, 0x9000},
0xFF1E: {0x3E, 0x9000},
0xFF1F: {0x3F, 0x9000},
0xFF20: {0x40, 0x9000},
0xFF21: {0x41, 0x9000},
0xFF22: {0x42, 0x9000},
0xFF23: {0x43, 0x9000},
0xFF24: {0x44, 0x9000},
0xFF25: {0x45, 0x9000},
0xFF26: {0x46, 0x9000},
0xFF27: {0x47, 0x9000},
0xFF28: {0x48, 0x9000},
0xFF29: {0x49, 0x9000},
0xFF2A: {0x4A, 0x9000},
0xFF2B: {0x4B, 0x9000},
0xFF2C: {0x4C, 0x9000},
0xFF2D: {0x4D, 0x9000},
0xFF2E: {0x4E, 0x9000},
0xFF2F: {0x4F, 0x9000},
0xFF30: {0x50, 0x9000},
0xFF31: {0x51, 0x9000},
0xFF32: {0x52, 0x9000},
0xFF33: {0x53, 0x9000},
0xFF34: {0x54, 0x9000},
0xFF35: {0x55, 0x9000},
0xFF36: {0x56, 0x9000},
0xFF37: {0x57, 0x9000},
0xFF38: {0x58, 0x9000},
0xFF39: {0x59, 0x9000},
0xFF3A: {0x5A, 0x9000},
0xFF3B: {0x5B, 0x9000},
0xFF3C: {0x5C, 0x9000},
0xFF3D: {0x5D, 0x9000},
0xFF3E: {0x5E, 0x9000},
0xFF3F: {0x5F, 0x9000},
0xFF40: {0x60, 0x9000},
0xFF41: {0x61, 0x9000},
0xFF42: {0x62, 0x9000},
0xFF43: {0x63, 0x9000},
0xFF44: {0x64, 0x9000},
0xFF45: {0x65, 0x9000},
0xFF46: {0x66, 0x9000},
0xFF47: {0x67, 0x9000},
0xFF48: {0x68, 0x9000},
0xFF49: {0x69, 0x9000},
0xFF4A: {0x6A, 0x9000},
0xFF4B: {0x6B, 0x9000},
0xFF4C: {0x6C, 0x9000},
0xFF4D: {0x6D, 0x9000},
0xFF4E: {0x6E, 0x9000},
0xFF4F: {0x6F, 0x9000},
0xFF50: {0x70, 0x9000},
0xFF51: {0x71, 0x9000},
0xFF52: {0x72, 0x9000},
0xFF53: {0x73, 0x9000},
0xFF54: {0x74, 0x9000},
0xFF55: {0x75, 0x9000},
0xFF56: {0x76, 0x9000},
0xFF57: {0x77, 0x9000},
0xFF58: {0x78, 0x9000},
0xFF59: {0x79, 0x9000},
0xFF5A: {0x7A, 0x9000},
0xFF5B: {0x7B, 0x9000},
0xFF5C: {0x7C, 0x9000},
0xFF5D: {0x7D, 0x9000},
0xFF5E: {0x7E, 0x9000},
0xFF5F: {0x2985, 0x9000},
0xFF60: {0x2986, 0x9000},
0xFF61: {0x3002, 0xB000},
0xFF62: {0x300C, 0xB000},
0xFF63: {0x300D, 0xB000},
0xFF64: {0x3001, 0xB000},
0xFF65: {0x30FB, 0xB000},
0xFF66: {0x30F2, 0xB000},
0xFF67: {0x30A1, 0xB000},
0xFF68: {0x30A3, 0xB000},
0xFF69: {0x30A5, 0xB000},
0xFF6A: {0x30A7, 0xB000},
0xFF6B: {0x30A9, 0xB000},
0xFF6C: {0x30E3, 0xB000},
0xFF6D: {0x30E5, 0xB000},
0xFF6E: {0x30E7, 0xB000},
0xFF6F: {0x30C3, 0xB000},
0xFF70: {0x30FC, 0xB000},
0xFF71: {0x30A2, 0xB000},
0xFF72: {0x30A4, 0xB000},
0xFF73: {0x30A6, 0xB000},
0xFF74: {0x30A8, 0xB000},
0xFF75: {0x30AA, 0xB000},
0xFF76: {0x30AB, 0xB000},
0xFF77: {0x30AD, 0xB000},
0xFF78: {0x30AF, 0xB000},
0xFF79: {0x30B1, 0xB000},
0xFF7A: {0x30B3, 0xB000},
0xFF7B: {0x30B5, 0xB000},
0xFF7C: {0x30B7, 0xB000},
0xFF7D: {0x30B9, 0xB000},
0xFF7E: {0x30BB, 0xB000},
0xFF7F: {0x30BD, 0xB000},
0xFF80: {0x30BF, 0xB000},
0xFF81: {0x30C1, 0xB000},
0xFF82: {0x30C4, 0xB000},
0xFF83: {0x30C6, 0xB000},
0xFF84: {0x30C8, 0xB000},
0xFF85: {0x30CA, 0xB000},
0xFF86: {0x30CB, 0xB000},
0xFF87: {0x30CC, 0xB000},
0xFF88: {0x30CD, 0xB000},
0xFF89: {0x30CE, 0xB000},
0xFF8A: {0x30CF, 0xB000},
0xFF8B: {0x30D2, 0xB000},
0xFF8C: {0x30D5, 0xB000},
0xFF8D: {0x30D8, 0xB000},
0xFF8E: {0x30DB, 0xB000},
0xFF8F: {0x30DE, 0xB000},
0xFF90: {0x30DF, 0xB000},
0xFF91: {0x30E0, 0xB000},
0xFF92: {0x30E1, 0xB000},
0xFF93: {0x30E2, 0xB000},
0xFF94: {0x30E4, 0xB000},
0xFF95: {0x30E6, 0xB000},
0xFF96: {0x30E8, 0xB000},
0xFF97: {0x30E9, 0xB000},
0xFF98: {0x30EA, 0xB000},
0xFF99: {0x30EB, 0xB000},
0xFF9A: {0x30EC, 0xB000},
0xFF9B: {0x30ED, 0xB000},
0xFF9C: {0x30EF, 0xB000},
0xFF9D: {0x30F3, 0xB000},
0xFF9E: {0x3099, 0xB000},
0xFF9F: {0x309A, 0xB000},
0xFFA0: {0x3164, 0xB000},
0xFFA1: {0x3131, 0xB000},
0xFFA2: {0x3132, 0xB000},
0xFFA3: {0x3133, 0xB000},
0xFFA4: {0x3134, 0xB000},
0xFFA5: {0x3135, 0xB000},
0xFFA6: {0x3136, 0xB000},
0xFFA7: {0x3137, 0xB000},
0xFFA8: {0x3138, 0xB000},
0xFFA9: {0x3139, 0xB000},
0xFFAA: {0x313A, 0xB000},
0xFFAB: {0x313B, 0xB000},
0xFFAC: {0x313C, 0xB000},
0xFFAD: {0x313D, 0xB000},
0xFFAE: {0x313E, 0xB000},
0xFFAF: {0x313F, 0xB000},
0xFFB0: {0x3140, 0xB000},
0xFFB1: {0x3141, 0xB000},
0xFFB2: {0x3142, 0xB000},
0xFFB3: {0x3143, 0xB000},
0xFFB4: {0x3144, 0xB000},
0xFFB5: {0x3145, 0xB000},
0xFFB6: {0x3146, 0xB000},
0xFFB7: {0x3147, 0xB000},
0xFFB8: {0x3148, 0xB000},
0xFFB9: {0x3149, 0xB000},
0xFFBA: {0x314A, 0xB000},
0xFFBB: {0x314B, 0xB000},
0xFFBC: {0x314C, 0xB000},
0xFFBD: {0x314D, 0xB000},
0xFFBE: {0x314E, 0xB000},
0xFFC2: {0x314F, 0xB000},
0xFFC3: {0x3150, 0xB000},
0xFFC4: {0x3151, 0xB000},
0xFFC5: {0x3152, 0xB000},
0xFFC6: {0x3153, 0xB000},
0xFFC7: {0x3154, 0xB000},
0xFFCA: {0x3155, 0xB000},
0xFFCB: {0x3156, 0xB000},
0xFFCC: {0x3157, 0xB000},
0xFFCD: {0x3158, 0xB000},
0xFFCE: {0x3159, 0xB000},
0xFFCF: {0x315A, 0xB000},
0xFFD2: {0x315B, 0xB000},
0xFFD3: {0x315C, 0xB000},
0xFFD4: {0x315D, 0xB000},
0xFFD5: {0x315E, 0xB000},
0xFFD6: {0x315F, 0xB000},
0xFFD7: {0x3160, 0xB000},
0xFFDA: {0x3161, 0xB000},
0xFFDB: {0x3162, 0xB000},
0xFFDC: {0x3163, 0xB000},
0xFFE0: {0xA2, 0x9000},
0xFFE1: {0xA3, 0x9000},
0xFFE2: {0xAC, 0x9000},
0xFFE3: {0xAF, 0x9000},
0xFFE4: {0xA6, 0x9000},
0xFFE5: {0xA5, 0x9000},
0xFFE6: {0x20A9, 0x9000},
0xFFE8: {0x2502, 0xB000},
0xFFE9: {0x2190, 0xB000},
0xFFEA: {0x2191, 0xB000},
0xFFEB: {0x2192, 0xB000},
0xFFEC: {0x2193, 0xB000},
0xFFED: {0x25A0, 0xB000},
0xFFEE: {0x25CB, 0xB000},
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,59 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package width
import (
"testing"
"golang.org/x/text/internal/testtext"
)
const (
loSurrogate = 0xD800
hiSurrogate = 0xDFFF
)
func TestTables(t *testing.T) {
testtext.SkipIfNotLong(t)
runes := map[rune]Kind{}
getWidthData(func(r rune, tag elem, _ rune) {
runes[r] = tag.kind()
})
for r := rune(0); r < 0x10FFFF; r++ {
if loSurrogate <= r && r <= hiSurrogate {
continue
}
p := LookupRune(r)
if got, want := p.Kind(), runes[r]; got != want {
t.Errorf("Kind of %U was %s; want %s.", r, got, want)
}
want, mapped := foldRune(r)
if got := p.Folded(); (got == 0) == mapped || got != 0 && got != want {
t.Errorf("Folded(%U) = %U; want %U", r, got, want)
}
want, mapped = widenRune(r)
if got := p.Wide(); (got == 0) == mapped || got != 0 && got != want {
t.Errorf("Wide(%U) = %U; want %U", r, got, want)
}
want, mapped = narrowRune(r)
if got := p.Narrow(); (got == 0) == mapped || got != 0 && got != want {
t.Errorf("Narrow(%U) = %U; want %U", r, got, want)
}
}
}
// TestAmbiguous verifies that that ambiguous runes with a mapping always map to
// a halfwidth rune.
func TestAmbiguous(t *testing.T) {
for r, m := range mapRunes {
if m.e != tagAmbiguous {
continue
}
if k := mapRunes[m.r].e.kind(); k != EastAsianHalfwidth {
t.Errorf("Rune %U is ambiguous and maps to a rune of type %v", r, k)
}
}
}

View File

@@ -1,239 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package width
import (
"unicode/utf8"
"golang.org/x/text/transform"
)
type foldTransform struct {
transform.NopResetter
}
func (foldTransform) Span(src []byte, atEOF bool) (n int, err error) {
for n < len(src) {
if src[n] < utf8.RuneSelf {
// ASCII fast path.
for n++; n < len(src) && src[n] < utf8.RuneSelf; n++ {
}
continue
}
v, size := trie.lookup(src[n:])
if size == 0 { // incomplete UTF-8 encoding
if !atEOF {
err = transform.ErrShortSrc
} else {
n = len(src)
}
break
}
if elem(v)&tagNeedsFold != 0 {
err = transform.ErrEndOfSpan
break
}
n += size
}
return n, err
}
func (foldTransform) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
for nSrc < len(src) {
if src[nSrc] < utf8.RuneSelf {
// ASCII fast path.
start, end := nSrc, len(src)
if d := len(dst) - nDst; d < end-start {
end = nSrc + d
}
for nSrc++; nSrc < end && src[nSrc] < utf8.RuneSelf; nSrc++ {
}
n := copy(dst[nDst:], src[start:nSrc])
if nDst += n; nDst == len(dst) {
nSrc = start + n
if nSrc == len(src) {
return nDst, nSrc, nil
}
if src[nSrc] < utf8.RuneSelf {
return nDst, nSrc, transform.ErrShortDst
}
}
continue
}
v, size := trie.lookup(src[nSrc:])
if size == 0 { // incomplete UTF-8 encoding
if !atEOF {
return nDst, nSrc, transform.ErrShortSrc
}
size = 1 // gobble 1 byte
}
if elem(v)&tagNeedsFold == 0 {
if size != copy(dst[nDst:], src[nSrc:nSrc+size]) {
return nDst, nSrc, transform.ErrShortDst
}
nDst += size
} else {
data := inverseData[byte(v)]
if len(dst)-nDst < int(data[0]) {
return nDst, nSrc, transform.ErrShortDst
}
i := 1
for end := int(data[0]); i < end; i++ {
dst[nDst] = data[i]
nDst++
}
dst[nDst] = data[i] ^ src[nSrc+size-1]
nDst++
}
nSrc += size
}
return nDst, nSrc, nil
}
type narrowTransform struct {
transform.NopResetter
}
func (narrowTransform) Span(src []byte, atEOF bool) (n int, err error) {
for n < len(src) {
if src[n] < utf8.RuneSelf {
// ASCII fast path.
for n++; n < len(src) && src[n] < utf8.RuneSelf; n++ {
}
continue
}
v, size := trie.lookup(src[n:])
if size == 0 { // incomplete UTF-8 encoding
if !atEOF {
err = transform.ErrShortSrc
} else {
n = len(src)
}
break
}
if k := elem(v).kind(); byte(v) == 0 || k != EastAsianFullwidth && k != EastAsianWide && k != EastAsianAmbiguous {
} else {
err = transform.ErrEndOfSpan
break
}
n += size
}
return n, err
}
func (narrowTransform) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
for nSrc < len(src) {
if src[nSrc] < utf8.RuneSelf {
// ASCII fast path.
start, end := nSrc, len(src)
if d := len(dst) - nDst; d < end-start {
end = nSrc + d
}
for nSrc++; nSrc < end && src[nSrc] < utf8.RuneSelf; nSrc++ {
}
n := copy(dst[nDst:], src[start:nSrc])
if nDst += n; nDst == len(dst) {
nSrc = start + n
if nSrc == len(src) {
return nDst, nSrc, nil
}
if src[nSrc] < utf8.RuneSelf {
return nDst, nSrc, transform.ErrShortDst
}
}
continue
}
v, size := trie.lookup(src[nSrc:])
if size == 0 { // incomplete UTF-8 encoding
if !atEOF {
return nDst, nSrc, transform.ErrShortSrc
}
size = 1 // gobble 1 byte
}
if k := elem(v).kind(); byte(v) == 0 || k != EastAsianFullwidth && k != EastAsianWide && k != EastAsianAmbiguous {
if size != copy(dst[nDst:], src[nSrc:nSrc+size]) {
return nDst, nSrc, transform.ErrShortDst
}
nDst += size
} else {
data := inverseData[byte(v)]
if len(dst)-nDst < int(data[0]) {
return nDst, nSrc, transform.ErrShortDst
}
i := 1
for end := int(data[0]); i < end; i++ {
dst[nDst] = data[i]
nDst++
}
dst[nDst] = data[i] ^ src[nSrc+size-1]
nDst++
}
nSrc += size
}
return nDst, nSrc, nil
}
type wideTransform struct {
transform.NopResetter
}
func (wideTransform) Span(src []byte, atEOF bool) (n int, err error) {
for n < len(src) {
// TODO: Consider ASCII fast path. Special-casing ASCII handling can
// reduce the ns/op of BenchmarkWideASCII by about 30%. This is probably
// not enough to warrant the extra code and complexity.
v, size := trie.lookup(src[n:])
if size == 0 { // incomplete UTF-8 encoding
if !atEOF {
err = transform.ErrShortSrc
} else {
n = len(src)
}
break
}
if k := elem(v).kind(); byte(v) == 0 || k != EastAsianHalfwidth && k != EastAsianNarrow {
} else {
err = transform.ErrEndOfSpan
break
}
n += size
}
return n, err
}
func (wideTransform) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
for nSrc < len(src) {
// TODO: Consider ASCII fast path. Special-casing ASCII handling can
// reduce the ns/op of BenchmarkWideASCII by about 30%. This is probably
// not enough to warrant the extra code and complexity.
v, size := trie.lookup(src[nSrc:])
if size == 0 { // incomplete UTF-8 encoding
if !atEOF {
return nDst, nSrc, transform.ErrShortSrc
}
size = 1 // gobble 1 byte
}
if k := elem(v).kind(); byte(v) == 0 || k != EastAsianHalfwidth && k != EastAsianNarrow {
if size != copy(dst[nDst:], src[nSrc:nSrc+size]) {
return nDst, nSrc, transform.ErrShortDst
}
nDst += size
} else {
data := inverseData[byte(v)]
if len(dst)-nDst < int(data[0]) {
return nDst, nSrc, transform.ErrShortDst
}
i := 1
for end := int(data[0]); i < end; i++ {
dst[nDst] = data[i]
nDst++
}
dst[nDst] = data[i] ^ src[nSrc+size-1]
nDst++
}
nSrc += size
}
return nDst, nSrc, nil
}

View File

@@ -1,701 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package width
import (
"bytes"
"strings"
"testing"
"golang.org/x/text/internal/testtext"
"golang.org/x/text/transform"
)
func foldRune(r rune) (folded rune, ok bool) {
alt, ok := mapRunes[r]
if ok && alt.e&tagNeedsFold != 0 {
return alt.r, true
}
return r, false
}
func widenRune(r rune) (wide rune, ok bool) {
alt, ok := mapRunes[r]
if k := alt.e.kind(); k == EastAsianHalfwidth || k == EastAsianNarrow {
return alt.r, true
}
return r, false
}
func narrowRune(r rune) (narrow rune, ok bool) {
alt, ok := mapRunes[r]
if k := alt.e.kind(); k == EastAsianFullwidth || k == EastAsianWide || k == EastAsianAmbiguous {
return alt.r, true
}
return r, false
}
func TestFoldSingleRunes(t *testing.T) {
for r := rune(0); r < 0x1FFFF; r++ {
if loSurrogate <= r && r <= hiSurrogate {
continue
}
x, _ := foldRune(r)
want := string(x)
got := Fold.String(string(r))
if got != want {
t.Errorf("Fold().String(%U) = %+q; want %+q", r, got, want)
}
}
}
type transformTest struct {
desc string
src string
nBuf int
nDst int
atEOF bool
dst string
nSrc int
err error
nSpan int
errSpan error
}
func (tc *transformTest) doTest(t *testing.T, tr Transformer) {
testtext.Run(t, tc.desc, func(t *testing.T) {
b := make([]byte, tc.nBuf)
nDst, nSrc, err := tr.Transform(b, []byte(tc.src), tc.atEOF)
if got := string(b[:nDst]); got != tc.dst[:nDst] {
t.Errorf("dst was %+q; want %+q", got, tc.dst)
}
if nDst != tc.nDst {
t.Errorf("nDst was %d; want %d", nDst, tc.nDst)
}
if nSrc != tc.nSrc {
t.Errorf("nSrc was %d; want %d", nSrc, tc.nSrc)
}
if err != tc.err {
t.Errorf("error was %v; want %v", err, tc.err)
}
if got := tr.String(tc.src); got != tc.dst {
t.Errorf("String(%q) = %q; want %q", tc.src, got, tc.dst)
}
n, err := tr.Span([]byte(tc.src), tc.atEOF)
if n != tc.nSpan || err != tc.errSpan {
t.Errorf("Span: got %d, %v; want %d, %v", n, err, tc.nSpan, tc.errSpan)
}
})
}
func TestFold(t *testing.T) {
for _, tc := range []transformTest{{
desc: "empty",
src: "",
nBuf: 10,
dst: "",
nDst: 0,
nSrc: 0,
atEOF: false,
err: nil,
nSpan: 0,
errSpan: nil,
}, {
desc: "short source 1",
src: "a\xc2",
nBuf: 10,
dst: "a\xc2",
nDst: 1,
nSrc: 1,
atEOF: false,
err: transform.ErrShortSrc,
nSpan: 1,
errSpan: transform.ErrShortSrc,
}, {
desc: "short source 2",
src: "a\xe0\x80",
nBuf: 10,
dst: "a\xe0\x80",
nDst: 1,
nSrc: 1,
atEOF: false,
err: transform.ErrShortSrc,
nSpan: 1,
errSpan: transform.ErrShortSrc,
}, {
desc: "incomplete but terminated source 1",
src: "a\xc2",
nBuf: 10,
dst: "a\xc2",
nDst: 2,
nSrc: 2,
atEOF: true,
err: nil,
nSpan: 2,
errSpan: nil,
}, {
desc: "incomplete but terminated source 2",
src: "a\xe0\x80",
nBuf: 10,
dst: "a\xe0\x80",
nDst: 3,
nSrc: 3,
atEOF: true,
err: nil,
nSpan: 3,
errSpan: nil,
}, {
desc: "exact fit dst",
src: "a\uff01",
nBuf: 2,
dst: "a!",
nDst: 2,
nSrc: 4,
atEOF: false,
err: nil,
nSpan: 1,
errSpan: transform.ErrEndOfSpan,
}, {
desc: "exact fit dst and src ascii",
src: "ab",
nBuf: 2,
dst: "ab",
nDst: 2,
nSrc: 2,
atEOF: true,
err: nil,
nSpan: 2,
errSpan: nil,
}, {
desc: "empty dst",
src: "\u0300",
nBuf: 0,
dst: "\u0300",
nDst: 0,
nSrc: 0,
atEOF: true,
err: transform.ErrShortDst,
nSpan: 2,
errSpan: nil,
}, {
desc: "empty dst ascii",
src: "a",
nBuf: 0,
dst: "a",
nDst: 0,
nSrc: 0,
atEOF: true,
err: transform.ErrShortDst,
nSpan: 1,
errSpan: nil,
}, {
desc: "short dst 1",
src: "a\uffe0", // ¢
nBuf: 2,
dst: "a\u00a2", // ¢
nDst: 1,
nSrc: 1,
atEOF: false,
err: transform.ErrShortDst,
nSpan: 1,
errSpan: transform.ErrEndOfSpan,
}, {
desc: "short dst 2",
src: "不夠",
nBuf: 3,
dst: "不夠",
nDst: 3,
nSrc: 3,
atEOF: true,
err: transform.ErrShortDst,
nSpan: 6,
errSpan: nil,
}, {
desc: "short dst fast path",
src: "fast",
nDst: 3,
dst: "fast",
nBuf: 3,
nSrc: 3,
atEOF: true,
err: transform.ErrShortDst,
nSpan: 4,
errSpan: nil,
}, {
desc: "short dst larger buffer",
src: "\uff21" + strings.Repeat("0", 127) + "B",
nBuf: 128,
dst: "A" + strings.Repeat("0", 127) + "B",
nDst: 128,
nSrc: 130,
atEOF: true,
err: transform.ErrShortDst,
nSpan: 0,
errSpan: transform.ErrEndOfSpan,
}, {
desc: "fast path alternation",
src: "fast路徑fast路徑",
nBuf: 20,
dst: "fast路徑fast路徑",
nDst: 20,
nSrc: 20,
atEOF: true,
err: nil,
nSpan: 20,
errSpan: nil,
}} {
tc.doTest(t, Fold)
}
}
func TestWidenSingleRunes(t *testing.T) {
for r := rune(0); r < 0x1FFFF; r++ {
if loSurrogate <= r && r <= hiSurrogate {
continue
}
alt, _ := widenRune(r)
want := string(alt)
got := Widen.String(string(r))
if got != want {
t.Errorf("Widen().String(%U) = %+q; want %+q", r, got, want)
}
}
}
func TestWiden(t *testing.T) {
for _, tc := range []transformTest{{
desc: "empty",
src: "",
nBuf: 10,
dst: "",
nDst: 0,
nSrc: 0,
atEOF: false,
err: nil,
nSpan: 0,
errSpan: nil,
}, {
desc: "short source 1",
src: "a\xc2",
nBuf: 10,
dst: "\xc2",
nDst: 3,
nSrc: 1,
atEOF: false,
err: transform.ErrShortSrc,
nSpan: 0,
errSpan: transform.ErrEndOfSpan,
}, {
desc: "short source 2",
src: "a\xe0\x80",
nBuf: 10,
dst: "\xe0\x80",
nDst: 3,
nSrc: 1,
atEOF: false,
err: transform.ErrShortSrc,
nSpan: 0,
errSpan: transform.ErrEndOfSpan,
}, {
desc: "incomplete but terminated source 1",
src: "a\xc2",
nBuf: 10,
dst: "\xc2",
nDst: 4,
nSrc: 2,
atEOF: true,
err: nil,
nSpan: 0,
errSpan: transform.ErrEndOfSpan,
}, {
desc: "incomplete but terminated source 2",
src: "a\xe0\x80",
nBuf: 10,
dst: "\xe0\x80",
nDst: 5,
nSrc: 3,
atEOF: true,
err: nil,
nSpan: 0,
errSpan: transform.ErrEndOfSpan,
}, {
desc: "short source 1 some span",
src: "\xc2",
nBuf: 10,
dst: "\xc2",
nDst: 3,
nSrc: 3,
atEOF: false,
err: transform.ErrShortSrc,
nSpan: 3,
errSpan: transform.ErrShortSrc,
}, {
desc: "short source 2 some span",
src: "\xe0\x80",
nBuf: 10,
dst: "\xe0\x80",
nDst: 3,
nSrc: 3,
atEOF: false,
err: transform.ErrShortSrc,
nSpan: 3,
errSpan: transform.ErrShortSrc,
}, {
desc: "incomplete but terminated source 1 some span",
src: "\xc2",
nBuf: 10,
dst: "\xc2",
nDst: 4,
nSrc: 4,
atEOF: true,
err: nil,
nSpan: 4,
errSpan: nil,
}, {
desc: "incomplete but terminated source 2 some span",
src: "\xe0\x80",
nBuf: 10,
dst: "\xe0\x80",
nDst: 5,
nSrc: 5,
atEOF: true,
err: nil,
nSpan: 5,
errSpan: nil,
}, {
desc: "exact fit dst",
src: "a!",
nBuf: 6,
dst: "\uff01",
nDst: 6,
nSrc: 2,
atEOF: false,
err: nil,
nSpan: 0,
errSpan: transform.ErrEndOfSpan,
}, {
desc: "empty dst",
src: "\u0300",
nBuf: 0,
dst: "\u0300",
nDst: 0,
nSrc: 0,
atEOF: true,
err: transform.ErrShortDst,
nSpan: 2,
errSpan: nil,
}, {
desc: "empty dst ascii",
src: "a",
nBuf: 0,
dst: "",
nDst: 0,
nSrc: 0,
atEOF: true,
err: transform.ErrShortDst,
nSpan: 0,
errSpan: transform.ErrEndOfSpan,
}, {
desc: "short dst 1",
src: "a\uffe0",
nBuf: 4,
dst: "\uffe0",
nDst: 3,
nSrc: 1,
atEOF: false,
err: transform.ErrShortDst,
nSpan: 0,
errSpan: transform.ErrEndOfSpan,
}, {
desc: "short dst 2",
src: "不夠",
nBuf: 3,
dst: "不夠",
nDst: 3,
nSrc: 3,
atEOF: true,
err: transform.ErrShortDst,
nSpan: 6,
errSpan: nil,
}, {
desc: "short dst ascii",
src: "ascii",
nBuf: 3,
dst: "", // U+ff41, ...
nDst: 3,
nSrc: 1,
atEOF: true,
err: transform.ErrShortDst,
nSpan: 0,
errSpan: transform.ErrEndOfSpan,
}, {
desc: "ambiguous",
src: "\uffe9",
nBuf: 4,
dst: "\u2190",
nDst: 3,
nSrc: 3,
atEOF: false,
err: nil,
nSpan: 0,
errSpan: transform.ErrEndOfSpan,
}} {
tc.doTest(t, Widen)
}
}
func TestNarrowSingleRunes(t *testing.T) {
for r := rune(0); r < 0x1FFFF; r++ {
if loSurrogate <= r && r <= hiSurrogate {
continue
}
alt, _ := narrowRune(r)
want := string(alt)
got := Narrow.String(string(r))
if got != want {
t.Errorf("Narrow().String(%U) = %+q; want %+q", r, got, want)
}
}
}
func TestNarrow(t *testing.T) {
for _, tc := range []transformTest{{
desc: "empty",
src: "",
nBuf: 10,
dst: "",
nDst: 0,
nSrc: 0,
atEOF: false,
err: nil,
nSpan: 0,
errSpan: nil,
}, {
desc: "short source 1",
src: "a\xc2",
nBuf: 10,
dst: "a\xc2",
nDst: 1,
nSrc: 1,
atEOF: false,
err: transform.ErrShortSrc,
nSpan: 1,
errSpan: transform.ErrShortSrc,
}, {
desc: "short source 2",
src: "\xe0\x80",
nBuf: 10,
dst: "a\xe0\x80",
nDst: 1,
nSrc: 3,
atEOF: false,
err: transform.ErrShortSrc,
nSpan: 0,
errSpan: transform.ErrEndOfSpan,
}, {
desc: "incomplete but terminated source 1",
src: "\xc2",
nBuf: 10,
dst: "a\xc2",
nDst: 2,
nSrc: 4,
atEOF: true,
err: nil,
nSpan: 0,
errSpan: transform.ErrEndOfSpan,
}, {
desc: "incomplete but terminated source 2",
src: "\xe0\x80",
nBuf: 10,
dst: "a\xe0\x80",
nDst: 3,
nSrc: 5,
atEOF: true,
err: nil,
nSpan: 0,
errSpan: transform.ErrEndOfSpan,
}, {
desc: "exact fit dst",
src: "\uff01",
nBuf: 2,
dst: "a!",
nDst: 2,
nSrc: 6,
atEOF: false,
err: nil,
nSpan: 0,
errSpan: transform.ErrEndOfSpan,
}, {
desc: "exact fit dst some span",
src: "a\uff01",
nBuf: 2,
dst: "a!",
nDst: 2,
nSrc: 4,
atEOF: false,
err: nil,
nSpan: 1,
errSpan: transform.ErrEndOfSpan,
}, {
desc: "empty dst",
src: "\u0300",
nBuf: 0,
dst: "\u0300",
nDst: 0,
nSrc: 0,
atEOF: true,
err: transform.ErrShortDst,
nSpan: 2,
errSpan: nil,
}, {
desc: "empty dst ascii",
src: "a",
nBuf: 0,
dst: "a",
nDst: 0,
nSrc: 0,
atEOF: true,
err: transform.ErrShortDst,
nSpan: 1,
errSpan: nil,
}, {
desc: "short dst 1",
src: "\uffe0", // ¢
nBuf: 2,
dst: "a\u00a2", // ¢
nDst: 1,
nSrc: 3,
atEOF: false,
err: transform.ErrShortDst,
nSpan: 0,
errSpan: transform.ErrEndOfSpan,
}, {
desc: "short dst 2",
src: "不夠",
nBuf: 3,
dst: "不夠",
nDst: 3,
nSrc: 3,
atEOF: true,
err: transform.ErrShortDst,
nSpan: 6,
errSpan: nil,
}, {
// Create a narrow variant of ambiguous runes, if they exist.
desc: "ambiguous",
src: "\u2190",
nBuf: 4,
dst: "\uffe9",
nDst: 3,
nSrc: 3,
atEOF: false,
err: nil,
nSpan: 0,
errSpan: transform.ErrEndOfSpan,
}, {
desc: "short dst fast path",
src: "fast",
nBuf: 3,
dst: "fast",
nDst: 3,
nSrc: 3,
atEOF: true,
err: transform.ErrShortDst,
nSpan: 4,
errSpan: nil,
}, {
desc: "short dst larger buffer",
src: "\uff21" + strings.Repeat("0", 127) + "B",
nBuf: 128,
dst: "A" + strings.Repeat("0", 127) + "B",
nDst: 128,
nSrc: 130,
atEOF: true,
err: transform.ErrShortDst,
nSpan: 0,
errSpan: transform.ErrEndOfSpan,
}, {
desc: "fast path alternation",
src: "fast路徑fast路徑",
nBuf: 20,
dst: "fast路徑fast路徑",
nDst: 20,
nSrc: 20,
atEOF: true,
err: nil,
nSpan: 20,
errSpan: nil,
}} {
tc.doTest(t, Narrow)
}
}
func bench(b *testing.B, t Transformer, s string) {
dst := make([]byte, 1024)
src := []byte(s)
b.SetBytes(int64(len(src)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
t.Transform(dst, src, true)
}
}
func changingRunes(f func(r rune) (rune, bool)) string {
buf := &bytes.Buffer{}
for r := rune(0); r <= 0xFFFF; r++ {
if _, ok := foldRune(r); ok {
buf.WriteRune(r)
}
}
return buf.String()
}
func BenchmarkFoldASCII(b *testing.B) {
bench(b, Fold, testtext.ASCII)
}
func BenchmarkFoldCJK(b *testing.B) {
bench(b, Fold, testtext.CJK)
}
func BenchmarkFoldNonCanonical(b *testing.B) {
bench(b, Fold, changingRunes(foldRune))
}
func BenchmarkFoldOther(b *testing.B) {
bench(b, Fold, testtext.TwoByteUTF8+testtext.ThreeByteUTF8)
}
func BenchmarkWideASCII(b *testing.B) {
bench(b, Widen, testtext.ASCII)
}
func BenchmarkWideCJK(b *testing.B) {
bench(b, Widen, testtext.CJK)
}
func BenchmarkWideNonCanonical(b *testing.B) {
bench(b, Widen, changingRunes(widenRune))
}
func BenchmarkWideOther(b *testing.B) {
bench(b, Widen, testtext.TwoByteUTF8+testtext.ThreeByteUTF8)
}
func BenchmarkNarrowASCII(b *testing.B) {
bench(b, Narrow, testtext.ASCII)
}
func BenchmarkNarrowCJK(b *testing.B) {
bench(b, Narrow, testtext.CJK)
}
func BenchmarkNarrowNonCanonical(b *testing.B) {
bench(b, Narrow, changingRunes(narrowRune))
}
func BenchmarkNarrowOther(b *testing.B) {
bench(b, Narrow, testtext.TwoByteUTF8+testtext.ThreeByteUTF8)
}

View File

@@ -1,30 +0,0 @@
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
package width
// elem is an entry of the width trie. The high byte is used to encode the type
// of the rune. The low byte is used to store the index to a mapping entry in
// the inverseData array.
type elem uint16
const (
tagNeutral elem = iota << typeShift
tagAmbiguous
tagWide
tagNarrow
tagFullwidth
tagHalfwidth
)
const (
numTypeBits = 3
typeShift = 16 - numTypeBits
// tagNeedsFold is true for all fullwidth and halfwidth runes except for
// the Won sign U+20A9.
tagNeedsFold = 0x1000
// The Korean Won sign is halfwidth, but SHOULD NOT be mapped to a wide
// variant.
wonSign rune = 0x20A9
)

View File

@@ -1,206 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:generate stringer -type=Kind
//go:generate go run gen.go gen_common.go gen_trieval.go
// Package width provides functionality for handling different widths in text.
//
// Wide characters behave like ideographs; they tend to allow line breaks after
// each character and remain upright in vertical text layout. Narrow characters
// are kept together in words or runs that are rotated sideways in vertical text
// layout.
//
// For more information, see http://unicode.org/reports/tr11/.
package width // import "golang.org/x/text/width"
import (
"unicode/utf8"
"golang.org/x/text/transform"
)
// TODO
// 1) Reduce table size by compressing blocks.
// 2) API proposition for computing display length
// (approximation, fixed pitch only).
// 3) Implement display length.
// Kind indicates the type of width property as defined in http://unicode.org/reports/tr11/.
type Kind int
const (
// Neutral characters do not occur in legacy East Asian character sets.
Neutral Kind = iota
// EastAsianAmbiguous characters that can be sometimes wide and sometimes
// narrow and require additional information not contained in the character
// code to further resolve their width.
EastAsianAmbiguous
// EastAsianWide characters are wide in its usual form. They occur only in
// the context of East Asian typography. These runes may have explicit
// halfwidth counterparts.
EastAsianWide
// EastAsianNarrow characters are narrow in its usual form. They often have
// fullwidth counterparts.
EastAsianNarrow
// Note: there exist Narrow runes that do not have fullwidth or wide
// counterparts, despite what the definition says (e.g. U+27E6).
// EastAsianFullwidth characters have a compatibility decompositions of type
// wide that map to a narrow counterpart.
EastAsianFullwidth
// EastAsianHalfwidth characters have a compatibility decomposition of type
// narrow that map to a wide or ambiguous counterpart, plus U+20A9 ₩ WON
// SIGN.
EastAsianHalfwidth
// Note: there exist runes that have a halfwidth counterparts but that are
// classified as Ambiguous, rather than wide (e.g. U+2190).
)
// TODO: the generated tries need to return size 1 for invalid runes for the
// width to be computed correctly (each byte should render width 1)
var trie = newWidthTrie(0)
// Lookup reports the Properties of the first rune in b and the number of bytes
// of its UTF-8 encoding.
func Lookup(b []byte) (p Properties, size int) {
v, sz := trie.lookup(b)
return Properties{elem(v), b[sz-1]}, sz
}
// LookupString reports the Properties of the first rune in s and the number of
// bytes of its UTF-8 encoding.
func LookupString(s string) (p Properties, size int) {
v, sz := trie.lookupString(s)
return Properties{elem(v), s[sz-1]}, sz
}
// LookupRune reports the Properties of rune r.
func LookupRune(r rune) Properties {
var buf [4]byte
n := utf8.EncodeRune(buf[:], r)
v, _ := trie.lookup(buf[:n])
last := byte(r)
if r >= utf8.RuneSelf {
last = 0x80 + byte(r&0x3f)
}
return Properties{elem(v), last}
}
// Properties provides access to width properties of a rune.
type Properties struct {
elem elem
last byte
}
func (e elem) kind() Kind {
return Kind(e >> typeShift)
}
// Kind returns the Kind of a rune as defined in Unicode TR #11.
// See http://unicode.org/reports/tr11/ for more details.
func (p Properties) Kind() Kind {
return p.elem.kind()
}
// Folded returns the folded variant of a rune or 0 if the rune is canonical.
func (p Properties) Folded() rune {
if p.elem&tagNeedsFold != 0 {
buf := inverseData[byte(p.elem)]
buf[buf[0]] ^= p.last
r, _ := utf8.DecodeRune(buf[1 : 1+buf[0]])
return r
}
return 0
}
// Narrow returns the narrow variant of a rune or 0 if the rune is already
// narrow or doesn't have a narrow variant.
func (p Properties) Narrow() rune {
if k := p.elem.kind(); byte(p.elem) != 0 && (k == EastAsianFullwidth || k == EastAsianWide || k == EastAsianAmbiguous) {
buf := inverseData[byte(p.elem)]
buf[buf[0]] ^= p.last
r, _ := utf8.DecodeRune(buf[1 : 1+buf[0]])
return r
}
return 0
}
// Wide returns the wide variant of a rune or 0 if the rune is already
// wide or doesn't have a wide variant.
func (p Properties) Wide() rune {
if k := p.elem.kind(); byte(p.elem) != 0 && (k == EastAsianHalfwidth || k == EastAsianNarrow) {
buf := inverseData[byte(p.elem)]
buf[buf[0]] ^= p.last
r, _ := utf8.DecodeRune(buf[1 : 1+buf[0]])
return r
}
return 0
}
// TODO for Properties:
// - Add Fullwidth/Halfwidth or Inverted methods for computing variants
// mapping.
// - Add width information (including information on non-spacing runes).
// Transformer implements the transform.Transformer interface.
type Transformer struct {
t transform.SpanningTransformer
}
// Reset implements the transform.Transformer interface.
func (t Transformer) Reset() { t.t.Reset() }
// Transform implements the transform.Transformer interface.
func (t Transformer) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
return t.t.Transform(dst, src, atEOF)
}
// Span implements the transform.SpanningTransformer interface.
func (t Transformer) Span(src []byte, atEOF bool) (n int, err error) {
return t.t.Span(src, atEOF)
}
// Bytes returns a new byte slice with the result of applying t to b.
func (t Transformer) Bytes(b []byte) []byte {
b, _, _ = transform.Bytes(t, b)
return b
}
// String returns a string with the result of applying t to s.
func (t Transformer) String(s string) string {
s, _, _ = transform.String(t, s)
return s
}
var (
// Fold is a transform that maps all runes to their canonical width.
//
// Note that the NFKC and NFKD transforms in golang.org/x/text/unicode/norm
// provide a more generic folding mechanism.
Fold Transformer = Transformer{foldTransform{}}
// Widen is a transform that maps runes to their wide variant, if
// available.
Widen Transformer = Transformer{wideTransform{}}
// Narrow is a transform that maps runes to their narrow variant, if
// available.
Narrow Transformer = Transformer{narrowTransform{}}
)
// TODO: Consider the following options:
// - Treat Ambiguous runes that have a halfwidth counterpart as wide, or some
// generalized variant of this.
// - Consider a wide Won character to be the default width (or some generalized
// variant of this).
// - Filter the set of characters that gets converted (the preferred approach is
// to allow applying filters to transforms).

3
vendor/golang.org/x/time/AUTHORS generated vendored Normal file
View File

@@ -0,0 +1,3 @@
# This source code refers to The Go Authors for copyright purposes.
# The master list of authors is in the main Go distribution,
# visible at http://tip.golang.org/AUTHORS.

26
vendor/golang.org/x/time/CONTRIBUTING.md generated vendored Normal file
View File

@@ -0,0 +1,26 @@
# Contributing to Go
Go is an open source project.
It is the work of hundreds of contributors. We appreciate your help!
## Filing issues
When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions:
1. What version of Go are you using (`go version`)?
2. What operating system and processor architecture are you using?
3. What did you do?
4. What did you expect to see?
5. What did you see instead?
General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
The gophers there will answer or ask you to file an issue if you've tripped over a bug.
## Contributing code
Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html)
before sending patches.
Unless otherwise noted, the Go source files are distributed under
the BSD-style license found in the LICENSE file.

3
vendor/golang.org/x/time/CONTRIBUTORS generated vendored Normal file
View File

@@ -0,0 +1,3 @@
# This source code was written by the Go contributors.
# The master list of contributors is in the main Go distribution,
# visible at http://tip.golang.org/CONTRIBUTORS.

27
vendor/golang.org/x/time/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,27 @@
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

22
vendor/golang.org/x/time/PATENTS generated vendored Normal file
View File

@@ -0,0 +1,22 @@
Additional IP Rights Grant (Patents)
"This implementation" means the copyrightable works distributed by
Google as part of the Go project.
Google hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section)
patent license to make, have made, use, offer to sell, sell, import,
transfer and otherwise run, modify and propagate the contents of this
implementation of Go, where such license applies only to those patent
claims, both currently owned or controlled by Google and acquired in
the future, licensable by Google that are necessarily infringed by this
implementation of Go. This grant does not include claims that would be
infringed only as a consequence of further modification of this
implementation. If you or your agent or exclusive licensee institute or
order or agree to the institution of patent litigation against any
entity (including a cross-claim or counterclaim in a lawsuit) alleging
that this implementation of Go or any code incorporated within this
implementation of Go constitutes direct or contributory patent
infringement, or inducement of patent infringement, then any patent
rights granted to you under this License for this implementation of Go
shall terminate as of the date such litigation is filed.

17
vendor/golang.org/x/time/README.md generated vendored Normal file
View File

@@ -0,0 +1,17 @@
# Go Time
This repository provides supplementary Go time packages.
## Download/Install
The easiest way to install is to run `go get -u golang.org/x/time`. You can
also manually git clone the repository to `$GOPATH/src/golang.org/x/time`.
## Report Issues / Send Patches
This repository uses Gerrit for code changes. To learn how to submit changes to
this repository, see https://golang.org/doc/contribute.html.
The main issue tracker for the time repository is located at
https://github.com/golang/go/issues. Prefix your issue with "x/time:" in the
subject line, so it is easy to find.

384
vendor/golang.org/x/time/rate/rate.go generated vendored Normal file
View File

@@ -0,0 +1,384 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package rate provides a rate limiter.
package rate
import (
"fmt"
"math"
"sync"
"time"
)
// Limit defines the maximum frequency of some events.
// Limit is represented as number of events per second.
// A zero Limit allows no events.
type Limit float64
// Inf is the infinite rate limit; it allows all events (even if burst is zero).
const Inf = Limit(math.MaxFloat64)
// Every converts a minimum time interval between events to a Limit.
func Every(interval time.Duration) Limit {
if interval <= 0 {
return Inf
}
return 1 / Limit(interval.Seconds())
}
// A Limiter controls how frequently events are allowed to happen.
// It implements a "token bucket" of size b, initially full and refilled
// at rate r tokens per second.
// Informally, in any large enough time interval, the Limiter limits the
// rate to r tokens per second, with a maximum burst size of b events.
// As a special case, if r == Inf (the infinite rate), b is ignored.
// See https://en.wikipedia.org/wiki/Token_bucket for more about token buckets.
//
// The zero value is a valid Limiter, but it will reject all events.
// Use NewLimiter to create non-zero Limiters.
//
// Limiter has three main methods, Allow, Reserve, and Wait.
// Most callers should use Wait.
//
// Each of the three methods consumes a single token.
// They differ in their behavior when no token is available.
// If no token is available, Allow returns false.
// If no token is available, Reserve returns a reservation for a future token
// and the amount of time the caller must wait before using it.
// If no token is available, Wait blocks until one can be obtained
// or its associated context.Context is canceled.
//
// The methods AllowN, ReserveN, and WaitN consume n tokens.
type Limiter struct {
limit Limit
burst int
mu sync.Mutex
tokens float64
// last is the last time the limiter's tokens field was updated
last time.Time
// lastEvent is the latest time of a rate-limited event (past or future)
lastEvent time.Time
}
// Limit returns the maximum overall event rate.
func (lim *Limiter) Limit() Limit {
lim.mu.Lock()
defer lim.mu.Unlock()
return lim.limit
}
// Burst returns the maximum burst size. Burst is the maximum number of tokens
// that can be consumed in a single call to Allow, Reserve, or Wait, so higher
// Burst values allow more events to happen at once.
// A zero Burst allows no events, unless limit == Inf.
func (lim *Limiter) Burst() int {
return lim.burst
}
// NewLimiter returns a new Limiter that allows events up to rate r and permits
// bursts of at most b tokens.
func NewLimiter(r Limit, b int) *Limiter {
return &Limiter{
limit: r,
burst: b,
}
}
// Allow is shorthand for AllowN(time.Now(), 1).
func (lim *Limiter) Allow() bool {
return lim.AllowN(time.Now(), 1)
}
// AllowN reports whether n events may happen at time now.
// Use this method if you intend to drop / skip events that exceed the rate limit.
// Otherwise use Reserve or Wait.
func (lim *Limiter) AllowN(now time.Time, n int) bool {
return lim.reserveN(now, n, 0).ok
}
// A Reservation holds information about events that are permitted by a Limiter to happen after a delay.
// A Reservation may be canceled, which may enable the Limiter to permit additional events.
type Reservation struct {
ok bool
lim *Limiter
tokens int
timeToAct time.Time
// This is the Limit at reservation time, it can change later.
limit Limit
}
// OK returns whether the limiter can provide the requested number of tokens
// within the maximum wait time. If OK is false, Delay returns InfDuration, and
// Cancel does nothing.
func (r *Reservation) OK() bool {
return r.ok
}
// Delay is shorthand for DelayFrom(time.Now()).
func (r *Reservation) Delay() time.Duration {
return r.DelayFrom(time.Now())
}
// InfDuration is the duration returned by Delay when a Reservation is not OK.
const InfDuration = time.Duration(1<<63 - 1)
// DelayFrom returns the duration for which the reservation holder must wait
// before taking the reserved action. Zero duration means act immediately.
// InfDuration means the limiter cannot grant the tokens requested in this
// Reservation within the maximum wait time.
func (r *Reservation) DelayFrom(now time.Time) time.Duration {
if !r.ok {
return InfDuration
}
delay := r.timeToAct.Sub(now)
if delay < 0 {
return 0
}
return delay
}
// Cancel is shorthand for CancelAt(time.Now()).
func (r *Reservation) Cancel() {
r.CancelAt(time.Now())
return
}
// CancelAt indicates that the reservation holder will not perform the reserved action
// and reverses the effects of this Reservation on the rate limit as much as possible,
// considering that other reservations may have already been made.
func (r *Reservation) CancelAt(now time.Time) {
if !r.ok {
return
}
r.lim.mu.Lock()
defer r.lim.mu.Unlock()
if r.lim.limit == Inf || r.tokens == 0 || r.timeToAct.Before(now) {
return
}
// calculate tokens to restore
// The duration between lim.lastEvent and r.timeToAct tells us how many tokens were reserved
// after r was obtained. These tokens should not be restored.
restoreTokens := float64(r.tokens) - r.limit.tokensFromDuration(r.lim.lastEvent.Sub(r.timeToAct))
if restoreTokens <= 0 {
return
}
// advance time to now
now, _, tokens := r.lim.advance(now)
// calculate new number of tokens
tokens += restoreTokens
if burst := float64(r.lim.burst); tokens > burst {
tokens = burst
}
// update state
r.lim.last = now
r.lim.tokens = tokens
if r.timeToAct == r.lim.lastEvent {
prevEvent := r.timeToAct.Add(r.limit.durationFromTokens(float64(-r.tokens)))
if !prevEvent.Before(now) {
r.lim.lastEvent = prevEvent
}
}
return
}
// Reserve is shorthand for ReserveN(time.Now(), 1).
func (lim *Limiter) Reserve() *Reservation {
return lim.ReserveN(time.Now(), 1)
}
// ReserveN returns a Reservation that indicates how long the caller must wait before n events happen.
// The Limiter takes this Reservation into account when allowing future events.
// ReserveN returns false if n exceeds the Limiter's burst size.
// Usage example:
// r := lim.ReserveN(time.Now(), 1)
// if !r.OK() {
// // Not allowed to act! Did you remember to set lim.burst to be > 0 ?
// return
// }
// time.Sleep(r.Delay())
// Act()
// Use this method if you wish to wait and slow down in accordance with the rate limit without dropping events.
// If you need to respect a deadline or cancel the delay, use Wait instead.
// To drop or skip events exceeding rate limit, use Allow instead.
func (lim *Limiter) ReserveN(now time.Time, n int) *Reservation {
r := lim.reserveN(now, n, InfDuration)
return &r
}
// contextContext is a temporary(?) copy of the context.Context type
// to support both Go 1.6 using golang.org/x/net/context and Go 1.7+
// with the built-in context package. If people ever stop using Go 1.6
// we can remove this.
type contextContext interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key interface{}) interface{}
}
// Wait is shorthand for WaitN(ctx, 1).
func (lim *Limiter) wait(ctx contextContext) (err error) {
return lim.WaitN(ctx, 1)
}
// WaitN blocks until lim permits n events to happen.
// It returns an error if n exceeds the Limiter's burst size, the Context is
// canceled, or the expected wait time exceeds the Context's Deadline.
// The burst limit is ignored if the rate limit is Inf.
func (lim *Limiter) waitN(ctx contextContext, n int) (err error) {
if n > lim.burst && lim.limit != Inf {
return fmt.Errorf("rate: Wait(n=%d) exceeds limiter's burst %d", n, lim.burst)
}
// Check if ctx is already cancelled
select {
case <-ctx.Done():
return ctx.Err()
default:
}
// Determine wait limit
now := time.Now()
waitLimit := InfDuration
if deadline, ok := ctx.Deadline(); ok {
waitLimit = deadline.Sub(now)
}
// Reserve
r := lim.reserveN(now, n, waitLimit)
if !r.ok {
return fmt.Errorf("rate: Wait(n=%d) would exceed context deadline", n)
}
// Wait if necessary
delay := r.DelayFrom(now)
if delay == 0 {
return nil
}
t := time.NewTimer(delay)
defer t.Stop()
select {
case <-t.C:
// We can proceed.
return nil
case <-ctx.Done():
// Context was canceled before we could proceed. Cancel the
// reservation, which may permit other events to proceed sooner.
r.Cancel()
return ctx.Err()
}
}
// SetLimit is shorthand for SetLimitAt(time.Now(), newLimit).
func (lim *Limiter) SetLimit(newLimit Limit) {
lim.SetLimitAt(time.Now(), newLimit)
}
// SetLimitAt sets a new Limit for the limiter. The new Limit, and Burst, may be violated
// or underutilized by those which reserved (using Reserve or Wait) but did not yet act
// before SetLimitAt was called.
func (lim *Limiter) SetLimitAt(now time.Time, newLimit Limit) {
lim.mu.Lock()
defer lim.mu.Unlock()
now, _, tokens := lim.advance(now)
lim.last = now
lim.tokens = tokens
lim.limit = newLimit
}
// reserveN is a helper method for AllowN, ReserveN, and WaitN.
// maxFutureReserve specifies the maximum reservation wait duration allowed.
// reserveN returns Reservation, not *Reservation, to avoid allocation in AllowN and WaitN.
func (lim *Limiter) reserveN(now time.Time, n int, maxFutureReserve time.Duration) Reservation {
lim.mu.Lock()
if lim.limit == Inf {
lim.mu.Unlock()
return Reservation{
ok: true,
lim: lim,
tokens: n,
timeToAct: now,
}
}
now, last, tokens := lim.advance(now)
// Calculate the remaining number of tokens resulting from the request.
tokens -= float64(n)
// Calculate the wait duration
var waitDuration time.Duration
if tokens < 0 {
waitDuration = lim.limit.durationFromTokens(-tokens)
}
// Decide result
ok := n <= lim.burst && waitDuration <= maxFutureReserve
// Prepare reservation
r := Reservation{
ok: ok,
lim: lim,
limit: lim.limit,
}
if ok {
r.tokens = n
r.timeToAct = now.Add(waitDuration)
}
// Update state
if ok {
lim.last = now
lim.tokens = tokens
lim.lastEvent = r.timeToAct
} else {
lim.last = last
}
lim.mu.Unlock()
return r
}
// advance calculates and returns an updated state for lim resulting from the passage of time.
// lim is not changed.
func (lim *Limiter) advance(now time.Time) (newNow time.Time, newLast time.Time, newTokens float64) {
last := lim.last
if now.Before(last) {
last = now
}
// Avoid making delta overflow below when last is very old.
maxElapsed := lim.limit.durationFromTokens(float64(lim.burst) - lim.tokens)
elapsed := now.Sub(last)
if elapsed > maxElapsed {
elapsed = maxElapsed
}
// Calculate the new number of tokens, due to time that passed.
delta := lim.limit.tokensFromDuration(elapsed)
tokens := lim.tokens + delta
if burst := float64(lim.burst); tokens > burst {
tokens = burst
}
return now, last, tokens
}
// durationFromTokens is a unit conversion function from the number of tokens to the duration
// of time it takes to accumulate them at a rate of limit tokens per second.
func (limit Limit) durationFromTokens(tokens float64) time.Duration {
seconds := tokens / float64(limit)
return time.Nanosecond * time.Duration(1e9*seconds)
}
// tokensFromDuration is a unit conversion function from a time duration to the number of tokens
// which could be accumulated during that duration at a rate of limit tokens per second.
func (limit Limit) tokensFromDuration(d time.Duration) float64 {
return d.Seconds() * float64(limit)
}

21
vendor/golang.org/x/time/rate/rate_go16.go generated vendored Normal file
View File

@@ -0,0 +1,21 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !go1.7
package rate
import "golang.org/x/net/context"
// Wait is shorthand for WaitN(ctx, 1).
func (lim *Limiter) Wait(ctx context.Context) (err error) {
return lim.waitN(ctx, 1)
}
// WaitN blocks until lim permits n events to happen.
// It returns an error if n exceeds the Limiter's burst size, the Context is
// canceled, or the expected wait time exceeds the Context's Deadline.
func (lim *Limiter) WaitN(ctx context.Context, n int) (err error) {
return lim.waitN(ctx, n)
}

21
vendor/golang.org/x/time/rate/rate_go17.go generated vendored Normal file
View File

@@ -0,0 +1,21 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.7
package rate
import "context"
// Wait is shorthand for WaitN(ctx, 1).
func (lim *Limiter) Wait(ctx context.Context) (err error) {
return lim.waitN(ctx, 1)
}
// WaitN blocks until lim permits n events to happen.
// It returns an error if n exceeds the Limiter's burst size, the Context is
// canceled, or the expected wait time exceeds the Context's Deadline.
func (lim *Limiter) WaitN(ctx context.Context, n int) (err error) {
return lim.waitN(ctx, n)
}

459
vendor/golang.org/x/time/rate/rate_test.go generated vendored Normal file
View File

@@ -0,0 +1,459 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.7
package rate
import (
"context"
"math"
"runtime"
"sync"
"sync/atomic"
"testing"
"time"
)
func TestLimit(t *testing.T) {
if Limit(10) == Inf {
t.Errorf("Limit(10) == Inf should be false")
}
}
func closeEnough(a, b Limit) bool {
return (math.Abs(float64(a)/float64(b)) - 1.0) < 1e-9
}
func TestEvery(t *testing.T) {
cases := []struct {
interval time.Duration
lim Limit
}{
{0, Inf},
{-1, Inf},
{1 * time.Nanosecond, Limit(1e9)},
{1 * time.Microsecond, Limit(1e6)},
{1 * time.Millisecond, Limit(1e3)},
{10 * time.Millisecond, Limit(100)},
{100 * time.Millisecond, Limit(10)},
{1 * time.Second, Limit(1)},
{2 * time.Second, Limit(0.5)},
{time.Duration(2.5 * float64(time.Second)), Limit(0.4)},
{4 * time.Second, Limit(0.25)},
{10 * time.Second, Limit(0.1)},
{time.Duration(math.MaxInt64), Limit(1e9 / float64(math.MaxInt64))},
}
for _, tc := range cases {
lim := Every(tc.interval)
if !closeEnough(lim, tc.lim) {
t.Errorf("Every(%v) = %v want %v", tc.interval, lim, tc.lim)
}
}
}
const (
d = 100 * time.Millisecond
)
var (
t0 = time.Now()
t1 = t0.Add(time.Duration(1) * d)
t2 = t0.Add(time.Duration(2) * d)
t3 = t0.Add(time.Duration(3) * d)
t4 = t0.Add(time.Duration(4) * d)
t5 = t0.Add(time.Duration(5) * d)
t9 = t0.Add(time.Duration(9) * d)
)
type allow struct {
t time.Time
n int
ok bool
}
func run(t *testing.T, lim *Limiter, allows []allow) {
for i, allow := range allows {
ok := lim.AllowN(allow.t, allow.n)
if ok != allow.ok {
t.Errorf("step %d: lim.AllowN(%v, %v) = %v want %v",
i, allow.t, allow.n, ok, allow.ok)
}
}
}
func TestLimiterBurst1(t *testing.T) {
run(t, NewLimiter(10, 1), []allow{
{t0, 1, true},
{t0, 1, false},
{t0, 1, false},
{t1, 1, true},
{t1, 1, false},
{t1, 1, false},
{t2, 2, false}, // burst size is 1, so n=2 always fails
{t2, 1, true},
{t2, 1, false},
})
}
func TestLimiterBurst3(t *testing.T) {
run(t, NewLimiter(10, 3), []allow{
{t0, 2, true},
{t0, 2, false},
{t0, 1, true},
{t0, 1, false},
{t1, 4, false},
{t2, 1, true},
{t3, 1, true},
{t4, 1, true},
{t4, 1, true},
{t4, 1, false},
{t4, 1, false},
{t9, 3, true},
{t9, 0, true},
})
}
func TestLimiterJumpBackwards(t *testing.T) {
run(t, NewLimiter(10, 3), []allow{
{t1, 1, true}, // start at t1
{t0, 1, true}, // jump back to t0, two tokens remain
{t0, 1, true},
{t0, 1, false},
{t0, 1, false},
{t1, 1, true}, // got a token
{t1, 1, false},
{t1, 1, false},
{t2, 1, true}, // got another token
{t2, 1, false},
{t2, 1, false},
})
}
func TestSimultaneousRequests(t *testing.T) {
const (
limit = 1
burst = 5
numRequests = 15
)
var (
wg sync.WaitGroup
numOK = uint32(0)
)
// Very slow replenishing bucket.
lim := NewLimiter(limit, burst)
// Tries to take a token, atomically updates the counter and decreases the wait
// group counter.
f := func() {
defer wg.Done()
if ok := lim.Allow(); ok {
atomic.AddUint32(&numOK, 1)
}
}
wg.Add(numRequests)
for i := 0; i < numRequests; i++ {
go f()
}
wg.Wait()
if numOK != burst {
t.Errorf("numOK = %d, want %d", numOK, burst)
}
}
func TestLongRunningQPS(t *testing.T) {
if testing.Short() {
t.Skip("skipping in short mode")
}
if runtime.GOOS == "openbsd" {
t.Skip("low resolution time.Sleep invalidates test (golang.org/issue/14183)")
return
}
// The test runs for a few seconds executing many requests and then checks
// that overall number of requests is reasonable.
const (
limit = 100
burst = 100
)
var numOK = int32(0)
lim := NewLimiter(limit, burst)
var wg sync.WaitGroup
f := func() {
if ok := lim.Allow(); ok {
atomic.AddInt32(&numOK, 1)
}
wg.Done()
}
start := time.Now()
end := start.Add(5 * time.Second)
for time.Now().Before(end) {
wg.Add(1)
go f()
// This will still offer ~500 requests per second, but won't consume
// outrageous amount of CPU.
time.Sleep(2 * time.Millisecond)
}
wg.Wait()
elapsed := time.Since(start)
ideal := burst + (limit * float64(elapsed) / float64(time.Second))
// We should never get more requests than allowed.
if want := int32(ideal + 1); numOK > want {
t.Errorf("numOK = %d, want %d (ideal %f)", numOK, want, ideal)
}
// We should get very close to the number of requests allowed.
if want := int32(0.999 * ideal); numOK < want {
t.Errorf("numOK = %d, want %d (ideal %f)", numOK, want, ideal)
}
}
type request struct {
t time.Time
n int
act time.Time
ok bool
}
// dFromDuration converts a duration to a multiple of the global constant d
func dFromDuration(dur time.Duration) int {
// Adding a millisecond to be swallowed by the integer division
// because we don't care about small inaccuracies
return int((dur + time.Millisecond) / d)
}
// dSince returns multiples of d since t0
func dSince(t time.Time) int {
return dFromDuration(t.Sub(t0))
}
func runReserve(t *testing.T, lim *Limiter, req request) *Reservation {
return runReserveMax(t, lim, req, InfDuration)
}
func runReserveMax(t *testing.T, lim *Limiter, req request, maxReserve time.Duration) *Reservation {
r := lim.reserveN(req.t, req.n, maxReserve)
if r.ok && (dSince(r.timeToAct) != dSince(req.act)) || r.ok != req.ok {
t.Errorf("lim.reserveN(t%d, %v, %v) = (t%d, %v) want (t%d, %v)",
dSince(req.t), req.n, maxReserve, dSince(r.timeToAct), r.ok, dSince(req.act), req.ok)
}
return &r
}
func TestSimpleReserve(t *testing.T) {
lim := NewLimiter(10, 2)
runReserve(t, lim, request{t0, 2, t0, true})
runReserve(t, lim, request{t0, 2, t2, true})
runReserve(t, lim, request{t3, 2, t4, true})
}
func TestMix(t *testing.T) {
lim := NewLimiter(10, 2)
runReserve(t, lim, request{t0, 3, t1, false}) // should return false because n > Burst
runReserve(t, lim, request{t0, 2, t0, true})
run(t, lim, []allow{{t1, 2, false}}) // not enought tokens - don't allow
runReserve(t, lim, request{t1, 2, t2, true})
run(t, lim, []allow{{t1, 1, false}}) // negative tokens - don't allow
run(t, lim, []allow{{t3, 1, true}})
}
func TestCancelInvalid(t *testing.T) {
lim := NewLimiter(10, 2)
runReserve(t, lim, request{t0, 2, t0, true})
r := runReserve(t, lim, request{t0, 3, t3, false})
r.CancelAt(t0) // should have no effect
runReserve(t, lim, request{t0, 2, t2, true}) // did not get extra tokens
}
func TestCancelLast(t *testing.T) {
lim := NewLimiter(10, 2)
runReserve(t, lim, request{t0, 2, t0, true})
r := runReserve(t, lim, request{t0, 2, t2, true})
r.CancelAt(t1) // got 2 tokens back
runReserve(t, lim, request{t1, 2, t2, true})
}
func TestCancelTooLate(t *testing.T) {
lim := NewLimiter(10, 2)
runReserve(t, lim, request{t0, 2, t0, true})
r := runReserve(t, lim, request{t0, 2, t2, true})
r.CancelAt(t3) // too late to cancel - should have no effect
runReserve(t, lim, request{t3, 2, t4, true})
}
func TestCancel0Tokens(t *testing.T) {
lim := NewLimiter(10, 2)
runReserve(t, lim, request{t0, 2, t0, true})
r := runReserve(t, lim, request{t0, 1, t1, true})
runReserve(t, lim, request{t0, 1, t2, true})
r.CancelAt(t0) // got 0 tokens back
runReserve(t, lim, request{t0, 1, t3, true})
}
func TestCancel1Token(t *testing.T) {
lim := NewLimiter(10, 2)
runReserve(t, lim, request{t0, 2, t0, true})
r := runReserve(t, lim, request{t0, 2, t2, true})
runReserve(t, lim, request{t0, 1, t3, true})
r.CancelAt(t2) // got 1 token back
runReserve(t, lim, request{t2, 2, t4, true})
}
func TestCancelMulti(t *testing.T) {
lim := NewLimiter(10, 4)
runReserve(t, lim, request{t0, 4, t0, true})
rA := runReserve(t, lim, request{t0, 3, t3, true})
runReserve(t, lim, request{t0, 1, t4, true})
rC := runReserve(t, lim, request{t0, 1, t5, true})
rC.CancelAt(t1) // get 1 token back
rA.CancelAt(t1) // get 2 tokens back, as if C was never reserved
runReserve(t, lim, request{t1, 3, t5, true})
}
func TestReserveJumpBack(t *testing.T) {
lim := NewLimiter(10, 2)
runReserve(t, lim, request{t1, 2, t1, true}) // start at t1
runReserve(t, lim, request{t0, 1, t1, true}) // should violate Limit,Burst
runReserve(t, lim, request{t2, 2, t3, true})
}
func TestReserveJumpBackCancel(t *testing.T) {
lim := NewLimiter(10, 2)
runReserve(t, lim, request{t1, 2, t1, true}) // start at t1
r := runReserve(t, lim, request{t1, 2, t3, true})
runReserve(t, lim, request{t1, 1, t4, true})
r.CancelAt(t0) // cancel at t0, get 1 token back
runReserve(t, lim, request{t1, 2, t4, true}) // should violate Limit,Burst
}
func TestReserveSetLimit(t *testing.T) {
lim := NewLimiter(5, 2)
runReserve(t, lim, request{t0, 2, t0, true})
runReserve(t, lim, request{t0, 2, t4, true})
lim.SetLimitAt(t2, 10)
runReserve(t, lim, request{t2, 1, t4, true}) // violates Limit and Burst
}
func TestReserveSetLimitCancel(t *testing.T) {
lim := NewLimiter(5, 2)
runReserve(t, lim, request{t0, 2, t0, true})
r := runReserve(t, lim, request{t0, 2, t4, true})
lim.SetLimitAt(t2, 10)
r.CancelAt(t2) // 2 tokens back
runReserve(t, lim, request{t2, 2, t3, true})
}
func TestReserveMax(t *testing.T) {
lim := NewLimiter(10, 2)
maxT := d
runReserveMax(t, lim, request{t0, 2, t0, true}, maxT)
runReserveMax(t, lim, request{t0, 1, t1, true}, maxT) // reserve for close future
runReserveMax(t, lim, request{t0, 1, t2, false}, maxT) // time to act too far in the future
}
type wait struct {
name string
ctx context.Context
n int
delay int // in multiples of d
nilErr bool
}
func runWait(t *testing.T, lim *Limiter, w wait) {
start := time.Now()
err := lim.WaitN(w.ctx, w.n)
delay := time.Now().Sub(start)
if (w.nilErr && err != nil) || (!w.nilErr && err == nil) || w.delay != dFromDuration(delay) {
errString := "<nil>"
if !w.nilErr {
errString = "<non-nil error>"
}
t.Errorf("lim.WaitN(%v, lim, %v) = %v with delay %v ; want %v with delay %v",
w.name, w.n, err, delay, errString, d*time.Duration(w.delay))
}
}
func TestWaitSimple(t *testing.T) {
lim := NewLimiter(10, 3)
ctx, cancel := context.WithCancel(context.Background())
cancel()
runWait(t, lim, wait{"already-cancelled", ctx, 1, 0, false})
runWait(t, lim, wait{"exceed-burst-error", context.Background(), 4, 0, false})
runWait(t, lim, wait{"act-now", context.Background(), 2, 0, true})
runWait(t, lim, wait{"act-later", context.Background(), 3, 2, true})
}
func TestWaitCancel(t *testing.T) {
lim := NewLimiter(10, 3)
ctx, cancel := context.WithCancel(context.Background())
runWait(t, lim, wait{"act-now", ctx, 2, 0, true}) // after this lim.tokens = 1
go func() {
time.Sleep(d)
cancel()
}()
runWait(t, lim, wait{"will-cancel", ctx, 3, 1, false})
// should get 3 tokens back, and have lim.tokens = 2
t.Logf("tokens:%v last:%v lastEvent:%v", lim.tokens, lim.last, lim.lastEvent)
runWait(t, lim, wait{"act-now-after-cancel", context.Background(), 2, 0, true})
}
func TestWaitTimeout(t *testing.T) {
lim := NewLimiter(10, 3)
ctx, cancel := context.WithTimeout(context.Background(), d)
defer cancel()
runWait(t, lim, wait{"act-now", ctx, 2, 0, true})
runWait(t, lim, wait{"w-timeout-err", ctx, 3, 0, false})
}
func TestWaitInf(t *testing.T) {
lim := NewLimiter(Inf, 0)
runWait(t, lim, wait{"exceed-burst-no-error", context.Background(), 3, 0, true})
}
func BenchmarkAllowN(b *testing.B) {
lim := NewLimiter(Every(1*time.Second), 1)
now := time.Now()
b.ReportAllocs()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
lim.AllowN(now, 1)
}
})
}
func BenchmarkWaitNNoDelay(b *testing.B) {
lim := NewLimiter(Limit(b.N), b.N)
ctx := context.Background()
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
lim.WaitN(ctx, 1)
}
}