Fixing race conditions in the code base (#5966)

* Adding initial race detector

* Remove setting of config twice

* Fixing config file watch and config reload on license save

* Fixing config file watch and config reload on license save

* Fixing build error

* Fixing locking issue

* Fixing makefile

* Fixing race in config

* Fixing race in status unit test

* Adding EE race tests

* Fixing race in cluster info

* Removing code that's isn't needed

* Fixing some more races

* Fixing govet issue
Этот коммит содержится в:
Corey Hulen
2017-04-04 11:42:07 -07:00
коммит произвёл Harrison Healey
родитель 32460bf63b
Коммит 6bf080393d
26 изменённых файлов: 1438 добавлений и 207 удалений

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

@@ -190,6 +190,39 @@ check-server-style: govet
check-style: check-client-style check-server-style check-style: check-client-style check-server-style
test-te-race: start-docker prepare-enterprise
@echo Testing TE race conditions
@echo "Packages to test: "$(TE_PACKAGES)
@for package in $(TE_PACKAGES); do \
echo "Testing "$$package; \
$(GO) test $(GOFLAGS) -race -run=$(TESTS) -test.v -test.timeout=3000s $$package || exit 1; \
done
test-ee-race: start-docker prepare-enterprise
@echo Testing EE race conditions
ifeq ($(BUILD_ENTERPRISE_READY),true)
@echo "Packages to test: "$(EE_PACKAGES)
for package in $(EE_PACKAGES); do \
echo "Testing "$$package; \
$(GO) test $(GOFLAGS) -race -run=$(TESTS) -c $$package; \
if [ -f $$(basename $$package).test ]; then \
echo "Testing "$$package; \
./$$(basename $$package).test -test.v -test.timeout=2000s || exit 1; \
rm -r $$(basename $$package).test; \
fi; \
done
rm -f config/*.crt
rm -f config/*.key
endif
test-server-race: test-te-race test-ee-race
test-te: start-docker prepare-enterprise test-te: start-docker prepare-enterprise
@echo Testing TE @echo Testing TE

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

@@ -86,6 +86,18 @@ func Setup() *TestHelper {
return &TestHelper{} return &TestHelper{}
} }
func ReloadConfigForSetup() {
utils.LoadConfig("config.json")
utils.InitTranslations(utils.Cfg.LocalizationSettings)
utils.Cfg.TeamSettings.MaxUsersPerTeam = 50
*utils.Cfg.RateLimitSettings.Enable = false
utils.Cfg.EmailSettings.SendEmailNotifications = true
utils.Cfg.EmailSettings.SMTPServer = "dockerhost"
utils.Cfg.EmailSettings.SMTPPort = "2500"
utils.Cfg.EmailSettings.FeedbackEmail = "test@example.com"
*utils.Cfg.TeamSettings.EnableOpenServer = true
}
func (me *TestHelper) InitBasic() *TestHelper { func (me *TestHelper) InitBasic() *TestHelper {
me.BasicClient = me.CreateClient() me.BasicClient = me.CreateClient()
me.BasicUser = me.CreateUser(me.BasicClient) me.BasicUser = me.CreateUser(me.BasicClient)

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

@@ -205,6 +205,7 @@ func TestStatuses(t *testing.T) {
} }
func TestGetStatusesByIds(t *testing.T) { func TestGetStatusesByIds(t *testing.T) {
ReloadConfigForSetup()
th := Setup().InitBasic() th := Setup().InitBasic()
Client := th.BasicClient Client := th.BasicClient

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

@@ -61,7 +61,6 @@ func TestSendChangeUsernameEmail(t *testing.T) {
func TestSendEmailChangeVerifyEmail(t *testing.T) { func TestSendEmailChangeVerifyEmail(t *testing.T) {
Setup() Setup()
utils.LoadConfig("config.json")
var userId string = "5349853498543jdfvndf9834" var userId string = "5349853498543jdfvndf9834"
var newUserEmail string = "newtest@example.com" var newUserEmail string = "newtest@example.com"
@@ -113,7 +112,6 @@ func TestSendEmailChangeVerifyEmail(t *testing.T) {
func TestSendEmailChangeEmail(t *testing.T) { func TestSendEmailChangeEmail(t *testing.T) {
Setup() Setup()
utils.LoadConfig("config.json")
var oldEmail string = "test@example.com" var oldEmail string = "test@example.com"
var newUserEmail string = "newtest@example.com" var newUserEmail string = "newtest@example.com"
@@ -161,7 +159,6 @@ func TestSendEmailChangeEmail(t *testing.T) {
func TestSendVerifyEmail(t *testing.T) { func TestSendVerifyEmail(t *testing.T) {
Setup() Setup()
utils.LoadConfig("config.json")
var userId string = "5349853498543jdfvndf9834" var userId string = "5349853498543jdfvndf9834"
var userEmail string = "test@example.com" var userEmail string = "test@example.com"
@@ -213,7 +210,6 @@ func TestSendVerifyEmail(t *testing.T) {
func TestSendSignInChangeEmail(t *testing.T) { func TestSendSignInChangeEmail(t *testing.T) {
Setup() Setup()
utils.LoadConfig("config.json")
var email string = "test@example.com" var email string = "test@example.com"
var locale string = "en" var locale string = "en"
@@ -261,7 +257,6 @@ func TestSendSignInChangeEmail(t *testing.T) {
func TestSendWelcomeEmail(t *testing.T) { func TestSendWelcomeEmail(t *testing.T) {
Setup() Setup()
utils.LoadConfig("config.json")
var userId string = "32432nkjnijn432uj32" var userId string = "32432nkjnijn432uj32"
var email string = "test@example.com" var email string = "test@example.com"
@@ -355,7 +350,6 @@ func TestSendWelcomeEmail(t *testing.T) {
func TestSendPasswordChangeEmail(t *testing.T) { func TestSendPasswordChangeEmail(t *testing.T) {
Setup() Setup()
utils.LoadConfig("config.json")
var email string = "test@example.com" var email string = "test@example.com"
var locale string = "en" var locale string = "en"
@@ -403,7 +397,6 @@ func TestSendPasswordChangeEmail(t *testing.T) {
func TestSendMfaChangeEmail(t *testing.T) { func TestSendMfaChangeEmail(t *testing.T) {
Setup() Setup()
utils.LoadConfig("config.json")
var email string = "test@example.com" var email string = "test@example.com"
var locale string = "en" var locale string = "en"
@@ -488,7 +481,6 @@ func TestSendMfaChangeEmail(t *testing.T) {
func TestSendInviteEmails(t *testing.T) { func TestSendInviteEmails(t *testing.T) {
th := Setup().InitBasic() th := Setup().InitBasic()
utils.LoadConfig("config.json")
var email1 string = "test1@example.com" var email1 string = "test1@example.com"
var email2 string = "test2@example.com" var email2 string = "test2@example.com"
@@ -564,7 +556,6 @@ func TestSendInviteEmails(t *testing.T) {
func TestSendPasswordReset(t *testing.T) { func TestSendPasswordReset(t *testing.T) {
th := Setup().InitBasic() th := Setup().InitBasic()
utils.LoadConfig("config.json")
var siteURL string = "http://test.mattermost.io" var siteURL string = "http://test.mattermost.io"
// var locale string = "en" // var locale string = "en"

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

@@ -8,6 +8,7 @@ import (
"hash/fnv" "hash/fnv"
"runtime" "runtime"
"runtime/debug" "runtime/debug"
"sync/atomic"
l4g "github.com/alecthomas/log4go" l4g "github.com/alecthomas/log4go"
@@ -18,6 +19,7 @@ import (
type Hub struct { type Hub struct {
connections []*WebConn connections []*WebConn
count int64
register chan *WebConn register chan *WebConn
unregister chan *WebConn unregister chan *WebConn
broadcast chan *model.WebSocketEvent broadcast chan *model.WebSocketEvent
@@ -43,12 +45,12 @@ func NewWebHub() *Hub {
func TotalWebsocketConnections() int { func TotalWebsocketConnections() int {
// This is racy, but it's only used for reporting information // This is racy, but it's only used for reporting information
// so it's probably OK // so it's probably OK
count := 0 count := int64(0)
for _, hub := range hubs { for _, hub := range hubs {
count = count + len(hub.connections) count = count + atomic.LoadInt64(&hub.count)
} }
return count return int(count)
} }
func HubStart() { func HubStart() {
@@ -248,6 +250,7 @@ func (h *Hub) Start() {
select { select {
case webCon := <-h.register: case webCon := <-h.register:
h.connections = append(h.connections, webCon) h.connections = append(h.connections, webCon)
atomic.StoreInt64(&h.count, int64(len(h.connections)))
case webCon := <-h.unregister: case webCon := <-h.unregister:
userId := webCon.UserId userId := webCon.UserId

11
glide.lock сгенерированный
Просмотреть файл

@@ -1,8 +1,9 @@
hash: a64cfc8472f6345146f4d111d841cca8b8efb25e3d4872865670a3f7db63b23b hash: 193ce14426dc6d4ae2da1c1aad08389a157529f829ed12948095239e18e045a5
updated: 2017-03-24T16:11:53.990600794-07:00 updated: 2017-03-30T22:26:27.084209918-07:00
imports: imports:
- name: github.com/alecthomas/log4go - name: github.com/alecthomas/log4go
version: e5dc62318d9bd58682f1dceb53a4b24e8253682f version: 3fbce08846379ec7f4f6bc7fce6dd01ce28fae4c
repo: https://github.com/mattermost/log4go.git
- name: github.com/beorn7/perks - name: github.com/beorn7/perks
version: 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9 version: 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
subpackages: subpackages:
@@ -104,7 +105,7 @@ imports:
- name: github.com/pelletier/go-buffruneio - name: github.com/pelletier/go-buffruneio
version: c37440a7cf42ac63b919c752ca73a85067e05992 version: c37440a7cf42ac63b919c752ca73a85067e05992
- name: github.com/pelletier/go-toml - name: github.com/pelletier/go-toml
version: f6e7596e8daafd44dc9e5c208dc73035020c8481 version: e32a2e04744250647a72bf17da1b09befc03b6b1
- name: github.com/prometheus/client_golang - name: github.com/prometheus/client_golang
version: c5b7fccd204277076155f10851dad72b76a49317 version: c5b7fccd204277076155f10851dad72b76a49317
subpackages: subpackages:
@@ -178,7 +179,7 @@ imports:
subpackages: subpackages:
- unix - unix
- name: golang.org/x/text - name: golang.org/x/text
version: fc7fa097411d30e6708badff276c4c164425590c version: 65f4f820a7954b82e5c9325e1e088a4fda098f36
subpackages: subpackages:
- transform - transform
- unicode/norm - unicode/norm

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

@@ -2,6 +2,7 @@ package: github.com/mattermost/platform
import: import:
- package: github.com/NYTimes/gziphandler - package: github.com/NYTimes/gziphandler
- package: github.com/alecthomas/log4go - package: github.com/alecthomas/log4go
repo: https://github.com/mattermost/log4go.git
- package: github.com/dgryski/dgoogauth - package: github.com/dgryski/dgoogauth
- package: github.com/disintegration/imaging - package: github.com/disintegration/imaging
version: v1.0.0 version: v1.0.0

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

@@ -6,19 +6,25 @@ package model
import ( import (
"encoding/json" "encoding/json"
"io" "io"
"strings"
"sync"
"sync/atomic"
) )
type ClusterInfo struct { type ClusterInfo struct {
Id string `json:"id"` Id string `json:"id"`
Version string `json:"version"` Version string `json:"version"`
ConfigHash string `json:"config_hash"` ConfigHash string `json:"config_hash"`
InterNodeUrl string `json:"internode_url"` InterNodeUrl string `json:"internode_url"`
Hostname string `json:"hostname"` Hostname string `json:"hostname"`
LastSuccessfulPing int64 `json:"last_ping"` LastSuccessfulPing int64 `json:"last_ping"`
IsAlive bool `json:"is_alive"` Alive int32 `json:"is_alive"`
Mutex sync.RWMutex `json:"-"`
} }
func (me *ClusterInfo) ToJson() string { func (me *ClusterInfo) ToJson() string {
me.Mutex.RLock()
defer me.Mutex.RUnlock()
b, err := json.Marshal(me) b, err := json.Marshal(me)
if err != nil { if err != nil {
return "" return ""
@@ -27,9 +33,15 @@ func (me *ClusterInfo) ToJson() string {
} }
} }
func (me *ClusterInfo) Copy() *ClusterInfo {
json := me.ToJson()
return ClusterInfoFromJson(strings.NewReader(json))
}
func ClusterInfoFromJson(data io.Reader) *ClusterInfo { func ClusterInfoFromJson(data io.Reader) *ClusterInfo {
decoder := json.NewDecoder(data) decoder := json.NewDecoder(data)
var me ClusterInfo var me ClusterInfo
me.Mutex = sync.RWMutex{}
err := decoder.Decode(&me) err := decoder.Decode(&me)
if err == nil { if err == nil {
return &me return &me
@@ -38,7 +50,21 @@ func ClusterInfoFromJson(data io.Reader) *ClusterInfo {
} }
} }
func (me *ClusterInfo) SetAlive(alive bool) {
if alive {
atomic.StoreInt32(&me.Alive, 1)
} else {
atomic.StoreInt32(&me.Alive, 0)
}
}
func (me *ClusterInfo) IsAlive() bool {
return atomic.LoadInt32(&me.Alive) == 1
}
func (me *ClusterInfo) HaveEstablishedInitialContact() bool { func (me *ClusterInfo) HaveEstablishedInitialContact() bool {
me.Mutex.RLock()
defer me.Mutex.RUnlock()
if me.Id != "" { if me.Id != "" {
return true return true
} }
@@ -46,6 +72,16 @@ func (me *ClusterInfo) HaveEstablishedInitialContact() bool {
return false return false
} }
func (me *ClusterInfo) IdEqualTo(in string) bool {
me.Mutex.RLock()
defer me.Mutex.RUnlock()
if me.Id == in {
return true
}
return false
}
func ClusterInfosToJson(objmap []*ClusterInfo) string { func ClusterInfosToJson(objmap []*ClusterInfo) string {
if b, err := json.Marshal(objmap); err != nil { if b, err := json.Marshal(objmap); err != nil {
return "" return ""

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

@@ -16,6 +16,16 @@ func TestClusterInfoJson(t *testing.T) {
if cluster.Id != result.Id { if cluster.Id != result.Id {
t.Fatal("Ids do not match") t.Fatal("Ids do not match")
} }
cluster.SetAlive(true)
if !cluster.IsAlive() {
t.Fatal("should be live")
}
cluster.SetAlive(false)
if cluster.IsAlive() {
t.Fatal("should be not live")
}
} }
func TestClusterInfosJson(t *testing.T) { func TestClusterInfosJson(t *testing.T) {

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

@@ -5,6 +5,7 @@ package model
import ( import (
"fmt" "fmt"
"sync"
"time" "time"
) )
@@ -18,17 +19,24 @@ type ScheduledTask struct {
timer *time.Timer timer *time.Timer
} }
var taskMutex = sync.Mutex{}
var tasks = make(map[string]*ScheduledTask) var tasks = make(map[string]*ScheduledTask)
func addTask(task *ScheduledTask) { func addTask(task *ScheduledTask) {
taskMutex.Lock()
defer taskMutex.Unlock()
tasks[task.Name] = task tasks[task.Name] = task
} }
func removeTaskByName(name string) { func removeTaskByName(name string) {
taskMutex.Lock()
defer taskMutex.Unlock()
delete(tasks, name) delete(tasks, name)
} }
func GetTaskByName(name string) *ScheduledTask { func GetTaskByName(name string) *ScheduledTask {
taskMutex.Lock()
defer taskMutex.Unlock()
if task, ok := tasks[name]; ok { if task, ok := tasks[name]; ok {
return task return task
} }
@@ -36,6 +44,8 @@ func GetTaskByName(name string) *ScheduledTask {
} }
func GetAllTasks() *map[string]*ScheduledTask { func GetAllTasks() *map[string]*ScheduledTask {
taskMutex.Lock()
defer taskMutex.Unlock()
return &tasks return &tasks
} }

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

@@ -72,6 +72,8 @@ func FindDir(dir string) string {
} }
func DisableDebugLogForTest() { func DisableDebugLogForTest() {
cfgMutex.Lock()
defer cfgMutex.Unlock()
if l4g.Global["stdout"] != nil { if l4g.Global["stdout"] != nil {
originalDisableDebugLvl = l4g.Global["stdout"].Level originalDisableDebugLvl = l4g.Global["stdout"].Level
l4g.Global["stdout"].Level = l4g.ERROR l4g.Global["stdout"].Level = l4g.ERROR
@@ -79,6 +81,8 @@ func DisableDebugLogForTest() {
} }
func EnableDebugLogForTest() { func EnableDebugLogForTest() {
cfgMutex.Lock()
defer cfgMutex.Unlock()
if l4g.Global["stdout"] != nil { if l4g.Global["stdout"] != nil {
l4g.Global["stdout"].Level = originalDisableDebugLvl l4g.Global["stdout"].Level = originalDisableDebugLvl
} }

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

@@ -47,7 +47,6 @@ func (w *FileLogWriter) LogWrite(rec *LogRecord) {
func (w *FileLogWriter) Close() { func (w *FileLogWriter) Close() {
close(w.rec) close(w.rec)
w.file.Sync()
} }
// NewFileLogWriter creates a new LogWriter which writes to the given file and // NewFileLogWriter creates a new LogWriter which writes to the given file and
@@ -79,6 +78,7 @@ func NewFileLogWriter(fname string, rotate bool) *FileLogWriter {
defer func() { defer func() {
if w.file != nil { if w.file != nil {
fmt.Fprint(w.file, FormatLogRecord(w.trailer, &LogRecord{Created: time.Now()})) fmt.Fprint(w.file, FormatLogRecord(w.trailer, &LogRecord{Created: time.Now()}))
w.file.Sync()
w.file.Close() w.file.Close()
} }
}() }()

4
vendor/github.com/alecthomas/log4go/pattlog.go сгенерированный поставляемый
Просмотреть файл

@@ -7,6 +7,7 @@ import (
"fmt" "fmt"
"io" "io"
"strings" "strings"
"sync"
) )
const ( const (
@@ -22,6 +23,7 @@ type formatCacheType struct {
} }
var formatCache = &formatCacheType{} var formatCache = &formatCacheType{}
var mutex sync.Mutex
// Known format codes: // Known format codes:
// %T - Time (15:04:05 MST) // %T - Time (15:04:05 MST)
@@ -44,6 +46,7 @@ func FormatLogRecord(format string, rec *LogRecord) string {
out := bytes.NewBuffer(make([]byte, 0, 64)) out := bytes.NewBuffer(make([]byte, 0, 64))
secs := rec.Created.UnixNano() / 1e9 secs := rec.Created.UnixNano() / 1e9
mutex.Lock()
cache := *formatCache cache := *formatCache
if cache.LastUpdateSeconds != secs { if cache.LastUpdateSeconds != secs {
month, day, year := rec.Created.Month(), rec.Created.Day(), rec.Created.Year() month, day, year := rec.Created.Month(), rec.Created.Day(), rec.Created.Year()
@@ -59,6 +62,7 @@ func FormatLogRecord(format string, rec *LogRecord) string {
cache = *updated cache = *updated
formatCache = updated formatCache = updated
} }
mutex.Unlock()
// Split the string into pieces by % signs // Split the string into pieces by % signs
pieces := bytes.Split([]byte(format), []byte{'%'}) pieces := bytes.Split([]byte(format), []byte{'%'})

459
vendor/github.com/pelletier/go-toml/marshal.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,459 @@
package toml
import (
"errors"
"fmt"
"reflect"
"strings"
"time"
)
/*
TomlTree structural types and corresponding marshal types
-------------------------------------------------------------------------------
*TomlTree (*)struct, (*)map[string]interface{}
[]*TomlTree (*)[](*)struct, (*)[](*)map[string]interface{}
[]interface{} (as interface{}) (*)[]primitive, (*)[]([]interface{})
interface{} (*)primitive
TomlTree primitive types and corresponding marshal types
-----------------------------------------------------------
uint64 uint, uint8-uint64, pointers to same
int64 int, int8-uint64, pointers to same
float64 float32, float64, pointers to same
string string, pointers to same
bool bool, pointers to same
time.Time time.Time{}, pointers to same
*/
type tomlOpts struct {
name string
include bool
omitempty bool
}
var timeType = reflect.TypeOf(time.Time{})
// Check if the given marshall type maps to a TomlTree primitive
func isPrimitive(mtype reflect.Type) bool {
switch mtype.Kind() {
case reflect.Ptr:
return isPrimitive(mtype.Elem())
case reflect.Bool:
return true
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return true
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return true
case reflect.Float32, reflect.Float64:
return true
case reflect.String:
return true
case reflect.Struct:
return mtype == timeType
default:
return false
}
}
// Check if the given marshall type maps to a TomlTree slice
func isTreeSlice(mtype reflect.Type) bool {
switch mtype.Kind() {
case reflect.Slice:
return !isOtherSlice(mtype)
default:
return false
}
}
// Check if the given marshall type maps to a non-TomlTree slice
func isOtherSlice(mtype reflect.Type) bool {
switch mtype.Kind() {
case reflect.Ptr:
return isOtherSlice(mtype.Elem())
case reflect.Slice:
return isPrimitive(mtype.Elem()) || isOtherSlice(mtype.Elem())
default:
return false
}
}
// Check if the given marshall type maps to a TomlTree
func isTree(mtype reflect.Type) bool {
switch mtype.Kind() {
case reflect.Map:
return true
case reflect.Struct:
return !isPrimitive(mtype)
default:
return false
}
}
/*
Marshal returns the TOML encoding of v. Behavior is similar to the Go json
encoder, except that there is no concept of a Marshaler interface or MarshalTOML
function for sub-structs, and currently only definite types can be marshaled
(i.e. no `interface{}`).
Note that pointers are automatically assigned the "omitempty" option, as TOML
explicity does not handle null values (saying instead the label should be
dropped).
*/
func Marshal(v interface{}) ([]byte, error) {
mtype := reflect.TypeOf(v)
if mtype.Kind() != reflect.Struct {
return []byte{}, errors.New("Only a struct can be marshaled to TOML")
}
sval := reflect.ValueOf(v)
t, err := valueToTree(mtype, sval)
if err != nil {
return []byte{}, err
}
s, err := t.ToTomlString()
return []byte(s), err
}
// Convert given marshal struct or map value to toml tree
func valueToTree(mtype reflect.Type, mval reflect.Value) (*TomlTree, error) {
if mtype.Kind() == reflect.Ptr {
return valueToTree(mtype.Elem(), mval.Elem())
}
tval := newTomlTree()
switch mtype.Kind() {
case reflect.Struct:
for i := 0; i < mtype.NumField(); i++ {
mtypef, mvalf := mtype.Field(i), mval.Field(i)
opts := tomlOptions(mtypef)
if opts.include && (!opts.omitempty || !isZero(mvalf)) {
val, err := valueToToml(mtypef.Type, mvalf)
if err != nil {
return nil, err
}
tval.Set(opts.name, val)
}
}
case reflect.Map:
for _, key := range mval.MapKeys() {
mvalf := mval.MapIndex(key)
val, err := valueToToml(mtype.Elem(), mvalf)
if err != nil {
return nil, err
}
tval.Set(key.String(), val)
}
}
return tval, nil
}
// Convert given marshal slice to slice of Toml trees
func valueToTreeSlice(mtype reflect.Type, mval reflect.Value) ([]*TomlTree, error) {
tval := make([]*TomlTree, mval.Len(), mval.Len())
for i := 0; i < mval.Len(); i++ {
val, err := valueToTree(mtype.Elem(), mval.Index(i))
if err != nil {
return nil, err
}
tval[i] = val
}
return tval, nil
}
// Convert given marshal slice to slice of toml values
func valueToOtherSlice(mtype reflect.Type, mval reflect.Value) (interface{}, error) {
tval := make([]interface{}, mval.Len(), mval.Len())
for i := 0; i < mval.Len(); i++ {
val, err := valueToToml(mtype.Elem(), mval.Index(i))
if err != nil {
return nil, err
}
tval[i] = val
}
return tval, nil
}
// Convert given marshal value to toml value
func valueToToml(mtype reflect.Type, mval reflect.Value) (interface{}, error) {
if mtype.Kind() == reflect.Ptr {
return valueToToml(mtype.Elem(), mval.Elem())
}
switch {
case isTree(mtype):
return valueToTree(mtype, mval)
case isTreeSlice(mtype):
return valueToTreeSlice(mtype, mval)
case isOtherSlice(mtype):
return valueToOtherSlice(mtype, mval)
default:
switch mtype.Kind() {
case reflect.Bool:
return mval.Bool(), nil
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return mval.Int(), nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return mval.Uint(), nil
case reflect.Float32, reflect.Float64:
return mval.Float(), nil
case reflect.String:
return mval.String(), nil
case reflect.Struct:
return mval.Interface().(time.Time), nil
default:
return nil, fmt.Errorf("Marshal can't handle %v(%v)", mtype, mtype.Kind())
}
}
}
/*
Unmarshal parses the TOML-encoded data and stores the result in the value
pointed to by v. Behavior is similar to the Go json encoder, except that there
is no concept of an Unmarshaler interface or UnmarshalTOML function for
sub-structs, and currently only definite types can be unmarshaled to (i.e. no
`interface{}`).
*/
func Unmarshal(data []byte, v interface{}) error {
mtype := reflect.TypeOf(v)
if mtype.Kind() != reflect.Ptr || mtype.Elem().Kind() != reflect.Struct {
return errors.New("Only a pointer to struct can be unmarshaled from TOML")
}
t, err := Load(string(data))
if err != nil {
return err
}
sval, err := valueFromTree(mtype.Elem(), t)
if err != nil {
return err
}
reflect.ValueOf(v).Elem().Set(sval)
return nil
}
// Convert toml tree to marshal struct or map, using marshal type
func valueFromTree(mtype reflect.Type, tval *TomlTree) (reflect.Value, error) {
if mtype.Kind() == reflect.Ptr {
return unwrapPointer(mtype, tval)
}
var mval reflect.Value
switch mtype.Kind() {
case reflect.Struct:
mval = reflect.New(mtype).Elem()
for i := 0; i < mtype.NumField(); i++ {
mtypef := mtype.Field(i)
opts := tomlOptions(mtypef)
if opts.include {
key := opts.name
exists := tval.Has(key)
if exists {
val := tval.Get(key)
mvalf, err := valueFromToml(mtypef.Type, val)
if err != nil {
return mval, formatError(err, tval.GetPosition(key))
}
mval.Field(i).Set(mvalf)
}
}
}
case reflect.Map:
mval = reflect.MakeMap(mtype)
for _, key := range tval.Keys() {
val := tval.Get(key)
mvalf, err := valueFromToml(mtype.Elem(), val)
if err != nil {
return mval, formatError(err, tval.GetPosition(key))
}
mval.SetMapIndex(reflect.ValueOf(key), mvalf)
}
}
return mval, nil
}
// Convert toml value to marshal struct/map slice, using marshal type
func valueFromTreeSlice(mtype reflect.Type, tval []*TomlTree) (reflect.Value, error) {
mval := reflect.MakeSlice(mtype, len(tval), len(tval))
for i := 0; i < len(tval); i++ {
val, err := valueFromTree(mtype.Elem(), tval[i])
if err != nil {
return mval, err
}
mval.Index(i).Set(val)
}
return mval, nil
}
// Convert toml value to marshal primitive slice, using marshal type
func valueFromOtherSlice(mtype reflect.Type, tval []interface{}) (reflect.Value, error) {
mval := reflect.MakeSlice(mtype, len(tval), len(tval))
for i := 0; i < len(tval); i++ {
val, err := valueFromToml(mtype.Elem(), tval[i])
if err != nil {
return mval, err
}
mval.Index(i).Set(val)
}
return mval, nil
}
// Convert toml value to marshal value, using marshal type
func valueFromToml(mtype reflect.Type, tval interface{}) (reflect.Value, error) {
if mtype.Kind() == reflect.Ptr {
return unwrapPointer(mtype, tval)
}
switch {
case isTree(mtype):
return valueFromTree(mtype, tval.(*TomlTree))
case isTreeSlice(mtype):
return valueFromTreeSlice(mtype, tval.([]*TomlTree))
case isOtherSlice(mtype):
return valueFromOtherSlice(mtype, tval.([]interface{}))
default:
switch mtype.Kind() {
case reflect.Bool:
val, ok := tval.(bool)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to bool", tval, tval)
}
return reflect.ValueOf(val), nil
case reflect.Int:
val, ok := tval.(int64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to int", tval, tval)
}
return reflect.ValueOf(int(val)), nil
case reflect.Int8:
val, ok := tval.(int64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to int", tval, tval)
}
return reflect.ValueOf(int8(val)), nil
case reflect.Int16:
val, ok := tval.(int64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to int", tval, tval)
}
return reflect.ValueOf(int16(val)), nil
case reflect.Int32:
val, ok := tval.(int64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to int", tval, tval)
}
return reflect.ValueOf(int32(val)), nil
case reflect.Int64:
val, ok := tval.(int64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to int", tval, tval)
}
return reflect.ValueOf(val), nil
case reflect.Uint:
val, ok := tval.(int64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to uint", tval, tval)
}
return reflect.ValueOf(uint(val)), nil
case reflect.Uint8:
val, ok := tval.(int64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to uint", tval, tval)
}
return reflect.ValueOf(uint8(val)), nil
case reflect.Uint16:
val, ok := tval.(int64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to uint", tval, tval)
}
return reflect.ValueOf(uint16(val)), nil
case reflect.Uint32:
val, ok := tval.(int64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to uint", tval, tval)
}
return reflect.ValueOf(uint32(val)), nil
case reflect.Uint64:
val, ok := tval.(int64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to uint", tval, tval)
}
return reflect.ValueOf(uint64(val)), nil
case reflect.Float32:
val, ok := tval.(float64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to float", tval, tval)
}
return reflect.ValueOf(float32(val)), nil
case reflect.Float64:
val, ok := tval.(float64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to float", tval, tval)
}
return reflect.ValueOf(val), nil
case reflect.String:
val, ok := tval.(string)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to string", tval, tval)
}
return reflect.ValueOf(val), nil
case reflect.Struct:
val, ok := tval.(time.Time)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to time", tval, tval)
}
return reflect.ValueOf(val), nil
default:
return reflect.ValueOf(nil), fmt.Errorf("Unmarshal can't handle %v(%v)", mtype, mtype.Kind())
}
}
}
func unwrapPointer(mtype reflect.Type, tval interface{}) (reflect.Value, error) {
val, err := valueFromToml(mtype.Elem(), tval)
if err != nil {
return reflect.ValueOf(nil), err
}
mval := reflect.New(mtype.Elem())
mval.Elem().Set(val)
return mval, nil
}
func tomlOptions(vf reflect.StructField) tomlOpts {
tag := vf.Tag.Get("toml")
parse := strings.Split(tag, ",")
result := tomlOpts{vf.Name, true, false}
if parse[0] != "" {
if parse[0] == "-" && len(parse) == 1 {
result.include = false
} else {
result.name = strings.Trim(parse[0], " ")
}
}
if vf.PkgPath != "" {
result.include = false
}
if len(parse) > 1 && strings.Trim(parse[1], " ") == "omitempty" {
result.omitempty = true
}
if vf.Type.Kind() == reflect.Ptr {
result.omitempty = true
}
return result
}
func isZero(val reflect.Value) bool {
switch val.Type().Kind() {
case reflect.Map:
fallthrough
case reflect.Array:
fallthrough
case reflect.Slice:
return val.Len() == 0
default:
return reflect.DeepEqual(val.Interface(), reflect.Zero(val.Type()).Interface())
}
}
func formatError(err error, pos Position) error {
if err.Error()[0] == '(' { // Error already contains position information
return err
}
return fmt.Errorf("%s: %s", pos, err)
}

535
vendor/github.com/pelletier/go-toml/marshal_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,535 @@
package toml
import (
"bytes"
"encoding/json"
"io/ioutil"
"reflect"
"testing"
"time"
)
type basicMarshalTestStruct struct {
String string `toml:"string"`
StringList []string `toml:"strlist"`
Sub basicMarshalTestSubStruct `toml:"subdoc"`
SubList []basicMarshalTestSubStruct `toml:"sublist"`
}
type basicMarshalTestSubStruct struct {
String2 string
}
var basicTestData = basicMarshalTestStruct{
String: "Hello",
StringList: []string{"Howdy", "Hey There"},
Sub: basicMarshalTestSubStruct{"One"},
SubList: []basicMarshalTestSubStruct{{"Two"}, {"Three"}},
}
var basicTestToml = []byte(`string = "Hello"
strlist = ["Howdy","Hey There"]
[subdoc]
String2 = "One"
[[sublist]]
String2 = "Two"
[[sublist]]
String2 = "Three"
`)
func TestBasicMarshal(t *testing.T) {
result, err := Marshal(basicTestData)
if err != nil {
t.Fatal(err)
}
expected := basicTestToml
if !bytes.Equal(result, expected) {
t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
}
}
func TestBasicUnmarshal(t *testing.T) {
result := basicMarshalTestStruct{}
err := Unmarshal(basicTestToml, &result)
expected := basicTestData
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(result, expected) {
t.Errorf("Bad unmarshal: expected %v, got %v", expected, result)
}
}
type testDoc struct {
Title string `toml:"title"`
Basics testDocBasics `toml:"basic"`
BasicLists testDocBasicLists `toml:"basic_lists"`
BasicMap map[string]string `toml:"basic_map"`
Subdocs testDocSubs `toml:"subdoc"`
SubDocList []testSubDoc `toml:"subdoclist"`
SubDocPtrs []*testSubDoc `toml:"subdocptrs"`
err int `toml:"shouldntBeHere"`
unexported int `toml:"shouldntBeHere"`
Unexported2 int `toml:"-"`
}
type testDocBasics struct {
Bool bool `toml:"bool"`
Date time.Time `toml:"date"`
Float float32 `toml:"float"`
Int int `toml:"int"`
Uint uint `toml:"uint"`
String *string `toml:"string"`
unexported int `toml:"shouldntBeHere"`
}
type testDocBasicLists struct {
Bools []bool `toml:"bools"`
Dates []time.Time `toml:"dates"`
Floats []*float32 `toml:"floats"`
Ints []int `toml:"ints"`
Strings []string `toml:"strings"`
UInts []uint `toml:"uints"`
}
type testDocSubs struct {
First testSubDoc `toml:"first"`
Second *testSubDoc `toml:"second"`
}
type testSubDoc struct {
Name string `toml:"name"`
unexported int `toml:"shouldntBeHere"`
}
var biteMe = "Bite me"
var float1 float32 = 12.3
var float2 float32 = 45.6
var float3 float32 = 78.9
var subdoc = testSubDoc{"Second", 0}
var docData = testDoc{
Title: "TOML Marshal Testing",
unexported: 0,
Unexported2: 0,
Basics: testDocBasics{
Bool: true,
Date: time.Date(1979, 5, 27, 7, 32, 0, 0, time.UTC),
Float: 123.4,
Int: 5000,
Uint: 5001,
String: &biteMe,
unexported: 0,
},
BasicLists: testDocBasicLists{
Bools: []bool{true, false, true},
Dates: []time.Time{
time.Date(1979, 5, 27, 7, 32, 0, 0, time.UTC),
time.Date(1980, 5, 27, 7, 32, 0, 0, time.UTC),
},
Floats: []*float32{&float1, &float2, &float3},
Ints: []int{8001, 8001, 8002},
Strings: []string{"One", "Two", "Three"},
UInts: []uint{5002, 5003},
},
BasicMap: map[string]string{
"one": "one",
"two": "two",
},
Subdocs: testDocSubs{
First: testSubDoc{"First", 0},
Second: &subdoc,
},
SubDocList: []testSubDoc{
testSubDoc{"List.First", 0},
testSubDoc{"List.Second", 0},
},
SubDocPtrs: []*testSubDoc{&subdoc},
}
func TestDocMarshal(t *testing.T) {
result, err := Marshal(docData)
if err != nil {
t.Fatal(err)
}
expected, _ := ioutil.ReadFile("marshal_test.toml")
if !bytes.Equal(result, expected) {
t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
}
}
func TestDocUnmarshal(t *testing.T) {
result := testDoc{}
tomlData, _ := ioutil.ReadFile("marshal_test.toml")
err := Unmarshal(tomlData, &result)
expected := docData
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(result, expected) {
resStr, _ := json.MarshalIndent(result, "", " ")
expStr, _ := json.MarshalIndent(expected, "", " ")
t.Errorf("Bad unmarshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expStr, resStr)
}
}
type tomlTypeCheckTest struct {
name string
item interface{}
typ int //0=primitive, 1=otherslice, 2=treeslice, 3=tree
}
func TestTypeChecks(t *testing.T) {
tests := []tomlTypeCheckTest{
{"integer", 2, 0},
{"time", time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC), 0},
{"stringlist", []string{"hello", "hi"}, 1},
{"timelist", []time.Time{time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)}, 1},
{"objectlist", []tomlTypeCheckTest{}, 2},
{"object", tomlTypeCheckTest{}, 3},
}
for _, test := range tests {
expected := []bool{false, false, false, false}
expected[test.typ] = true
result := []bool{
isPrimitive(reflect.TypeOf(test.item)),
isOtherSlice(reflect.TypeOf(test.item)),
isTreeSlice(reflect.TypeOf(test.item)),
isTree(reflect.TypeOf(test.item)),
}
if !reflect.DeepEqual(expected, result) {
t.Errorf("Bad type check on %q: expected %v, got %v", test.name, expected, result)
}
}
}
type unexportedMarshalTestStruct struct {
String string `toml:"string"`
StringList []string `toml:"strlist"`
Sub basicMarshalTestSubStruct `toml:"subdoc"`
SubList []basicMarshalTestSubStruct `toml:"sublist"`
unexported int `toml:"shouldntBeHere"`
Unexported2 int `toml:"-"`
}
var unexportedTestData = unexportedMarshalTestStruct{
String: "Hello",
StringList: []string{"Howdy", "Hey There"},
Sub: basicMarshalTestSubStruct{"One"},
SubList: []basicMarshalTestSubStruct{{"Two"}, {"Three"}},
unexported: 0,
Unexported2: 0,
}
var unexportedTestToml = []byte(`string = "Hello"
strlist = ["Howdy","Hey There"]
unexported = 1
shouldntBeHere = 2
[subdoc]
String2 = "One"
[[sublist]]
String2 = "Two"
[[sublist]]
String2 = "Three"
`)
func TestUnexportedUnmarshal(t *testing.T) {
result := unexportedMarshalTestStruct{}
err := Unmarshal(unexportedTestToml, &result)
expected := unexportedTestData
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(result, expected) {
t.Errorf("Bad unexported unmarshal: expected %v, got %v", expected, result)
}
}
type errStruct struct {
Bool bool `toml:"bool"`
Date time.Time `toml:"date"`
Float float64 `toml:"float"`
Int int16 `toml:"int"`
String *string `toml:"string"`
}
var errTomls = []string{
"bool = truly\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"",
"bool = true\ndate = 1979-05-27T07:3200Z\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"",
"bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123a4\nint = 5000\nstring = \"Bite me\"",
"bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = j000\nstring = \"Bite me\"",
"bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = Bite me",
"bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = Bite me",
"bool = 1\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"",
"bool = true\ndate = 1\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"",
"bool = true\ndate = 1979-05-27T07:32:00Z\n\"sorry\"\nint = 5000\nstring = \"Bite me\"",
"bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = \"sorry\"\nstring = \"Bite me\"",
"bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = 1",
}
type mapErr struct {
Vals map[string]float64
}
type intErr struct {
Int1 int
Int2 int8
Int3 int16
Int4 int32
Int5 int64
UInt1 uint
UInt2 uint8
UInt3 uint16
UInt4 uint32
UInt5 uint64
Flt1 float32
Flt2 float64
}
var intErrTomls = []string{
"Int1 = []\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
"Int1 = 1\nInt2 = []\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
"Int1 = 1\nInt2 = 2\nInt3 = []\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
"Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = []\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
"Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = []\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
"Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = []\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
"Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = []\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
"Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = []\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
"Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = []\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
"Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = []\nFlt1 = 1.0\nFlt2 = 2.0",
"Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = []\nFlt2 = 2.0",
"Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = []",
}
func TestErrUnmarshal(t *testing.T) {
for ind, toml := range errTomls {
result := errStruct{}
err := Unmarshal([]byte(toml), &result)
if err == nil {
t.Errorf("Expected err from case %d\n", ind)
}
}
result2 := mapErr{}
err := Unmarshal([]byte("[Vals]\nfred=\"1.2\""), &result2)
if err == nil {
t.Errorf("Expected err from map")
}
for ind, toml := range intErrTomls {
result3 := intErr{}
err := Unmarshal([]byte(toml), &result3)
if err == nil {
t.Errorf("Expected int err from case %d\n", ind)
}
}
}
type emptyMarshalTestStruct struct {
Title string `toml:"title"`
Bool bool `toml:"bool"`
Int int `toml:"int"`
String string `toml:"string"`
StringList []string `toml:"stringlist"`
Ptr *basicMarshalTestStruct `toml:"ptr"`
Map map[string]string `toml:"map"`
}
var emptyTestData = emptyMarshalTestStruct{
Title: "Placeholder",
Bool: false,
Int: 0,
String: "",
StringList: []string{},
Ptr: nil,
Map: map[string]string{},
}
var emptyTestToml = []byte(`bool = false
int = 0
string = ""
stringlist = []
title = "Placeholder"
[map]
`)
type emptyMarshalTestStruct2 struct {
Title string `toml:"title"`
Bool bool `toml:"bool,omitempty"`
Int int `toml:"int, omitempty"`
String string `toml:"string,omitempty "`
StringList []string `toml:"stringlist,omitempty"`
Ptr *basicMarshalTestStruct `toml:"ptr,omitempty"`
Map map[string]string `toml:"map,omitempty"`
}
var emptyTestData2 = emptyMarshalTestStruct2{
Title: "Placeholder",
Bool: false,
Int: 0,
String: "",
StringList: []string{},
Ptr: nil,
Map: map[string]string{},
}
var emptyTestToml2 = []byte(`title = "Placeholder"
`)
func TestEmptyMarshal(t *testing.T) {
result, err := Marshal(emptyTestData)
if err != nil {
t.Fatal(err)
}
expected := emptyTestToml
if !bytes.Equal(result, expected) {
t.Errorf("Bad empty marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
}
}
func TestEmptyMarshalOmit(t *testing.T) {
result, err := Marshal(emptyTestData2)
if err != nil {
t.Fatal(err)
}
expected := emptyTestToml2
if !bytes.Equal(result, expected) {
t.Errorf("Bad empty omit marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
}
}
func TestEmptyUnmarshal(t *testing.T) {
result := emptyMarshalTestStruct{}
err := Unmarshal(emptyTestToml, &result)
expected := emptyTestData
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(result, expected) {
t.Errorf("Bad empty unmarshal: expected %v, got %v", expected, result)
}
}
func TestEmptyUnmarshalOmit(t *testing.T) {
result := emptyMarshalTestStruct2{}
err := Unmarshal(emptyTestToml, &result)
expected := emptyTestData2
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(result, expected) {
t.Errorf("Bad empty omit unmarshal: expected %v, got %v", expected, result)
}
}
type pointerMarshalTestStruct struct {
Str *string
List *[]string
ListPtr *[]*string
Map *map[string]string
MapPtr *map[string]*string
EmptyStr *string
EmptyList *[]string
EmptyMap *map[string]string
DblPtr *[]*[]*string
}
var pointerStr = "Hello"
var pointerList = []string{"Hello back"}
var pointerListPtr = []*string{&pointerStr}
var pointerMap = map[string]string{"response": "Goodbye"}
var pointerMapPtr = map[string]*string{"alternate": &pointerStr}
var pointerTestData = pointerMarshalTestStruct{
Str: &pointerStr,
List: &pointerList,
ListPtr: &pointerListPtr,
Map: &pointerMap,
MapPtr: &pointerMapPtr,
EmptyStr: nil,
EmptyList: nil,
EmptyMap: nil,
}
var pointerTestToml = []byte(`List = ["Hello back"]
ListPtr = ["Hello"]
Str = "Hello"
[Map]
response = "Goodbye"
[MapPtr]
alternate = "Hello"
`)
func TestPointerMarshal(t *testing.T) {
result, err := Marshal(pointerTestData)
if err != nil {
t.Fatal(err)
}
expected := pointerTestToml
if !bytes.Equal(result, expected) {
t.Errorf("Bad pointer marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
}
}
func TestPointerUnmarshal(t *testing.T) {
result := pointerMarshalTestStruct{}
err := Unmarshal(pointerTestToml, &result)
expected := pointerTestData
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(result, expected) {
t.Errorf("Bad pointer unmarshal: expected %v, got %v", expected, result)
}
}
type nestedMarshalTestStruct struct {
String [][]string
//Struct [][]basicMarshalTestSubStruct
StringPtr *[]*[]*string
// StructPtr *[]*[]*basicMarshalTestSubStruct
}
var str1 = "Three"
var str2 = "Four"
var strPtr = []*string{&str1, &str2}
var strPtr2 = []*[]*string{&strPtr}
var nestedTestData = nestedMarshalTestStruct{
String: [][]string{[]string{"Five", "Six"}, []string{"One", "Two"}},
StringPtr: &strPtr2,
}
var nestedTestToml = []byte(`String = [["Five","Six"],["One","Two"]]
StringPtr = [["Three","Four"]]
`)
func TestNestedMarshal(t *testing.T) {
result, err := Marshal(nestedTestData)
if err != nil {
t.Fatal(err)
}
expected := nestedTestToml
if !bytes.Equal(result, expected) {
t.Errorf("Bad nested marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
}
}
func TestNestedUnmarshal(t *testing.T) {
result := nestedMarshalTestStruct{}
err := Unmarshal(nestedTestToml, &result)
expected := nestedTestData
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(result, expected) {
t.Errorf("Bad nested unmarshal: expected %v, got %v", expected, result)
}
}

38
vendor/github.com/pelletier/go-toml/marshal_test.toml сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,38 @@
title = "TOML Marshal Testing"
[basic]
bool = true
date = 1979-05-27T07:32:00Z
float = 123.4
int = 5000
string = "Bite me"
uint = 5001
[basic_lists]
bools = [true,false,true]
dates = [1979-05-27T07:32:00Z,1980-05-27T07:32:00Z]
floats = [12.3,45.6,78.9]
ints = [8001,8001,8002]
strings = ["One","Two","Three"]
uints = [5002,5003]
[basic_map]
one = "one"
two = "two"
[subdoc]
[subdoc.first]
name = "First"
[subdoc.second]
name = "Second"
[[subdoclist]]
name = "List.First"
[[subdoclist]]
name = "List.Second"
[[subdocptrs]]
name = "Second"

84
vendor/golang.org/x/text/encoding/charmap/charmap.go сгенерированный поставляемый
Просмотреть файл

@@ -33,32 +33,32 @@ var (
ISO8859_8I encoding.Encoding = &iso8859_8I ISO8859_8I encoding.Encoding = &iso8859_8I
iso8859_6E = internal.Encoding{ iso8859_6E = internal.Encoding{
ISO8859_6, Encoding: ISO8859_6,
"ISO-8859-6E", Name: "ISO-8859-6E",
identifier.ISO88596E, MIB: identifier.ISO88596E,
} }
iso8859_6I = internal.Encoding{ iso8859_6I = internal.Encoding{
ISO8859_6, Encoding: ISO8859_6,
"ISO-8859-6I", Name: "ISO-8859-6I",
identifier.ISO88596I, MIB: identifier.ISO88596I,
} }
iso8859_8E = internal.Encoding{ iso8859_8E = internal.Encoding{
ISO8859_8, Encoding: ISO8859_8,
"ISO-8859-8E", Name: "ISO-8859-8E",
identifier.ISO88598E, MIB: identifier.ISO88598E,
} }
iso8859_8I = internal.Encoding{ iso8859_8I = internal.Encoding{
ISO8859_8, Encoding: ISO8859_8,
"ISO-8859-8I", Name: "ISO-8859-8I",
identifier.ISO88598I, MIB: identifier.ISO88598I,
} }
) )
// All is a list of all defined encodings in this package. // All is a list of all defined encodings in this package.
var All = listAll var All []encoding.Encoding = listAll
// TODO: implement these encodings, in order of importance. // TODO: implement these encodings, in order of importance.
// ASCII, ISO8859_1: Rather common. Close to Windows 1252. // ASCII, ISO8859_1: Rather common. Close to Windows 1252.
@@ -70,8 +70,8 @@ type utf8Enc struct {
data [3]byte data [3]byte
} }
// charmap describes an 8-bit character set encoding. // Charmap is an 8-bit character set encoding.
type charmap struct { type Charmap struct {
// name is the encoding's name. // name is the encoding's name.
name string name string
// mib is the encoding type of this encoder. // mib is the encoding type of this encoder.
@@ -79,7 +79,7 @@ type charmap struct {
// asciiSuperset states whether the encoding is a superset of ASCII. // asciiSuperset states whether the encoding is a superset of ASCII.
asciiSuperset bool asciiSuperset bool
// low is the lower bound of the encoded byte for a non-ASCII rune. If // low is the lower bound of the encoded byte for a non-ASCII rune. If
// charmap.asciiSuperset is true then this will be 0x80, otherwise 0x00. // Charmap.asciiSuperset is true then this will be 0x80, otherwise 0x00.
low uint8 low uint8
// replacement is the encoded replacement character. // replacement is the encoded replacement character.
replacement byte replacement byte
@@ -91,26 +91,30 @@ type charmap struct {
encode [256]uint32 encode [256]uint32
} }
func (m *charmap) NewDecoder() *encoding.Decoder { // NewDecoder implements the encoding.Encoding interface.
func (m *Charmap) NewDecoder() *encoding.Decoder {
return &encoding.Decoder{Transformer: charmapDecoder{charmap: m}} return &encoding.Decoder{Transformer: charmapDecoder{charmap: m}}
} }
func (m *charmap) NewEncoder() *encoding.Encoder { // NewEncoder implements the encoding.Encoding interface.
func (m *Charmap) NewEncoder() *encoding.Encoder {
return &encoding.Encoder{Transformer: charmapEncoder{charmap: m}} return &encoding.Encoder{Transformer: charmapEncoder{charmap: m}}
} }
func (m *charmap) String() string { // String returns the Charmap's name.
func (m *Charmap) String() string {
return m.name return m.name
} }
func (m *charmap) ID() (mib identifier.MIB, other string) { // ID implements an internal interface.
func (m *Charmap) ID() (mib identifier.MIB, other string) {
return m.mib, "" return m.mib, ""
} }
// charmapDecoder implements transform.Transformer by decoding to UTF-8. // charmapDecoder implements transform.Transformer by decoding to UTF-8.
type charmapDecoder struct { type charmapDecoder struct {
transform.NopResetter transform.NopResetter
charmap *charmap charmap *Charmap
} }
func (m charmapDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { func (m charmapDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
@@ -142,10 +146,22 @@ func (m charmapDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int,
return nDst, nSrc, err return nDst, nSrc, err
} }
// DecodeByte returns the Charmap's rune decoding of the byte b.
func (m *Charmap) DecodeByte(b byte) rune {
switch x := &m.decode[b]; x.len {
case 1:
return rune(x.data[0])
case 2:
return rune(x.data[0]&0x1f)<<6 | rune(x.data[1]&0x3f)
default:
return rune(x.data[0]&0x0f)<<12 | rune(x.data[1]&0x3f)<<6 | rune(x.data[2]&0x3f)
}
}
// charmapEncoder implements transform.Transformer by encoding from UTF-8. // charmapEncoder implements transform.Transformer by encoding from UTF-8.
type charmapEncoder struct { type charmapEncoder struct {
transform.NopResetter transform.NopResetter
charmap *charmap charmap *Charmap
} }
func (m charmapEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { func (m charmapEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
@@ -207,3 +223,27 @@ loop:
} }
return nDst, nSrc, err return nDst, nSrc, err
} }
// EncodeRune returns the Charmap's byte encoding of the rune r. ok is whether
// r is in the Charmap's repertoire. If not, b is set to the Charmap's
// replacement byte. This is often the ASCII substitute character '\x1a'.
func (m *Charmap) EncodeRune(r rune) (b byte, ok bool) {
if r < utf8.RuneSelf && m.asciiSuperset {
return byte(r), true
}
for low, high := int(m.low), 0x100; ; {
if low >= high {
return m.replacement, false
}
mid := (low + high) / 2
got := m.encode[mid]
gotRune := rune(got & (1<<24 - 1))
if gotRune < r {
low = mid + 1
} else if gotRune > r {
high = mid
} else {
return byte(got >> 24), true
}
}
}

53
vendor/golang.org/x/text/encoding/charmap/charmap_test.go сгенерированный поставляемый
Просмотреть файл

@@ -16,9 +16,11 @@ import (
func dec(e encoding.Encoding) (dir string, t transform.Transformer, err error) { func dec(e encoding.Encoding) (dir string, t transform.Transformer, err error) {
return "Decode", e.NewDecoder(), nil return "Decode", e.NewDecoder(), nil
} }
func encASCIISuperset(e encoding.Encoding) (dir string, t transform.Transformer, err error) { func encASCIISuperset(e encoding.Encoding) (dir string, t transform.Transformer, err error) {
return "Encode", e.NewEncoder(), internal.ErrASCIIReplacement return "Encode", e.NewEncoder(), internal.ErrASCIIReplacement
} }
func encEBCDIC(e encoding.Encoding) (dir string, t transform.Transformer, err error) { func encEBCDIC(e encoding.Encoding) (dir string, t transform.Transformer, err error) {
return "Encode", e.NewEncoder(), internal.RepertoireError(0x3f) return "Encode", e.NewEncoder(), internal.RepertoireError(0x3f)
} }
@@ -200,6 +202,57 @@ func TestBasics(t *testing.T) {
} }
} }
var windows1255TestCases = []struct {
b byte
ok bool
r rune
}{
{'\x00', true, '\u0000'},
{'\x1a', true, '\u001a'},
{'\x61', true, '\u0061'},
{'\x7f', true, '\u007f'},
{'\x80', true, '\u20ac'},
{'\x95', true, '\u2022'},
{'\xa0', true, '\u00a0'},
{'\xc0', true, '\u05b0'},
{'\xfc', true, '\ufffd'},
{'\xfd', true, '\u200e'},
{'\xfe', true, '\u200f'},
{'\xff', true, '\ufffd'},
{encoding.ASCIISub, false, '\u0400'},
{encoding.ASCIISub, false, '\u2603'},
{encoding.ASCIISub, false, '\U0001f4a9'},
}
func TestDecodeByte(t *testing.T) {
for _, tc := range windows1255TestCases {
if !tc.ok {
continue
}
got := Windows1255.DecodeByte(tc.b)
want := tc.r
if got != want {
t.Errorf("DecodeByte(%#02x): got %#08x, want %#08x", tc.b, got, want)
}
}
}
func TestEncodeRune(t *testing.T) {
for _, tc := range windows1255TestCases {
// There can be multiple tc.b values that map to tc.r = '\ufffd'.
if tc.r == '\ufffd' {
continue
}
gotB, gotOK := Windows1255.EncodeRune(tc.r)
wantB, wantOK := tc.b, tc.ok
if gotB != wantB || gotOK != wantOK {
t.Errorf("EncodeRune(%#08x): got (%#02x, %t), want (%#02x, %t)", tc.r, gotB, gotOK, wantB, wantOK)
}
}
}
func TestFiles(t *testing.T) { enctest.TestFile(t, Windows1252) } func TestFiles(t *testing.T) { enctest.TestFile(t, Windows1252) }
func BenchmarkEncoding(b *testing.B) { enctest.Benchmark(b, Windows1252) } func BenchmarkEncoding(b *testing.B) { enctest.Benchmark(b, Windows1252) }

4
vendor/golang.org/x/text/encoding/charmap/maketables.go сгенерированный поставляемый
Просмотреть файл

@@ -494,7 +494,7 @@ func main() {
if e.comment != "" { if e.comment != "" {
printf("//\n// %s\n", e.comment) printf("//\n// %s\n", e.comment)
} }
printf("var %s encoding.Encoding = &%s\n\nvar %s = charmap{\nname: %q,\n", printf("var %s *Charmap = &%s\n\nvar %s = Charmap{\nname: %q,\n",
varName, lowerVarName, lowerVarName, e.name) varName, lowerVarName, lowerVarName, e.name)
if mibs[e.mib] { if mibs[e.mib] {
log.Fatalf("MIB type %q declared multiple times.", e.mib) log.Fatalf("MIB type %q declared multiple times.", e.mib)
@@ -540,7 +540,7 @@ func main() {
} }
printf("},\n}\n") printf("},\n}\n")
// Add an estimate of the size of a single charmap{} struct value, which // Add an estimate of the size of a single Charmap{} struct value, which
// includes two 256 elem arrays of 4 bytes and some extra fields, which // includes two 256 elem arrays of 4 bytes and some extra fields, which
// align to 3 uint64s on 64-bit architectures. // align to 3 uint64s on 64-bit architectures.
w.Size += 2*4*256 + 3*8 w.Size += 2*4*256 + 3*8

190
vendor/golang.org/x/text/encoding/charmap/tables.go сгенерированный поставляемый
Просмотреть файл

@@ -1,4 +1,4 @@
// This file was generated by go generate; DO NOT EDIT // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
package charmap package charmap
@@ -8,9 +8,9 @@ import (
) )
// CodePage037 is the IBM Code Page 037 encoding. // CodePage037 is the IBM Code Page 037 encoding.
var CodePage037 encoding.Encoding = &codePage037 var CodePage037 *Charmap = &codePage037
var codePage037 = charmap{ var codePage037 = Charmap{
name: "IBM Code Page 037", name: "IBM Code Page 037",
mib: identifier.IBM037, mib: identifier.IBM037,
asciiSuperset: false, asciiSuperset: false,
@@ -183,9 +183,9 @@ var codePage037 = charmap{
} }
// CodePage437 is the IBM Code Page 437 encoding. // CodePage437 is the IBM Code Page 437 encoding.
var CodePage437 encoding.Encoding = &codePage437 var CodePage437 *Charmap = &codePage437
var codePage437 = charmap{ var codePage437 = Charmap{
name: "IBM Code Page 437", name: "IBM Code Page 437",
mib: identifier.PC8CodePage437, mib: identifier.PC8CodePage437,
asciiSuperset: true, asciiSuperset: true,
@@ -358,9 +358,9 @@ var codePage437 = charmap{
} }
// CodePage850 is the IBM Code Page 850 encoding. // CodePage850 is the IBM Code Page 850 encoding.
var CodePage850 encoding.Encoding = &codePage850 var CodePage850 *Charmap = &codePage850
var codePage850 = charmap{ var codePage850 = Charmap{
name: "IBM Code Page 850", name: "IBM Code Page 850",
mib: identifier.PC850Multilingual, mib: identifier.PC850Multilingual,
asciiSuperset: true, asciiSuperset: true,
@@ -533,9 +533,9 @@ var codePage850 = charmap{
} }
// CodePage852 is the IBM Code Page 852 encoding. // CodePage852 is the IBM Code Page 852 encoding.
var CodePage852 encoding.Encoding = &codePage852 var CodePage852 *Charmap = &codePage852
var codePage852 = charmap{ var codePage852 = Charmap{
name: "IBM Code Page 852", name: "IBM Code Page 852",
mib: identifier.PCp852, mib: identifier.PCp852,
asciiSuperset: true, asciiSuperset: true,
@@ -708,9 +708,9 @@ var codePage852 = charmap{
} }
// CodePage855 is the IBM Code Page 855 encoding. // CodePage855 is the IBM Code Page 855 encoding.
var CodePage855 encoding.Encoding = &codePage855 var CodePage855 *Charmap = &codePage855
var codePage855 = charmap{ var codePage855 = Charmap{
name: "IBM Code Page 855", name: "IBM Code Page 855",
mib: identifier.IBM855, mib: identifier.IBM855,
asciiSuperset: true, asciiSuperset: true,
@@ -883,9 +883,9 @@ var codePage855 = charmap{
} }
// CodePage858 is the Windows Code Page 858 encoding. // CodePage858 is the Windows Code Page 858 encoding.
var CodePage858 encoding.Encoding = &codePage858 var CodePage858 *Charmap = &codePage858
var codePage858 = charmap{ var codePage858 = Charmap{
name: "Windows Code Page 858", name: "Windows Code Page 858",
mib: identifier.IBM00858, mib: identifier.IBM00858,
asciiSuperset: true, asciiSuperset: true,
@@ -1058,9 +1058,9 @@ var codePage858 = charmap{
} }
// CodePage860 is the IBM Code Page 860 encoding. // CodePage860 is the IBM Code Page 860 encoding.
var CodePage860 encoding.Encoding = &codePage860 var CodePage860 *Charmap = &codePage860
var codePage860 = charmap{ var codePage860 = Charmap{
name: "IBM Code Page 860", name: "IBM Code Page 860",
mib: identifier.IBM860, mib: identifier.IBM860,
asciiSuperset: true, asciiSuperset: true,
@@ -1233,9 +1233,9 @@ var codePage860 = charmap{
} }
// CodePage862 is the IBM Code Page 862 encoding. // CodePage862 is the IBM Code Page 862 encoding.
var CodePage862 encoding.Encoding = &codePage862 var CodePage862 *Charmap = &codePage862
var codePage862 = charmap{ var codePage862 = Charmap{
name: "IBM Code Page 862", name: "IBM Code Page 862",
mib: identifier.PC862LatinHebrew, mib: identifier.PC862LatinHebrew,
asciiSuperset: true, asciiSuperset: true,
@@ -1408,9 +1408,9 @@ var codePage862 = charmap{
} }
// CodePage863 is the IBM Code Page 863 encoding. // CodePage863 is the IBM Code Page 863 encoding.
var CodePage863 encoding.Encoding = &codePage863 var CodePage863 *Charmap = &codePage863
var codePage863 = charmap{ var codePage863 = Charmap{
name: "IBM Code Page 863", name: "IBM Code Page 863",
mib: identifier.IBM863, mib: identifier.IBM863,
asciiSuperset: true, asciiSuperset: true,
@@ -1583,9 +1583,9 @@ var codePage863 = charmap{
} }
// CodePage865 is the IBM Code Page 865 encoding. // CodePage865 is the IBM Code Page 865 encoding.
var CodePage865 encoding.Encoding = &codePage865 var CodePage865 *Charmap = &codePage865
var codePage865 = charmap{ var codePage865 = Charmap{
name: "IBM Code Page 865", name: "IBM Code Page 865",
mib: identifier.IBM865, mib: identifier.IBM865,
asciiSuperset: true, asciiSuperset: true,
@@ -1758,9 +1758,9 @@ var codePage865 = charmap{
} }
// CodePage866 is the IBM Code Page 866 encoding. // CodePage866 is the IBM Code Page 866 encoding.
var CodePage866 encoding.Encoding = &codePage866 var CodePage866 *Charmap = &codePage866
var codePage866 = charmap{ var codePage866 = Charmap{
name: "IBM Code Page 866", name: "IBM Code Page 866",
mib: identifier.IBM866, mib: identifier.IBM866,
asciiSuperset: true, asciiSuperset: true,
@@ -1933,9 +1933,9 @@ var codePage866 = charmap{
} }
// CodePage1047 is the IBM Code Page 1047 encoding. // CodePage1047 is the IBM Code Page 1047 encoding.
var CodePage1047 encoding.Encoding = &codePage1047 var CodePage1047 *Charmap = &codePage1047
var codePage1047 = charmap{ var codePage1047 = Charmap{
name: "IBM Code Page 1047", name: "IBM Code Page 1047",
mib: identifier.IBM1047, mib: identifier.IBM1047,
asciiSuperset: false, asciiSuperset: false,
@@ -2108,9 +2108,9 @@ var codePage1047 = charmap{
} }
// CodePage1140 is the IBM Code Page 1140 encoding. // CodePage1140 is the IBM Code Page 1140 encoding.
var CodePage1140 encoding.Encoding = &codePage1140 var CodePage1140 *Charmap = &codePage1140
var codePage1140 = charmap{ var codePage1140 = Charmap{
name: "IBM Code Page 1140", name: "IBM Code Page 1140",
mib: identifier.IBM01140, mib: identifier.IBM01140,
asciiSuperset: false, asciiSuperset: false,
@@ -2283,9 +2283,9 @@ var codePage1140 = charmap{
} }
// ISO8859_1 is the ISO 8859-1 encoding. // ISO8859_1 is the ISO 8859-1 encoding.
var ISO8859_1 encoding.Encoding = &iso8859_1 var ISO8859_1 *Charmap = &iso8859_1
var iso8859_1 = charmap{ var iso8859_1 = Charmap{
name: "ISO 8859-1", name: "ISO 8859-1",
mib: identifier.ISOLatin1, mib: identifier.ISOLatin1,
asciiSuperset: true, asciiSuperset: true,
@@ -2458,9 +2458,9 @@ var iso8859_1 = charmap{
} }
// ISO8859_2 is the ISO 8859-2 encoding. // ISO8859_2 is the ISO 8859-2 encoding.
var ISO8859_2 encoding.Encoding = &iso8859_2 var ISO8859_2 *Charmap = &iso8859_2
var iso8859_2 = charmap{ var iso8859_2 = Charmap{
name: "ISO 8859-2", name: "ISO 8859-2",
mib: identifier.ISOLatin2, mib: identifier.ISOLatin2,
asciiSuperset: true, asciiSuperset: true,
@@ -2633,9 +2633,9 @@ var iso8859_2 = charmap{
} }
// ISO8859_3 is the ISO 8859-3 encoding. // ISO8859_3 is the ISO 8859-3 encoding.
var ISO8859_3 encoding.Encoding = &iso8859_3 var ISO8859_3 *Charmap = &iso8859_3
var iso8859_3 = charmap{ var iso8859_3 = Charmap{
name: "ISO 8859-3", name: "ISO 8859-3",
mib: identifier.ISOLatin3, mib: identifier.ISOLatin3,
asciiSuperset: true, asciiSuperset: true,
@@ -2808,9 +2808,9 @@ var iso8859_3 = charmap{
} }
// ISO8859_4 is the ISO 8859-4 encoding. // ISO8859_4 is the ISO 8859-4 encoding.
var ISO8859_4 encoding.Encoding = &iso8859_4 var ISO8859_4 *Charmap = &iso8859_4
var iso8859_4 = charmap{ var iso8859_4 = Charmap{
name: "ISO 8859-4", name: "ISO 8859-4",
mib: identifier.ISOLatin4, mib: identifier.ISOLatin4,
asciiSuperset: true, asciiSuperset: true,
@@ -2983,9 +2983,9 @@ var iso8859_4 = charmap{
} }
// ISO8859_5 is the ISO 8859-5 encoding. // ISO8859_5 is the ISO 8859-5 encoding.
var ISO8859_5 encoding.Encoding = &iso8859_5 var ISO8859_5 *Charmap = &iso8859_5
var iso8859_5 = charmap{ var iso8859_5 = Charmap{
name: "ISO 8859-5", name: "ISO 8859-5",
mib: identifier.ISOLatinCyrillic, mib: identifier.ISOLatinCyrillic,
asciiSuperset: true, asciiSuperset: true,
@@ -3158,9 +3158,9 @@ var iso8859_5 = charmap{
} }
// ISO8859_6 is the ISO 8859-6 encoding. // ISO8859_6 is the ISO 8859-6 encoding.
var ISO8859_6 encoding.Encoding = &iso8859_6 var ISO8859_6 *Charmap = &iso8859_6
var iso8859_6 = charmap{ var iso8859_6 = Charmap{
name: "ISO 8859-6", name: "ISO 8859-6",
mib: identifier.ISOLatinArabic, mib: identifier.ISOLatinArabic,
asciiSuperset: true, asciiSuperset: true,
@@ -3333,9 +3333,9 @@ var iso8859_6 = charmap{
} }
// ISO8859_7 is the ISO 8859-7 encoding. // ISO8859_7 is the ISO 8859-7 encoding.
var ISO8859_7 encoding.Encoding = &iso8859_7 var ISO8859_7 *Charmap = &iso8859_7
var iso8859_7 = charmap{ var iso8859_7 = Charmap{
name: "ISO 8859-7", name: "ISO 8859-7",
mib: identifier.ISOLatinGreek, mib: identifier.ISOLatinGreek,
asciiSuperset: true, asciiSuperset: true,
@@ -3508,9 +3508,9 @@ var iso8859_7 = charmap{
} }
// ISO8859_8 is the ISO 8859-8 encoding. // ISO8859_8 is the ISO 8859-8 encoding.
var ISO8859_8 encoding.Encoding = &iso8859_8 var ISO8859_8 *Charmap = &iso8859_8
var iso8859_8 = charmap{ var iso8859_8 = Charmap{
name: "ISO 8859-8", name: "ISO 8859-8",
mib: identifier.ISOLatinHebrew, mib: identifier.ISOLatinHebrew,
asciiSuperset: true, asciiSuperset: true,
@@ -3683,9 +3683,9 @@ var iso8859_8 = charmap{
} }
// ISO8859_9 is the ISO 8859-9 encoding. // ISO8859_9 is the ISO 8859-9 encoding.
var ISO8859_9 encoding.Encoding = &iso8859_9 var ISO8859_9 *Charmap = &iso8859_9
var iso8859_9 = charmap{ var iso8859_9 = Charmap{
name: "ISO 8859-9", name: "ISO 8859-9",
mib: identifier.ISOLatin5, mib: identifier.ISOLatin5,
asciiSuperset: true, asciiSuperset: true,
@@ -3858,9 +3858,9 @@ var iso8859_9 = charmap{
} }
// ISO8859_10 is the ISO 8859-10 encoding. // ISO8859_10 is the ISO 8859-10 encoding.
var ISO8859_10 encoding.Encoding = &iso8859_10 var ISO8859_10 *Charmap = &iso8859_10
var iso8859_10 = charmap{ var iso8859_10 = Charmap{
name: "ISO 8859-10", name: "ISO 8859-10",
mib: identifier.ISOLatin6, mib: identifier.ISOLatin6,
asciiSuperset: true, asciiSuperset: true,
@@ -4033,9 +4033,9 @@ var iso8859_10 = charmap{
} }
// ISO8859_13 is the ISO 8859-13 encoding. // ISO8859_13 is the ISO 8859-13 encoding.
var ISO8859_13 encoding.Encoding = &iso8859_13 var ISO8859_13 *Charmap = &iso8859_13
var iso8859_13 = charmap{ var iso8859_13 = Charmap{
name: "ISO 8859-13", name: "ISO 8859-13",
mib: identifier.ISO885913, mib: identifier.ISO885913,
asciiSuperset: true, asciiSuperset: true,
@@ -4208,9 +4208,9 @@ var iso8859_13 = charmap{
} }
// ISO8859_14 is the ISO 8859-14 encoding. // ISO8859_14 is the ISO 8859-14 encoding.
var ISO8859_14 encoding.Encoding = &iso8859_14 var ISO8859_14 *Charmap = &iso8859_14
var iso8859_14 = charmap{ var iso8859_14 = Charmap{
name: "ISO 8859-14", name: "ISO 8859-14",
mib: identifier.ISO885914, mib: identifier.ISO885914,
asciiSuperset: true, asciiSuperset: true,
@@ -4383,9 +4383,9 @@ var iso8859_14 = charmap{
} }
// ISO8859_15 is the ISO 8859-15 encoding. // ISO8859_15 is the ISO 8859-15 encoding.
var ISO8859_15 encoding.Encoding = &iso8859_15 var ISO8859_15 *Charmap = &iso8859_15
var iso8859_15 = charmap{ var iso8859_15 = Charmap{
name: "ISO 8859-15", name: "ISO 8859-15",
mib: identifier.ISO885915, mib: identifier.ISO885915,
asciiSuperset: true, asciiSuperset: true,
@@ -4558,9 +4558,9 @@ var iso8859_15 = charmap{
} }
// ISO8859_16 is the ISO 8859-16 encoding. // ISO8859_16 is the ISO 8859-16 encoding.
var ISO8859_16 encoding.Encoding = &iso8859_16 var ISO8859_16 *Charmap = &iso8859_16
var iso8859_16 = charmap{ var iso8859_16 = Charmap{
name: "ISO 8859-16", name: "ISO 8859-16",
mib: identifier.ISO885916, mib: identifier.ISO885916,
asciiSuperset: true, asciiSuperset: true,
@@ -4733,9 +4733,9 @@ var iso8859_16 = charmap{
} }
// KOI8R is the KOI8-R encoding. // KOI8R is the KOI8-R encoding.
var KOI8R encoding.Encoding = &koi8R var KOI8R *Charmap = &koi8R
var koi8R = charmap{ var koi8R = Charmap{
name: "KOI8-R", name: "KOI8-R",
mib: identifier.KOI8R, mib: identifier.KOI8R,
asciiSuperset: true, asciiSuperset: true,
@@ -4908,9 +4908,9 @@ var koi8R = charmap{
} }
// KOI8U is the KOI8-U encoding. // KOI8U is the KOI8-U encoding.
var KOI8U encoding.Encoding = &koi8U var KOI8U *Charmap = &koi8U
var koi8U = charmap{ var koi8U = Charmap{
name: "KOI8-U", name: "KOI8-U",
mib: identifier.KOI8U, mib: identifier.KOI8U,
asciiSuperset: true, asciiSuperset: true,
@@ -5083,9 +5083,9 @@ var koi8U = charmap{
} }
// Macintosh is the Macintosh encoding. // Macintosh is the Macintosh encoding.
var Macintosh encoding.Encoding = &macintosh var Macintosh *Charmap = &macintosh
var macintosh = charmap{ var macintosh = Charmap{
name: "Macintosh", name: "Macintosh",
mib: identifier.Macintosh, mib: identifier.Macintosh,
asciiSuperset: true, asciiSuperset: true,
@@ -5258,9 +5258,9 @@ var macintosh = charmap{
} }
// MacintoshCyrillic is the Macintosh Cyrillic encoding. // MacintoshCyrillic is the Macintosh Cyrillic encoding.
var MacintoshCyrillic encoding.Encoding = &macintoshCyrillic var MacintoshCyrillic *Charmap = &macintoshCyrillic
var macintoshCyrillic = charmap{ var macintoshCyrillic = Charmap{
name: "Macintosh Cyrillic", name: "Macintosh Cyrillic",
mib: identifier.MacintoshCyrillic, mib: identifier.MacintoshCyrillic,
asciiSuperset: true, asciiSuperset: true,
@@ -5433,9 +5433,9 @@ var macintoshCyrillic = charmap{
} }
// Windows874 is the Windows 874 encoding. // Windows874 is the Windows 874 encoding.
var Windows874 encoding.Encoding = &windows874 var Windows874 *Charmap = &windows874
var windows874 = charmap{ var windows874 = Charmap{
name: "Windows 874", name: "Windows 874",
mib: identifier.Windows874, mib: identifier.Windows874,
asciiSuperset: true, asciiSuperset: true,
@@ -5608,9 +5608,9 @@ var windows874 = charmap{
} }
// Windows1250 is the Windows 1250 encoding. // Windows1250 is the Windows 1250 encoding.
var Windows1250 encoding.Encoding = &windows1250 var Windows1250 *Charmap = &windows1250
var windows1250 = charmap{ var windows1250 = Charmap{
name: "Windows 1250", name: "Windows 1250",
mib: identifier.Windows1250, mib: identifier.Windows1250,
asciiSuperset: true, asciiSuperset: true,
@@ -5783,9 +5783,9 @@ var windows1250 = charmap{
} }
// Windows1251 is the Windows 1251 encoding. // Windows1251 is the Windows 1251 encoding.
var Windows1251 encoding.Encoding = &windows1251 var Windows1251 *Charmap = &windows1251
var windows1251 = charmap{ var windows1251 = Charmap{
name: "Windows 1251", name: "Windows 1251",
mib: identifier.Windows1251, mib: identifier.Windows1251,
asciiSuperset: true, asciiSuperset: true,
@@ -5958,9 +5958,9 @@ var windows1251 = charmap{
} }
// Windows1252 is the Windows 1252 encoding. // Windows1252 is the Windows 1252 encoding.
var Windows1252 encoding.Encoding = &windows1252 var Windows1252 *Charmap = &windows1252
var windows1252 = charmap{ var windows1252 = Charmap{
name: "Windows 1252", name: "Windows 1252",
mib: identifier.Windows1252, mib: identifier.Windows1252,
asciiSuperset: true, asciiSuperset: true,
@@ -6133,9 +6133,9 @@ var windows1252 = charmap{
} }
// Windows1253 is the Windows 1253 encoding. // Windows1253 is the Windows 1253 encoding.
var Windows1253 encoding.Encoding = &windows1253 var Windows1253 *Charmap = &windows1253
var windows1253 = charmap{ var windows1253 = Charmap{
name: "Windows 1253", name: "Windows 1253",
mib: identifier.Windows1253, mib: identifier.Windows1253,
asciiSuperset: true, asciiSuperset: true,
@@ -6308,9 +6308,9 @@ var windows1253 = charmap{
} }
// Windows1254 is the Windows 1254 encoding. // Windows1254 is the Windows 1254 encoding.
var Windows1254 encoding.Encoding = &windows1254 var Windows1254 *Charmap = &windows1254
var windows1254 = charmap{ var windows1254 = Charmap{
name: "Windows 1254", name: "Windows 1254",
mib: identifier.Windows1254, mib: identifier.Windows1254,
asciiSuperset: true, asciiSuperset: true,
@@ -6483,9 +6483,9 @@ var windows1254 = charmap{
} }
// Windows1255 is the Windows 1255 encoding. // Windows1255 is the Windows 1255 encoding.
var Windows1255 encoding.Encoding = &windows1255 var Windows1255 *Charmap = &windows1255
var windows1255 = charmap{ var windows1255 = Charmap{
name: "Windows 1255", name: "Windows 1255",
mib: identifier.Windows1255, mib: identifier.Windows1255,
asciiSuperset: true, asciiSuperset: true,
@@ -6593,7 +6593,7 @@ var windows1255 = charmap{
{2, [3]byte{0xd6, 0xb4, 0x00}}, {2, [3]byte{0xd6, 0xb5, 0x00}}, {2, [3]byte{0xd6, 0xb4, 0x00}}, {2, [3]byte{0xd6, 0xb5, 0x00}},
{2, [3]byte{0xd6, 0xb6, 0x00}}, {2, [3]byte{0xd6, 0xb7, 0x00}}, {2, [3]byte{0xd6, 0xb6, 0x00}}, {2, [3]byte{0xd6, 0xb7, 0x00}},
{2, [3]byte{0xd6, 0xb8, 0x00}}, {2, [3]byte{0xd6, 0xb9, 0x00}}, {2, [3]byte{0xd6, 0xb8, 0x00}}, {2, [3]byte{0xd6, 0xb9, 0x00}},
{3, [3]byte{0xef, 0xbf, 0xbd}}, {2, [3]byte{0xd6, 0xbb, 0x00}}, {2, [3]byte{0xd6, 0xba, 0x00}}, {2, [3]byte{0xd6, 0xbb, 0x00}},
{2, [3]byte{0xd6, 0xbc, 0x00}}, {2, [3]byte{0xd6, 0xbd, 0x00}}, {2, [3]byte{0xd6, 0xbc, 0x00}}, {2, [3]byte{0xd6, 0xbd, 0x00}},
{2, [3]byte{0xd6, 0xbe, 0x00}}, {2, [3]byte{0xd6, 0xbf, 0x00}}, {2, [3]byte{0xd6, 0xbe, 0x00}}, {2, [3]byte{0xd6, 0xbf, 0x00}},
{2, [3]byte{0xd7, 0x80, 0x00}}, {2, [3]byte{0xd7, 0x81, 0x00}}, {2, [3]byte{0xd7, 0x80, 0x00}}, {2, [3]byte{0xd7, 0x81, 0x00}},
@@ -6643,24 +6643,24 @@ var windows1255 = charmap{
0xb20000b2, 0xb30000b3, 0xb40000b4, 0xb50000b5, 0xb60000b6, 0xb70000b7, 0xb80000b8, 0xb90000b9, 0xb20000b2, 0xb30000b3, 0xb40000b4, 0xb50000b5, 0xb60000b6, 0xb70000b7, 0xb80000b8, 0xb90000b9,
0xbb0000bb, 0xbc0000bc, 0xbd0000bd, 0xbe0000be, 0xbf0000bf, 0xaa0000d7, 0xba0000f7, 0x83000192, 0xbb0000bb, 0xbc0000bc, 0xbd0000bd, 0xbe0000be, 0xbf0000bf, 0xaa0000d7, 0xba0000f7, 0x83000192,
0x880002c6, 0x980002dc, 0xc00005b0, 0xc10005b1, 0xc20005b2, 0xc30005b3, 0xc40005b4, 0xc50005b5, 0x880002c6, 0x980002dc, 0xc00005b0, 0xc10005b1, 0xc20005b2, 0xc30005b3, 0xc40005b4, 0xc50005b5,
0xc60005b6, 0xc70005b7, 0xc80005b8, 0xc90005b9, 0xcb0005bb, 0xcc0005bc, 0xcd0005bd, 0xce0005be, 0xc60005b6, 0xc70005b7, 0xc80005b8, 0xc90005b9, 0xca0005ba, 0xcb0005bb, 0xcc0005bc, 0xcd0005bd,
0xcf0005bf, 0xd00005c0, 0xd10005c1, 0xd20005c2, 0xd30005c3, 0xe00005d0, 0xe10005d1, 0xe20005d2, 0xce0005be, 0xcf0005bf, 0xd00005c0, 0xd10005c1, 0xd20005c2, 0xd30005c3, 0xe00005d0, 0xe10005d1,
0xe30005d3, 0xe40005d4, 0xe50005d5, 0xe60005d6, 0xe70005d7, 0xe80005d8, 0xe90005d9, 0xea0005da, 0xe20005d2, 0xe30005d3, 0xe40005d4, 0xe50005d5, 0xe60005d6, 0xe70005d7, 0xe80005d8, 0xe90005d9,
0xeb0005db, 0xec0005dc, 0xed0005dd, 0xee0005de, 0xef0005df, 0xf00005e0, 0xf10005e1, 0xf20005e2, 0xea0005da, 0xeb0005db, 0xec0005dc, 0xed0005dd, 0xee0005de, 0xef0005df, 0xf00005e0, 0xf10005e1,
0xf30005e3, 0xf40005e4, 0xf50005e5, 0xf60005e6, 0xf70005e7, 0xf80005e8, 0xf90005e9, 0xfa0005ea, 0xf20005e2, 0xf30005e3, 0xf40005e4, 0xf50005e5, 0xf60005e6, 0xf70005e7, 0xf80005e8, 0xf90005e9,
0xd40005f0, 0xd50005f1, 0xd60005f2, 0xd70005f3, 0xd80005f4, 0xfd00200e, 0xfe00200f, 0x96002013, 0xfa0005ea, 0xd40005f0, 0xd50005f1, 0xd60005f2, 0xd70005f3, 0xd80005f4, 0xfd00200e, 0xfe00200f,
0x97002014, 0x91002018, 0x92002019, 0x8200201a, 0x9300201c, 0x9400201d, 0x8400201e, 0x86002020, 0x96002013, 0x97002014, 0x91002018, 0x92002019, 0x8200201a, 0x9300201c, 0x9400201d, 0x8400201e,
0x87002021, 0x95002022, 0x85002026, 0x89002030, 0x8b002039, 0x9b00203a, 0xa40020aa, 0x800020ac, 0x86002020, 0x87002021, 0x95002022, 0x85002026, 0x89002030, 0x8b002039, 0x9b00203a, 0xa40020aa,
0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x800020ac, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122,
0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122,
0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122, 0x99002122,
}, },
} }
// Windows1256 is the Windows 1256 encoding. // Windows1256 is the Windows 1256 encoding.
var Windows1256 encoding.Encoding = &windows1256 var Windows1256 *Charmap = &windows1256
var windows1256 = charmap{ var windows1256 = Charmap{
name: "Windows 1256", name: "Windows 1256",
mib: identifier.Windows1256, mib: identifier.Windows1256,
asciiSuperset: true, asciiSuperset: true,
@@ -6833,9 +6833,9 @@ var windows1256 = charmap{
} }
// Windows1257 is the Windows 1257 encoding. // Windows1257 is the Windows 1257 encoding.
var Windows1257 encoding.Encoding = &windows1257 var Windows1257 *Charmap = &windows1257
var windows1257 = charmap{ var windows1257 = Charmap{
name: "Windows 1257", name: "Windows 1257",
mib: identifier.Windows1257, mib: identifier.Windows1257,
asciiSuperset: true, asciiSuperset: true,
@@ -7008,9 +7008,9 @@ var windows1257 = charmap{
} }
// Windows1258 is the Windows 1258 encoding. // Windows1258 is the Windows 1258 encoding.
var Windows1258 encoding.Encoding = &windows1258 var Windows1258 *Charmap = &windows1258
var windows1258 = charmap{ var windows1258 = Charmap{
name: "Windows 1258", name: "Windows 1258",
mib: identifier.Windows1258, mib: identifier.Windows1258,
asciiSuperset: true, asciiSuperset: true,
@@ -7185,9 +7185,9 @@ var windows1258 = charmap{
// XUserDefined is the X-User-Defined encoding. // XUserDefined is the X-User-Defined encoding.
// //
// It is defined at http://encoding.spec.whatwg.org/#x-user-defined // It is defined at http://encoding.spec.whatwg.org/#x-user-defined
var XUserDefined encoding.Encoding = &xUserDefined var XUserDefined *Charmap = &xUserDefined
var xUserDefined = charmap{ var xUserDefined = Charmap{
name: "X-User-Defined", name: "X-User-Defined",
mib: identifier.XUserDefined, mib: identifier.XUserDefined,
asciiSuperset: true, asciiSuperset: true,

2
vendor/golang.org/x/text/internal/number/gen.go сгенерированный поставляемый
Просмотреть файл

@@ -364,7 +364,7 @@ func genFormats(w *gen.CodeWriter, data *cldr.CLDR) {
} }
// Fill the first slot with a dummy so we can identify unspecified tags. // Fill the first slot with a dummy so we can identify unspecified tags.
formats := []number.Format{{}} formats := []number.Pattern{{}}
patterns := map[string]int{} patterns := map[string]int{}
// TODO: It would be possible to eliminate two of these slices by having // TODO: It would be possible to eliminate two of these slices by having

2
vendor/golang.org/x/text/internal/number/number.go сгенерированный поставляемый
Просмотреть файл

@@ -136,7 +136,7 @@ func (n Info) Symbol(t SymbolType) string {
return symData.Elem(int(symIndex[n.symIndex][t])) return symData.Elem(int(symIndex[n.symIndex][t]))
} }
func formatForLang(t language.Tag, index []byte) *Format { func formatForLang(t language.Tag, index []byte) *Pattern {
for ; ; t = t.Parent() { for ; ; t = t.Parent() {
if x, ok := language.CompactIndex(t); ok { if x, ok := language.CompactIndex(t); ok {
return &formats[index[x]] return &formats[index[x]]

24
vendor/golang.org/x/text/internal/number/pattern.go сгенерированный поставляемый
Просмотреть файл

@@ -31,14 +31,14 @@ import (
// TODO: replace special characters in affixes (-, +, ¤) with control codes. // TODO: replace special characters in affixes (-, +, ¤) with control codes.
// Format holds information for formatting numbers. It is designed to hold // Pattern holds information for formatting numbers. It is designed to hold
// information from CLDR number patterns. // information from CLDR number patterns.
// //
// This pattern is precompiled for all patterns for all languages. Even though // This pattern is precompiled for all patterns for all languages. Even though
// the number of patterns is not very large, we want to keep this small. // the number of patterns is not very large, we want to keep this small.
// //
// This type is only intended for internal use. // This type is only intended for internal use.
type Format struct { type Pattern struct {
// TODO: this struct can be packed a lot better than it is now. Should be // TODO: this struct can be packed a lot better than it is now. Should be
// possible to make it 32 bytes. // possible to make it 32 bytes.
@@ -53,7 +53,7 @@ type Format struct {
FormatWidth uint16 FormatWidth uint16
GroupingSize [2]uint8 GroupingSize [2]uint8
Flags FormatFlag Flags PatternFlag
// Number of digits. // Number of digits.
MinIntegerDigits uint8 MinIntegerDigits uint8
@@ -65,11 +65,11 @@ type Format struct {
MinExponentDigits uint8 MinExponentDigits uint8
} }
// A FormatFlag is a bit mask for the flag field of a Format. // A PatternFlag is a bit mask for the flag field of a Format.
type FormatFlag uint8 type PatternFlag uint8
const ( const (
AlwaysSign FormatFlag = 1 << iota AlwaysSign PatternFlag = 1 << iota
AlwaysExpSign AlwaysExpSign
AlwaysDecimalSeparator AlwaysDecimalSeparator
ParenthesisForNegative // Common pattern. Saves space. ParenthesisForNegative // Common pattern. Saves space.
@@ -85,7 +85,7 @@ const (
) )
type parser struct { type parser struct {
*Format *Pattern
leadingSharps int leadingSharps int
@@ -126,8 +126,8 @@ var (
// ParsePattern extracts formatting information from a CLDR number pattern. // ParsePattern extracts formatting information from a CLDR number pattern.
// //
// See http://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns. // See http://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns.
func ParsePattern(s string) (f *Format, err error) { func ParsePattern(s string) (f *Pattern, err error) {
p := parser{Format: &Format{}} p := parser{Pattern: &Pattern{}}
s = p.parseSubPattern(s) s = p.parseSubPattern(s)
@@ -137,7 +137,7 @@ func ParsePattern(s string) (f *Format, err error) {
p.setError(errors.New("format: error parsing first sub pattern")) p.setError(errors.New("format: error parsing first sub pattern"))
return nil, p.err return nil, p.err
} }
neg := parser{Format: &Format{}} // just for extracting the affixes. neg := parser{Pattern: &Pattern{}} // just for extracting the affixes.
s = neg.parseSubPattern(s[len(";"):]) s = neg.parseSubPattern(s[len(";"):])
p.NegOffset = uint16(len(p.buf)) p.NegOffset = uint16(len(p.buf))
p.buf = append(p.buf, neg.buf...) p.buf = append(p.buf, neg.buf...)
@@ -154,7 +154,7 @@ func ParsePattern(s string) (f *Format, err error) {
} else { } else {
p.Affix = affix p.Affix = affix
} }
return p.Format, nil return p.Pattern, nil
} }
func (p *parser) parseSubPattern(s string) string { func (p *parser) parseSubPattern(s string) string {
@@ -170,7 +170,7 @@ func (p *parser) parseSubPattern(s string) string {
return s return s
} }
func (p *parser) parsePad(s string, f FormatFlag) (tail string) { func (p *parser) parsePad(s string, f PatternFlag) (tail string) {
if len(s) >= 2 && s[0] == '*' { if len(s) >= 2 && s[0] == '*' {
r, sz := utf8.DecodeRuneInString(s[1:]) r, sz := utf8.DecodeRuneInString(s[1:])
if p.PadRune != 0 { if p.PadRune != 0 {

64
vendor/golang.org/x/text/internal/number/pattern_test.go сгенерированный поставляемый
Просмотреть файл

@@ -12,48 +12,48 @@ import (
var testCases = []struct { var testCases = []struct {
pat string pat string
want *Format want *Pattern
}{{ }{{
"#", "#",
&Format{ &Pattern{
FormatWidth: 1, FormatWidth: 1,
// TODO: Should MinIntegerDigits be 1? // TODO: Should MinIntegerDigits be 1?
}, },
}, { }, {
"0", "0",
&Format{ &Pattern{
FormatWidth: 1, FormatWidth: 1,
MinIntegerDigits: 1, MinIntegerDigits: 1,
}, },
}, { }, {
"0000", "0000",
&Format{ &Pattern{
FormatWidth: 4, FormatWidth: 4,
MinIntegerDigits: 4, MinIntegerDigits: 4,
}, },
}, { }, {
".#", ".#",
&Format{ &Pattern{
FormatWidth: 2, FormatWidth: 2,
MaxFractionDigits: 1, MaxFractionDigits: 1,
}, },
}, { }, {
"#0.###", "#0.###",
&Format{ &Pattern{
FormatWidth: 6, FormatWidth: 6,
MinIntegerDigits: 1, MinIntegerDigits: 1,
MaxFractionDigits: 3, MaxFractionDigits: 3,
}, },
}, { }, {
"#0.######", "#0.######",
&Format{ &Pattern{
FormatWidth: 9, FormatWidth: 9,
MinIntegerDigits: 1, MinIntegerDigits: 1,
MaxFractionDigits: 6, MaxFractionDigits: 6,
}, },
}, { }, {
"#,##0.###", "#,##0.###",
&Format{ &Pattern{
FormatWidth: 9, FormatWidth: 9,
GroupingSize: [2]uint8{3, 0}, GroupingSize: [2]uint8{3, 0},
MinIntegerDigits: 1, MinIntegerDigits: 1,
@@ -61,7 +61,7 @@ var testCases = []struct {
}, },
}, { }, {
"#,##,##0.###", "#,##,##0.###",
&Format{ &Pattern{
FormatWidth: 12, FormatWidth: 12,
GroupingSize: [2]uint8{3, 2}, GroupingSize: [2]uint8{3, 2},
MinIntegerDigits: 1, MinIntegerDigits: 1,
@@ -70,7 +70,7 @@ var testCases = []struct {
}, { }, {
// Ignore additional separators. // Ignore additional separators.
"#,####,##,##0.###", "#,####,##,##0.###",
&Format{ &Pattern{
FormatWidth: 17, FormatWidth: 17,
GroupingSize: [2]uint8{3, 2}, GroupingSize: [2]uint8{3, 2},
MinIntegerDigits: 1, MinIntegerDigits: 1,
@@ -78,21 +78,21 @@ var testCases = []struct {
}, },
}, { }, {
"#E0", "#E0",
&Format{ &Pattern{
FormatWidth: 3, FormatWidth: 3,
MaxIntegerDigits: 1, MaxIntegerDigits: 1,
MinExponentDigits: 1, MinExponentDigits: 1,
}, },
}, { }, {
"0E0", "0E0",
&Format{ &Pattern{
FormatWidth: 3, FormatWidth: 3,
MinIntegerDigits: 1, MinIntegerDigits: 1,
MinExponentDigits: 1, MinExponentDigits: 1,
}, },
}, { }, {
"##00.0#E0", "##00.0#E0",
&Format{ &Pattern{
FormatWidth: 9, FormatWidth: 9,
MinIntegerDigits: 2, MinIntegerDigits: 2,
MaxIntegerDigits: 4, MaxIntegerDigits: 4,
@@ -102,7 +102,7 @@ var testCases = []struct {
}, },
}, { }, {
"#00.0E+0", "#00.0E+0",
&Format{ &Pattern{
FormatWidth: 8, FormatWidth: 8,
Flags: AlwaysExpSign, Flags: AlwaysExpSign,
MinIntegerDigits: 2, MinIntegerDigits: 2,
@@ -120,7 +120,7 @@ var testCases = []struct {
}, { }, {
// significant digits // significant digits
"@", "@",
&Format{ &Pattern{
FormatWidth: 1, FormatWidth: 1,
MinSignificantDigits: 1, MinSignificantDigits: 1,
MaxSignificantDigits: 1, MaxSignificantDigits: 1,
@@ -128,14 +128,14 @@ var testCases = []struct {
}, { }, {
// significant digits // significant digits
"@@@@", "@@@@",
&Format{ &Pattern{
FormatWidth: 4, FormatWidth: 4,
MinSignificantDigits: 4, MinSignificantDigits: 4,
MaxSignificantDigits: 4, MaxSignificantDigits: 4,
}, },
}, { }, {
"@###", "@###",
&Format{ &Pattern{
FormatWidth: 4, FormatWidth: 4,
MinSignificantDigits: 1, MinSignificantDigits: 1,
MaxSignificantDigits: 4, MaxSignificantDigits: 4,
@@ -143,7 +143,7 @@ var testCases = []struct {
}, { }, {
// Exponents in significant digits mode gets normalized. // Exponents in significant digits mode gets normalized.
"@@E0", "@@E0",
&Format{ &Pattern{
FormatWidth: 4, FormatWidth: 4,
MinIntegerDigits: 1, MinIntegerDigits: 1,
MaxIntegerDigits: 1, MaxIntegerDigits: 1,
@@ -153,7 +153,7 @@ var testCases = []struct {
}, },
}, { }, {
"@###E00", "@###E00",
&Format{ &Pattern{
FormatWidth: 7, FormatWidth: 7,
MinIntegerDigits: 1, MinIntegerDigits: 1,
MaxIntegerDigits: 1, MaxIntegerDigits: 1,
@@ -168,7 +168,7 @@ var testCases = []struct {
}, { }, {
//alternative negative pattern //alternative negative pattern
"#0.###;(#0.###)", "#0.###;(#0.###)",
&Format{ &Pattern{
Affix: "\x00\x00\x01(\x01)", Affix: "\x00\x00\x01(\x01)",
NegOffset: 2, NegOffset: 2,
FormatWidth: 6, FormatWidth: 6,
@@ -178,7 +178,7 @@ var testCases = []struct {
}, { }, {
// Rounding increments // Rounding increments
"1.05", "1.05",
&Format{ &Pattern{
RoundIncrement: 105, RoundIncrement: 105,
FormatWidth: 4, FormatWidth: 4,
MinIntegerDigits: 1, MinIntegerDigits: 1,
@@ -187,7 +187,7 @@ var testCases = []struct {
}, },
}, { }, {
"0.0%", "0.0%",
&Format{ &Pattern{
Affix: "\x00\x01%", Affix: "\x00\x01%",
Multiplier: 100, Multiplier: 100,
FormatWidth: 4, FormatWidth: 4,
@@ -197,7 +197,7 @@ var testCases = []struct {
}, },
}, { }, {
"0.0‰", "0.0‰",
&Format{ &Pattern{
Affix: "\x00\x03‰", Affix: "\x00\x03‰",
Multiplier: 1000, Multiplier: 1000,
FormatWidth: 4, FormatWidth: 4,
@@ -207,7 +207,7 @@ var testCases = []struct {
}, },
}, { }, {
"#,##0.00¤", "#,##0.00¤",
&Format{ &Pattern{
Affix: "\x00\x02¤", Affix: "\x00\x02¤",
FormatWidth: 9, FormatWidth: 9,
GroupingSize: [2]uint8{3, 0}, GroupingSize: [2]uint8{3, 0},
@@ -217,7 +217,7 @@ var testCases = []struct {
}, },
}, { }, {
"#,##0.00 ¤;(#,##0.00 ¤)", "#,##0.00 ¤;(#,##0.00 ¤)",
&Format{Affix: "\x00\x04\u00a0¤\x01(\x05\u00a0¤)", &Pattern{Affix: "\x00\x04\u00a0¤\x01(\x05\u00a0¤)",
NegOffset: 6, NegOffset: 6,
Multiplier: 0, Multiplier: 0,
FormatWidth: 10, FormatWidth: 10,
@@ -229,28 +229,28 @@ var testCases = []struct {
}, { }, {
// padding // padding
"*x#", "*x#",
&Format{ &Pattern{
PadRune: 'x', PadRune: 'x',
FormatWidth: 1, FormatWidth: 1,
}, },
}, { }, {
// padding // padding
"#*x", "#*x",
&Format{ &Pattern{
PadRune: 'x', PadRune: 'x',
FormatWidth: 1, FormatWidth: 1,
Flags: PadBeforeSuffix, Flags: PadBeforeSuffix,
}, },
}, { }, {
"*xpre#suf", "*xpre#suf",
&Format{ &Pattern{
Affix: "\x03pre\x03suf", Affix: "\x03pre\x03suf",
PadRune: 'x', PadRune: 'x',
FormatWidth: 7, FormatWidth: 7,
}, },
}, { }, {
"pre*x#suf", "pre*x#suf",
&Format{ &Pattern{
Affix: "\x03pre\x03suf", Affix: "\x03pre\x03suf",
PadRune: 'x', PadRune: 'x',
FormatWidth: 7, FormatWidth: 7,
@@ -258,7 +258,7 @@ var testCases = []struct {
}, },
}, { }, {
"pre#*xsuf", "pre#*xsuf",
&Format{ &Pattern{
Affix: "\x03pre\x03suf", Affix: "\x03pre\x03suf",
PadRune: 'x', PadRune: 'x',
FormatWidth: 7, FormatWidth: 7,
@@ -266,7 +266,7 @@ var testCases = []struct {
}, },
}, { }, {
"pre#suf*x", "pre#suf*x",
&Format{ &Pattern{
Affix: "\x03pre\x03suf", Affix: "\x03pre\x03suf",
PadRune: 'x', PadRune: 'x',
FormatWidth: 7, FormatWidth: 7,
@@ -293,7 +293,7 @@ func TestParsePattern(t *testing.T) {
} }
func TestPatternSize(t *testing.T) { func TestPatternSize(t *testing.T) {
if sz := unsafe.Sizeof(Format{}); sz > 48 { if sz := unsafe.Sizeof(Pattern{}); sz > 48 {
t.Errorf("got %d; want 48", sz) t.Errorf("got %d; want 48", sz)
} }

32
vendor/golang.org/x/text/internal/number/tables.go сгенерированный поставляемый
Просмотреть файл

@@ -1376,7 +1376,7 @@ var tagToPercent = []uint8{ // 752 elements
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
} // Size: 776 bytes } // Size: 776 bytes
var formats = []Format{Format{Affix: "", var formats = []Pattern{Pattern{Affix: "",
Offset: 0x0, Offset: 0x0,
NegOffset: 0x0, NegOffset: 0x0,
Multiplier: 0x0, Multiplier: 0x0,
@@ -1393,7 +1393,7 @@ var formats = []Format{Format{Affix: "",
MinSignificantDigits: 0x0, MinSignificantDigits: 0x0,
MaxSignificantDigits: 0x0, MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0}, MinExponentDigits: 0x0},
Format{Affix: "", Pattern{Affix: "",
Offset: 0x0, Offset: 0x0,
NegOffset: 0x0, NegOffset: 0x0,
Multiplier: 0x0, Multiplier: 0x0,
@@ -1410,7 +1410,7 @@ var formats = []Format{Format{Affix: "",
MinSignificantDigits: 0x0, MinSignificantDigits: 0x0,
MaxSignificantDigits: 0x0, MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0}, MinExponentDigits: 0x0},
Format{Affix: "", Pattern{Affix: "",
Offset: 0x0, Offset: 0x0,
NegOffset: 0x0, NegOffset: 0x0,
Multiplier: 0x0, Multiplier: 0x0,
@@ -1427,7 +1427,7 @@ var formats = []Format{Format{Affix: "",
MinSignificantDigits: 0x0, MinSignificantDigits: 0x0,
MaxSignificantDigits: 0x0, MaxSignificantDigits: 0x0,
MinExponentDigits: 0x1}, MinExponentDigits: 0x1},
Format{Affix: "\x00\x03\u00a0%", Pattern{Affix: "\x00\x03\u00a0%",
Offset: 0x0, Offset: 0x0,
NegOffset: 0x0, NegOffset: 0x0,
Multiplier: 0x64, Multiplier: 0x64,
@@ -1444,7 +1444,7 @@ var formats = []Format{Format{Affix: "",
MinSignificantDigits: 0x0, MinSignificantDigits: 0x0,
MaxSignificantDigits: 0x0, MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0}, MinExponentDigits: 0x0},
Format{Affix: "\x00\x01%", Pattern{Affix: "\x00\x01%",
Offset: 0x0, Offset: 0x0,
NegOffset: 0x0, NegOffset: 0x0,
Multiplier: 0x64, Multiplier: 0x64,
@@ -1461,7 +1461,7 @@ var formats = []Format{Format{Affix: "",
MinSignificantDigits: 0x0, MinSignificantDigits: 0x0,
MaxSignificantDigits: 0x0, MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0}, MinExponentDigits: 0x0},
Format{Affix: "", Pattern{Affix: "",
Offset: 0x0, Offset: 0x0,
NegOffset: 0x0, NegOffset: 0x0,
Multiplier: 0x0, Multiplier: 0x0,
@@ -1478,7 +1478,7 @@ var formats = []Format{Format{Affix: "",
MinSignificantDigits: 0x0, MinSignificantDigits: 0x0,
MaxSignificantDigits: 0x0, MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0}, MinExponentDigits: 0x0},
Format{Affix: "\x00\x01%", Pattern{Affix: "\x00\x01%",
Offset: 0x0, Offset: 0x0,
NegOffset: 0x0, NegOffset: 0x0,
Multiplier: 0x64, Multiplier: 0x64,
@@ -1495,7 +1495,7 @@ var formats = []Format{Format{Affix: "",
MinSignificantDigits: 0x0, MinSignificantDigits: 0x0,
MaxSignificantDigits: 0x0, MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0}, MinExponentDigits: 0x0},
Format{Affix: "\x00\x03\u00a0%", Pattern{Affix: "\x00\x03\u00a0%",
Offset: 0x0, Offset: 0x0,
NegOffset: 0x0, NegOffset: 0x0,
Multiplier: 0x64, Multiplier: 0x64,
@@ -1512,7 +1512,7 @@ var formats = []Format{Format{Affix: "",
MinSignificantDigits: 0x0, MinSignificantDigits: 0x0,
MaxSignificantDigits: 0x0, MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0}, MinExponentDigits: 0x0},
Format{Affix: "", Pattern{Affix: "",
Offset: 0x0, Offset: 0x0,
NegOffset: 0x0, NegOffset: 0x0,
Multiplier: 0x0, Multiplier: 0x0,
@@ -1529,7 +1529,7 @@ var formats = []Format{Format{Affix: "",
MinSignificantDigits: 0x0, MinSignificantDigits: 0x0,
MaxSignificantDigits: 0x0, MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0}, MinExponentDigits: 0x0},
Format{Affix: "", Pattern{Affix: "",
Offset: 0x0, Offset: 0x0,
NegOffset: 0x0, NegOffset: 0x0,
Multiplier: 0x0, Multiplier: 0x0,
@@ -1546,7 +1546,7 @@ var formats = []Format{Format{Affix: "",
MinSignificantDigits: 0x0, MinSignificantDigits: 0x0,
MaxSignificantDigits: 0x0, MaxSignificantDigits: 0x0,
MinExponentDigits: 0x3}, MinExponentDigits: 0x3},
Format{Affix: "\x00\x01%", Pattern{Affix: "\x00\x01%",
Offset: 0x0, Offset: 0x0,
NegOffset: 0x0, NegOffset: 0x0,
Multiplier: 0x64, Multiplier: 0x64,
@@ -1563,7 +1563,7 @@ var formats = []Format{Format{Affix: "",
MinSignificantDigits: 0x0, MinSignificantDigits: 0x0,
MaxSignificantDigits: 0x0, MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0}, MinExponentDigits: 0x0},
Format{Affix: "\x03%\u00a0\x00", Pattern{Affix: "\x03%\u00a0\x00",
Offset: 0x0, Offset: 0x0,
NegOffset: 0x0, NegOffset: 0x0,
Multiplier: 0x64, Multiplier: 0x64,
@@ -1580,7 +1580,7 @@ var formats = []Format{Format{Affix: "",
MinSignificantDigits: 0x0, MinSignificantDigits: 0x0,
MaxSignificantDigits: 0x0, MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0}, MinExponentDigits: 0x0},
Format{Affix: "\x03%\u00a0\x00\x04%\u00a0-\x00", Pattern{Affix: "\x03%\u00a0\x00\x04%\u00a0-\x00",
Offset: 0x0, Offset: 0x0,
NegOffset: 0x5, NegOffset: 0x5,
Multiplier: 0x64, Multiplier: 0x64,
@@ -1597,7 +1597,7 @@ var formats = []Format{Format{Affix: "",
MinSignificantDigits: 0x0, MinSignificantDigits: 0x0,
MaxSignificantDigits: 0x0, MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0}, MinExponentDigits: 0x0},
Format{Affix: "\x01[\x01]", Pattern{Affix: "\x01[\x01]",
Offset: 0x0, Offset: 0x0,
NegOffset: 0x0, NegOffset: 0x0,
Multiplier: 0x0, Multiplier: 0x0,
@@ -1614,7 +1614,7 @@ var formats = []Format{Format{Affix: "",
MinSignificantDigits: 0x0, MinSignificantDigits: 0x0,
MaxSignificantDigits: 0x0, MaxSignificantDigits: 0x0,
MinExponentDigits: 0x1}, MinExponentDigits: 0x1},
Format{Affix: "", Pattern{Affix: "",
Offset: 0x0, Offset: 0x0,
NegOffset: 0x0, NegOffset: 0x0,
Multiplier: 0x0, Multiplier: 0x0,
@@ -1631,7 +1631,7 @@ var formats = []Format{Format{Affix: "",
MinSignificantDigits: 0x0, MinSignificantDigits: 0x0,
MaxSignificantDigits: 0x0, MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0}, MinExponentDigits: 0x0},
Format{Affix: "\x01%\x00", Pattern{Affix: "\x01%\x00",
Offset: 0x0, Offset: 0x0,
NegOffset: 0x0, NegOffset: 0x0,
Multiplier: 0x64, Multiplier: 0x64,

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

@@ -79,7 +79,7 @@ export default class ClusterTable extends React.Component {
clusterInfo.id = Utils.localizeMessage('admin.cluster.unknown', 'unknown'); clusterInfo.id = Utils.localizeMessage('admin.cluster.unknown', 'unknown');
} }
if (clusterInfo.is_alive) { if (clusterInfo.is_alive > 0) {
status = ( status = (
<img <img
className='cluster-status' className='cluster-status'