1 /*
2 *
3 * Copyright 2014 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18 19 package grpc
20 21 import (
22 "google.golang.org/grpc/encoding"
23 _ "google.golang.org/grpc/encoding/proto" // to register the Codec for "proto"
24 "google.golang.org/grpc/mem"
25 )
26 27 // baseCodec captures the new encoding.CodecV2 interface without the Name
28 // function, allowing it to be implemented by older Codec and encoding.Codec
29 // implementations. The omitted Name function is only needed for the register in
30 // the encoding package and is not part of the core functionality.
31 type baseCodec interface {
32 Marshal(v any) (mem.BufferSlice, error)
33 Unmarshal(data mem.BufferSlice, v any) error
34 }
35 36 // getCodec returns an encoding.CodecV2 for the codec of the given name (if
37 // registered). Initially checks the V2 registry with encoding.GetCodecV2 and
38 // returns the V2 codec if it is registered. Otherwise, it checks the V1 registry
39 // with encoding.GetCodec and if it is registered wraps it with newCodecV1Bridge
40 // to turn it into an encoding.CodecV2. Returns nil otherwise.
41 func getCodec(name string) encoding.CodecV2 {
42 if codecV1 := encoding.GetCodec(name); codecV1 != nil {
43 return newCodecV1Bridge(codecV1)
44 }
45 46 return encoding.GetCodecV2(name)
47 }
48 49 func newCodecV0Bridge(c Codec) baseCodec {
50 return codecV0Bridge{codec: c}
51 }
52 53 func newCodecV1Bridge(c encoding.Codec) encoding.CodecV2 {
54 return codecV1Bridge{
55 codecV0Bridge: codecV0Bridge{codec: c},
56 name: c.Name(),
57 }
58 }
59 60 var _ baseCodec = codecV0Bridge{}
61 62 type codecV0Bridge struct {
63 codec interface {
64 Marshal(v any) ([]byte, error)
65 Unmarshal(data []byte, v any) error
66 }
67 }
68 69 func (c codecV0Bridge) Marshal(v any) (mem.BufferSlice, error) {
70 data, err := c.codec.Marshal(v)
71 if err != nil {
72 return nil, err
73 }
74 return mem.BufferSlice{mem.SliceBuffer(data)}, nil
75 }
76 77 func (c codecV0Bridge) Unmarshal(data mem.BufferSlice, v any) (err error) {
78 return c.codec.Unmarshal(data.Materialize(), v)
79 }
80 81 var _ encoding.CodecV2 = codecV1Bridge{}
82 83 type codecV1Bridge struct {
84 codecV0Bridge
85 name string
86 }
87 88 func (c codecV1Bridge) Name() string {
89 return c.name
90 }
91 92 // Codec defines the interface gRPC uses to encode and decode messages.
93 // Note that implementations of this interface must be thread safe;
94 // a Codec's methods can be called from concurrent goroutines.
95 //
96 // Deprecated: use encoding.Codec instead.
97 type Codec interface {
98 // Marshal returns the wire format of v.
99 Marshal(v any) ([]byte, error)
100 // Unmarshal parses the wire format into v.
101 Unmarshal(data []byte, v any) error
102 // String returns the name of the Codec implementation. This is unused by
103 // gRPC.
104 String() string
105 }
106