blob: caa9f17c2840ed13c25cd8a981b0679b71b3dffb [file] [log] [blame]
Joe Tsaieeca8bb2018-12-04 16:24:22 -08001// Copyright 2010 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 protoV1
6
7// Unmarshaler is the interface representing objects that can
8// unmarshal themselves. The argument points to data that may be
9// overwritten, so implementations should not keep references to the
10// buffer.
11// Unmarshal implementations should not clear the receiver.
12// Any unmarshaled data should be merged into the receiver.
13// Callers of Unmarshal that do not want to retain existing data
14// should Reset the receiver before calling Unmarshal.
15type Unmarshaler interface {
16 Unmarshal([]byte) error
17}
18
19// newUnmarshaler is the interface representing objects that can
20// unmarshal themselves. The semantics are identical to Unmarshaler.
21//
22// This exists to support protoc-gen-go generated messages.
23// The proto package will stop type-asserting to this interface in the future.
24//
25// DO NOT DEPEND ON THIS.
26type newUnmarshaler interface {
27 XXX_Unmarshal([]byte) error
28}
29
30// Unmarshal parses the protocol buffer representation in buf and places the
31// decoded result in pb. If the struct underlying pb does not match
32// the data in buf, the results can be unpredictable.
33//
34// Unmarshal resets pb before starting to unmarshal, so any
35// existing data in pb is always removed. Use UnmarshalMerge
36// to preserve and append to existing data.
37func Unmarshal(buf []byte, pb Message) error {
38 pb.Reset()
39 if u, ok := pb.(newUnmarshaler); ok {
40 return u.XXX_Unmarshal(buf)
41 }
42 if u, ok := pb.(Unmarshaler); ok {
43 return u.Unmarshal(buf)
44 }
45 return NewBuffer(buf).Unmarshal(pb)
46}
47
48// Unmarshal parses the protocol buffer representation in the
49// Buffer and places the decoded result in pb. If the struct
50// underlying pb does not match the data in the buffer, the results can be
51// unpredictable.
52//
53// Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal.
54func (p *Buffer) Unmarshal(pb Message) error {
55 // If the object can unmarshal itself, let it.
56 if u, ok := pb.(newUnmarshaler); ok {
57 err := u.XXX_Unmarshal(p.buf[p.index:])
58 p.index = len(p.buf)
59 return err
60 }
61 if u, ok := pb.(Unmarshaler); ok {
62 // NOTE: The history of proto have unfortunately been inconsistent
63 // whether Unmarshaler should or should not implicitly clear itself.
64 // Some implementations do, most do not.
65 // Thus, calling this here may or may not do what people want.
66 //
67 // See https://github.com/golang/protobuf/issues/424
68 err := u.Unmarshal(p.buf[p.index:])
69 p.index = len(p.buf)
70 return err
71 }
72
73 // Slow workaround for messages that aren't Unmarshalers.
74 // This includes some hand-coded .pb.go files and
75 // bootstrap protos.
76 // TODO: fix all of those and then add Unmarshal to
77 // the Message interface. Then:
78 // The cast above and code below can be deleted.
79 // The old unmarshaler can be deleted.
80 // Clients can call Unmarshal directly (can already do that, actually).
81 var info InternalMessageInfo
82 err := info.Unmarshal(pb, p.buf[p.index:])
83 p.index = len(p.buf)
84 return err
85}