| /* | |
| * | |
| * Copyright 2019 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/codes" | |
| "google.golang.org/grpc/mem" | |
| "google.golang.org/grpc/status" | |
| ) | |
| // PreparedMsg is responsible for creating a Marshalled and Compressed object. | |
| // | |
| // # Experimental | |
| // | |
| // Notice: This type is EXPERIMENTAL and may be changed or removed in a | |
| // later release. | |
| type PreparedMsg struct { | |
| // Struct for preparing msg before sending them | |
| encodedData mem.BufferSlice | |
| hdr []byte | |
| payload mem.BufferSlice | |
| pf payloadFormat | |
| } | |
| // Encode marshalls and compresses the message using the codec and compressor for the stream. | |
| func (p *PreparedMsg) Encode(s Stream, msg any) error { | |
| ctx := s.Context() | |
| rpcInfo, ok := rpcInfoFromContext(ctx) | |
| if !ok { | |
| return status.Errorf(codes.Internal, "grpc: unable to get rpcInfo") | |
| } | |
| // check if the context has the relevant information to prepareMsg | |
| if rpcInfo.preloaderInfo.codec == nil { | |
| return status.Errorf(codes.Internal, "grpc: rpcInfo.preloaderInfo.codec is nil") | |
| } | |
| // prepare the msg | |
| data, err := encode(rpcInfo.preloaderInfo.codec, msg) | |
| if err != nil { | |
| return err | |
| } | |
| materializedData := data.Materialize() | |
| data.Free() | |
| p.encodedData = mem.BufferSlice{mem.SliceBuffer(materializedData)} | |
| // TODO: it should be possible to grab the bufferPool from the underlying | |
| // stream implementation with a type cast to its actual type (such as | |
| // addrConnStream) and accessing the buffer pool directly. | |
| var compData mem.BufferSlice | |
| compData, p.pf, err = compress(p.encodedData, rpcInfo.preloaderInfo.cp, rpcInfo.preloaderInfo.comp, mem.DefaultBufferPool()) | |
| if err != nil { | |
| return err | |
| } | |
| if p.pf.isCompressed() { | |
| materializedCompData := compData.Materialize() | |
| compData.Free() | |
| compData = mem.BufferSlice{mem.SliceBuffer(materializedCompData)} | |
| } | |
| p.hdr, p.payload = msgHeader(p.encodedData, compData, p.pf) | |
| return nil | |
| } |