lazyproto

package
v0.28.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 11, 2024 License: MIT Imports: 9 Imported by: 0

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrTagNotFound is returned by [PartialDecodeResult.FieldData] when the specified tag(s) do not
	// exist in the result.
	ErrTagNotFound = fmt.Errorf("the requested tag does not exist in the partial decode result")
)

Functions

This section is empty.

Types

type DecodeResult

type DecodeResult struct {
	// contains filtered or unexported fields
}

DecodeResult holds a (possibly nested) mapping of integer field tags to FieldData instances which can be used to retrieve typed values for specific Protobuf message fields.

func Decode

func Decode(data []byte, def Def) (res DecodeResult, err error)

Decode extracts the specified field tags from data without unmarshaling the entire message. The methods on the returned PartialDecodeResult can be used to retrieve the decoded values.

The def param is an optionally nested mapping of protobuf field tags declaring which values should be decoded from the message. If the value for a given tag is a nested mapping and the wire type in the encoded data is WireTypeLengthDelimited , the contents are treated as a nested message and is decoded recursively.

The purpose of this API is to avoid fully unmarshalling nested message data when only a small subset of field values are needed, so [PartialDecodeResult] and FieldData only support extracting scalar values or slices of scalar values. Consumers that need to decode entire messages will need to use [Unmarshal] instead.

func (*DecodeResult) Close

func (r *DecodeResult) Close() error

Close releases all internal resources held by r.

Consumers should always call Close() on instances returned by Decode to ensure that internal resources are cleaned up.

func (*DecodeResult) FieldData

func (r *DecodeResult) FieldData(tags ...int) (*FieldData, error)

The FieldData method returns a FieldData instance for the specified tag "path", if it exists.

The tags parameter is a list of one or more integer field tags that act as a "path" to a particular field to support retreiving fields from nested messages. Each value is used to retreieve the field data at the corresponding level of nesting, i.e. a value of [1, 2] would return the field data for tag 2 within the nested data for tag 1 at the root.

Example
// data contains the serialized bytes of an Example Protobuf message that is
// defined as:
//	message Example {
//		int64  id     = 1;
//		Nested nested = 2;
//	}
//	message Nested {
//		string name        = 1;
//		string description = 2;
//	}
data := []byte{
	// id: 1
	(1 << 3), 0x1,
	// nested: 10 bytes
	(2 << 3) | 2, 0x0A,
	// nested.name: foo
	(1 << 3) | 2, 0x03, 0x66, 0x6f, 0x6f,
	// nested.description: bar
	(2 << 3) | 2, 0x03, 0x62, 0x61, 0x72,
}
def := NewDef()
// extract tags 1 and 2 from the nested message at tag 2 in the outer message
_ = def.NestedTag(2, 1, 2)
res, err := Decode(data, def)
if err != nil {
	fmt.Println("error from decode:", err)
	return
}
defer func() {
	if err := res.Close(); err != nil {
		fmt.Println("error from DecodeResult.Close():", err)
	}
}()
// grab the field data
nameData, err := res.FieldData(2, 1)
if err != nil {
	fmt.Println("error accessing field data for 'name':", err)
	return
}
descriptionData, err := res.FieldData(2, 2)
if err != nil {
	fmt.Println("error accessing field data for 'description':", err)
	return
}
// extract the values
name, err := nameData.StringValue()
if err != nil {
	fmt.Println("error retrieving string value for 'name':", err)
	return
}
description, err := descriptionData.StringValue()
if err != nil {
	fmt.Println("error retrieving string value for 'description':", err)
	return
}
fmt.Printf("name: %s\ndescription: %s", name, description)
Output:

name: foo
description: bar

type Def

type Def map[int]Def

A Def is an optionally nested mapping of protobuf field tags declaring which values should be decoded from a message. If the value for given tag maps to a nested definition and the wire type in the message data is WireTypeLengthDelimited, the contents are treated as a nested message and the nested mapping is applied to the field data recursively.

Tags must be valid [Protobuf field tags] (between 1 and 19000 or between 20000 and 536870911).

Because a given tag can map to either a scalar value or a sub-mapping for decoding a nested message, we have an edge case where a consumer cannot extract both the bytes of a nested message and individual fields. For this case use a negative tag value to add a mapping that will return the raw bytes of the nested message field.

// extract both the raw bytes of the nested message at field 3 *and* the value of field 1 within
// that nested message
def := lazyproto.NewDef()
_ = def.Tags(-3)
_ = def.NestedTag(3, 1)
decodeResult, _ := lazyproto.Decode(data, def)
...
// get the raw bytes
fd, _ := decodeResult.FieldData(-3)
raw, _ := fd.BytesValue()
...
// get the value of field 1 within the nested message
fd, _ = decodeResult.FieldData(3, 1)
v, _ := fd.StringValue()
...

func NewDef

func NewDef(tags ...int) Def

NewDef initializes and returns a new Def with mappings for the specified field tags.

func (Def) Get

func (d Def) Get(tag int) (Def, bool)

Get returns the mapping value for tag plus a boolean indicating whether or not the mapping existed

func (Def) NestedTag

func (d Def) NestedTag(tag int, nestedTags ...int) Def

NestedTag adds a mapping for tag to a nested Def with the specified field tags for the nested message, replacing any existing mapping, and returns the nested Def

func (Def) Tags

func (d Def) Tags(tags ...int) Def

Tags adds one or more field tags to the mapping, replacing any existing mappings, and returns the Def.

func (Def) Validate

func (d Def) Validate() error

Validate checks that d is structurally and semantically valid and returns an error if it is not.

type FieldData

type FieldData struct {
	// contains filtered or unexported fields
}

FieldData is a wrapper around lazily-decoded Protobuf field data, with accessors for retrieving typed values.

All methods potentially return an error because the Protobuf encoding is not self-describing. We must instead rely on the consumer having some prior knowledge of the message data and using that knowledge to access the fields appropriately.

The XxxValue() methods convert the lazily decoded field data into a single value of the appropriate Go type. If the decoded message contained repeated data for the field, the last value is returned.

Similarly, the XxxValues() methods convert the data into a slice of the appropriate Go type. If the decoded message contained only a single value, or the field is not defined as repeated, the methods return a one-element slice. We err on the side of determinism since it's not possible to distinguish between these two scenarios based on only the encoded data.

For both XxxValue() and XxxValues(), if the source data was not of the correct Protobuf wire type for the target Go type a WireTypeMismatchError error is returned with relevant details.

A zero-valued instance is the equivalent of a varint field with no data. All methods valid for varint data will return ErrTagNotFound and all others will return a WireTypeMismatchError.

To avoid panics, any method called on a nil instance returns a zero value and ErrTagNotFound.

func (*FieldData) BoolValue

func (fd *FieldData) BoolValue() (bool, error)

BoolValue converts the lazily-decoded field data into a bool.

Since Protobuf encodes boolean values as integers, any varint-encoded integer value is valid. A value of zero is treated as false and any non-zero value is treated as true.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) BoolValues

func (fd *FieldData) BoolValues() ([]bool, error)

BoolValues converts the lazily-decoded field data into a []bool.

Since Protobuf encodes boolean values as integers, any varint-encoded integer value is valid. A value of zero is treated as false and any non-zero value is treated as true.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) BytesValue

func (fd *FieldData) BytesValue() ([]byte, error)

BytesValue converts the lazily-decoded field data into a []byte.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) BytesValues

func (fd *FieldData) BytesValues() ([][]byte, error)

BytesValues converts the lazily-decoded field data into a [][]byte.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) Fixed32Value

func (fd *FieldData) Fixed32Value() (uint32, error)

Fixed32Value converts the lazily-decoded field data into a uint32.

Use this method to retreive values that are defined as fixed32 in the Protobuf message. Fields that are defined as uint32 (and so use the Protobuf base128 varint encoding) should be retrieved using Int32Value() instead.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) Fixed32Values

func (fd *FieldData) Fixed32Values() ([]uint32, error)

Fixed32Values converts the lazily-decoded field data into a []uint32.

Use this method to retreive values that are defined as fixed32 in the Protobuf message. Fields that are defined as uint32 (and so use the Protobuf base128 varint encoding) should be retrieved using Int32Values() instead.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) Fixed64Value

func (fd *FieldData) Fixed64Value() (uint64, error)

Fixed64Value converts the lazily-decoded field data into a uint64.

Use this method to retreive values that are defined as fixed64 in the Protobuf message. Fields that are defined as uint64 (and so use the Protobuf base128 varint encoding) should be retrieved using Int64Value() instead.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) Fixed64Values

func (fd *FieldData) Fixed64Values() ([]uint64, error)

Fixed64Values converts the lazily-decoded field data into a []uint64.

Use this method to retreive values that are defined as fixed64 in the Protobuf message. Fields that are defined as uint64 (and so use the Protobuf base128 varint encoding) should be retrieved using Int64Values() instead.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) Float32Value

func (fd *FieldData) Float32Value() (float32, error)

Float32Value converts the lazily-decoded field data into a float32.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) Float32Values

func (fd *FieldData) Float32Values() ([]float32, error)

Float32Values converts the lazily-decoded field data into a []float32.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) Float64Value

func (fd *FieldData) Float64Value() (float64, error)

Float64Value converts the lazily-decoded field data into a float64.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) Float64Values

func (fd *FieldData) Float64Values() ([]float64, error)

Float64Values converts the lazily-decoded field data into a []float64.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) Int32Value

func (fd *FieldData) Int32Value() (int32, error)

Int32Value converts the lazily-decoded field data into an int32.

Use this method to retreive values that are defined as int32 in the Protobuf message. Fields that are defined as sint32 (and so use the Protobuf ZigZag encoding) should be retrieved using SInt32Value() instead.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) Int32Values

func (fd *FieldData) Int32Values() ([]int32, error)

Int32Values converts the lazily-decoded field data into a []int32.

Use this method to retreive values that are defined as int32 in the Protobuf message. Fields that are defined as sint32 (and so use the Protobuf ZigZag encoding) should be retrieved using SInt32Values() instead.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) Int64Value

func (fd *FieldData) Int64Value() (int64, error)

Int64Value converts the lazily-decoded field data into an int64.

Use this method to retreive values that are defined as int64 in the Protobuf message. Fields that are defined as sint64 (and so use the Protobuf ZigZag encoding) should be retrieved using SInt64Value() instead.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) Int64Values

func (fd *FieldData) Int64Values() ([]int64, error)

Int64Values converts the lazily-decoded field data into a []int64.

Use this method to retreive values that are defined as int64 in the Protobuf message. Fields that are defined as sint64 (and so use the Protobuf ZigZag encoding) should be retrieved using SInt64Values() instead.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) SInt32Value

func (fd *FieldData) SInt32Value() (int32, error)

SInt32Value converts the lazily-decoded field data into an int32.

Use this method to retreive values that are defined as sint32 in the Protobuf message. Fields that are defined as int32 (and so use the Protobuf base128 varint encoding) should be retrieved using Int32Value() instead.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) SInt32Values

func (fd *FieldData) SInt32Values() ([]int32, error)

SInt32Values converts the lazily-decoded field data into a []int32.

Use this method to retreive values that are defined as sint32 in the Protobuf message. Fields that are defined as int32 (and so use the Protobuf base128 varint encoding) should be retrieved using Int32Values() instead.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) SInt64Value

func (fd *FieldData) SInt64Value() (int64, error)

SInt64Value converts the lazily-decoded field data into an int64.

Use this method to retreive values that are defined as sint64 in the Protobuf message. Fields that are defined as int64 (and so use the Protobuf base128 varint encoding) should be retrieved using Int64Value() instead.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) SInt64Values

func (fd *FieldData) SInt64Values() ([]int64, error)

SInt64Values converts the lazily-decoded field data into a []int64.

Use this method to retreive values that are defined as sint64 in the Protobuf message. Fields that are defined as int64 (and so use the Protobuf base128 varint encoding) should be retrieved using Int64Values() instead.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) StringValue

func (fd *FieldData) StringValue() (string, error)

StringValue converts the lazily-decoded field data into a string.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) StringValues

func (fd *FieldData) StringValues() ([]string, error)

StringValues converts the lazily-decoded field data into a []string.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) UInt32Value

func (fd *FieldData) UInt32Value() (uint32, error)

UInt32Value converts the lazily-decoded field data into a uint32.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) UInt32Values

func (fd *FieldData) UInt32Values() ([]uint32, error)

UInt32Values converts the lazily-decoded field data into a []uint32.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) UInt64Value

func (fd *FieldData) UInt64Value() (uint64, error)

UInt64Value converts the lazily-decoded field data into a uint64.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

func (*FieldData) UInt64Values

func (fd *FieldData) UInt64Values() ([]uint64, error)

UInt64Values converts the lazily-decoded field data into a []uint64.

See the FieldData docs for more specific details about interpreting lazily-decoded data.

type RawValueConversionError

type RawValueConversionError string

RawValueConversionError is returned when the lazily-decoded value for a Protobuf field could not be converted to the requested Go type.

func (*RawValueConversionError) Error

func (e *RawValueConversionError) Error() string

Error satisfies the error interface

type WireTypeMismatchError

type WireTypeMismatchError string

WireTypeMismatchError is returned when the actual type of a lazily decoded Protobuf field does not match one of the supported types.

func (*WireTypeMismatchError) Error

func (e *WireTypeMismatchError) Error() string

Error satisfies the error interface

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL