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
19package grpc
20
21import (
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.
31type 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.
41func 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
49func newCodecV0Bridge(c Codec) baseCodec {
50 return codecV0Bridge{codec: c}
51}
52
53func newCodecV1Bridge(c encoding.Codec) encoding.CodecV2 {
54 return codecV1Bridge{
55 codecV0Bridge: codecV0Bridge{codec: c},
56 name: c.Name(),
57 }
58}
59
60var _ baseCodec = codecV0Bridge{}
61
62type codecV0Bridge struct {
63 codec interface {
64 Marshal(v any) ([]byte, error)
65 Unmarshal(data []byte, v any) error
66 }
67}
68
69func (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
77func (c codecV0Bridge) Unmarshal(data mem.BufferSlice, v any) (err error) {
78 return c.codec.Unmarshal(data.Materialize(), v)
79}
80
81var _ encoding.CodecV2 = codecV1Bridge{}
82
83type codecV1Bridge struct {
84 codecV0Bridge
85 name string
86}
87
88func (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.
97type 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}