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