| /* | |
| * | |
| * Copyright 2024 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 encoding | |
| import ( | |
| "strings" | |
| "google.golang.org/grpc/mem" | |
| ) | |
| // CodecV2 defines the interface gRPC uses to encode and decode messages. Note | |
| // that implementations of this interface must be thread safe; a CodecV2's | |
| // methods can be called from concurrent goroutines. | |
| type CodecV2 interface { | |
| // Marshal returns the wire format of v. The buffers in the returned | |
| // [mem.BufferSlice] must have at least one reference each, which will be freed | |
| // by gRPC when they are no longer needed. | |
| Marshal(v any) (out mem.BufferSlice, err error) | |
| // Unmarshal parses the wire format into v. Note that data will be freed as soon | |
| // as this function returns. If the codec wishes to guarantee access to the data | |
| // after this function, it must take its own reference that it frees when it is | |
| // no longer needed. | |
| Unmarshal(data mem.BufferSlice, v any) error | |
| // Name returns the name of the Codec implementation. The returned string | |
| // will be used as part of content type in transmission. The result must be | |
| // static; the result cannot change between calls. | |
| Name() string | |
| } | |
| // RegisterCodecV2 registers the provided CodecV2 for use with all gRPC clients and | |
| // servers. | |
| // | |
| // The CodecV2 will be stored and looked up by result of its Name() method, which | |
| // should match the content-subtype of the encoding handled by the CodecV2. This | |
| // is case-insensitive, and is stored and looked up as lowercase. If the | |
| // result of calling Name() is an empty string, RegisterCodecV2 will panic. See | |
| // Content-Type on | |
| // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for | |
| // more details. | |
| // | |
| // If both a Codec and CodecV2 are registered with the same name, the CodecV2 | |
| // will be used. | |
| // | |
| // NOTE: this function must only be called during initialization time (i.e. in | |
| // an init() function), and is not thread-safe. If multiple Codecs are | |
| // registered with the same name, the one registered last will take effect. | |
| func RegisterCodecV2(codec CodecV2) { | |
| if codec == nil { | |
| panic("cannot register a nil CodecV2") | |
| } | |
| if codec.Name() == "" { | |
| panic("cannot register CodecV2 with empty string result for Name()") | |
| } | |
| contentSubtype := strings.ToLower(codec.Name()) | |
| registeredCodecs[contentSubtype] = codec | |
| } | |
| // GetCodecV2 gets a registered CodecV2 by content-subtype, or nil if no CodecV2 is | |
| // registered for the content-subtype. | |
| // | |
| // The content-subtype is expected to be lowercase. | |
| func GetCodecV2(contentSubtype string) CodecV2 { | |
| c, _ := registeredCodecs[contentSubtype].(CodecV2) | |
| return c | |
| } |