github.com/whiteCcinn/protobuf-go@v1.0.9/internal/impl/legacy_export.go (about) 1 // Copyright 2019 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package impl 6 7 import ( 8 "encoding/binary" 9 "encoding/json" 10 "hash/crc32" 11 "math" 12 "reflect" 13 14 "github.com/whiteCcinn/protobuf-go/internal/errors" 15 "github.com/whiteCcinn/protobuf-go/reflect/protoreflect" 16 "github.com/whiteCcinn/protobuf-go/runtime/protoiface" 17 ) 18 19 // These functions exist to support exported APIs in generated protobufs. 20 // While these are deprecated, they cannot be removed for compatibility reasons. 21 22 // LegacyEnumName returns the name of enums used in legacy code. 23 func (Export) LegacyEnumName(ed protoreflect.EnumDescriptor) string { 24 return legacyEnumName(ed) 25 } 26 27 // LegacyMessageTypeOf returns the protoreflect.MessageType for m, 28 // with name used as the message name if necessary. 29 func (Export) LegacyMessageTypeOf(m protoiface.MessageV1, name protoreflect.FullName) protoreflect.MessageType { 30 if mv := (Export{}).protoMessageV2Of(m); mv != nil { 31 return mv.ProtoReflect().Type() 32 } 33 return legacyLoadMessageType(reflect.TypeOf(m), name) 34 } 35 36 // UnmarshalJSONEnum unmarshals an enum from a JSON-encoded input. 37 // The input can either be a string representing the enum value by name, 38 // or a number representing the enum number itself. 39 func (Export) UnmarshalJSONEnum(ed protoreflect.EnumDescriptor, b []byte) (protoreflect.EnumNumber, error) { 40 if b[0] == '"' { 41 var name protoreflect.Name 42 if err := json.Unmarshal(b, &name); err != nil { 43 return 0, errors.New("invalid input for enum %v: %s", ed.FullName(), b) 44 } 45 ev := ed.Values().ByName(name) 46 if ev == nil { 47 return 0, errors.New("invalid value for enum %v: %s", ed.FullName(), name) 48 } 49 return ev.Number(), nil 50 } else { 51 var num protoreflect.EnumNumber 52 if err := json.Unmarshal(b, &num); err != nil { 53 return 0, errors.New("invalid input for enum %v: %s", ed.FullName(), b) 54 } 55 return num, nil 56 } 57 } 58 59 // CompressGZIP compresses the input as a GZIP-encoded file. 60 // The current implementation does no compression. 61 func (Export) CompressGZIP(in []byte) (out []byte) { 62 // RFC 1952, section 2.3.1. 63 var gzipHeader = [10]byte{0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff} 64 65 // RFC 1951, section 3.2.4. 66 var blockHeader [5]byte 67 const maxBlockSize = math.MaxUint16 68 numBlocks := 1 + len(in)/maxBlockSize 69 70 // RFC 1952, section 2.3.1. 71 var gzipFooter [8]byte 72 binary.LittleEndian.PutUint32(gzipFooter[0:4], crc32.ChecksumIEEE(in)) 73 binary.LittleEndian.PutUint32(gzipFooter[4:8], uint32(len(in))) 74 75 // Encode the input without compression using raw DEFLATE blocks. 76 out = make([]byte, 0, len(gzipHeader)+len(blockHeader)*numBlocks+len(in)+len(gzipFooter)) 77 out = append(out, gzipHeader[:]...) 78 for blockHeader[0] == 0 { 79 blockSize := maxBlockSize 80 if blockSize > len(in) { 81 blockHeader[0] = 0x01 // final bit per RFC 1951, section 3.2.3. 82 blockSize = len(in) 83 } 84 binary.LittleEndian.PutUint16(blockHeader[1:3], uint16(blockSize)) 85 binary.LittleEndian.PutUint16(blockHeader[3:5], ^uint16(blockSize)) 86 out = append(out, blockHeader[:]...) 87 out = append(out, in[:blockSize]...) 88 in = in[blockSize:] 89 } 90 out = append(out, gzipFooter[:]...) 91 return out 92 }