blob: 84d31ac889dafb41a3a97cb7d8b61ab7416e8e22 [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 (
8 "google.golang.org/protobuf/internal/encoding/wire"
9 "google.golang.org/protobuf/internal/errors"
Damien Neilce3384c2019-11-06 13:18:28 -080010 "google.golang.org/protobuf/internal/flags"
Damien Neile91877d2019-06-27 10:54:42 -070011 "google.golang.org/protobuf/proto"
12 pref "google.golang.org/protobuf/reflect/protoreflect"
13 preg "google.golang.org/protobuf/reflect/protoregistry"
14 piface "google.golang.org/protobuf/runtime/protoiface"
15)
16
17// unmarshalOptions is a more efficient representation of UnmarshalOptions.
18//
19// We don't preserve the AllowPartial flag, because fast-path (un)marshal
20// operations always allow partial messages.
21type unmarshalOptions struct {
Damien Neil2f643a92020-01-21 09:56:01 -080022 flags unmarshalOptionFlags
23
24 // Keep this field's type identical to (proto.UnmarshalOptions).Resolver
25 // to avoid a type conversion on assignment.
26 resolver interface {
Damien Neilf12fb452020-01-21 11:27:51 -080027 FindExtensionByName(field pref.FullName) (pref.ExtensionType, error)
28 FindExtensionByNumber(message pref.FullName, field pref.FieldNumber) (pref.ExtensionType, error)
Damien Neil2f643a92020-01-21 09:56:01 -080029 }
Damien Neile91877d2019-06-27 10:54:42 -070030}
31
32type unmarshalOptionFlags uint8
33
34const (
35 unmarshalDiscardUnknown unmarshalOptionFlags = 1 << iota
36)
37
38func newUnmarshalOptions(opts piface.UnmarshalOptions) unmarshalOptions {
39 o := unmarshalOptions{
40 resolver: opts.Resolver,
41 }
42 if opts.DiscardUnknown {
43 o.flags |= unmarshalDiscardUnknown
44 }
45 return o
46}
47
48func (o unmarshalOptions) Options() proto.UnmarshalOptions {
49 return proto.UnmarshalOptions{
Joe Tsai705acad2019-09-14 18:22:59 -070050 Merge: true,
Damien Neile91877d2019-06-27 10:54:42 -070051 AllowPartial: true,
52 DiscardUnknown: o.DiscardUnknown(),
53 Resolver: o.Resolver(),
54 }
55}
56
57func (o unmarshalOptions) DiscardUnknown() bool { return o.flags&unmarshalDiscardUnknown != 0 }
58func (o unmarshalOptions) Resolver() preg.ExtensionTypeResolver { return o.resolver }
59
Damien Neilf0831e82020-01-21 14:25:12 -080060type unmarshalOutput struct {
61 n int // number of bytes consumed
62}
63
Damien Neile91877d2019-06-27 10:54:42 -070064// unmarshal is protoreflect.Methods.Unmarshal.
Damien Neil61781dd2020-01-21 13:29:51 -080065func (mi *MessageInfo) unmarshal(m pref.Message, in piface.UnmarshalInput) (piface.UnmarshalOutput, error) {
Joe Tsai0f81b382019-07-10 23:14:31 -070066 var p pointer
67 if ms, ok := m.(*messageState); ok {
68 p = ms.pointer()
69 } else {
70 p = m.(*messageReflectWrapper).pointer()
71 }
Damien Neil61781dd2020-01-21 13:29:51 -080072 _, err := mi.unmarshalPointer(in.Buf, p, 0, newUnmarshalOptions(in.Options))
73 return piface.UnmarshalOutput{}, err
Damien Neile91877d2019-06-27 10:54:42 -070074}
75
76// errUnknown is returned during unmarshaling to indicate a parse error that
77// should result in a field being placed in the unknown fields section (for example,
78// when the wire type doesn't match) as opposed to the entire unmarshal operation
79// failing (for example, when a field extends past the available input).
80//
81// This is a sentinel error which should never be visible to the user.
82var errUnknown = errors.New("unknown")
83
Damien Neilf0831e82020-01-21 14:25:12 -080084func (mi *MessageInfo) unmarshalPointer(b []byte, p pointer, groupTag wire.Number, opts unmarshalOptions) (out unmarshalOutput, err error) {
Damien Neile91877d2019-06-27 10:54:42 -070085 mi.init()
Damien Neilce3384c2019-11-06 13:18:28 -080086 if flags.ProtoLegacy && mi.isMessageSet {
87 return unmarshalMessageSet(mi, b, p, opts)
88 }
Damien Neile91877d2019-06-27 10:54:42 -070089 var exts *map[int32]ExtensionField
90 start := len(b)
91 for len(b) > 0 {
92 // Parse the tag (field number and wire type).
93 // TODO: inline 1 and 2 byte variants?
94 num, wtyp, n := wire.ConsumeTag(b)
95 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -080096 return out, wire.ParseError(n)
Damien Neile91877d2019-06-27 10:54:42 -070097 }
Damien Neilfe15dd42019-12-06 15:36:03 -080098 if num > wire.MaxValidNumber {
Damien Neilf0831e82020-01-21 14:25:12 -080099 return out, errors.New("invalid field number")
Damien Neilfe15dd42019-12-06 15:36:03 -0800100 }
Damien Neile91877d2019-06-27 10:54:42 -0700101 b = b[n:]
102
Damien Neil2ae60932020-01-14 11:12:21 -0800103 if wtyp == wire.EndGroupType {
104 if num != groupTag {
Damien Neilf0831e82020-01-21 14:25:12 -0800105 return out, errors.New("mismatching end group marker")
Damien Neil2ae60932020-01-14 11:12:21 -0800106 }
Damien Neilf0831e82020-01-21 14:25:12 -0800107 out.n = start - len(b)
108 return out, nil
Damien Neil2ae60932020-01-14 11:12:21 -0800109 }
110
Damien Neile91877d2019-06-27 10:54:42 -0700111 var f *coderFieldInfo
112 if int(num) < len(mi.denseCoderFields) {
113 f = mi.denseCoderFields[num]
114 } else {
115 f = mi.coderFields[num]
116 }
117 err := errUnknown
118 switch {
119 case f != nil:
120 if f.funcs.unmarshal == nil {
121 break
122 }
Damien Neilf0831e82020-01-21 14:25:12 -0800123 var o unmarshalOutput
124 o, err = f.funcs.unmarshal(b, p.Apply(f.offset), wtyp, opts)
125 n = o.n
Damien Neile91877d2019-06-27 10:54:42 -0700126 default:
127 // Possible extension.
128 if exts == nil && mi.extensionOffset.IsValid() {
129 exts = p.Apply(mi.extensionOffset).Extensions()
130 if *exts == nil {
131 *exts = make(map[int32]ExtensionField)
132 }
133 }
134 if exts == nil {
135 break
136 }
Damien Neilf0831e82020-01-21 14:25:12 -0800137 var o unmarshalOutput
138 o, err = mi.unmarshalExtension(b, num, wtyp, *exts, opts)
139 n = o.n
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 }
149 if mi.unknownOffset.IsValid() {
150 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 Neilf0831e82020-01-21 14:25:12 -0800160 out.n = start
161 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700162}
163
Damien Neilf0831e82020-01-21 14:25:12 -0800164func (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 -0700165 x := exts[int32(num)]
Damien Neilef19a2a2019-11-01 12:00:37 -0700166 xt := x.Type()
Damien Neile91877d2019-06-27 10:54:42 -0700167 if xt == nil {
168 var err error
Damien Neil16163b42019-08-06 15:43:25 -0700169 xt, err = opts.Resolver().FindExtensionByNumber(mi.Desc.FullName(), num)
Damien Neile91877d2019-06-27 10:54:42 -0700170 if err != nil {
171 if err == preg.NotFound {
Damien Neilf0831e82020-01-21 14:25:12 -0800172 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700173 }
Damien Neilf0831e82020-01-21 14:25:12 -0800174 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700175 }
Damien Neile91877d2019-06-27 10:54:42 -0700176 }
Damien Neil79571e92019-12-09 10:24:36 -0800177 xi := getExtensionFieldInfo(xt)
Damien Neile91877d2019-06-27 10:54:42 -0700178 if xi.funcs.unmarshal == nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800179 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700180 }
Damien Neil68b81c32019-08-22 11:41:32 -0700181 ival := x.Value()
182 if !ival.IsValid() && xi.unmarshalNeedsValue {
Damien Neile91877d2019-06-27 10:54:42 -0700183 // Create a new message, list, or map value to fill in.
184 // For enums, create a prototype value to let the unmarshal func know the
185 // concrete type.
Damien Neil68b81c32019-08-22 11:41:32 -0700186 ival = xt.New()
Damien Neile91877d2019-06-27 10:54:42 -0700187 }
Damien Neilf0831e82020-01-21 14:25:12 -0800188 v, out, err := xi.funcs.unmarshal(b, ival, num, wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700189 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800190 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700191 }
Damien Neil68b81c32019-08-22 11:41:32 -0700192 x.Set(xt, v)
Damien Neile91877d2019-06-27 10:54:42 -0700193 exts[int32(num)] = x
Damien Neilf0831e82020-01-21 14:25:12 -0800194 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700195}