blob: 3cd7f5af9298ff6e6546dc7317b9858b72345bfa [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
Damien Neil524c6062020-01-28 13:32:01 -080019type unmarshalOptions piface.UnmarshalOptions
Damien Neile91877d2019-06-27 10:54:42 -070020
21func (o unmarshalOptions) Options() proto.UnmarshalOptions {
22 return proto.UnmarshalOptions{
Joe Tsai705acad2019-09-14 18:22:59 -070023 Merge: true,
Damien Neile91877d2019-06-27 10:54:42 -070024 AllowPartial: true,
25 DiscardUnknown: o.DiscardUnknown(),
Damien Neil524c6062020-01-28 13:32:01 -080026 Resolver: o.Resolver,
Damien Neile91877d2019-06-27 10:54:42 -070027 }
28}
29
Damien Neil524c6062020-01-28 13:32:01 -080030func (o unmarshalOptions) DiscardUnknown() bool { return o.Flags&piface.UnmarshalDiscardUnknown != 0 }
Damien Neile91877d2019-06-27 10:54:42 -070031
Damien Neilf0831e82020-01-21 14:25:12 -080032type unmarshalOutput struct {
Damien Neilc600d6c2020-01-21 15:00:33 -080033 n int // number of bytes consumed
34 initialized bool
Damien Neilf0831e82020-01-21 14:25:12 -080035}
36
Damien Neile91877d2019-06-27 10:54:42 -070037// unmarshal is protoreflect.Methods.Unmarshal.
Damien Neild30e5612020-01-22 10:28:16 -080038func (mi *MessageInfo) unmarshal(m pref.Message, in piface.UnmarshalInput, opts piface.UnmarshalOptions) (piface.UnmarshalOutput, error) {
Joe Tsai0f81b382019-07-10 23:14:31 -070039 var p pointer
40 if ms, ok := m.(*messageState); ok {
41 p = ms.pointer()
42 } else {
43 p = m.(*messageReflectWrapper).pointer()
44 }
Damien Neil524c6062020-01-28 13:32:01 -080045 out, err := mi.unmarshalPointer(in.Buf, p, 0, unmarshalOptions(opts))
Damien Neilc600d6c2020-01-21 15:00:33 -080046 return piface.UnmarshalOutput{
47 Initialized: out.initialized,
48 }, err
Damien Neile91877d2019-06-27 10:54:42 -070049}
50
51// errUnknown is returned during unmarshaling to indicate a parse error that
52// should result in a field being placed in the unknown fields section (for example,
53// when the wire type doesn't match) as opposed to the entire unmarshal operation
54// failing (for example, when a field extends past the available input).
55//
56// This is a sentinel error which should never be visible to the user.
57var errUnknown = errors.New("unknown")
58
Damien Neilf0831e82020-01-21 14:25:12 -080059func (mi *MessageInfo) unmarshalPointer(b []byte, p pointer, groupTag wire.Number, opts unmarshalOptions) (out unmarshalOutput, err error) {
Damien Neile91877d2019-06-27 10:54:42 -070060 mi.init()
Damien Neilce3384c2019-11-06 13:18:28 -080061 if flags.ProtoLegacy && mi.isMessageSet {
62 return unmarshalMessageSet(mi, b, p, opts)
63 }
Damien Neilc600d6c2020-01-21 15:00:33 -080064 initialized := true
65 var requiredMask uint64
Damien Neile91877d2019-06-27 10:54:42 -070066 var exts *map[int32]ExtensionField
67 start := len(b)
68 for len(b) > 0 {
69 // Parse the tag (field number and wire type).
Damien Neilce8f7f62020-01-24 16:00:20 -080070 var tag uint64
71 if b[0] < 0x80 {
72 tag = uint64(b[0])
73 b = b[1:]
74 } else if len(b) >= 2 && b[1] < 128 {
75 tag = uint64(b[0]&0x7f) + uint64(b[1])<<7
76 b = b[2:]
77 } else {
78 var n int
79 tag, n = wire.ConsumeVarint(b)
80 if n < 0 {
81 return out, wire.ParseError(n)
82 }
83 b = b[n:]
Damien Neile91877d2019-06-27 10:54:42 -070084 }
Damien Neilce8f7f62020-01-24 16:00:20 -080085 num := wire.Number(tag >> 3)
86 wtyp := wire.Type(tag & 7)
87
88 if num < wire.MinValidNumber || num > wire.MaxValidNumber {
Damien Neilf0831e82020-01-21 14:25:12 -080089 return out, errors.New("invalid field number")
Damien Neilfe15dd42019-12-06 15:36:03 -080090 }
Damien Neile91877d2019-06-27 10:54:42 -070091
Damien Neil2ae60932020-01-14 11:12:21 -080092 if wtyp == wire.EndGroupType {
93 if num != groupTag {
Damien Neilf0831e82020-01-21 14:25:12 -080094 return out, errors.New("mismatching end group marker")
Damien Neil2ae60932020-01-14 11:12:21 -080095 }
Damien Neilc600d6c2020-01-21 15:00:33 -080096 groupTag = 0
97 break
Damien Neil2ae60932020-01-14 11:12:21 -080098 }
99
Damien Neile91877d2019-06-27 10:54:42 -0700100 var f *coderFieldInfo
101 if int(num) < len(mi.denseCoderFields) {
102 f = mi.denseCoderFields[num]
103 } else {
104 f = mi.coderFields[num]
105 }
Damien Neilce8f7f62020-01-24 16:00:20 -0800106 var n int
Damien Neile91877d2019-06-27 10:54:42 -0700107 err := errUnknown
108 switch {
109 case f != nil:
110 if f.funcs.unmarshal == nil {
111 break
112 }
Damien Neilf0831e82020-01-21 14:25:12 -0800113 var o unmarshalOutput
114 o, err = f.funcs.unmarshal(b, p.Apply(f.offset), wtyp, opts)
115 n = o.n
Damien Neil170b2bf2020-01-24 16:42:42 -0800116 if err != nil {
117 break
Damien Neilc600d6c2020-01-21 15:00:33 -0800118 }
Damien Neil170b2bf2020-01-24 16:42:42 -0800119 requiredMask |= f.validation.requiredBit
Damien Neilc600d6c2020-01-21 15:00:33 -0800120 if f.funcs.isInit != nil && !o.initialized {
121 initialized = false
122 }
Damien Neile91877d2019-06-27 10:54:42 -0700123 default:
124 // Possible extension.
125 if exts == nil && mi.extensionOffset.IsValid() {
126 exts = p.Apply(mi.extensionOffset).Extensions()
127 if *exts == nil {
128 *exts = make(map[int32]ExtensionField)
129 }
130 }
131 if exts == nil {
132 break
133 }
Damien Neilf0831e82020-01-21 14:25:12 -0800134 var o unmarshalOutput
135 o, err = mi.unmarshalExtension(b, num, wtyp, *exts, opts)
136 n = o.n
Damien Neilc600d6c2020-01-21 15:00:33 -0800137 if !o.initialized {
138 initialized = false
139 }
Damien Neile91877d2019-06-27 10:54:42 -0700140 }
141 if err != nil {
142 if err != errUnknown {
Damien Neilf0831e82020-01-21 14:25:12 -0800143 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700144 }
145 n = wire.ConsumeFieldValue(num, wtyp, b)
146 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800147 return out, wire.ParseError(n)
Damien Neile91877d2019-06-27 10:54:42 -0700148 }
Damien Neila60e7092020-01-28 14:53:44 -0800149 if !opts.DiscardUnknown() && mi.unknownOffset.IsValid() {
Damien Neile91877d2019-06-27 10:54:42 -0700150 u := p.Apply(mi.unknownOffset).Bytes()
151 *u = wire.AppendTag(*u, num, wtyp)
152 *u = append(*u, b[:n]...)
153 }
154 }
155 b = b[n:]
156 }
157 if groupTag != 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800158 return out, errors.New("missing end group marker")
Damien Neile91877d2019-06-27 10:54:42 -0700159 }
Damien Neilc600d6c2020-01-21 15:00:33 -0800160 if mi.numRequiredFields > 0 && bits.OnesCount64(requiredMask) != int(mi.numRequiredFields) {
161 initialized = false
162 }
163 if initialized {
164 out.initialized = true
165 }
166 out.n = start - len(b)
Damien Neilf0831e82020-01-21 14:25:12 -0800167 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700168}
169
Damien Neilf0831e82020-01-21 14:25:12 -0800170func (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 -0700171 x := exts[int32(num)]
Damien Neilef19a2a2019-11-01 12:00:37 -0700172 xt := x.Type()
Damien Neile91877d2019-06-27 10:54:42 -0700173 if xt == nil {
174 var err error
Damien Neil524c6062020-01-28 13:32:01 -0800175 xt, err = opts.Resolver.FindExtensionByNumber(mi.Desc.FullName(), num)
Damien Neile91877d2019-06-27 10:54:42 -0700176 if err != nil {
177 if err == preg.NotFound {
Damien Neilf0831e82020-01-21 14:25:12 -0800178 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700179 }
Damien Neilf0831e82020-01-21 14:25:12 -0800180 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700181 }
Damien Neile91877d2019-06-27 10:54:42 -0700182 }
Damien Neil79571e92019-12-09 10:24:36 -0800183 xi := getExtensionFieldInfo(xt)
Damien Neile91877d2019-06-27 10:54:42 -0700184 if xi.funcs.unmarshal == nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800185 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700186 }
Damien Neil68b81c32019-08-22 11:41:32 -0700187 ival := x.Value()
188 if !ival.IsValid() && xi.unmarshalNeedsValue {
Damien Neile91877d2019-06-27 10:54:42 -0700189 // Create a new message, list, or map value to fill in.
190 // For enums, create a prototype value to let the unmarshal func know the
191 // concrete type.
Damien Neil68b81c32019-08-22 11:41:32 -0700192 ival = xt.New()
Damien Neile91877d2019-06-27 10:54:42 -0700193 }
Damien Neilf0831e82020-01-21 14:25:12 -0800194 v, out, err := xi.funcs.unmarshal(b, ival, num, wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700195 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800196 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700197 }
Damien Neil68b81c32019-08-22 11:41:32 -0700198 x.Set(xt, v)
Damien Neile91877d2019-06-27 10:54:42 -0700199 exts[int32(num)] = x
Damien Neilf0831e82020-01-21 14:25:12 -0800200 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700201}