File: tags.go

package info (click to toggle)
golang-gopkg-rethinkdb-rethinkdb-go.v6 6.2.1-5
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 2,736 kB
  • sloc: python: 1,382; makefile: 16; sh: 9
file content (114 lines) | stat: -rw-r--r-- 2,336 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// This code is based on encoding/json and gorilla/schema

package encoding

import (
	"reflect"
	"strconv"
	"strings"
	"unicode"
)

var (
	Tags []string
)

const (
	TagName       = "rethinkdb"
	OldTagName    = "gorethink"
	JSONTagName   = "json"
	RefTagName    = "rethinkdb_ref"
	OldRefTagName = "gorethink_ref"
)

// tagOptions is the string following a comma in a struct field's
// tag, or the empty string. It does not include the leading comma.
type tagOptions string

func getTag(sf reflect.StructField) string {
	if Tags == nil {
		value := sf.Tag.Get(TagName)
		if value == "" {
			return sf.Tag.Get(OldTagName)
		}
		return value
	}

	for _, tagName := range Tags {
		if tag := sf.Tag.Get(tagName); tag != "" {
			return tag
		}
	}

	return ""
}

func getRefTag(sf reflect.StructField) string {
	value := sf.Tag.Get(RefTagName)
	if value == "" {
		return sf.Tag.Get(OldRefTagName)
	}
	return value
}

// parseTag splits a struct field's tag into its name and
// comma-separated options.
func parseTag(tag string) (string, tagOptions) {
	if idx := strings.Index(tag, ","); idx != -1 {
		return tag[:idx], tagOptions(tag[idx+1:])
	}
	return tag, tagOptions("")
}

func parseCompoundIndex(tag string) (string, int, bool) {
	lIdx := strings.Index(tag, "[")
	rIdx := strings.Index(tag, "]")
	if lIdx > 1 && rIdx > lIdx+1 {
		if elemIndex_, err := strconv.ParseInt(tag[lIdx+1:rIdx], 10, 64); err == nil {
			return tag[:lIdx], int(elemIndex_), true
		}
	}

	return tag, 0, false
}

func isValidTag(s string) bool {
	if s == "" {
		return false
	}
	for _, c := range s {
		switch {
		case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
			// Backslash and quote chars are reserved, but
			// otherwise any punctuation chars are allowed
			// in a tag name.
		default:
			if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
				return false
			}
		}
	}
	return true
}

// Contains returns whether checks that a comma-separated list of options
// contains a particular substr flag. substr must be surrounded by a
// string boundary or commas.
func (o tagOptions) Contains(optionName string) bool {
	if len(o) == 0 {
		return false
	}
	s := string(o)
	for s != "" {
		var next string
		i := strings.Index(s, ",")
		if i >= 0 {
			s, next = s[:i], s[i+1:]
		}
		if s == optionName {
			return true
		}
		s = next
	}
	return false
}