...

Source file src/google.golang.org/protobuf/internal/impl/legacy_export.go

Documentation: google.golang.org/protobuf/internal/impl

     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  	"google.golang.org/protobuf/internal/errors"
    15  	"google.golang.org/protobuf/reflect/protoreflect"
    16  	"google.golang.org/protobuf/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  }
    93  

View as plain text