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  }