| /* | |
| * | |
| * Copyright 2014 gRPC authors. | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| * | |
| */ | |
| package grpc | |
| import ( | |
| "google.golang.org/grpc/encoding" | |
| _ "google.golang.org/grpc/encoding/proto" // to register the Codec for "proto" | |
| "google.golang.org/grpc/mem" | |
| ) | |
| // baseCodec captures the new encoding.CodecV2 interface without the Name | |
| // function, allowing it to be implemented by older Codec and encoding.Codec | |
| // implementations. The omitted Name function is only needed for the register in | |
| // the encoding package and is not part of the core functionality. | |
| type baseCodec interface { | |
| Marshal(v any) (mem.BufferSlice, error) | |
| Unmarshal(data mem.BufferSlice, v any) error | |
| } | |
| // getCodec returns an encoding.CodecV2 for the codec of the given name (if | |
| // registered). Initially checks the V2 registry with encoding.GetCodecV2 and | |
| // returns the V2 codec if it is registered. Otherwise, it checks the V1 registry | |
| // with encoding.GetCodec and if it is registered wraps it with newCodecV1Bridge | |
| // to turn it into an encoding.CodecV2. Returns nil otherwise. | |
| func getCodec(name string) encoding.CodecV2 { | |
| if codecV1 := encoding.GetCodec(name); codecV1 != nil { | |
| return newCodecV1Bridge(codecV1) | |
| } | |
| return encoding.GetCodecV2(name) | |
| } | |
| func newCodecV0Bridge(c Codec) baseCodec { | |
| return codecV0Bridge{codec: c} | |
| } | |
| func newCodecV1Bridge(c encoding.Codec) encoding.CodecV2 { | |
| return codecV1Bridge{ | |
| codecV0Bridge: codecV0Bridge{codec: c}, | |
| name: c.Name(), | |
| } | |
| } | |
| var _ baseCodec = codecV0Bridge{} | |
| type codecV0Bridge struct { | |
| codec interface { | |
| Marshal(v any) ([]byte, error) | |
| Unmarshal(data []byte, v any) error | |
| } | |
| } | |
| func (c codecV0Bridge) Marshal(v any) (mem.BufferSlice, error) { | |
| data, err := c.codec.Marshal(v) | |
| if err != nil { | |
| return nil, err | |
| } | |
| return mem.BufferSlice{mem.SliceBuffer(data)}, nil | |
| } | |
| func (c codecV0Bridge) Unmarshal(data mem.BufferSlice, v any) (err error) { | |
| return c.codec.Unmarshal(data.Materialize(), v) | |
| } | |
| var _ encoding.CodecV2 = codecV1Bridge{} | |
| type codecV1Bridge struct { | |
| codecV0Bridge | |
| name string | |
| } | |
| func (c codecV1Bridge) Name() string { | |
| return c.name | |
| } | |
| // Codec defines the interface gRPC uses to encode and decode messages. | |
| // Note that implementations of this interface must be thread safe; | |
| // a Codec's methods can be called from concurrent goroutines. | |
| // | |
| // Deprecated: use encoding.Codec instead. | |
| type Codec interface { | |
| // Marshal returns the wire format of v. | |
| Marshal(v any) ([]byte, error) | |
| // Unmarshal parses the wire format into v. | |
| Unmarshal(data []byte, v any) error | |
| // String returns the name of the Codec implementation. This is unused by | |
| // gRPC. | |
| String() string | |
| } |