blob: 2b871c4015ae96dccd1a3bc2af5f6a5d6af32876 [file] [log] [blame]
Damien Neilba23aa52018-12-07 14:38:17 -08001// Copyright 2018 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style.
3// license that can be found in the LICENSE file.
4
5package proto
6
7import (
Damien Neilba23aa52018-12-07 14:38:17 -08008 "github.com/golang/protobuf/v2/internal/encoding/wire"
Damien Neil96c229a2019-04-03 12:17:24 -07009 "github.com/golang/protobuf/v2/internal/errors"
Damien Neilba23aa52018-12-07 14:38:17 -080010 "github.com/golang/protobuf/v2/internal/pragma"
11 "github.com/golang/protobuf/v2/reflect/protoreflect"
Damien Neil0d3e8cc2019-04-01 13:31:55 -070012 "github.com/golang/protobuf/v2/runtime/protoiface"
Damien Neilba23aa52018-12-07 14:38:17 -080013)
14
15// UnmarshalOptions configures the unmarshaler.
16//
17// Example usage:
18// err := UnmarshalOptions{DiscardUnknown: true}.Unmarshal(b, m)
19type UnmarshalOptions struct {
Damien Neil96c229a2019-04-03 12:17:24 -070020 // AllowPartial accepts input for messages that will result in missing
21 // required fields. If AllowPartial is false (the default), Unmarshal will
22 // return an error if there are any missing required fields.
23 AllowPartial bool
24
Damien Neilba23aa52018-12-07 14:38:17 -080025 // If DiscardUnknown is set, unknown fields are ignored.
26 DiscardUnknown bool
27
Damien Neil0d3e8cc2019-04-01 13:31:55 -070028 // Reflection forces use of the reflection-based decoder, even for
29 // messages which implement fast-path deserialization.
30 Reflection bool
31
Damien Neilba23aa52018-12-07 14:38:17 -080032 pragma.NoUnkeyedLiterals
33}
34
Damien Neil0d3e8cc2019-04-01 13:31:55 -070035var _ = protoiface.UnmarshalOptions(UnmarshalOptions{})
36
Damien Neilba23aa52018-12-07 14:38:17 -080037// Unmarshal parses the wire-format message in b and places the result in m.
38func Unmarshal(b []byte, m Message) error {
39 return UnmarshalOptions{}.Unmarshal(b, m)
40}
41
42// Unmarshal parses the wire-format message in b and places the result in m.
43func (o UnmarshalOptions) Unmarshal(b []byte, m Message) error {
44 // TODO: Reset m?
Damien Neil0d3e8cc2019-04-01 13:31:55 -070045 if err := o.unmarshalMessageFast(b, m); err != errInternalNoFast {
46 return err
47 }
Damien Neilba23aa52018-12-07 14:38:17 -080048 return o.unmarshalMessage(b, m.ProtoReflect())
49}
50
Damien Neil0d3e8cc2019-04-01 13:31:55 -070051func (o UnmarshalOptions) unmarshalMessageFast(b []byte, m Message) error {
52 if o.Reflection {
53 return errInternalNoFast
54 }
55 methods := protoMethods(m)
56 if methods == nil || methods.Unmarshal == nil {
57 return errInternalNoFast
58 }
59 return methods.Unmarshal(b, m, protoiface.UnmarshalOptions(o))
60}
61
Damien Neilba23aa52018-12-07 14:38:17 -080062func (o UnmarshalOptions) unmarshalMessage(b []byte, m protoreflect.Message) error {
63 messageType := m.Type()
64 fieldTypes := messageType.Fields()
65 knownFields := m.KnownFields()
66 unknownFields := m.UnknownFields()
Damien Neil96c229a2019-04-03 12:17:24 -070067 var nerr errors.NonFatal
Damien Neilba23aa52018-12-07 14:38:17 -080068 for len(b) > 0 {
69 // Parse the tag (field number and wire type).
70 num, wtyp, tagLen := wire.ConsumeTag(b)
71 if tagLen < 0 {
72 return wire.ParseError(tagLen)
73 }
74
75 // Parse the field value.
76 fieldType := fieldTypes.ByNumber(num)
Damien Neild068d302018-12-17 14:06:08 -080077 if fieldType == nil {
78 fieldType = knownFields.ExtensionTypes().ByNumber(num)
79 }
Damien Neilba23aa52018-12-07 14:38:17 -080080 var err error
81 var valLen int
82 switch {
83 case fieldType == nil:
84 err = errUnknown
85 case fieldType.Cardinality() != protoreflect.Repeated:
86 valLen, err = o.unmarshalScalarField(b[tagLen:], wtyp, num, knownFields, fieldType)
87 case !fieldType.IsMap():
88 valLen, err = o.unmarshalList(b[tagLen:], wtyp, num, knownFields.Get(num).List(), fieldType.Kind())
89 default:
90 valLen, err = o.unmarshalMap(b[tagLen:], wtyp, num, knownFields.Get(num).Map(), fieldType)
91 }
92 if err == errUnknown {
93 valLen = wire.ConsumeFieldValue(num, wtyp, b[tagLen:])
94 if valLen < 0 {
95 return wire.ParseError(valLen)
96 }
97 unknownFields.Set(num, append(unknownFields.Get(num), b[:tagLen+valLen]...))
Damien Neil96c229a2019-04-03 12:17:24 -070098 } else if !nerr.Merge(err) {
Damien Neilba23aa52018-12-07 14:38:17 -080099 return err
100 }
101 b = b[tagLen+valLen:]
102 }
Damien Neil96c229a2019-04-03 12:17:24 -0700103 if !o.AllowPartial {
104 checkRequiredFields(m, &nerr)
105 }
106 return nerr.E
Damien Neilba23aa52018-12-07 14:38:17 -0800107}
108
109func (o UnmarshalOptions) unmarshalScalarField(b []byte, wtyp wire.Type, num wire.Number, knownFields protoreflect.KnownFields, field protoreflect.FieldDescriptor) (n int, err error) {
110 v, n, err := o.unmarshalScalar(b, wtyp, num, field.Kind())
111 if err != nil {
112 return 0, err
113 }
114 switch field.Kind() {
115 case protoreflect.GroupKind, protoreflect.MessageKind:
116 // Messages are merged with any existing message value,
117 // unless the message is part of a oneof.
118 //
119 // TODO: C++ merges into oneofs, while v1 does not.
120 // Evaluate which behavior to pick.
121 var m protoreflect.Message
122 if knownFields.Has(num) && field.OneofType() == nil {
123 m = knownFields.Get(num).Message()
124 } else {
Joe Tsai3bc7d6f2019-01-09 02:57:13 -0800125 m = knownFields.NewMessage(num)
Damien Neilba23aa52018-12-07 14:38:17 -0800126 knownFields.Set(num, protoreflect.ValueOf(m))
127 }
Damien Neil96c229a2019-04-03 12:17:24 -0700128 // Pass up errors (fatal and otherwise).
129 err = o.unmarshalMessage(v.Bytes(), m)
Damien Neilba23aa52018-12-07 14:38:17 -0800130 default:
131 // Non-message scalars replace the previous value.
132 knownFields.Set(num, v)
133 }
Damien Neil96c229a2019-04-03 12:17:24 -0700134 return n, err
Damien Neilba23aa52018-12-07 14:38:17 -0800135}
136
137func (o UnmarshalOptions) unmarshalMap(b []byte, wtyp wire.Type, num wire.Number, mapv protoreflect.Map, field protoreflect.FieldDescriptor) (n int, err error) {
138 if wtyp != wire.BytesType {
139 return 0, errUnknown
140 }
141 b, n = wire.ConsumeBytes(b)
142 if n < 0 {
143 return 0, wire.ParseError(n)
144 }
145 var (
146 keyField = field.MessageType().Fields().ByNumber(1)
147 valField = field.MessageType().Fields().ByNumber(2)
148 key protoreflect.Value
149 val protoreflect.Value
150 haveKey bool
151 haveVal bool
152 )
153 switch valField.Kind() {
154 case protoreflect.GroupKind, protoreflect.MessageKind:
Joe Tsai3bc7d6f2019-01-09 02:57:13 -0800155 val = protoreflect.ValueOf(mapv.NewMessage())
Damien Neilba23aa52018-12-07 14:38:17 -0800156 }
157 // Map entries are represented as a two-element message with fields
158 // containing the key and value.
Damien Neil96c229a2019-04-03 12:17:24 -0700159 var nerr errors.NonFatal
Damien Neilba23aa52018-12-07 14:38:17 -0800160 for len(b) > 0 {
161 num, wtyp, n := wire.ConsumeTag(b)
162 if n < 0 {
163 return 0, wire.ParseError(n)
164 }
165 b = b[n:]
166 err = errUnknown
167 switch num {
168 case 1:
169 key, n, err = o.unmarshalScalar(b, wtyp, num, keyField.Kind())
170 if err != nil {
171 break
172 }
173 haveKey = true
174 case 2:
175 var v protoreflect.Value
176 v, n, err = o.unmarshalScalar(b, wtyp, num, valField.Kind())
177 if err != nil {
178 break
179 }
180 switch valField.Kind() {
181 case protoreflect.GroupKind, protoreflect.MessageKind:
Damien Neil96c229a2019-04-03 12:17:24 -0700182 if err := o.unmarshalMessage(v.Bytes(), val.Message()); !nerr.Merge(err) {
Damien Neilba23aa52018-12-07 14:38:17 -0800183 return 0, err
184 }
185 default:
186 val = v
187 }
188 haveVal = true
189 }
190 if err == errUnknown {
191 n = wire.ConsumeFieldValue(num, wtyp, b)
192 if n < 0 {
193 return 0, wire.ParseError(n)
194 }
Damien Neil96c229a2019-04-03 12:17:24 -0700195 } else if !nerr.Merge(err) {
Damien Neilba23aa52018-12-07 14:38:17 -0800196 return 0, err
197 }
198 b = b[n:]
199 }
200 // Every map entry should have entries for key and value, but this is not strictly required.
201 if !haveKey {
202 key = keyField.Default()
203 }
204 if !haveVal {
205 switch valField.Kind() {
206 case protoreflect.GroupKind, protoreflect.MessageKind:
Damien Neil96c229a2019-04-03 12:17:24 -0700207 if !o.AllowPartial {
208 checkRequiredFields(val.Message(), &nerr)
Damien Neilba23aa52018-12-07 14:38:17 -0800209 }
210 default:
211 val = valField.Default()
212 }
213 }
214 mapv.Set(key.MapKey(), val)
Damien Neil96c229a2019-04-03 12:17:24 -0700215 return n, nerr.E
Damien Neilba23aa52018-12-07 14:38:17 -0800216}
217
218// errUnknown is used internally to indicate fields which should be added
219// to the unknown field set of a message. It is never returned from an exported
220// function.
Damien Neil96c229a2019-04-03 12:17:24 -0700221var errUnknown = errors.New("BUG: internal error (unknown)")