blob: fc93525a1f54905e4c29128bd6fff8adc925d2e8 [file] [log] [blame]
Damien Neile91877d2019-06-27 10:54:42 -07001// Copyright 2019 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 impl
6
7import (
Damien Neilc600d6c2020-01-21 15:00:33 -08008 "math/bits"
9
Damien Neile91877d2019-06-27 10:54:42 -070010 "google.golang.org/protobuf/internal/encoding/wire"
11 "google.golang.org/protobuf/internal/errors"
Damien Neilce3384c2019-11-06 13:18:28 -080012 "google.golang.org/protobuf/internal/flags"
Damien Neile91877d2019-06-27 10:54:42 -070013 "google.golang.org/protobuf/proto"
14 pref "google.golang.org/protobuf/reflect/protoreflect"
15 preg "google.golang.org/protobuf/reflect/protoregistry"
16 piface "google.golang.org/protobuf/runtime/protoiface"
17)
18
19// unmarshalOptions is a more efficient representation of UnmarshalOptions.
20//
21// We don't preserve the AllowPartial flag, because fast-path (un)marshal
22// operations always allow partial messages.
23type unmarshalOptions struct {
Damien Neil2f643a92020-01-21 09:56:01 -080024 flags unmarshalOptionFlags
25
26 // Keep this field's type identical to (proto.UnmarshalOptions).Resolver
27 // to avoid a type conversion on assignment.
28 resolver interface {
Damien Neilf12fb452020-01-21 11:27:51 -080029 FindExtensionByName(field pref.FullName) (pref.ExtensionType, error)
30 FindExtensionByNumber(message pref.FullName, field pref.FieldNumber) (pref.ExtensionType, error)
Damien Neil2f643a92020-01-21 09:56:01 -080031 }
Damien Neile91877d2019-06-27 10:54:42 -070032}
33
34type unmarshalOptionFlags uint8
35
36const (
37 unmarshalDiscardUnknown unmarshalOptionFlags = 1 << iota
38)
39
40func newUnmarshalOptions(opts piface.UnmarshalOptions) unmarshalOptions {
41 o := unmarshalOptions{
42 resolver: opts.Resolver,
43 }
44 if opts.DiscardUnknown {
45 o.flags |= unmarshalDiscardUnknown
46 }
47 return o
48}
49
50func (o unmarshalOptions) Options() proto.UnmarshalOptions {
51 return proto.UnmarshalOptions{
Joe Tsai705acad2019-09-14 18:22:59 -070052 Merge: true,
Damien Neile91877d2019-06-27 10:54:42 -070053 AllowPartial: true,
54 DiscardUnknown: o.DiscardUnknown(),
55 Resolver: o.Resolver(),
56 }
57}
58
59func (o unmarshalOptions) DiscardUnknown() bool { return o.flags&unmarshalDiscardUnknown != 0 }
60func (o unmarshalOptions) Resolver() preg.ExtensionTypeResolver { return o.resolver }
61
Damien Neilf0831e82020-01-21 14:25:12 -080062type unmarshalOutput struct {
Damien Neilc600d6c2020-01-21 15:00:33 -080063 n int // number of bytes consumed
64 initialized bool
Damien Neilf0831e82020-01-21 14:25:12 -080065}
66
Damien Neile91877d2019-06-27 10:54:42 -070067// unmarshal is protoreflect.Methods.Unmarshal.
Damien Neild30e5612020-01-22 10:28:16 -080068func (mi *MessageInfo) unmarshal(m pref.Message, in piface.UnmarshalInput, opts piface.UnmarshalOptions) (piface.UnmarshalOutput, error) {
Joe Tsai0f81b382019-07-10 23:14:31 -070069 var p pointer
70 if ms, ok := m.(*messageState); ok {
71 p = ms.pointer()
72 } else {
73 p = m.(*messageReflectWrapper).pointer()
74 }
Damien Neilc600d6c2020-01-21 15:00:33 -080075 out, err := mi.unmarshalPointer(in.Buf, p, 0, newUnmarshalOptions(opts))
76 return piface.UnmarshalOutput{
77 Initialized: out.initialized,
78 }, err
Damien Neile91877d2019-06-27 10:54:42 -070079}
80
81// errUnknown is returned during unmarshaling to indicate a parse error that
82// should result in a field being placed in the unknown fields section (for example,
83// when the wire type doesn't match) as opposed to the entire unmarshal operation
84// failing (for example, when a field extends past the available input).
85//
86// This is a sentinel error which should never be visible to the user.
87var errUnknown = errors.New("unknown")
88
Damien Neilf0831e82020-01-21 14:25:12 -080089func (mi *MessageInfo) unmarshalPointer(b []byte, p pointer, groupTag wire.Number, opts unmarshalOptions) (out unmarshalOutput, err error) {
Damien Neile91877d2019-06-27 10:54:42 -070090 mi.init()
Damien Neilce3384c2019-11-06 13:18:28 -080091 if flags.ProtoLegacy && mi.isMessageSet {
92 return unmarshalMessageSet(mi, b, p, opts)
93 }
Damien Neilc600d6c2020-01-21 15:00:33 -080094 initialized := true
95 var requiredMask uint64
Damien Neile91877d2019-06-27 10:54:42 -070096 var exts *map[int32]ExtensionField
97 start := len(b)
98 for len(b) > 0 {
99 // Parse the tag (field number and wire type).
100 // TODO: inline 1 and 2 byte variants?
101 num, wtyp, n := wire.ConsumeTag(b)
102 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800103 return out, wire.ParseError(n)
Damien Neile91877d2019-06-27 10:54:42 -0700104 }
Damien Neilfe15dd42019-12-06 15:36:03 -0800105 if num > wire.MaxValidNumber {
Damien Neilf0831e82020-01-21 14:25:12 -0800106 return out, errors.New("invalid field number")
Damien Neilfe15dd42019-12-06 15:36:03 -0800107 }
Damien Neile91877d2019-06-27 10:54:42 -0700108 b = b[n:]
109
Damien Neil2ae60932020-01-14 11:12:21 -0800110 if wtyp == wire.EndGroupType {
111 if num != groupTag {
Damien Neilf0831e82020-01-21 14:25:12 -0800112 return out, errors.New("mismatching end group marker")
Damien Neil2ae60932020-01-14 11:12:21 -0800113 }
Damien Neilc600d6c2020-01-21 15:00:33 -0800114 groupTag = 0
115 break
Damien Neil2ae60932020-01-14 11:12:21 -0800116 }
117
Damien Neile91877d2019-06-27 10:54:42 -0700118 var f *coderFieldInfo
119 if int(num) < len(mi.denseCoderFields) {
120 f = mi.denseCoderFields[num]
121 } else {
122 f = mi.coderFields[num]
123 }
124 err := errUnknown
125 switch {
126 case f != nil:
127 if f.funcs.unmarshal == nil {
128 break
129 }
Damien Neilf0831e82020-01-21 14:25:12 -0800130 var o unmarshalOutput
131 o, err = f.funcs.unmarshal(b, p.Apply(f.offset), wtyp, opts)
132 n = o.n
Damien Neilc600d6c2020-01-21 15:00:33 -0800133 if reqi := f.validation.requiredIndex; reqi > 0 && err == nil {
134 requiredMask |= 1 << (reqi - 1)
135 }
136 if f.funcs.isInit != nil && !o.initialized {
137 initialized = false
138 }
Damien Neile91877d2019-06-27 10:54:42 -0700139 default:
140 // Possible extension.
141 if exts == nil && mi.extensionOffset.IsValid() {
142 exts = p.Apply(mi.extensionOffset).Extensions()
143 if *exts == nil {
144 *exts = make(map[int32]ExtensionField)
145 }
146 }
147 if exts == nil {
148 break
149 }
Damien Neilf0831e82020-01-21 14:25:12 -0800150 var o unmarshalOutput
151 o, err = mi.unmarshalExtension(b, num, wtyp, *exts, opts)
152 n = o.n
Damien Neilc600d6c2020-01-21 15:00:33 -0800153 if !o.initialized {
154 initialized = false
155 }
Damien Neile91877d2019-06-27 10:54:42 -0700156 }
157 if err != nil {
158 if err != errUnknown {
Damien Neilf0831e82020-01-21 14:25:12 -0800159 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700160 }
161 n = wire.ConsumeFieldValue(num, wtyp, b)
162 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800163 return out, wire.ParseError(n)
Damien Neile91877d2019-06-27 10:54:42 -0700164 }
165 if mi.unknownOffset.IsValid() {
166 u := p.Apply(mi.unknownOffset).Bytes()
167 *u = wire.AppendTag(*u, num, wtyp)
168 *u = append(*u, b[:n]...)
169 }
170 }
171 b = b[n:]
172 }
173 if groupTag != 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800174 return out, errors.New("missing end group marker")
Damien Neile91877d2019-06-27 10:54:42 -0700175 }
Damien Neilc600d6c2020-01-21 15:00:33 -0800176 if mi.numRequiredFields > 0 && bits.OnesCount64(requiredMask) != int(mi.numRequiredFields) {
177 initialized = false
178 }
179 if initialized {
180 out.initialized = true
181 }
182 out.n = start - len(b)
Damien Neilf0831e82020-01-21 14:25:12 -0800183 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700184}
185
Damien Neilf0831e82020-01-21 14:25:12 -0800186func (mi *MessageInfo) unmarshalExtension(b []byte, num wire.Number, wtyp wire.Type, exts map[int32]ExtensionField, opts unmarshalOptions) (out unmarshalOutput, err error) {
Damien Neile91877d2019-06-27 10:54:42 -0700187 x := exts[int32(num)]
Damien Neilef19a2a2019-11-01 12:00:37 -0700188 xt := x.Type()
Damien Neile91877d2019-06-27 10:54:42 -0700189 if xt == nil {
190 var err error
Damien Neil16163b42019-08-06 15:43:25 -0700191 xt, err = opts.Resolver().FindExtensionByNumber(mi.Desc.FullName(), num)
Damien Neile91877d2019-06-27 10:54:42 -0700192 if err != nil {
193 if err == preg.NotFound {
Damien Neilf0831e82020-01-21 14:25:12 -0800194 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700195 }
Damien Neilf0831e82020-01-21 14:25:12 -0800196 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700197 }
Damien Neile91877d2019-06-27 10:54:42 -0700198 }
Damien Neil79571e92019-12-09 10:24:36 -0800199 xi := getExtensionFieldInfo(xt)
Damien Neile91877d2019-06-27 10:54:42 -0700200 if xi.funcs.unmarshal == nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800201 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700202 }
Damien Neil68b81c32019-08-22 11:41:32 -0700203 ival := x.Value()
204 if !ival.IsValid() && xi.unmarshalNeedsValue {
Damien Neile91877d2019-06-27 10:54:42 -0700205 // Create a new message, list, or map value to fill in.
206 // For enums, create a prototype value to let the unmarshal func know the
207 // concrete type.
Damien Neil68b81c32019-08-22 11:41:32 -0700208 ival = xt.New()
Damien Neile91877d2019-06-27 10:54:42 -0700209 }
Damien Neilf0831e82020-01-21 14:25:12 -0800210 v, out, err := xi.funcs.unmarshal(b, ival, num, wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700211 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800212 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700213 }
Damien Neil68b81c32019-08-22 11:41:32 -0700214 x.Set(xt, v)
Damien Neile91877d2019-06-27 10:54:42 -0700215 exts[int32(num)] = x
Damien Neilf0831e82020-01-21 14:25:12 -0800216 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700217}