Skip to content

Commit 64ed1f9

Browse files
committed
Library structs internalized. The line of importing fatih's struct was replaced to the internal one.
1 parent b168f13 commit 64ed1f9

File tree

4 files changed

+756
-1
lines changed

4 files changed

+756
-1
lines changed

structs/field.go

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package structs
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"reflect"
7+
)
8+
9+
var (
10+
errNotExported = errors.New("field is not exported")
11+
errNotSettable = errors.New("field is not settable")
12+
)
13+
14+
// Field represents a single struct field that encapsulates high level
15+
// functions around the field.
16+
type Field struct {
17+
value reflect.Value
18+
field reflect.StructField
19+
defaultTag string
20+
}
21+
22+
// Tag returns the value associated with key in the tag string. If there is no
23+
// such key in the tag, Tag returns the empty string.
24+
func (f *Field) Tag(key string) string {
25+
return f.field.Tag.Get(key)
26+
}
27+
28+
// Value returns the underlying value of the field. It panics if the field
29+
// is not exported.
30+
func (f *Field) Value() interface{} {
31+
return f.value.Interface()
32+
}
33+
34+
// IsEmbedded returns true if the given field is an anonymous field (embedded)
35+
func (f *Field) IsEmbedded() bool {
36+
return f.field.Anonymous
37+
}
38+
39+
// IsExported returns true if the given field is exported.
40+
func (f *Field) IsExported() bool {
41+
return f.field.PkgPath == ""
42+
}
43+
44+
// IsZero returns true if the given field is not initialized (has a zero value).
45+
// It panics if the field is not exported.
46+
func (f *Field) IsZero() bool {
47+
zero := reflect.Zero(f.value.Type()).Interface()
48+
current := f.Value()
49+
50+
return reflect.DeepEqual(current, zero)
51+
}
52+
53+
// Name returns the name of the given field
54+
func (f *Field) Name() string {
55+
return f.field.Name
56+
}
57+
58+
// Kind returns the fields kind, such as "string", "map", "bool", etc ..
59+
func (f *Field) Kind() reflect.Kind {
60+
return f.value.Kind()
61+
}
62+
63+
// Set sets the field to given value v. It returns an error if the field is not
64+
// settable (not addressable or not exported) or if the given value's type
65+
// doesn't match the fields type.
66+
func (f *Field) Set(val interface{}) error {
67+
// we can't set unexported fields, so be sure this field is exported
68+
if !f.IsExported() {
69+
return errNotExported
70+
}
71+
72+
// do we get here? not sure...
73+
if !f.value.CanSet() {
74+
return errNotSettable
75+
}
76+
77+
given := reflect.ValueOf(val)
78+
79+
if f.value.Kind() != given.Kind() {
80+
return fmt.Errorf("wrong kind. got: %s want: %s", given.Kind(), f.value.Kind())
81+
}
82+
83+
f.value.Set(given)
84+
return nil
85+
}
86+
87+
// Zero sets the field to its zero value. It returns an error if the field is not
88+
// settable (not addressable or not exported).
89+
func (f *Field) Zero() error {
90+
zero := reflect.Zero(f.value.Type()).Interface()
91+
return f.Set(zero)
92+
}
93+
94+
// Fields returns a slice of Fields. This is particular handy to get the fields
95+
// of a nested struct . A struct tag with the content of "-" ignores the
96+
// checking of that particular field. Example:
97+
//
98+
// // Field is ignored by this package.
99+
// Field *http.Request `structs:"-"`
100+
//
101+
// It panics if field is not exported or if field's kind is not struct
102+
func (f *Field) Fields() []*Field {
103+
return getFields(f.value, f.defaultTag)
104+
}
105+
106+
// Field returns the field from a nested struct. It panics if the nested struct
107+
// is not exported or if the field was not found.
108+
func (f *Field) Field(name string) *Field {
109+
field, ok := f.FieldOk(name)
110+
if !ok {
111+
panic("field not found")
112+
}
113+
114+
return field
115+
}
116+
117+
// FieldOk returns the field from a nested struct. The boolean returns whether
118+
// the field was found (true) or not (false).
119+
func (f *Field) FieldOk(name string) (*Field, bool) {
120+
value := &f.value
121+
// value must be settable so we need to make sure it holds the address of the
122+
// variable and not a copy, so we can pass the pointer to strctVal instead of a
123+
// copy (which is not assigned to any variable, hence not settable).
124+
// see "https://blog.golang.org/laws-of-reflection#TOC_8."
125+
if f.value.Kind() != reflect.Ptr {
126+
a := f.value.Addr()
127+
value = &a
128+
}
129+
v := strctVal(value.Interface())
130+
t := v.Type()
131+
132+
field, ok := t.FieldByName(name)
133+
if !ok {
134+
return nil, false
135+
}
136+
137+
return &Field{
138+
field: field,
139+
value: v.FieldByName(name),
140+
}, true
141+
}

0 commit comments

Comments
 (0)