google.golang.org/grpc@v1.72.2/codec.go (about) 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 }