1package pgs
2
3import (
4	"github.com/golang/protobuf/proto"
5	"github.com/golang/protobuf/protoc-gen-go/descriptor"
6)
7
8// A Field describes a member of a Message. A field may also be a member of a
9// OneOf on the Message.
10type Field interface {
11	Entity
12
13	// Descriptor returns the proto descriptor for this field
14	Descriptor() *descriptor.FieldDescriptorProto
15
16	// Message returns the Message containing this Field.
17	Message() Message
18
19	// InOneOf returns true if the field is in a OneOf of the parent Message.
20	InOneOf() bool
21
22	// OneOf returns the OneOf that this field is apart of. Nil is returned if
23	// the field is not within a OneOf.
24	OneOf() OneOf
25
26	// Type returns the FieldType of this Field.
27	Type() FieldType
28
29	// Required returns whether or not the field is labeled as required. This
30	// will only be true if the syntax is proto2.
31	Required() bool
32
33	setMessage(m Message)
34	setOneOf(o OneOf)
35	addType(t FieldType)
36}
37
38type field struct {
39	desc  *descriptor.FieldDescriptorProto
40	fqn   string
41	msg   Message
42	oneof OneOf
43	typ   FieldType
44
45	info SourceCodeInfo
46}
47
48func (f *field) Name() Name                                   { return Name(f.desc.GetName()) }
49func (f *field) FullyQualifiedName() string                   { return f.fqn }
50func (f *field) Syntax() Syntax                               { return f.msg.Syntax() }
51func (f *field) Package() Package                             { return f.msg.Package() }
52func (f *field) Imports() []File                              { return f.typ.Imports() }
53func (f *field) File() File                                   { return f.msg.File() }
54func (f *field) BuildTarget() bool                            { return f.msg.BuildTarget() }
55func (f *field) SourceCodeInfo() SourceCodeInfo               { return f.info }
56func (f *field) Descriptor() *descriptor.FieldDescriptorProto { return f.desc }
57func (f *field) Message() Message                             { return f.msg }
58func (f *field) InOneOf() bool                                { return f.oneof != nil }
59func (f *field) OneOf() OneOf                                 { return f.oneof }
60func (f *field) Type() FieldType                              { return f.typ }
61func (f *field) setMessage(m Message)                         { f.msg = m }
62func (f *field) setOneOf(o OneOf)                             { f.oneof = o }
63
64func (f *field) Required() bool {
65	return f.Syntax().SupportsRequiredPrefix() &&
66		f.desc.GetLabel() == descriptor.FieldDescriptorProto_LABEL_REQUIRED
67}
68
69func (f *field) addType(t FieldType) {
70	t.setField(f)
71	f.typ = t
72}
73
74func (f *field) Extension(desc *proto.ExtensionDesc, ext interface{}) (ok bool, err error) {
75	return extension(f.desc.GetOptions(), desc, &ext)
76}
77
78func (f *field) accept(v Visitor) (err error) {
79	if v == nil {
80		return
81	}
82
83	_, err = v.VisitField(f)
84	return
85}
86
87func (f *field) childAtPath(path []int32) Entity {
88	if len(path) == 0 {
89		return f
90	}
91	return nil
92}
93
94func (f *field) addSourceCodeInfo(info SourceCodeInfo) { f.info = info }
95
96var _ Field = (*field)(nil)
97