mirror of
https://github.com/coredns/coredns.git
synced 2026-02-06 23:43:10 -05:00
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:
92
vendor/golang.org/x/text/width/common_test.go
generated
vendored
92
vendor/golang.org/x/text/width/common_test.go
generated
vendored
@@ -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)
|
||||
})
|
||||
}
|
||||
52
vendor/golang.org/x/text/width/example_test.go
generated
vendored
52
vendor/golang.org/x/text/width/example_test.go
generated
vendored
@@ -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ヲ₩○¥A"
|
||||
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ヲ₩○¥A
|
||||
// [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ヲ₩○¥A"
|
||||
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ヲ₩○¥A
|
||||
// [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
115
vendor/golang.org/x/text/width/gen.go
generated
vendored
@@ -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 -> A (U+FF21 -> U+0041)
|
||||
// B -> 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())
|
||||
}
|
||||
96
vendor/golang.org/x/text/width/gen_common.go
generated
vendored
96
vendor/golang.org/x/text/width/gen_common.go
generated
vendored
@@ -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)
|
||||
})
|
||||
}
|
||||
34
vendor/golang.org/x/text/width/gen_trieval.go
generated
vendored
34
vendor/golang.org/x/text/width/gen_trieval.go
generated
vendored
@@ -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
|
||||
)
|
||||
16
vendor/golang.org/x/text/width/kind_string.go
generated
vendored
16
vendor/golang.org/x/text/width/kind_string.go
generated
vendored
@@ -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]]
|
||||
}
|
||||
461
vendor/golang.org/x/text/width/runes_test.go
generated
vendored
461
vendor/golang.org/x/text/width/runes_test.go
generated
vendored
@@ -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},
|
||||
}
|
||||
1318
vendor/golang.org/x/text/width/tables10.0.0.go
generated
vendored
1318
vendor/golang.org/x/text/width/tables10.0.0.go
generated
vendored
File diff suppressed because it is too large
Load Diff
1286
vendor/golang.org/x/text/width/tables9.0.0.go
generated
vendored
1286
vendor/golang.org/x/text/width/tables9.0.0.go
generated
vendored
File diff suppressed because it is too large
Load Diff
59
vendor/golang.org/x/text/width/tables_test.go
generated
vendored
59
vendor/golang.org/x/text/width/tables_test.go
generated
vendored
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
239
vendor/golang.org/x/text/width/transform.go
generated
vendored
239
vendor/golang.org/x/text/width/transform.go
generated
vendored
@@ -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
|
||||
}
|
||||
701
vendor/golang.org/x/text/width/transform_test.go
generated
vendored
701
vendor/golang.org/x/text/width/transform_test.go
generated
vendored
@@ -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: "a\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: "a\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: "a\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: "a\xe0\x80",
|
||||
nDst: 5,
|
||||
nSrc: 3,
|
||||
atEOF: true,
|
||||
err: nil,
|
||||
nSpan: 0,
|
||||
errSpan: transform.ErrEndOfSpan,
|
||||
}, {
|
||||
desc: "short source 1 some span",
|
||||
src: "a\xc2",
|
||||
nBuf: 10,
|
||||
dst: "a\xc2",
|
||||
nDst: 3,
|
||||
nSrc: 3,
|
||||
atEOF: false,
|
||||
err: transform.ErrShortSrc,
|
||||
nSpan: 3,
|
||||
errSpan: transform.ErrShortSrc,
|
||||
}, {
|
||||
desc: "short source 2 some span",
|
||||
src: "a\xe0\x80",
|
||||
nBuf: 10,
|
||||
dst: "a\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: "a\xc2",
|
||||
nBuf: 10,
|
||||
dst: "a\xc2",
|
||||
nDst: 4,
|
||||
nSrc: 4,
|
||||
atEOF: true,
|
||||
err: nil,
|
||||
nSpan: 4,
|
||||
errSpan: nil,
|
||||
}, {
|
||||
desc: "incomplete but terminated source 2 some span",
|
||||
src: "a\xe0\x80",
|
||||
nBuf: 10,
|
||||
dst: "a\xe0\x80",
|
||||
nDst: 5,
|
||||
nSrc: 5,
|
||||
atEOF: true,
|
||||
err: nil,
|
||||
nSpan: 5,
|
||||
errSpan: nil,
|
||||
}, {
|
||||
desc: "exact fit dst",
|
||||
src: "a!",
|
||||
nBuf: 6,
|
||||
dst: "a\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: "a",
|
||||
nDst: 0,
|
||||
nSrc: 0,
|
||||
atEOF: true,
|
||||
err: transform.ErrShortDst,
|
||||
nSpan: 0,
|
||||
errSpan: transform.ErrEndOfSpan,
|
||||
}, {
|
||||
desc: "short dst 1",
|
||||
src: "a\uffe0",
|
||||
nBuf: 4,
|
||||
dst: "a\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: "ascii", // 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: "a\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: "a\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: "a\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: "a\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: "a\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)
|
||||
}
|
||||
30
vendor/golang.org/x/text/width/trieval.go
generated
vendored
30
vendor/golang.org/x/text/width/trieval.go
generated
vendored
@@ -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
|
||||
)
|
||||
206
vendor/golang.org/x/text/width/width.go
generated
vendored
206
vendor/golang.org/x/text/width/width.go
generated
vendored
@@ -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
3
vendor/golang.org/x/time/AUTHORS
generated
vendored
Normal 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
26
vendor/golang.org/x/time/CONTRIBUTING.md
generated
vendored
Normal 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
3
vendor/golang.org/x/time/CONTRIBUTORS
generated
vendored
Normal 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
27
vendor/golang.org/x/time/LICENSE
generated
vendored
Normal 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
22
vendor/golang.org/x/time/PATENTS
generated
vendored
Normal 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
17
vendor/golang.org/x/time/README.md
generated
vendored
Normal 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
384
vendor/golang.org/x/time/rate/rate.go
generated
vendored
Normal 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
21
vendor/golang.org/x/time/rate/rate_go16.go
generated
vendored
Normal 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
21
vendor/golang.org/x/time/rate/rate_go17.go
generated
vendored
Normal 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
459
vendor/golang.org/x/time/rate/rate_test.go
generated
vendored
Normal 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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user