Checking in vendor folder for ease of using go get.
This commit is contained in:
parent
7a1251853b
commit
cdb4b5a1d0
3554 changed files with 1270116 additions and 0 deletions
82
vendor/golang.org/x/text/secure/precis/benchmark_test.go
generated
vendored
Normal file
82
vendor/golang.org/x/text/secure/precis/benchmark_test.go
generated
vendored
Normal file
|
@ -0,0 +1,82 @@
|
|||
// 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 precis
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/text/internal/testtext"
|
||||
)
|
||||
|
||||
var benchData = []struct{ name, str string }{
|
||||
{"ASCII", "Malvolio"},
|
||||
{"NotNormalized", "abcdefg\u0301\u031f"},
|
||||
{"Arabic", "دبي"},
|
||||
{"Hangul", "동일조건변경허락"},
|
||||
}
|
||||
|
||||
var benchProfiles = []struct {
|
||||
name string
|
||||
p *Profile
|
||||
}{
|
||||
{"FreeForm", NewFreeform()},
|
||||
{"Nickname", Nickname},
|
||||
{"OpaqueString", OpaqueString},
|
||||
{"UsernameCaseMapped", UsernameCaseMapped},
|
||||
{"UsernameCasePreserved", UsernameCasePreserved},
|
||||
}
|
||||
|
||||
func doBench(b *testing.B, f func(b *testing.B, p *Profile, s string)) {
|
||||
for _, bp := range benchProfiles {
|
||||
for _, d := range benchData {
|
||||
testtext.Bench(b, bp.name+"/"+d.name, func(b *testing.B) {
|
||||
f(b, bp.p, d.str)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkString(b *testing.B) {
|
||||
doBench(b, func(b *testing.B, p *Profile, s string) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
p.String(s)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkBytes(b *testing.B) {
|
||||
doBench(b, func(b *testing.B, p *Profile, s string) {
|
||||
src := []byte(s)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
p.Bytes(src)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkAppend(b *testing.B) {
|
||||
doBench(b, func(b *testing.B, p *Profile, s string) {
|
||||
src := []byte(s)
|
||||
dst := make([]byte, 0, 4096)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
p.Append(dst, src)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkTransform(b *testing.B) {
|
||||
doBench(b, func(b *testing.B, p *Profile, s string) {
|
||||
src := []byte(s)
|
||||
dst := make([]byte, 2*len(s))
|
||||
t := p.NewTransformer()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
t.Transform(dst, src, true)
|
||||
}
|
||||
})
|
||||
}
|
36
vendor/golang.org/x/text/secure/precis/class.go
generated
vendored
Normal file
36
vendor/golang.org/x/text/secure/precis/class.go
generated
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
// 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 precis
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// TODO: Add contextual character rules from Appendix A of RFC5892.
|
||||
|
||||
// A class is a set of characters that match certain derived properties. The
|
||||
// PRECIS framework defines two classes: The Freeform class and the Identifier
|
||||
// class. The freeform class should be used for profiles where expressiveness is
|
||||
// prioritized over safety such as nicknames or passwords. The identifier class
|
||||
// should be used for profiles where safety is the first priority such as
|
||||
// addressable network labels and usernames.
|
||||
type class struct {
|
||||
validFrom property
|
||||
}
|
||||
|
||||
// Contains satisfies the runes.Set interface and returns whether the given rune
|
||||
// is a member of the class.
|
||||
func (c class) Contains(r rune) bool {
|
||||
b := make([]byte, 4)
|
||||
n := utf8.EncodeRune(b, r)
|
||||
|
||||
trieval, _ := dpTrie.lookup(b[:n])
|
||||
return c.validFrom <= property(trieval)
|
||||
}
|
||||
|
||||
var (
|
||||
identifier = &class{validFrom: pValid}
|
||||
freeform = &class{validFrom: idDisOrFreePVal}
|
||||
)
|
50
vendor/golang.org/x/text/secure/precis/class_test.go
generated
vendored
Normal file
50
vendor/golang.org/x/text/secure/precis/class_test.go
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
// 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 precis
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/text/runes"
|
||||
)
|
||||
|
||||
// Compile-time regression test to ensure that Class is a Set
|
||||
var _ runes.Set = (*class)(nil)
|
||||
|
||||
// Ensure that certain characters are (or are not) in the identifer class.
|
||||
func TestClassContains(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
class *class
|
||||
allowed []rune
|
||||
disallowed []rune
|
||||
}{
|
||||
{
|
||||
name: "Identifier",
|
||||
class: identifier,
|
||||
allowed: []rune("Aa0\u0021\u007e\u00df\u3007"),
|
||||
disallowed: []rune("\u2150\u2100\u2200\u3164\u2190\u2600\u303b\u1e9b"),
|
||||
},
|
||||
{
|
||||
name: "Freeform",
|
||||
class: freeform,
|
||||
allowed: []rune("Aa0\u0021\u007e\u00df\u3007 \u2150\u2100\u2200\u2190\u2600\u1e9b"),
|
||||
disallowed: []rune("\u3164\u303b"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
for _, r := range rt.allowed {
|
||||
if !rt.class.Contains(r) {
|
||||
t.Errorf("Class %s should contain %U", rt.name, r)
|
||||
}
|
||||
}
|
||||
for _, r := range rt.disallowed {
|
||||
if rt.class.Contains(r) {
|
||||
t.Errorf("Class %s should not contain %U", rt.name, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
139
vendor/golang.org/x/text/secure/precis/context.go
generated
vendored
Normal file
139
vendor/golang.org/x/text/secure/precis/context.go
generated
vendored
Normal file
|
@ -0,0 +1,139 @@
|
|||
// Copyright 2016 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 precis
|
||||
|
||||
import "errors"
|
||||
|
||||
// This file contains tables and code related to context rules.
|
||||
|
||||
type catBitmap uint16
|
||||
|
||||
const (
|
||||
// These bits, once set depending on the current value, are never unset.
|
||||
bJapanese catBitmap = 1 << iota
|
||||
bArabicIndicDigit
|
||||
bExtendedArabicIndicDigit
|
||||
|
||||
// These bits are set on each iteration depending on the current value.
|
||||
bJoinStart
|
||||
bJoinMid
|
||||
bJoinEnd
|
||||
bVirama
|
||||
bLatinSmallL
|
||||
bGreek
|
||||
bHebrew
|
||||
|
||||
// These bits indicated which of the permanent bits need to be set at the
|
||||
// end of the checks.
|
||||
bMustHaveJapn
|
||||
|
||||
permanent = bJapanese | bArabicIndicDigit | bExtendedArabicIndicDigit | bMustHaveJapn
|
||||
)
|
||||
|
||||
const finalShift = 10
|
||||
|
||||
var errContext = errors.New("precis: contextual rule violated")
|
||||
|
||||
func init() {
|
||||
// Programmatically set these required bits as, manually setting them seems
|
||||
// too error prone.
|
||||
for i, ct := range categoryTransitions {
|
||||
categoryTransitions[i].keep |= permanent
|
||||
categoryTransitions[i].accept |= ct.term
|
||||
}
|
||||
}
|
||||
|
||||
var categoryTransitions = []struct {
|
||||
keep catBitmap // mask selecting which bits to keep from the previous state
|
||||
set catBitmap // mask for which bits to set for this transition
|
||||
|
||||
// These bitmaps are used for rules that require lookahead.
|
||||
// term&accept == term must be true, which is enforced programmatically.
|
||||
term catBitmap // bits accepted as termination condition
|
||||
accept catBitmap // bits that pass, but not sufficient as termination
|
||||
|
||||
// The rule function cannot take a *context as an argument, as it would
|
||||
// cause the context to escape, adding significant overhead.
|
||||
rule func(beforeBits catBitmap) (doLookahead bool, err error)
|
||||
}{
|
||||
joiningL: {set: bJoinStart},
|
||||
joiningD: {set: bJoinStart | bJoinEnd},
|
||||
joiningT: {keep: bJoinStart, set: bJoinMid},
|
||||
joiningR: {set: bJoinEnd},
|
||||
viramaModifier: {set: bVirama},
|
||||
viramaJoinT: {set: bVirama | bJoinMid},
|
||||
latinSmallL: {set: bLatinSmallL},
|
||||
greek: {set: bGreek},
|
||||
greekJoinT: {set: bGreek | bJoinMid},
|
||||
hebrew: {set: bHebrew},
|
||||
hebrewJoinT: {set: bHebrew | bJoinMid},
|
||||
japanese: {set: bJapanese},
|
||||
katakanaMiddleDot: {set: bMustHaveJapn},
|
||||
|
||||
zeroWidthNonJoiner: {
|
||||
term: bJoinEnd,
|
||||
accept: bJoinMid,
|
||||
rule: func(before catBitmap) (doLookAhead bool, err error) {
|
||||
if before&bVirama != 0 {
|
||||
return false, nil
|
||||
}
|
||||
if before&bJoinStart == 0 {
|
||||
return false, errContext
|
||||
}
|
||||
return true, nil
|
||||
},
|
||||
},
|
||||
zeroWidthJoiner: {
|
||||
rule: func(before catBitmap) (doLookAhead bool, err error) {
|
||||
if before&bVirama == 0 {
|
||||
err = errContext
|
||||
}
|
||||
return false, err
|
||||
},
|
||||
},
|
||||
middleDot: {
|
||||
term: bLatinSmallL,
|
||||
rule: func(before catBitmap) (doLookAhead bool, err error) {
|
||||
if before&bLatinSmallL == 0 {
|
||||
return false, errContext
|
||||
}
|
||||
return true, nil
|
||||
},
|
||||
},
|
||||
greekLowerNumeralSign: {
|
||||
set: bGreek,
|
||||
term: bGreek,
|
||||
rule: func(before catBitmap) (doLookAhead bool, err error) {
|
||||
return true, nil
|
||||
},
|
||||
},
|
||||
hebrewPreceding: {
|
||||
set: bHebrew,
|
||||
rule: func(before catBitmap) (doLookAhead bool, err error) {
|
||||
if before&bHebrew == 0 {
|
||||
err = errContext
|
||||
}
|
||||
return false, err
|
||||
},
|
||||
},
|
||||
arabicIndicDigit: {
|
||||
set: bArabicIndicDigit,
|
||||
rule: func(before catBitmap) (doLookAhead bool, err error) {
|
||||
if before&bExtendedArabicIndicDigit != 0 {
|
||||
err = errContext
|
||||
}
|
||||
return false, err
|
||||
},
|
||||
},
|
||||
extendedArabicIndicDigit: {
|
||||
set: bExtendedArabicIndicDigit,
|
||||
rule: func(before catBitmap) (doLookAhead bool, err error) {
|
||||
if before&bArabicIndicDigit != 0 {
|
||||
err = errContext
|
||||
}
|
||||
return false, err
|
||||
},
|
||||
},
|
||||
}
|
14
vendor/golang.org/x/text/secure/precis/doc.go
generated
vendored
Normal file
14
vendor/golang.org/x/text/secure/precis/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
// 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 precis contains types and functions for the preparation,
|
||||
// enforcement, and comparison of internationalized strings ("PRECIS") as
|
||||
// defined in RFC 8264. It also contains several pre-defined profiles for
|
||||
// passwords, nicknames, and usernames as defined in RFC 8265 and RFC 8266.
|
||||
//
|
||||
// BE ADVISED: This package is under construction and the API may change in
|
||||
// backwards incompatible ways and without notice.
|
||||
package precis // import "golang.org/x/text/secure/precis"
|
||||
|
||||
//go:generate go run gen.go gen_trieval.go
|
244
vendor/golang.org/x/text/secure/precis/enforce10.0.0_test.go
generated
vendored
Normal file
244
vendor/golang.org/x/text/secure/precis/enforce10.0.0_test.go
generated
vendored
Normal file
|
@ -0,0 +1,244 @@
|
|||
// 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.10
|
||||
|
||||
package precis
|
||||
|
||||
import (
|
||||
"golang.org/x/text/secure/bidirule"
|
||||
)
|
||||
|
||||
var enforceTestCases = []struct {
|
||||
name string
|
||||
p *Profile
|
||||
cases []testCase
|
||||
}{
|
||||
{"Basic", NewFreeform(), []testCase{
|
||||
{"e\u0301\u031f", "\u00e9\u031f", nil}, // normalize
|
||||
}},
|
||||
|
||||
{"Context Rule 1", NewFreeform(), []testCase{
|
||||
// Rule 1: zero-width non-joiner (U+200C)
|
||||
// From RFC:
|
||||
// False
|
||||
// If Canonical_Combining_Class(Before(cp)) .eq. Virama Then True;
|
||||
// If RegExpMatch((Joining_Type:{L,D})(Joining_Type:T)*\u200C
|
||||
// (Joining_Type:T)*(Joining_Type:{R,D})) Then True;
|
||||
//
|
||||
// Example runes for different joining types:
|
||||
// Join L: U+A872; PHAGS-PA SUPERFIXED LETTER RA
|
||||
// Join D: U+062C; HAH WITH DOT BELOW
|
||||
// Join T: U+0610; ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM
|
||||
// Join R: U+0627; ALEF
|
||||
// Virama: U+0A4D; GURMUKHI SIGN VIRAMA
|
||||
// Virama and Join T: U+0ACD; GUJARATI SIGN VIRAMA
|
||||
{"\u200c", "", errContext},
|
||||
{"\u200ca", "", errContext},
|
||||
{"a\u200c", "", errContext},
|
||||
{"\u200c\u0627", "", errContext}, // missing JoinStart
|
||||
{"\u062c\u200c", "", errContext}, // missing JoinEnd
|
||||
{"\u0610\u200c\u0610\u0627", "", errContext}, // missing JoinStart
|
||||
{"\u062c\u0610\u200c\u0610", "", errContext}, // missing JoinEnd
|
||||
|
||||
// Variants of: D T* U+200c T* R
|
||||
{"\u062c\u200c\u0627", "\u062c\u200c\u0627", nil},
|
||||
{"\u062c\u0610\u200c\u0610\u0627", "\u062c\u0610\u200c\u0610\u0627", nil},
|
||||
{"\u062c\u0610\u0610\u200c\u0610\u0610\u0627", "\u062c\u0610\u0610\u200c\u0610\u0610\u0627", nil},
|
||||
{"\u062c\u0610\u200c\u0627", "\u062c\u0610\u200c\u0627", nil},
|
||||
{"\u062c\u200c\u0610\u0627", "\u062c\u200c\u0610\u0627", nil},
|
||||
|
||||
// Variants of: L T* U+200c T* D
|
||||
{"\ua872\u200c\u062c", "\ua872\u200c\u062c", nil},
|
||||
{"\ua872\u0610\u200c\u0610\u062c", "\ua872\u0610\u200c\u0610\u062c", nil},
|
||||
{"\ua872\u0610\u0610\u200c\u0610\u0610\u062c", "\ua872\u0610\u0610\u200c\u0610\u0610\u062c", nil},
|
||||
{"\ua872\u0610\u200c\u062c", "\ua872\u0610\u200c\u062c", nil},
|
||||
{"\ua872\u200c\u0610\u062c", "\ua872\u200c\u0610\u062c", nil},
|
||||
|
||||
// Virama
|
||||
{"\u0a4d\u200c", "\u0a4d\u200c", nil},
|
||||
{"\ua872\u0a4d\u200c", "\ua872\u0a4d\u200c", nil},
|
||||
{"\ua872\u0a4d\u0610\u200c", "", errContext},
|
||||
{"\ua872\u0a4d\u0610\u200c", "", errContext},
|
||||
|
||||
{"\u0acd\u200c", "\u0acd\u200c", nil},
|
||||
{"\ua872\u0acd\u200c", "\ua872\u0acd\u200c", nil},
|
||||
{"\ua872\u0acd\u0610\u200c", "", errContext},
|
||||
{"\ua872\u0acd\u0610\u200c", "", errContext},
|
||||
|
||||
// Using Virama as join T
|
||||
{"\ua872\u0acd\u200c\u062c", "\ua872\u0acd\u200c\u062c", nil},
|
||||
{"\ua872\u200c\u0acd\u062c", "\ua872\u200c\u0acd\u062c", nil},
|
||||
}},
|
||||
|
||||
{"Context Rule 2", NewFreeform(), []testCase{
|
||||
// Rule 2: zero-width joiner (U+200D)
|
||||
{"\u200d", "", errContext},
|
||||
{"\u200da", "", errContext},
|
||||
{"a\u200d", "", errContext},
|
||||
|
||||
{"\u0a4d\u200d", "\u0a4d\u200d", nil},
|
||||
{"\ua872\u0a4d\u200d", "\ua872\u0a4d\u200d", nil},
|
||||
{"\u0a4da\u200d", "", errContext},
|
||||
}},
|
||||
|
||||
{"Context Rule 3", NewFreeform(), []testCase{
|
||||
// Rule 3: middle dot
|
||||
{"·", "", errContext},
|
||||
{"l·", "", errContext},
|
||||
{"·l", "", errContext},
|
||||
{"a·", "", errContext},
|
||||
{"l·a", "", errContext},
|
||||
{"a·a", "", errContext},
|
||||
{"l·l", "l·l", nil},
|
||||
{"al·la", "al·la", nil},
|
||||
}},
|
||||
|
||||
{"Context Rule 4", NewFreeform(), []testCase{
|
||||
// Rule 4: Greek lower numeral U+0375
|
||||
{"͵", "", errContext},
|
||||
{"͵a", "", errContext},
|
||||
{"α͵", "", errContext},
|
||||
{"͵α", "͵α", nil},
|
||||
{"α͵α", "α͵α", nil},
|
||||
{"͵͵α", "͵͵α", nil}, // The numeric sign is itself Greek.
|
||||
{"α͵͵α", "α͵͵α", nil},
|
||||
{"α͵͵", "", errContext},
|
||||
{"α͵͵a", "", errContext},
|
||||
}},
|
||||
|
||||
{"Context Rule 5+6", NewFreeform(), []testCase{
|
||||
// Rule 5+6: Hebrew preceding
|
||||
// U+05f3: Geresh
|
||||
{"׳", "", errContext},
|
||||
{"׳ה", "", errContext},
|
||||
{"a׳b", "", errContext},
|
||||
{"ש׳", "ש׳", nil}, // U+05e9 U+05f3
|
||||
{"ש׳׳׳", "ש׳׳׳", nil}, // U+05e9 U+05f3
|
||||
|
||||
// U+05f4: Gershayim
|
||||
{"״", "", errContext},
|
||||
{"״ה", "", errContext},
|
||||
{"a״b", "", errContext},
|
||||
{"ש״", "ש״", nil}, // U+05e9 U+05f4
|
||||
{"ש״״״", "ש״״״", nil}, // U+05e9 U+05f4
|
||||
{"aש״״״", "aש״״״", nil}, // U+05e9 U+05f4
|
||||
}},
|
||||
|
||||
{"Context Rule 7", NewFreeform(), []testCase{
|
||||
// Rule 7: Katakana middle Dot
|
||||
{"・", "", errContext},
|
||||
{"abc・", "", errContext},
|
||||
{"・def", "", errContext},
|
||||
{"abc・def", "", errContext},
|
||||
{"aヅc・def", "aヅc・def", nil},
|
||||
{"abc・dぶf", "abc・dぶf", nil},
|
||||
{"⺐bc・def", "⺐bc・def", nil},
|
||||
}},
|
||||
|
||||
{"Context Rule 8+9", NewFreeform(), []testCase{
|
||||
// Rule 8+9: Arabic Indic Digit
|
||||
{"١٢٣٤٥۶", "", errContext},
|
||||
{"۱۲۳۴۵٦", "", errContext},
|
||||
{"١٢٣٤٥", "١٢٣٤٥", nil},
|
||||
{"۱۲۳۴۵", "۱۲۳۴۵", nil},
|
||||
}},
|
||||
|
||||
{"Nickname", Nickname, []testCase{
|
||||
{" Swan of Avon ", "Swan of Avon", nil},
|
||||
{"", "", errEmptyString},
|
||||
{" ", "", errEmptyString},
|
||||
{" ", "", errEmptyString},
|
||||
{"a\u00A0a\u1680a\u2000a\u2001a\u2002a\u2003a\u2004a\u2005a\u2006a\u2007a\u2008a\u2009a\u200Aa\u202Fa\u205Fa\u3000a", "a a a a a a a a a a a a a a a a a", nil},
|
||||
{"Foo", "Foo", nil},
|
||||
{"foo", "foo", nil},
|
||||
{"Foo Bar", "Foo Bar", nil},
|
||||
{"foo bar", "foo bar", nil},
|
||||
{"\u03A3", "\u03A3", nil},
|
||||
{"\u03C3", "\u03C3", nil},
|
||||
// Greek final sigma is left as is (do not fold!)
|
||||
{"\u03C2", "\u03C2", nil},
|
||||
{"\u265A", "♚", nil},
|
||||
{"Richard \u2163", "Richard IV", nil},
|
||||
{"\u212B", "Å", nil},
|
||||
{"\uFB00", "ff", nil}, // because of NFKC
|
||||
{"שa", "שa", nil}, // no bidi rule
|
||||
{"동일조건변경허락", "동일조건변경허락", nil},
|
||||
}},
|
||||
{"OpaqueString", OpaqueString, []testCase{
|
||||
{" Swan of Avon ", " Swan of Avon ", nil},
|
||||
{"", "", errEmptyString},
|
||||
{" ", " ", nil},
|
||||
{" ", " ", nil},
|
||||
{"a\u00A0a\u1680a\u2000a\u2001a\u2002a\u2003a\u2004a\u2005a\u2006a\u2007a\u2008a\u2009a\u200Aa\u202Fa\u205Fa\u3000a", "a a a a a a a a a a a a a a a a a", nil},
|
||||
{"Foo", "Foo", nil},
|
||||
{"foo", "foo", nil},
|
||||
{"Foo Bar", "Foo Bar", nil},
|
||||
{"foo bar", "foo bar", nil},
|
||||
{"\u03C3", "\u03C3", nil},
|
||||
{"Richard \u2163", "Richard \u2163", nil},
|
||||
{"\u212B", "Å", nil},
|
||||
{"Jack of \u2666s", "Jack of \u2666s", nil},
|
||||
{"my cat is a \u0009by", "", errDisallowedRune},
|
||||
{"שa", "שa", nil}, // no bidi rule
|
||||
}},
|
||||
{"UsernameCaseMapped", UsernameCaseMapped, []testCase{
|
||||
// TODO: Should this work?
|
||||
// {UsernameCaseMapped, "", "", errDisallowedRune},
|
||||
{"juliet@example.com", "juliet@example.com", nil},
|
||||
{"fussball", "fussball", nil},
|
||||
{"fu\u00DFball", "fu\u00DFball", nil},
|
||||
{"\u03C0", "\u03C0", nil},
|
||||
{"\u03A3", "\u03C3", nil},
|
||||
{"\u03C3", "\u03C3", nil},
|
||||
// Greek final sigma is left as is (do not fold!)
|
||||
{"\u03C2", "\u03C2", nil},
|
||||
{"\u0049", "\u0069", nil},
|
||||
{"\u0049", "\u0069", nil},
|
||||
{"\u03D2", "", errDisallowedRune},
|
||||
{"\u03B0", "\u03B0", nil},
|
||||
{"foo bar", "", errDisallowedRune},
|
||||
{"♚", "", bidirule.ErrInvalid},
|
||||
{"\u007E", "~", nil},
|
||||
{"a", "a", nil},
|
||||
{"!", "!", nil},
|
||||
{"²", "", bidirule.ErrInvalid},
|
||||
{"\t", "", errDisallowedRune},
|
||||
{"\n", "", errDisallowedRune},
|
||||
{"\u26D6", "", bidirule.ErrInvalid},
|
||||
{"\u26FF", "", bidirule.ErrInvalid},
|
||||
{"\uFB00", "", errDisallowedRune},
|
||||
{"\u1680", "", bidirule.ErrInvalid},
|
||||
{" ", "", errDisallowedRune},
|
||||
{" ", "", errDisallowedRune},
|
||||
{"\u01C5", "", errDisallowedRune},
|
||||
{"\u16EE", "", errDisallowedRune}, // Nl RUNIC ARLAUG SYMBOL
|
||||
{"\u0488", "", bidirule.ErrInvalid}, // Me COMBINING CYRILLIC HUNDRED THOUSANDS SIGN
|
||||
{"\u212B", "\u00e5", nil}, // Angstrom sign, NFC -> U+00E5
|
||||
{"A\u030A", "å", nil}, // A + ring
|
||||
{"\u00C5", "å", nil}, // A with ring
|
||||
{"\u00E7", "ç", nil}, // c cedille
|
||||
{"\u0063\u0327", "ç", nil}, // c + cedille
|
||||
{"\u0158", "ř", nil},
|
||||
{"\u0052\u030C", "ř", nil},
|
||||
|
||||
{"\u1E61", "\u1E61", nil}, // LATIN SMALL LETTER S WITH DOT ABOVE
|
||||
|
||||
// Confusable characters ARE allowed and should NOT be mapped.
|
||||
{"\u0410", "\u0430", nil}, // CYRILLIC CAPITAL LETTER A
|
||||
|
||||
// Full width should be mapped to the canonical decomposition.
|
||||
{"AB", "ab", nil},
|
||||
{"שc", "", bidirule.ErrInvalid}, // bidi rule
|
||||
|
||||
}},
|
||||
{"UsernameCasePreserved", UsernameCasePreserved, []testCase{
|
||||
{"ABC", "ABC", nil},
|
||||
{"AB", "AB", nil},
|
||||
{"שc", "", bidirule.ErrInvalid}, // bidi rule
|
||||
{"\uFB00", "", errDisallowedRune},
|
||||
{"\u212B", "\u00c5", nil}, // Angstrom sign, NFC -> U+00E5
|
||||
{"ẛ", "", errDisallowedRune}, // LATIN SMALL LETTER LONG S WITH DOT ABOVE
|
||||
}},
|
||||
}
|
244
vendor/golang.org/x/text/secure/precis/enforce9.0.0_test.go
generated
vendored
Normal file
244
vendor/golang.org/x/text/secure/precis/enforce9.0.0_test.go
generated
vendored
Normal file
|
@ -0,0 +1,244 @@
|
|||
// 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.10
|
||||
|
||||
package precis
|
||||
|
||||
import (
|
||||
"golang.org/x/text/secure/bidirule"
|
||||
)
|
||||
|
||||
var enforceTestCases = []struct {
|
||||
name string
|
||||
p *Profile
|
||||
cases []testCase
|
||||
}{
|
||||
{"Basic", NewFreeform(), []testCase{
|
||||
{"e\u0301\u031f", "\u00e9\u031f", nil}, // normalize
|
||||
}},
|
||||
|
||||
{"Context Rule 1", NewFreeform(), []testCase{
|
||||
// Rule 1: zero-width non-joiner (U+200C)
|
||||
// From RFC:
|
||||
// False
|
||||
// If Canonical_Combining_Class(Before(cp)) .eq. Virama Then True;
|
||||
// If RegExpMatch((Joining_Type:{L,D})(Joining_Type:T)*\u200C
|
||||
// (Joining_Type:T)*(Joining_Type:{R,D})) Then True;
|
||||
//
|
||||
// Example runes for different joining types:
|
||||
// Join L: U+A872; PHAGS-PA SUPERFIXED LETTER RA
|
||||
// Join D: U+062C; HAH WITH DOT BELOW
|
||||
// Join T: U+0610; ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM
|
||||
// Join R: U+0627; ALEF
|
||||
// Virama: U+0A4D; GURMUKHI SIGN VIRAMA
|
||||
// Virama and Join T: U+0ACD; GUJARATI SIGN VIRAMA
|
||||
{"\u200c", "", errContext},
|
||||
{"\u200ca", "", errContext},
|
||||
{"a\u200c", "", errContext},
|
||||
{"\u200c\u0627", "", errContext}, // missing JoinStart
|
||||
{"\u062c\u200c", "", errContext}, // missing JoinEnd
|
||||
{"\u0610\u200c\u0610\u0627", "", errContext}, // missing JoinStart
|
||||
{"\u062c\u0610\u200c\u0610", "", errContext}, // missing JoinEnd
|
||||
|
||||
// Variants of: D T* U+200c T* R
|
||||
{"\u062c\u200c\u0627", "\u062c\u200c\u0627", nil},
|
||||
{"\u062c\u0610\u200c\u0610\u0627", "\u062c\u0610\u200c\u0610\u0627", nil},
|
||||
{"\u062c\u0610\u0610\u200c\u0610\u0610\u0627", "\u062c\u0610\u0610\u200c\u0610\u0610\u0627", nil},
|
||||
{"\u062c\u0610\u200c\u0627", "\u062c\u0610\u200c\u0627", nil},
|
||||
{"\u062c\u200c\u0610\u0627", "\u062c\u200c\u0610\u0627", nil},
|
||||
|
||||
// Variants of: L T* U+200c T* D
|
||||
{"\ua872\u200c\u062c", "\ua872\u200c\u062c", nil},
|
||||
{"\ua872\u0610\u200c\u0610\u062c", "\ua872\u0610\u200c\u0610\u062c", nil},
|
||||
{"\ua872\u0610\u0610\u200c\u0610\u0610\u062c", "\ua872\u0610\u0610\u200c\u0610\u0610\u062c", nil},
|
||||
{"\ua872\u0610\u200c\u062c", "\ua872\u0610\u200c\u062c", nil},
|
||||
{"\ua872\u200c\u0610\u062c", "\ua872\u200c\u0610\u062c", nil},
|
||||
|
||||
// Virama
|
||||
{"\u0a4d\u200c", "\u0a4d\u200c", nil},
|
||||
{"\ua872\u0a4d\u200c", "\ua872\u0a4d\u200c", nil},
|
||||
{"\ua872\u0a4d\u0610\u200c", "", errContext},
|
||||
{"\ua872\u0a4d\u0610\u200c", "", errContext},
|
||||
|
||||
{"\u0acd\u200c", "\u0acd\u200c", nil},
|
||||
{"\ua872\u0acd\u200c", "\ua872\u0acd\u200c", nil},
|
||||
{"\ua872\u0acd\u0610\u200c", "", errContext},
|
||||
{"\ua872\u0acd\u0610\u200c", "", errContext},
|
||||
|
||||
// Using Virama as join T
|
||||
{"\ua872\u0acd\u200c\u062c", "\ua872\u0acd\u200c\u062c", nil},
|
||||
{"\ua872\u200c\u0acd\u062c", "\ua872\u200c\u0acd\u062c", nil},
|
||||
}},
|
||||
|
||||
{"Context Rule 2", NewFreeform(), []testCase{
|
||||
// Rule 2: zero-width joiner (U+200D)
|
||||
{"\u200d", "", errContext},
|
||||
{"\u200da", "", errContext},
|
||||
{"a\u200d", "", errContext},
|
||||
|
||||
{"\u0a4d\u200d", "\u0a4d\u200d", nil},
|
||||
{"\ua872\u0a4d\u200d", "\ua872\u0a4d\u200d", nil},
|
||||
{"\u0a4da\u200d", "", errContext},
|
||||
}},
|
||||
|
||||
{"Context Rule 3", NewFreeform(), []testCase{
|
||||
// Rule 3: middle dot
|
||||
{"·", "", errContext},
|
||||
{"l·", "", errContext},
|
||||
{"·l", "", errContext},
|
||||
{"a·", "", errContext},
|
||||
{"l·a", "", errContext},
|
||||
{"a·a", "", errContext},
|
||||
{"l·l", "l·l", nil},
|
||||
{"al·la", "al·la", nil},
|
||||
}},
|
||||
|
||||
{"Context Rule 4", NewFreeform(), []testCase{
|
||||
// Rule 4: Greek lower numeral U+0375
|
||||
{"͵", "", errContext},
|
||||
{"͵a", "", errContext},
|
||||
{"α͵", "", errContext},
|
||||
{"͵α", "͵α", nil},
|
||||
{"α͵α", "α͵α", nil},
|
||||
{"͵͵α", "͵͵α", nil}, // The numeric sign is itself Greek.
|
||||
{"α͵͵α", "α͵͵α", nil},
|
||||
{"α͵͵", "", errContext},
|
||||
{"α͵͵a", "", errContext},
|
||||
}},
|
||||
|
||||
{"Context Rule 5+6", NewFreeform(), []testCase{
|
||||
// Rule 5+6: Hebrew preceding
|
||||
// U+05f3: Geresh
|
||||
{"׳", "", errContext},
|
||||
{"׳ה", "", errContext},
|
||||
{"a׳b", "", errContext},
|
||||
{"ש׳", "ש׳", nil}, // U+05e9 U+05f3
|
||||
{"ש׳׳׳", "ש׳׳׳", nil}, // U+05e9 U+05f3
|
||||
|
||||
// U+05f4: Gershayim
|
||||
{"״", "", errContext},
|
||||
{"״ה", "", errContext},
|
||||
{"a״b", "", errContext},
|
||||
{"ש״", "ש״", nil}, // U+05e9 U+05f4
|
||||
{"ש״״״", "ש״״״", nil}, // U+05e9 U+05f4
|
||||
{"aש״״״", "aש״״״", nil}, // U+05e9 U+05f4
|
||||
}},
|
||||
|
||||
{"Context Rule 7", NewFreeform(), []testCase{
|
||||
// Rule 7: Katakana middle Dot
|
||||
{"・", "", errContext},
|
||||
{"abc・", "", errContext},
|
||||
{"・def", "", errContext},
|
||||
{"abc・def", "", errContext},
|
||||
{"aヅc・def", "aヅc・def", nil},
|
||||
{"abc・dぶf", "abc・dぶf", nil},
|
||||
{"⺐bc・def", "⺐bc・def", nil},
|
||||
}},
|
||||
|
||||
{"Context Rule 8+9", NewFreeform(), []testCase{
|
||||
// Rule 8+9: Arabic Indic Digit
|
||||
{"١٢٣٤٥۶", "", errContext},
|
||||
{"۱۲۳۴۵٦", "", errContext},
|
||||
{"١٢٣٤٥", "١٢٣٤٥", nil},
|
||||
{"۱۲۳۴۵", "۱۲۳۴۵", nil},
|
||||
}},
|
||||
|
||||
{"Nickname", Nickname, []testCase{
|
||||
{" Swan of Avon ", "Swan of Avon", nil},
|
||||
{"", "", errEmptyString},
|
||||
{" ", "", errEmptyString},
|
||||
{" ", "", errEmptyString},
|
||||
{"a\u00A0a\u1680a\u2000a\u2001a\u2002a\u2003a\u2004a\u2005a\u2006a\u2007a\u2008a\u2009a\u200Aa\u202Fa\u205Fa\u3000a", "a a a a a a a a a a a a a a a a a", nil},
|
||||
{"Foo", "Foo", nil},
|
||||
{"foo", "foo", nil},
|
||||
{"Foo Bar", "Foo Bar", nil},
|
||||
{"foo bar", "foo bar", nil},
|
||||
{"\u03A3", "\u03A3", nil},
|
||||
{"\u03C3", "\u03C3", nil},
|
||||
// Greek final sigma is left as is (do not fold!)
|
||||
{"\u03C2", "\u03C2", nil},
|
||||
{"\u265A", "♚", nil},
|
||||
{"Richard \u2163", "Richard IV", nil},
|
||||
{"\u212B", "Å", nil},
|
||||
{"\uFB00", "ff", nil}, // because of NFKC
|
||||
{"שa", "שa", nil}, // no bidi rule
|
||||
{"동일조건변경허락", "동일조건변경허락", nil},
|
||||
}},
|
||||
{"OpaqueString", OpaqueString, []testCase{
|
||||
{" Swan of Avon ", " Swan of Avon ", nil},
|
||||
{"", "", errEmptyString},
|
||||
{" ", " ", nil},
|
||||
{" ", " ", nil},
|
||||
{"a\u00A0a\u1680a\u2000a\u2001a\u2002a\u2003a\u2004a\u2005a\u2006a\u2007a\u2008a\u2009a\u200Aa\u202Fa\u205Fa\u3000a", "a a a a a a a a a a a a a a a a a", nil},
|
||||
{"Foo", "Foo", nil},
|
||||
{"foo", "foo", nil},
|
||||
{"Foo Bar", "Foo Bar", nil},
|
||||
{"foo bar", "foo bar", nil},
|
||||
{"\u03C3", "\u03C3", nil},
|
||||
{"Richard \u2163", "Richard \u2163", nil},
|
||||
{"\u212B", "Å", nil},
|
||||
{"Jack of \u2666s", "Jack of \u2666s", nil},
|
||||
{"my cat is a \u0009by", "", errDisallowedRune},
|
||||
{"שa", "שa", nil}, // no bidi rule
|
||||
}},
|
||||
{"UsernameCaseMapped", UsernameCaseMapped, []testCase{
|
||||
// TODO: Should this work?
|
||||
// {UsernameCaseMapped, "", "", errDisallowedRune},
|
||||
{"juliet@example.com", "juliet@example.com", nil},
|
||||
{"fussball", "fussball", nil},
|
||||
{"fu\u00DFball", "fu\u00DFball", nil},
|
||||
{"\u03C0", "\u03C0", nil},
|
||||
{"\u03A3", "\u03C3", nil},
|
||||
{"\u03C3", "\u03C3", nil},
|
||||
// Greek final sigma is left as is (do not fold!)
|
||||
{"\u03C2", "\u03C2", nil},
|
||||
{"\u0049", "\u0069", nil},
|
||||
{"\u0049", "\u0069", nil},
|
||||
{"\u03D2", "", errDisallowedRune},
|
||||
{"\u03B0", "\u03B0", nil},
|
||||
{"foo bar", "", errDisallowedRune},
|
||||
{"♚", "", errDisallowedRune},
|
||||
{"\u007E", "~", nil},
|
||||
{"a", "a", nil},
|
||||
{"!", "!", nil},
|
||||
{"²", "", errDisallowedRune},
|
||||
{"\t", "", errDisallowedRune},
|
||||
{"\n", "", errDisallowedRune},
|
||||
{"\u26D6", "", errDisallowedRune},
|
||||
{"\u26FF", "", errDisallowedRune},
|
||||
{"\uFB00", "", errDisallowedRune},
|
||||
{"\u1680", "", errDisallowedRune},
|
||||
{" ", "", errDisallowedRune},
|
||||
{" ", "", errDisallowedRune},
|
||||
{"\u01C5", "", errDisallowedRune},
|
||||
{"\u16EE", "", errDisallowedRune}, // Nl RUNIC ARLAUG SYMBOL
|
||||
{"\u0488", "", errDisallowedRune}, // Me COMBINING CYRILLIC HUNDRED THOUSANDS SIGN
|
||||
{"\u212B", "\u00e5", nil}, // Angstrom sign, NFC -> U+00E5
|
||||
{"A\u030A", "å", nil}, // A + ring
|
||||
{"\u00C5", "å", nil}, // A with ring
|
||||
{"\u00E7", "ç", nil}, // c cedille
|
||||
{"\u0063\u0327", "ç", nil}, // c + cedille
|
||||
{"\u0158", "ř", nil},
|
||||
{"\u0052\u030C", "ř", nil},
|
||||
|
||||
{"\u1E61", "\u1E61", nil}, // LATIN SMALL LETTER S WITH DOT ABOVE
|
||||
|
||||
// Confusable characters ARE allowed and should NOT be mapped.
|
||||
{"\u0410", "\u0430", nil}, // CYRILLIC CAPITAL LETTER A
|
||||
|
||||
// Full width should be mapped to the canonical decomposition.
|
||||
{"AB", "ab", nil},
|
||||
{"שc", "", bidirule.ErrInvalid}, // bidi rule
|
||||
|
||||
}},
|
||||
{"UsernameCasePreserved", UsernameCasePreserved, []testCase{
|
||||
{"ABC", "ABC", nil},
|
||||
{"AB", "AB", nil},
|
||||
{"שc", "", bidirule.ErrInvalid}, // bidi rule
|
||||
{"\uFB00", "", errDisallowedRune},
|
||||
{"\u212B", "\u00c5", nil}, // Angstrom sign, NFC -> U+00E5
|
||||
{"ẛ", "", errDisallowedRune}, // LATIN SMALL LETTER LONG S WITH DOT ABOVE
|
||||
}},
|
||||
}
|
162
vendor/golang.org/x/text/secure/precis/enforce_test.go
generated
vendored
Normal file
162
vendor/golang.org/x/text/secure/precis/enforce_test.go
generated
vendored
Normal file
|
@ -0,0 +1,162 @@
|
|||
// 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 precis
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/text/internal/testtext"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
type testCase struct {
|
||||
input string
|
||||
output string
|
||||
err error
|
||||
}
|
||||
|
||||
func doTests(t *testing.T, fn func(t *testing.T, p *Profile, tc testCase)) {
|
||||
for _, g := range enforceTestCases {
|
||||
for i, tc := range g.cases {
|
||||
name := fmt.Sprintf("%s:%d:%+q", g.name, i, tc.input)
|
||||
testtext.Run(t, name, func(t *testing.T) {
|
||||
fn(t, g.p, tc)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestString(t *testing.T) {
|
||||
doTests(t, func(t *testing.T, p *Profile, tc testCase) {
|
||||
if e, err := p.String(tc.input); tc.err != err || e != tc.output {
|
||||
t.Errorf("got %+q (err: %v); want %+q (err: %v)", e, err, tc.output, tc.err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestBytes(t *testing.T) {
|
||||
doTests(t, func(t *testing.T, p *Profile, tc testCase) {
|
||||
if e, err := p.Bytes([]byte(tc.input)); tc.err != err || string(e) != tc.output {
|
||||
t.Errorf("got %+q (err: %v); want %+q (err: %v)", string(e), err, tc.output, tc.err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Copy", func(t *testing.T) {
|
||||
// Test that calling Bytes with something that doesn't transform returns a
|
||||
// copy.
|
||||
orig := []byte("hello")
|
||||
b, _ := NewFreeform().Bytes(orig)
|
||||
if reflect.ValueOf(b).Pointer() == reflect.ValueOf(orig).Pointer() {
|
||||
t.Error("original and result are the same slice; should be a copy")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestAppend(t *testing.T) {
|
||||
doTests(t, func(t *testing.T, p *Profile, tc testCase) {
|
||||
if e, err := p.Append(nil, []byte(tc.input)); tc.err != err || string(e) != tc.output {
|
||||
t.Errorf("got %+q (err: %v); want %+q (err: %v)", string(e), err, tc.output, tc.err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestStringMallocs(t *testing.T) {
|
||||
if n := testtext.AllocsPerRun(100, func() { UsernameCaseMapped.String("helloworld") }); n > 0 {
|
||||
// TODO: reduce this to 0.
|
||||
t.Skipf("got %f allocs, want 0", n)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendMallocs(t *testing.T) {
|
||||
str := []byte("helloworld")
|
||||
out := make([]byte, 0, len(str))
|
||||
if n := testtext.AllocsPerRun(100, func() { UsernameCaseMapped.Append(out, str) }); n > 0 {
|
||||
t.Errorf("got %f allocs, want 0", n)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransformMallocs(t *testing.T) {
|
||||
str := []byte("helloworld")
|
||||
out := make([]byte, 0, len(str))
|
||||
tr := UsernameCaseMapped.NewTransformer()
|
||||
if n := testtext.AllocsPerRun(100, func() {
|
||||
tr.Reset()
|
||||
tr.Transform(out, str, true)
|
||||
}); n > 0 {
|
||||
t.Errorf("got %f allocs, want 0", n)
|
||||
}
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// TestTransformerShortBuffers tests that the precis.Transformer implements the
|
||||
// spirit, not just the letter (the method signatures), of the
|
||||
// transform.Transformer interface.
|
||||
//
|
||||
// In particular, it tests that, if one or both of the dst or src buffers are
|
||||
// short, so that multiple Transform calls are required to complete the overall
|
||||
// transformation, the end result is identical to one Transform call with
|
||||
// sufficiently long buffers.
|
||||
func TestTransformerShortBuffers(t *testing.T) {
|
||||
srcUnit := []byte("a\u0300cce\u0301nts") // NFD normalization form.
|
||||
wantUnit := []byte("àccénts") // NFC normalization form.
|
||||
src := bytes.Repeat(srcUnit, 16)
|
||||
want := bytes.Repeat(wantUnit, 16)
|
||||
const long = 4096
|
||||
dst := make([]byte, long)
|
||||
|
||||
// 5, 7, 9, 11, 13, 16 and 17 are all pair-wise co-prime, which means that
|
||||
// slicing the dst and src buffers into 5, 7, 13 and 17 byte chunks will
|
||||
// fall at different places inside the repeated srcUnit's and wantUnit's.
|
||||
if len(srcUnit) != 11 || len(wantUnit) != 9 || len(src) > long || len(want) > long {
|
||||
t.Fatal("inconsistent lengths")
|
||||
}
|
||||
|
||||
tr := NewFreeform().NewTransformer()
|
||||
for _, deltaD := range []int{5, 7, 13, 17, long} {
|
||||
loop:
|
||||
for _, deltaS := range []int{5, 7, 13, 17, long} {
|
||||
tr.Reset()
|
||||
d0 := 0
|
||||
s0 := 0
|
||||
for {
|
||||
d1 := min(len(dst), d0+deltaD)
|
||||
s1 := min(len(src), s0+deltaS)
|
||||
nDst, nSrc, err := tr.Transform(dst[d0:d1:d1], src[s0:s1:s1], s1 == len(src))
|
||||
d0 += nDst
|
||||
s0 += nSrc
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
if err == transform.ErrShortDst || err == transform.ErrShortSrc {
|
||||
continue
|
||||
}
|
||||
t.Errorf("deltaD=%d, deltaS=%d: %v", deltaD, deltaS, err)
|
||||
continue loop
|
||||
}
|
||||
if s0 != len(src) {
|
||||
t.Errorf("deltaD=%d, deltaS=%d: s0: got %d, want %d", deltaD, deltaS, s0, len(src))
|
||||
continue
|
||||
}
|
||||
if d0 != len(want) {
|
||||
t.Errorf("deltaD=%d, deltaS=%d: d0: got %d, want %d", deltaD, deltaS, d0, len(want))
|
||||
continue
|
||||
}
|
||||
got := dst[:d0]
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("deltaD=%d, deltaS=%d:\ngot %q\nwant %q", deltaD, deltaS, got, want)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
310
vendor/golang.org/x/text/secure/precis/gen.go
generated
vendored
Normal file
310
vendor/golang.org/x/text/secure/precis/gen.go
generated
vendored
Normal file
|
@ -0,0 +1,310 @@
|
|||
// 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.
|
||||
|
||||
// Unicode table generator.
|
||||
// Data read from the web.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"log"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/internal/gen"
|
||||
"golang.org/x/text/internal/triegen"
|
||||
"golang.org/x/text/internal/ucd"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
"golang.org/x/text/unicode/rangetable"
|
||||
)
|
||||
|
||||
var outputFile = flag.String("output", "tables.go", "output file for generated tables; default tables.go")
|
||||
|
||||
var assigned, disallowedRunes *unicode.RangeTable
|
||||
|
||||
var runeCategory = map[rune]category{}
|
||||
|
||||
var overrides = map[category]category{
|
||||
viramaModifier: viramaJoinT,
|
||||
greek: greekJoinT,
|
||||
hebrew: hebrewJoinT,
|
||||
}
|
||||
|
||||
func setCategory(r rune, cat category) {
|
||||
if c, ok := runeCategory[r]; ok {
|
||||
if override, ok := overrides[c]; cat == joiningT && ok {
|
||||
cat = override
|
||||
} else {
|
||||
log.Fatalf("%U: multiple categories for rune (%v and %v)", r, c, cat)
|
||||
}
|
||||
}
|
||||
runeCategory[r] = cat
|
||||
}
|
||||
|
||||
func init() {
|
||||
if numCategories > 1<<propShift {
|
||||
log.Fatalf("Number of categories is %d; may at most be %d", numCategories, 1<<propShift)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
gen.Init()
|
||||
|
||||
// Load data
|
||||
runes := []rune{}
|
||||
// PrecisIgnorableProperties: https://tools.ietf.org/html/rfc7564#section-9.13
|
||||
ucd.Parse(gen.OpenUCDFile("DerivedCoreProperties.txt"), func(p *ucd.Parser) {
|
||||
if p.String(1) == "Default_Ignorable_Code_Point" {
|
||||
runes = append(runes, p.Rune(0))
|
||||
}
|
||||
})
|
||||
ucd.Parse(gen.OpenUCDFile("PropList.txt"), func(p *ucd.Parser) {
|
||||
switch p.String(1) {
|
||||
case "Noncharacter_Code_Point":
|
||||
runes = append(runes, p.Rune(0))
|
||||
}
|
||||
})
|
||||
// OldHangulJamo: https://tools.ietf.org/html/rfc5892#section-2.9
|
||||
ucd.Parse(gen.OpenUCDFile("HangulSyllableType.txt"), func(p *ucd.Parser) {
|
||||
switch p.String(1) {
|
||||
case "L", "V", "T":
|
||||
runes = append(runes, p.Rune(0))
|
||||
}
|
||||
})
|
||||
|
||||
disallowedRunes = rangetable.New(runes...)
|
||||
assigned = rangetable.Assigned(unicode.Version)
|
||||
|
||||
// Load category data.
|
||||
runeCategory['l'] = latinSmallL
|
||||
ucd.Parse(gen.OpenUCDFile("UnicodeData.txt"), func(p *ucd.Parser) {
|
||||
const cccVirama = 9
|
||||
if p.Int(ucd.CanonicalCombiningClass) == cccVirama {
|
||||
setCategory(p.Rune(0), viramaModifier)
|
||||
}
|
||||
})
|
||||
ucd.Parse(gen.OpenUCDFile("Scripts.txt"), func(p *ucd.Parser) {
|
||||
switch p.String(1) {
|
||||
case "Greek":
|
||||
setCategory(p.Rune(0), greek)
|
||||
case "Hebrew":
|
||||
setCategory(p.Rune(0), hebrew)
|
||||
case "Hiragana", "Katakana", "Han":
|
||||
setCategory(p.Rune(0), japanese)
|
||||
}
|
||||
})
|
||||
|
||||
// Set the rule categories associated with exceptions. This overrides any
|
||||
// previously set categories. The original categories are manually
|
||||
// reintroduced in the categoryTransitions table.
|
||||
for r, e := range exceptions {
|
||||
if e.cat != 0 {
|
||||
runeCategory[r] = e.cat
|
||||
}
|
||||
}
|
||||
cat := map[string]category{
|
||||
"L": joiningL,
|
||||
"D": joiningD,
|
||||
"T": joiningT,
|
||||
|
||||
"R": joiningR,
|
||||
}
|
||||
ucd.Parse(gen.OpenUCDFile("extracted/DerivedJoiningType.txt"), func(p *ucd.Parser) {
|
||||
switch v := p.String(1); v {
|
||||
case "L", "D", "T", "R":
|
||||
setCategory(p.Rune(0), cat[v])
|
||||
}
|
||||
})
|
||||
|
||||
writeTables()
|
||||
gen.Repackage("gen_trieval.go", "trieval.go", "precis")
|
||||
}
|
||||
|
||||
type exception struct {
|
||||
prop property
|
||||
cat category
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Programmatically add the Arabic and Indic digits to the exceptions map.
|
||||
// See comment in the exceptions map below why these are marked disallowed.
|
||||
for i := rune(0); i <= 9; i++ {
|
||||
exceptions[0x0660+i] = exception{
|
||||
prop: disallowed,
|
||||
cat: arabicIndicDigit,
|
||||
}
|
||||
exceptions[0x06F0+i] = exception{
|
||||
prop: disallowed,
|
||||
cat: extendedArabicIndicDigit,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The Exceptions class as defined in RFC 5892
|
||||
// https://tools.ietf.org/html/rfc5892#section-2.6
|
||||
var exceptions = map[rune]exception{
|
||||
0x00DF: {prop: pValid},
|
||||
0x03C2: {prop: pValid},
|
||||
0x06FD: {prop: pValid},
|
||||
0x06FE: {prop: pValid},
|
||||
0x0F0B: {prop: pValid},
|
||||
0x3007: {prop: pValid},
|
||||
|
||||
// ContextO|J rules are marked as disallowed, taking a "guilty until proven
|
||||
// innocent" approach. The main reason for this is that the check for
|
||||
// whether a context rule should be applied can be moved to the logic for
|
||||
// handing disallowed runes, taken it off the common path. The exception to
|
||||
// this rule is for katakanaMiddleDot, as the rule logic is handled without
|
||||
// using a rule function.
|
||||
|
||||
// ContextJ (Join control)
|
||||
0x200C: {prop: disallowed, cat: zeroWidthNonJoiner},
|
||||
0x200D: {prop: disallowed, cat: zeroWidthJoiner},
|
||||
|
||||
// ContextO
|
||||
0x00B7: {prop: disallowed, cat: middleDot},
|
||||
0x0375: {prop: disallowed, cat: greekLowerNumeralSign},
|
||||
0x05F3: {prop: disallowed, cat: hebrewPreceding}, // punctuation Geresh
|
||||
0x05F4: {prop: disallowed, cat: hebrewPreceding}, // punctuation Gershayim
|
||||
0x30FB: {prop: pValid, cat: katakanaMiddleDot},
|
||||
|
||||
// These are officially ContextO, but the implementation does not require
|
||||
// special treatment of these, so we simply mark them as valid.
|
||||
0x0660: {prop: pValid},
|
||||
0x0661: {prop: pValid},
|
||||
0x0662: {prop: pValid},
|
||||
0x0663: {prop: pValid},
|
||||
0x0664: {prop: pValid},
|
||||
0x0665: {prop: pValid},
|
||||
0x0666: {prop: pValid},
|
||||
0x0667: {prop: pValid},
|
||||
0x0668: {prop: pValid},
|
||||
0x0669: {prop: pValid},
|
||||
0x06F0: {prop: pValid},
|
||||
0x06F1: {prop: pValid},
|
||||
0x06F2: {prop: pValid},
|
||||
0x06F3: {prop: pValid},
|
||||
0x06F4: {prop: pValid},
|
||||
0x06F5: {prop: pValid},
|
||||
0x06F6: {prop: pValid},
|
||||
0x06F7: {prop: pValid},
|
||||
0x06F8: {prop: pValid},
|
||||
0x06F9: {prop: pValid},
|
||||
|
||||
0x0640: {prop: disallowed},
|
||||
0x07FA: {prop: disallowed},
|
||||
0x302E: {prop: disallowed},
|
||||
0x302F: {prop: disallowed},
|
||||
0x3031: {prop: disallowed},
|
||||
0x3032: {prop: disallowed},
|
||||
0x3033: {prop: disallowed},
|
||||
0x3034: {prop: disallowed},
|
||||
0x3035: {prop: disallowed},
|
||||
0x303B: {prop: disallowed},
|
||||
}
|
||||
|
||||
// LetterDigits: https://tools.ietf.org/html/rfc5892#section-2.1
|
||||
// r in {Ll, Lu, Lo, Nd, Lm, Mn, Mc}.
|
||||
func isLetterDigits(r rune) bool {
|
||||
return unicode.In(r,
|
||||
unicode.Ll, unicode.Lu, unicode.Lm, unicode.Lo, // Letters
|
||||
unicode.Mn, unicode.Mc, // Modifiers
|
||||
unicode.Nd, // Digits
|
||||
)
|
||||
}
|
||||
|
||||
func isIdDisAndFreePVal(r rune) bool {
|
||||
return unicode.In(r,
|
||||
// OtherLetterDigits: https://tools.ietf.org/html/rfc7564#section-9.18
|
||||
// r in in {Lt, Nl, No, Me}
|
||||
unicode.Lt, unicode.Nl, unicode.No, // Other letters / numbers
|
||||
unicode.Me, // Modifiers
|
||||
|
||||
// Spaces: https://tools.ietf.org/html/rfc7564#section-9.14
|
||||
// r in in {Zs}
|
||||
unicode.Zs,
|
||||
|
||||
// Symbols: https://tools.ietf.org/html/rfc7564#section-9.15
|
||||
// r in {Sm, Sc, Sk, So}
|
||||
unicode.Sm, unicode.Sc, unicode.Sk, unicode.So,
|
||||
|
||||
// Punctuation: https://tools.ietf.org/html/rfc7564#section-9.16
|
||||
// r in {Pc, Pd, Ps, Pe, Pi, Pf, Po}
|
||||
unicode.Pc, unicode.Pd, unicode.Ps, unicode.Pe,
|
||||
unicode.Pi, unicode.Pf, unicode.Po,
|
||||
)
|
||||
}
|
||||
|
||||
// HasCompat: https://tools.ietf.org/html/rfc7564#section-9.17
|
||||
func hasCompat(r rune) bool {
|
||||
return !norm.NFKC.IsNormalString(string(r))
|
||||
}
|
||||
|
||||
// From https://tools.ietf.org/html/rfc5892:
|
||||
//
|
||||
// If .cp. .in. Exceptions Then Exceptions(cp);
|
||||
// Else If .cp. .in. BackwardCompatible Then BackwardCompatible(cp);
|
||||
// Else If .cp. .in. Unassigned Then UNASSIGNED;
|
||||
// Else If .cp. .in. ASCII7 Then PVALID;
|
||||
// Else If .cp. .in. JoinControl Then CONTEXTJ;
|
||||
// Else If .cp. .in. OldHangulJamo Then DISALLOWED;
|
||||
// Else If .cp. .in. PrecisIgnorableProperties Then DISALLOWED;
|
||||
// Else If .cp. .in. Controls Then DISALLOWED;
|
||||
// Else If .cp. .in. HasCompat Then ID_DIS or FREE_PVAL;
|
||||
// Else If .cp. .in. LetterDigits Then PVALID;
|
||||
// Else If .cp. .in. OtherLetterDigits Then ID_DIS or FREE_PVAL;
|
||||
// Else If .cp. .in. Spaces Then ID_DIS or FREE_PVAL;
|
||||
// Else If .cp. .in. Symbols Then ID_DIS or FREE_PVAL;
|
||||
// Else If .cp. .in. Punctuation Then ID_DIS or FREE_PVAL;
|
||||
// Else DISALLOWED;
|
||||
|
||||
func writeTables() {
|
||||
propTrie := triegen.NewTrie("derivedProperties")
|
||||
w := gen.NewCodeWriter()
|
||||
defer w.WriteVersionedGoFile(*outputFile, "precis")
|
||||
gen.WriteUnicodeVersion(w)
|
||||
|
||||
// Iterate over all the runes...
|
||||
for i := rune(0); i < unicode.MaxRune; i++ {
|
||||
r := rune(i)
|
||||
|
||||
if !utf8.ValidRune(r) {
|
||||
continue
|
||||
}
|
||||
|
||||
e, ok := exceptions[i]
|
||||
p := e.prop
|
||||
switch {
|
||||
case ok:
|
||||
case !unicode.In(r, assigned):
|
||||
p = unassigned
|
||||
case r >= 0x0021 && r <= 0x007e: // Is ASCII 7
|
||||
p = pValid
|
||||
case unicode.In(r, disallowedRunes, unicode.Cc):
|
||||
p = disallowed
|
||||
case hasCompat(r):
|
||||
p = idDisOrFreePVal
|
||||
case isLetterDigits(r):
|
||||
p = pValid
|
||||
case isIdDisAndFreePVal(r):
|
||||
p = idDisOrFreePVal
|
||||
default:
|
||||
p = disallowed
|
||||
}
|
||||
cat := runeCategory[r]
|
||||
// Don't set category for runes that are disallowed.
|
||||
if p == disallowed {
|
||||
cat = exceptions[r].cat
|
||||
}
|
||||
propTrie.Insert(r, uint64(p)|uint64(cat))
|
||||
}
|
||||
sz, err := propTrie.Gen(w)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
w.Size += sz
|
||||
}
|
68
vendor/golang.org/x/text/secure/precis/gen_trieval.go
generated
vendored
Normal file
68
vendor/golang.org/x/text/secure/precis/gen_trieval.go
generated
vendored
Normal file
|
@ -0,0 +1,68 @@
|
|||
// 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
|
||||
|
||||
// entry is the entry of a trie table
|
||||
// 7..6 property (unassigned, disallowed, maybe, valid)
|
||||
// 5..0 category
|
||||
type entry uint8
|
||||
|
||||
const (
|
||||
propShift = 6
|
||||
propMask = 0xc0
|
||||
catMask = 0x3f
|
||||
)
|
||||
|
||||
func (e entry) property() property { return property(e & propMask) }
|
||||
func (e entry) category() category { return category(e & catMask) }
|
||||
|
||||
type property uint8
|
||||
|
||||
// The order of these constants matter. A Profile may consider runes to be
|
||||
// allowed either from pValid or idDisOrFreePVal.
|
||||
const (
|
||||
unassigned property = iota << propShift
|
||||
disallowed
|
||||
idDisOrFreePVal // disallowed for Identifier, pValid for FreeForm
|
||||
pValid
|
||||
)
|
||||
|
||||
// compute permutations of all properties and specialCategories.
|
||||
type category uint8
|
||||
|
||||
const (
|
||||
other category = iota
|
||||
|
||||
// Special rune types
|
||||
joiningL
|
||||
joiningD
|
||||
joiningT
|
||||
joiningR
|
||||
viramaModifier
|
||||
viramaJoinT // Virama + JoiningT
|
||||
latinSmallL // U+006c
|
||||
greek
|
||||
greekJoinT // Greek + JoiningT
|
||||
hebrew
|
||||
hebrewJoinT // Hebrew + JoiningT
|
||||
japanese // hirigana, katakana, han
|
||||
|
||||
// Special rune types associated with contextual rules defined in
|
||||
// https://tools.ietf.org/html/rfc5892#appendix-A.
|
||||
// ContextO
|
||||
zeroWidthNonJoiner // rule 1
|
||||
zeroWidthJoiner // rule 2
|
||||
// ContextJ
|
||||
middleDot // rule 3
|
||||
greekLowerNumeralSign // rule 4
|
||||
hebrewPreceding // rule 5 and 6
|
||||
katakanaMiddleDot // rule 7
|
||||
arabicIndicDigit // rule 8
|
||||
extendedArabicIndicDigit // rule 9
|
||||
|
||||
numCategories
|
||||
)
|
72
vendor/golang.org/x/text/secure/precis/nickname.go
generated
vendored
Normal file
72
vendor/golang.org/x/text/secure/precis/nickname.go
generated
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
// 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 precis
|
||||
|
||||
import (
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
type nickAdditionalMapping struct {
|
||||
// TODO: This transformer needs to be stateless somehow…
|
||||
notStart bool
|
||||
prevSpace bool
|
||||
}
|
||||
|
||||
func (t *nickAdditionalMapping) Reset() {
|
||||
t.prevSpace = false
|
||||
t.notStart = false
|
||||
}
|
||||
|
||||
func (t *nickAdditionalMapping) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
// RFC 8266 §2.1. Rules
|
||||
//
|
||||
// 2. Additional Mapping Rule: The additional mapping rule consists of
|
||||
// the following sub-rules.
|
||||
//
|
||||
// a. Map any instances of non-ASCII space to SPACE (U+0020); a
|
||||
// non-ASCII space is any Unicode code point having a general
|
||||
// category of "Zs", naturally with the exception of SPACE
|
||||
// (U+0020). (The inclusion of only ASCII space prevents
|
||||
// confusion with various non-ASCII space code points, many of
|
||||
// which are difficult to reproduce across different input
|
||||
// methods.)
|
||||
//
|
||||
// b. Remove any instances of the ASCII space character at the
|
||||
// beginning or end of a nickname (e.g., "stpeter " is mapped to
|
||||
// "stpeter").
|
||||
//
|
||||
// c. Map interior sequences of more than one ASCII space character
|
||||
// to a single ASCII space character (e.g., "St Peter" is
|
||||
// mapped to "St Peter").
|
||||
for nSrc < len(src) {
|
||||
r, size := utf8.DecodeRune(src[nSrc:])
|
||||
if size == 0 { // Incomplete UTF-8 encoding
|
||||
if !atEOF {
|
||||
return nDst, nSrc, transform.ErrShortSrc
|
||||
}
|
||||
size = 1
|
||||
}
|
||||
if unicode.Is(unicode.Zs, r) {
|
||||
t.prevSpace = true
|
||||
} else {
|
||||
if t.prevSpace && t.notStart {
|
||||
dst[nDst] = ' '
|
||||
nDst += 1
|
||||
}
|
||||
if size != copy(dst[nDst:], src[nSrc:nSrc+size]) {
|
||||
nDst += size
|
||||
return nDst, nSrc, transform.ErrShortDst
|
||||
}
|
||||
nDst += size
|
||||
t.prevSpace = false
|
||||
t.notStart = true
|
||||
}
|
||||
nSrc += size
|
||||
}
|
||||
return nDst, nSrc, nil
|
||||
}
|
157
vendor/golang.org/x/text/secure/precis/options.go
generated
vendored
Normal file
157
vendor/golang.org/x/text/secure/precis/options.go
generated
vendored
Normal file
|
@ -0,0 +1,157 @@
|
|||
// 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 precis
|
||||
|
||||
import (
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/runes"
|
||||
"golang.org/x/text/transform"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
)
|
||||
|
||||
// An Option is used to define the behavior and rules of a Profile.
|
||||
type Option func(*options)
|
||||
|
||||
type options struct {
|
||||
// Preparation options
|
||||
foldWidth bool
|
||||
|
||||
// Enforcement options
|
||||
asciiLower bool
|
||||
cases transform.SpanningTransformer
|
||||
disallow runes.Set
|
||||
norm transform.SpanningTransformer
|
||||
additional []func() transform.SpanningTransformer
|
||||
width transform.SpanningTransformer
|
||||
disallowEmpty bool
|
||||
bidiRule bool
|
||||
repeat bool
|
||||
|
||||
// Comparison options
|
||||
ignorecase bool
|
||||
}
|
||||
|
||||
func getOpts(o ...Option) (res options) {
|
||||
for _, f := range o {
|
||||
f(&res)
|
||||
}
|
||||
// Using a SpanningTransformer, instead of norm.Form prevents an allocation
|
||||
// down the road.
|
||||
if res.norm == nil {
|
||||
res.norm = norm.NFC
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
// The IgnoreCase option causes the profile to perform a case insensitive
|
||||
// comparison during the PRECIS comparison step.
|
||||
IgnoreCase Option = ignoreCase
|
||||
|
||||
// The FoldWidth option causes the profile to map non-canonical wide and
|
||||
// narrow variants to their decomposition mapping. This is useful for
|
||||
// profiles that are based on the identifier class which would otherwise
|
||||
// disallow such characters.
|
||||
FoldWidth Option = foldWidth
|
||||
|
||||
// The DisallowEmpty option causes the enforcement step to return an error if
|
||||
// the resulting string would be empty.
|
||||
DisallowEmpty Option = disallowEmpty
|
||||
|
||||
// The BidiRule option causes the Bidi Rule defined in RFC 5893 to be
|
||||
// applied.
|
||||
BidiRule Option = bidiRule
|
||||
)
|
||||
|
||||
var (
|
||||
ignoreCase = func(o *options) {
|
||||
o.ignorecase = true
|
||||
}
|
||||
foldWidth = func(o *options) {
|
||||
o.foldWidth = true
|
||||
}
|
||||
disallowEmpty = func(o *options) {
|
||||
o.disallowEmpty = true
|
||||
}
|
||||
bidiRule = func(o *options) {
|
||||
o.bidiRule = true
|
||||
}
|
||||
repeat = func(o *options) {
|
||||
o.repeat = true
|
||||
}
|
||||
)
|
||||
|
||||
// TODO: move this logic to package transform
|
||||
|
||||
type spanWrap struct{ transform.Transformer }
|
||||
|
||||
func (s spanWrap) Span(src []byte, atEOF bool) (n int, err error) {
|
||||
return 0, transform.ErrEndOfSpan
|
||||
}
|
||||
|
||||
// TODO: allow different types? For instance:
|
||||
// func() transform.Transformer
|
||||
// func() transform.SpanningTransformer
|
||||
// func([]byte) bool // validation only
|
||||
//
|
||||
// Also, would be great if we could detect if a transformer is reentrant.
|
||||
|
||||
// The AdditionalMapping option defines the additional mapping rule for the
|
||||
// Profile by applying Transformer's in sequence.
|
||||
func AdditionalMapping(t ...func() transform.Transformer) Option {
|
||||
return func(o *options) {
|
||||
for _, f := range t {
|
||||
sf := func() transform.SpanningTransformer {
|
||||
return f().(transform.SpanningTransformer)
|
||||
}
|
||||
if _, ok := f().(transform.SpanningTransformer); !ok {
|
||||
sf = func() transform.SpanningTransformer {
|
||||
return spanWrap{f()}
|
||||
}
|
||||
}
|
||||
o.additional = append(o.additional, sf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The Norm option defines a Profile's normalization rule. Defaults to NFC.
|
||||
func Norm(f norm.Form) Option {
|
||||
return func(o *options) {
|
||||
o.norm = f
|
||||
}
|
||||
}
|
||||
|
||||
// The FoldCase option defines a Profile's case mapping rule. Options can be
|
||||
// provided to determine the type of case folding used.
|
||||
func FoldCase(opts ...cases.Option) Option {
|
||||
return func(o *options) {
|
||||
o.asciiLower = true
|
||||
o.cases = cases.Fold(opts...)
|
||||
}
|
||||
}
|
||||
|
||||
// The LowerCase option defines a Profile's case mapping rule. Options can be
|
||||
// provided to determine the type of case folding used.
|
||||
func LowerCase(opts ...cases.Option) Option {
|
||||
return func(o *options) {
|
||||
o.asciiLower = true
|
||||
if len(opts) == 0 {
|
||||
o.cases = cases.Lower(language.Und, cases.HandleFinalSigma(false))
|
||||
return
|
||||
}
|
||||
|
||||
opts = append([]cases.Option{cases.HandleFinalSigma(false)}, opts...)
|
||||
o.cases = cases.Lower(language.Und, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
// The Disallow option further restricts a Profile's allowed characters beyond
|
||||
// what is disallowed by the underlying string class.
|
||||
func Disallow(set runes.Set) Option {
|
||||
return func(o *options) {
|
||||
o.disallow = set
|
||||
}
|
||||
}
|
402
vendor/golang.org/x/text/secure/precis/profile.go
generated
vendored
Normal file
402
vendor/golang.org/x/text/secure/precis/profile.go
generated
vendored
Normal file
|
@ -0,0 +1,402 @@
|
|||
// 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 precis
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/runes"
|
||||
"golang.org/x/text/secure/bidirule"
|
||||
"golang.org/x/text/transform"
|
||||
"golang.org/x/text/width"
|
||||
)
|
||||
|
||||
var (
|
||||
errDisallowedRune = errors.New("precis: disallowed rune encountered")
|
||||
)
|
||||
|
||||
var dpTrie = newDerivedPropertiesTrie(0)
|
||||
|
||||
// A Profile represents a set of rules for normalizing and validating strings in
|
||||
// the PRECIS framework.
|
||||
type Profile struct {
|
||||
options
|
||||
class *class
|
||||
}
|
||||
|
||||
// NewIdentifier creates a new PRECIS profile based on the Identifier string
|
||||
// class. Profiles created from this class are suitable for use where safety is
|
||||
// prioritized over expressiveness like network identifiers, user accounts, chat
|
||||
// rooms, and file names.
|
||||
func NewIdentifier(opts ...Option) *Profile {
|
||||
return &Profile{
|
||||
options: getOpts(opts...),
|
||||
class: identifier,
|
||||
}
|
||||
}
|
||||
|
||||
// NewFreeform creates a new PRECIS profile based on the Freeform string class.
|
||||
// Profiles created from this class are suitable for use where expressiveness is
|
||||
// prioritized over safety like passwords, and display-elements such as
|
||||
// nicknames in a chat room.
|
||||
func NewFreeform(opts ...Option) *Profile {
|
||||
return &Profile{
|
||||
options: getOpts(opts...),
|
||||
class: freeform,
|
||||
}
|
||||
}
|
||||
|
||||
// NewTransformer creates a new transform.Transformer that performs the PRECIS
|
||||
// preparation and enforcement steps on the given UTF-8 encoded bytes.
|
||||
func (p *Profile) NewTransformer() *Transformer {
|
||||
var ts []transform.Transformer
|
||||
|
||||
// These transforms are applied in the order defined in
|
||||
// https://tools.ietf.org/html/rfc7564#section-7
|
||||
|
||||
// RFC 8266 §2.1:
|
||||
//
|
||||
// Implementation experience has shown that applying the rules for the
|
||||
// Nickname profile is not an idempotent procedure for all code points.
|
||||
// Therefore, an implementation SHOULD apply the rules repeatedly until
|
||||
// the output string is stable; if the output string does not stabilize
|
||||
// after reapplying the rules three (3) additional times after the first
|
||||
// application, the implementation SHOULD terminate application of the
|
||||
// rules and reject the input string as invalid.
|
||||
//
|
||||
// There is no known string that will change indefinitely, so repeat 4 times
|
||||
// and rely on the Span method to keep things relatively performant.
|
||||
r := 1
|
||||
if p.options.repeat {
|
||||
r = 4
|
||||
}
|
||||
for ; r > 0; r-- {
|
||||
if p.options.foldWidth {
|
||||
ts = append(ts, width.Fold)
|
||||
}
|
||||
|
||||
for _, f := range p.options.additional {
|
||||
ts = append(ts, f())
|
||||
}
|
||||
|
||||
if p.options.cases != nil {
|
||||
ts = append(ts, p.options.cases)
|
||||
}
|
||||
|
||||
ts = append(ts, p.options.norm)
|
||||
|
||||
if p.options.bidiRule {
|
||||
ts = append(ts, bidirule.New())
|
||||
}
|
||||
|
||||
ts = append(ts, &checker{p: p, allowed: p.Allowed()})
|
||||
}
|
||||
|
||||
// TODO: Add the disallow empty rule with a dummy transformer?
|
||||
|
||||
return &Transformer{transform.Chain(ts...)}
|
||||
}
|
||||
|
||||
var errEmptyString = errors.New("precis: transformation resulted in empty string")
|
||||
|
||||
type buffers struct {
|
||||
src []byte
|
||||
buf [2][]byte
|
||||
next int
|
||||
}
|
||||
|
||||
func (b *buffers) apply(t transform.SpanningTransformer) (err error) {
|
||||
n, err := t.Span(b.src, true)
|
||||
if err != transform.ErrEndOfSpan {
|
||||
return err
|
||||
}
|
||||
x := b.next & 1
|
||||
if b.buf[x] == nil {
|
||||
b.buf[x] = make([]byte, 0, 8+len(b.src)+len(b.src)>>2)
|
||||
}
|
||||
span := append(b.buf[x][:0], b.src[:n]...)
|
||||
b.src, _, err = transform.Append(t, span, b.src[n:])
|
||||
b.buf[x] = b.src
|
||||
b.next++
|
||||
return err
|
||||
}
|
||||
|
||||
// Pre-allocate transformers when possible. In some cases this avoids allocation.
|
||||
var (
|
||||
foldWidthT transform.SpanningTransformer = width.Fold
|
||||
lowerCaseT transform.SpanningTransformer = cases.Lower(language.Und, cases.HandleFinalSigma(false))
|
||||
)
|
||||
|
||||
// TODO: make this a method on profile.
|
||||
|
||||
func (b *buffers) enforce(p *Profile, src []byte, comparing bool) (str []byte, err error) {
|
||||
b.src = src
|
||||
|
||||
ascii := true
|
||||
for _, c := range src {
|
||||
if c >= utf8.RuneSelf {
|
||||
ascii = false
|
||||
break
|
||||
}
|
||||
}
|
||||
// ASCII fast path.
|
||||
if ascii {
|
||||
for _, f := range p.options.additional {
|
||||
if err = b.apply(f()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
switch {
|
||||
case p.options.asciiLower || (comparing && p.options.ignorecase):
|
||||
for i, c := range b.src {
|
||||
if 'A' <= c && c <= 'Z' {
|
||||
b.src[i] = c ^ 1<<5
|
||||
}
|
||||
}
|
||||
case p.options.cases != nil:
|
||||
b.apply(p.options.cases)
|
||||
}
|
||||
c := checker{p: p}
|
||||
if _, err := c.span(b.src, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if p.disallow != nil {
|
||||
for _, c := range b.src {
|
||||
if p.disallow.Contains(rune(c)) {
|
||||
return nil, errDisallowedRune
|
||||
}
|
||||
}
|
||||
}
|
||||
if p.options.disallowEmpty && len(b.src) == 0 {
|
||||
return nil, errEmptyString
|
||||
}
|
||||
return b.src, nil
|
||||
}
|
||||
|
||||
// These transforms are applied in the order defined in
|
||||
// https://tools.ietf.org/html/rfc8264#section-7
|
||||
|
||||
r := 1
|
||||
if p.options.repeat {
|
||||
r = 4
|
||||
}
|
||||
for ; r > 0; r-- {
|
||||
// TODO: allow different width transforms options.
|
||||
if p.options.foldWidth || (p.options.ignorecase && comparing) {
|
||||
b.apply(foldWidthT)
|
||||
}
|
||||
for _, f := range p.options.additional {
|
||||
if err = b.apply(f()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if p.options.cases != nil {
|
||||
b.apply(p.options.cases)
|
||||
}
|
||||
if comparing && p.options.ignorecase {
|
||||
b.apply(lowerCaseT)
|
||||
}
|
||||
b.apply(p.norm)
|
||||
if p.options.bidiRule && !bidirule.Valid(b.src) {
|
||||
return nil, bidirule.ErrInvalid
|
||||
}
|
||||
c := checker{p: p}
|
||||
if _, err := c.span(b.src, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if p.disallow != nil {
|
||||
for i := 0; i < len(b.src); {
|
||||
r, size := utf8.DecodeRune(b.src[i:])
|
||||
if p.disallow.Contains(r) {
|
||||
return nil, errDisallowedRune
|
||||
}
|
||||
i += size
|
||||
}
|
||||
}
|
||||
if p.options.disallowEmpty && len(b.src) == 0 {
|
||||
return nil, errEmptyString
|
||||
}
|
||||
}
|
||||
return b.src, nil
|
||||
}
|
||||
|
||||
// Append appends the result of applying p to src writing the result to dst.
|
||||
// It returns an error if the input string is invalid.
|
||||
func (p *Profile) Append(dst, src []byte) ([]byte, error) {
|
||||
var buf buffers
|
||||
b, err := buf.enforce(p, src, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append(dst, b...), nil
|
||||
}
|
||||
|
||||
func processBytes(p *Profile, b []byte, key bool) ([]byte, error) {
|
||||
var buf buffers
|
||||
b, err := buf.enforce(p, b, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if buf.next == 0 {
|
||||
c := make([]byte, len(b))
|
||||
copy(c, b)
|
||||
return c, nil
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// Bytes returns a new byte slice with the result of applying the profile to b.
|
||||
func (p *Profile) Bytes(b []byte) ([]byte, error) {
|
||||
return processBytes(p, b, false)
|
||||
}
|
||||
|
||||
// AppendCompareKey appends the result of applying p to src (including any
|
||||
// optional rules to make strings comparable or useful in a map key such as
|
||||
// applying lowercasing) writing the result to dst. It returns an error if the
|
||||
// input string is invalid.
|
||||
func (p *Profile) AppendCompareKey(dst, src []byte) ([]byte, error) {
|
||||
var buf buffers
|
||||
b, err := buf.enforce(p, src, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append(dst, b...), nil
|
||||
}
|
||||
|
||||
func processString(p *Profile, s string, key bool) (string, error) {
|
||||
var buf buffers
|
||||
b, err := buf.enforce(p, []byte(s), key)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
// String returns a string with the result of applying the profile to s.
|
||||
func (p *Profile) String(s string) (string, error) {
|
||||
return processString(p, s, false)
|
||||
}
|
||||
|
||||
// CompareKey returns a string that can be used for comparison, hashing, or
|
||||
// collation.
|
||||
func (p *Profile) CompareKey(s string) (string, error) {
|
||||
return processString(p, s, true)
|
||||
}
|
||||
|
||||
// Compare enforces both strings, and then compares them for bit-string identity
|
||||
// (byte-for-byte equality). If either string cannot be enforced, the comparison
|
||||
// is false.
|
||||
func (p *Profile) Compare(a, b string) bool {
|
||||
var buf buffers
|
||||
|
||||
akey, err := buf.enforce(p, []byte(a), true)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
buf = buffers{}
|
||||
bkey, err := buf.enforce(p, []byte(b), true)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return bytes.Compare(akey, bkey) == 0
|
||||
}
|
||||
|
||||
// Allowed returns a runes.Set containing every rune that is a member of the
|
||||
// underlying profile's string class and not disallowed by any profile specific
|
||||
// rules.
|
||||
func (p *Profile) Allowed() runes.Set {
|
||||
if p.options.disallow != nil {
|
||||
return runes.Predicate(func(r rune) bool {
|
||||
return p.class.Contains(r) && !p.options.disallow.Contains(r)
|
||||
})
|
||||
}
|
||||
return p.class
|
||||
}
|
||||
|
||||
type checker struct {
|
||||
p *Profile
|
||||
allowed runes.Set
|
||||
|
||||
beforeBits catBitmap
|
||||
termBits catBitmap
|
||||
acceptBits catBitmap
|
||||
}
|
||||
|
||||
func (c *checker) Reset() {
|
||||
c.beforeBits = 0
|
||||
c.termBits = 0
|
||||
c.acceptBits = 0
|
||||
}
|
||||
|
||||
func (c *checker) span(src []byte, atEOF bool) (n int, err error) {
|
||||
for n < len(src) {
|
||||
e, sz := dpTrie.lookup(src[n:])
|
||||
d := categoryTransitions[category(e&catMask)]
|
||||
if sz == 0 {
|
||||
if !atEOF {
|
||||
return n, transform.ErrShortSrc
|
||||
}
|
||||
return n, errDisallowedRune
|
||||
}
|
||||
doLookAhead := false
|
||||
if property(e) < c.p.class.validFrom {
|
||||
if d.rule == nil {
|
||||
return n, errDisallowedRune
|
||||
}
|
||||
doLookAhead, err = d.rule(c.beforeBits)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
c.beforeBits &= d.keep
|
||||
c.beforeBits |= d.set
|
||||
if c.termBits != 0 {
|
||||
// We are currently in an unterminated lookahead.
|
||||
if c.beforeBits&c.termBits != 0 {
|
||||
c.termBits = 0
|
||||
c.acceptBits = 0
|
||||
} else if c.beforeBits&c.acceptBits == 0 {
|
||||
// Invalid continuation of the unterminated lookahead sequence.
|
||||
return n, errContext
|
||||
}
|
||||
}
|
||||
if doLookAhead {
|
||||
if c.termBits != 0 {
|
||||
// A previous lookahead run has not been terminated yet.
|
||||
return n, errContext
|
||||
}
|
||||
c.termBits = d.term
|
||||
c.acceptBits = d.accept
|
||||
}
|
||||
n += sz
|
||||
}
|
||||
if m := c.beforeBits >> finalShift; c.beforeBits&m != m || c.termBits != 0 {
|
||||
err = errContext
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// TODO: we may get rid of this transform if transform.Chain understands
|
||||
// something like a Spanner interface.
|
||||
func (c checker) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
short := false
|
||||
if len(dst) < len(src) {
|
||||
src = src[:len(dst)]
|
||||
atEOF = false
|
||||
short = true
|
||||
}
|
||||
nSrc, err = c.span(src, atEOF)
|
||||
nDst = copy(dst, src[:nSrc])
|
||||
if short && (err == transform.ErrShortSrc || err == nil) {
|
||||
err = transform.ErrShortDst
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
149
vendor/golang.org/x/text/secure/precis/profile_test.go
generated
vendored
Normal file
149
vendor/golang.org/x/text/secure/precis/profile_test.go
generated
vendored
Normal file
|
@ -0,0 +1,149 @@
|
|||
// Copyright 2016 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 precis
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"testing"
|
||||
"unicode"
|
||||
|
||||
"golang.org/x/text/internal/testtext"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// copyOrbit is a Transformer for the sole purpose of testing the apply method,
|
||||
// testing that apply will always call Span for the prefix of the input that
|
||||
// remains identical and then call Transform for the remainder. It will produce
|
||||
// inconsistent output for other usage patterns.
|
||||
// Provided that copyOrbit is used this way, the first t bytes of the output
|
||||
// will be identical to the input and the remaining output will be the result
|
||||
// of calling caseOrbit on the remaining input bytes.
|
||||
type copyOrbit int
|
||||
|
||||
func (t copyOrbit) Reset() {}
|
||||
func (t copyOrbit) Span(src []byte, atEOF bool) (n int, err error) {
|
||||
if int(t) == len(src) {
|
||||
return int(t), nil
|
||||
}
|
||||
return int(t), transform.ErrEndOfSpan
|
||||
}
|
||||
|
||||
// Transform implements transform.Transformer specifically for testing the apply method.
|
||||
// See documentation of copyOrbit before using this method.
|
||||
func (t copyOrbit) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
n := copy(dst, src)
|
||||
for i, c := range dst[:n] {
|
||||
dst[i] = orbitCase(c)
|
||||
}
|
||||
return n, n, nil
|
||||
}
|
||||
|
||||
func orbitCase(c byte) byte {
|
||||
if unicode.IsLower(rune(c)) {
|
||||
return byte(unicode.ToUpper(rune(c)))
|
||||
} else {
|
||||
return byte(unicode.ToLower(rune(c)))
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuffers(t *testing.T) {
|
||||
want := "Those who cannot remember the past are condemned to compute it."
|
||||
|
||||
spans := rand.Perm(len(want) + 1)
|
||||
|
||||
// Compute the result of applying copyOrbit(span) transforms in reverse.
|
||||
input := []byte(want)
|
||||
for i := len(spans) - 1; i >= 0; i-- {
|
||||
for j := spans[i]; j < len(input); j++ {
|
||||
input[j] = orbitCase(input[j])
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the copyOrbit(span) transforms.
|
||||
b := buffers{src: input}
|
||||
for _, n := range spans {
|
||||
b.apply(copyOrbit(n))
|
||||
if n%11 == 0 {
|
||||
b.apply(transform.Nop)
|
||||
}
|
||||
}
|
||||
if got := string(b.src); got != want {
|
||||
t.Errorf("got %q; want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
type compareTestCase struct {
|
||||
a string
|
||||
b string
|
||||
result bool
|
||||
}
|
||||
|
||||
var compareTestCases = []struct {
|
||||
name string
|
||||
p *Profile
|
||||
cases []compareTestCase
|
||||
}{
|
||||
{"Nickname", Nickname, []compareTestCase{
|
||||
{"a", "b", false},
|
||||
{" Swan of Avon ", "swan of avon", true},
|
||||
{"Foo", "foo", true},
|
||||
{"foo", "foo", true},
|
||||
{"Foo Bar", "foo bar", true},
|
||||
{"foo bar", "foo bar", true},
|
||||
{"\u03A3", "\u03C3", true},
|
||||
{"\u03A3", "\u03C2", false},
|
||||
{"\u03C3", "\u03C2", false},
|
||||
{"Richard \u2163", "richard iv", true},
|
||||
{"Å", "å", true},
|
||||
{"ff", "ff", true}, // because of NFKC
|
||||
{"ß", "sS", false},
|
||||
|
||||
// After applying the Nickname profile, \u00a8 becomes \u0020\u0308,
|
||||
// however because the nickname profile is not idempotent, applying it again
|
||||
// to \u0020\u0308 results in \u0308.
|
||||
{"\u00a8", "\u0020\u0308", true},
|
||||
{"\u00a8", "\u0308", true},
|
||||
{"\u0020\u0308", "\u0308", true},
|
||||
}},
|
||||
}
|
||||
|
||||
func doCompareTests(t *testing.T, fn func(t *testing.T, p *Profile, tc compareTestCase)) {
|
||||
for _, g := range compareTestCases {
|
||||
for i, tc := range g.cases {
|
||||
name := fmt.Sprintf("%s:%d:%+q", g.name, i, tc.a)
|
||||
testtext.Run(t, name, func(t *testing.T) {
|
||||
fn(t, g.p, tc)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompare(t *testing.T) {
|
||||
doCompareTests(t, func(t *testing.T, p *Profile, tc compareTestCase) {
|
||||
if result := p.Compare(tc.a, tc.b); result != tc.result {
|
||||
t.Errorf("got %v; want %v", result, tc.result)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestCompareString(t *testing.T) {
|
||||
doCompareTests(t, func(t *testing.T, p *Profile, tc compareTestCase) {
|
||||
a, err := p.CompareKey(tc.a)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error when creating key: %v", err)
|
||||
return
|
||||
}
|
||||
b, err := p.CompareKey(tc.b)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error when creating key: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if result := (a == b); result != tc.result {
|
||||
t.Errorf("got %v; want %v", result, tc.result)
|
||||
}
|
||||
})
|
||||
}
|
78
vendor/golang.org/x/text/secure/precis/profiles.go
generated
vendored
Normal file
78
vendor/golang.org/x/text/secure/precis/profiles.go
generated
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
// 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 precis
|
||||
|
||||
import (
|
||||
"unicode"
|
||||
|
||||
"golang.org/x/text/runes"
|
||||
"golang.org/x/text/transform"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
)
|
||||
|
||||
var (
|
||||
// Implements the Nickname profile specified in RFC 8266.
|
||||
Nickname *Profile = nickname
|
||||
|
||||
// Implements the UsernameCaseMapped profile specified in RFC 8265.
|
||||
UsernameCaseMapped *Profile = usernameCaseMap
|
||||
|
||||
// Implements the UsernameCasePreserved profile specified in RFC 8265.
|
||||
UsernameCasePreserved *Profile = usernameNoCaseMap
|
||||
|
||||
// Implements the OpaqueString profile defined in RFC 8265 for passwords and
|
||||
// other secure labels.
|
||||
OpaqueString *Profile = opaquestring
|
||||
)
|
||||
|
||||
var (
|
||||
nickname = &Profile{
|
||||
options: getOpts(
|
||||
AdditionalMapping(func() transform.Transformer {
|
||||
return &nickAdditionalMapping{}
|
||||
}),
|
||||
IgnoreCase,
|
||||
Norm(norm.NFKC),
|
||||
DisallowEmpty,
|
||||
repeat,
|
||||
),
|
||||
class: freeform,
|
||||
}
|
||||
usernameCaseMap = &Profile{
|
||||
options: getOpts(
|
||||
FoldWidth,
|
||||
LowerCase(),
|
||||
Norm(norm.NFC),
|
||||
BidiRule,
|
||||
),
|
||||
class: identifier,
|
||||
}
|
||||
usernameNoCaseMap = &Profile{
|
||||
options: getOpts(
|
||||
FoldWidth,
|
||||
Norm(norm.NFC),
|
||||
BidiRule,
|
||||
),
|
||||
class: identifier,
|
||||
}
|
||||
opaquestring = &Profile{
|
||||
options: getOpts(
|
||||
AdditionalMapping(func() transform.Transformer {
|
||||
return mapSpaces
|
||||
}),
|
||||
Norm(norm.NFC),
|
||||
DisallowEmpty,
|
||||
),
|
||||
class: freeform,
|
||||
}
|
||||
)
|
||||
|
||||
// mapSpaces is a shared value of a runes.Map transformer.
|
||||
var mapSpaces transform.Transformer = runes.Map(func(r rune) rune {
|
||||
if unicode.Is(unicode.Zs, r) {
|
||||
return ' '
|
||||
}
|
||||
return r
|
||||
})
|
3889
vendor/golang.org/x/text/secure/precis/tables10.0.0.go
generated
vendored
Normal file
3889
vendor/golang.org/x/text/secure/precis/tables10.0.0.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
3790
vendor/golang.org/x/text/secure/precis/tables9.0.0.go
generated
vendored
Normal file
3790
vendor/golang.org/x/text/secure/precis/tables9.0.0.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
69
vendor/golang.org/x/text/secure/precis/tables_test.go
generated
vendored
Normal file
69
vendor/golang.org/x/text/secure/precis/tables_test.go
generated
vendored
Normal file
|
@ -0,0 +1,69 @@
|
|||
// 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 precis
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/runes"
|
||||
"golang.org/x/text/unicode/rangetable"
|
||||
)
|
||||
|
||||
type tableTest struct {
|
||||
rangeTable *unicode.RangeTable
|
||||
prop property
|
||||
}
|
||||
|
||||
var exceptions = runes.Predicate(func(r rune) bool {
|
||||
switch uint32(r) {
|
||||
case 0x00DF, 0x03C2, 0x06FD, 0x06FE, 0x0F0B, 0x3007, 0x00B7, 0x0375, 0x05F3,
|
||||
0x05F4, 0x30FB, 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666,
|
||||
0x0667, 0x0668, 0x0669, 0x06F0, 0x06F1, 0x06F2, 0x06F3, 0x06F4, 0x06F5,
|
||||
0x06F6, 0x06F7, 0x06F8, 0x06F9, 0x0640, 0x07FA, 0x302E, 0x302F, 0x3031,
|
||||
0x3032, 0x3033, 0x3034, 0x3035, 0x303B:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
// Ensure that certain properties were generated correctly.
|
||||
func TestTable(t *testing.T) {
|
||||
tests := []tableTest{
|
||||
tableTest{
|
||||
rangetable.Merge(
|
||||
unicode.Lt, unicode.Nl, unicode.No, // Other letter digits
|
||||
unicode.Me, // Modifiers
|
||||
unicode.Zs, // Spaces
|
||||
unicode.So, // Symbols
|
||||
unicode.Pi, unicode.Pf, // Punctuation
|
||||
),
|
||||
idDisOrFreePVal,
|
||||
},
|
||||
tableTest{
|
||||
rangetable.New(0x30000, 0x30101, 0xDFFFF),
|
||||
unassigned,
|
||||
},
|
||||
}
|
||||
|
||||
assigned := rangetable.Assigned(UnicodeVersion)
|
||||
|
||||
for _, test := range tests {
|
||||
rangetable.Visit(test.rangeTable, func(r rune) {
|
||||
if !unicode.In(r, assigned) {
|
||||
return
|
||||
}
|
||||
b := make([]byte, 4)
|
||||
n := utf8.EncodeRune(b, r)
|
||||
trieval, _ := dpTrie.lookup(b[:n])
|
||||
p := entry(trieval).property()
|
||||
if p != test.prop && !exceptions.Contains(r) {
|
||||
t.Errorf("%U: got %+x; want %+x", r, test.prop, p)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
32
vendor/golang.org/x/text/secure/precis/transformer.go
generated
vendored
Normal file
32
vendor/golang.org/x/text/secure/precis/transformer.go
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
// 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 precis
|
||||
|
||||
import "golang.org/x/text/transform"
|
||||
|
||||
// Transformer implements the transform.Transformer interface.
|
||||
type Transformer struct {
|
||||
t transform.Transformer
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
64
vendor/golang.org/x/text/secure/precis/trieval.go
generated
vendored
Normal file
64
vendor/golang.org/x/text/secure/precis/trieval.go
generated
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
package precis
|
||||
|
||||
// entry is the entry of a trie table
|
||||
// 7..6 property (unassigned, disallowed, maybe, valid)
|
||||
// 5..0 category
|
||||
type entry uint8
|
||||
|
||||
const (
|
||||
propShift = 6
|
||||
propMask = 0xc0
|
||||
catMask = 0x3f
|
||||
)
|
||||
|
||||
func (e entry) property() property { return property(e & propMask) }
|
||||
func (e entry) category() category { return category(e & catMask) }
|
||||
|
||||
type property uint8
|
||||
|
||||
// The order of these constants matter. A Profile may consider runes to be
|
||||
// allowed either from pValid or idDisOrFreePVal.
|
||||
const (
|
||||
unassigned property = iota << propShift
|
||||
disallowed
|
||||
idDisOrFreePVal // disallowed for Identifier, pValid for FreeForm
|
||||
pValid
|
||||
)
|
||||
|
||||
// compute permutations of all properties and specialCategories.
|
||||
type category uint8
|
||||
|
||||
const (
|
||||
other category = iota
|
||||
|
||||
// Special rune types
|
||||
joiningL
|
||||
joiningD
|
||||
joiningT
|
||||
joiningR
|
||||
viramaModifier
|
||||
viramaJoinT // Virama + JoiningT
|
||||
latinSmallL // U+006c
|
||||
greek
|
||||
greekJoinT // Greek + JoiningT
|
||||
hebrew
|
||||
hebrewJoinT // Hebrew + JoiningT
|
||||
japanese // hirigana, katakana, han
|
||||
|
||||
// Special rune types associated with contextual rules defined in
|
||||
// https://tools.ietf.org/html/rfc5892#appendix-A.
|
||||
// ContextO
|
||||
zeroWidthNonJoiner // rule 1
|
||||
zeroWidthJoiner // rule 2
|
||||
// ContextJ
|
||||
middleDot // rule 3
|
||||
greekLowerNumeralSign // rule 4
|
||||
hebrewPreceding // rule 5 and 6
|
||||
katakanaMiddleDot // rule 7
|
||||
arabicIndicDigit // rule 8
|
||||
extendedArabicIndicDigit // rule 9
|
||||
|
||||
numCategories
|
||||
)
|
Loading…
Add table
Add a link
Reference in a new issue