Documentation
¶
Overview ¶
Package protobuf is a pure-Go (CGO-free) reimplementation of the runtime and builder surface of Ruby's google-protobuf gem — the object model a Ruby program sees as the Google::Protobuf namespace — without any Ruby runtime and without a C extension (upstream google-protobuf ships as a C extension around libprotobuf/upb).
It does not reimplement the protobuf wire format: it is a Ruby-faithful API layer built on top of google.golang.org/protobuf, the official pure-Go protobuf runtime. Descriptors are compiled with protodesc, messages are google.golang.org/protobuf/types/dynamicpb dynamic messages, and binary/JSON encoding delegate to proto.Marshal / protojson. Every byte on the wire is therefore produced by the canonical Go runtime, so encode/decode is wire-compatible with real protobuf by construction.
Mapping to the gem ¶
Ruby (google-protobuf) Go (this package)
---------------------- -----------------
Google::Protobuf::DescriptorPool *DescriptorPool
.generated_pool GeneratedPool()
#build { … } (*DescriptorPool).Build
#lookup(name) (*DescriptorPool).Lookup
Google::Protobuf::Descriptor *Descriptor (.Msgclass, .Lookup, .Each)
Google::Protobuf::EnumDescriptor *EnumDescriptor
Google::Protobuf::FieldDescriptor *FieldDescriptor
a generated message class *MessageClass (.New)
a message instance *Message (.Get/.Set/.ToH/.Equal/.Dup/.Inspect)
Google::Protobuf::RepeatedField *RepeatedField
Google::Protobuf::Map *Map
Google::Protobuf.encode / .decode Encode / Decode
Google::Protobuf.encode_json/.decode_json EncodeJSON / DecodeJSON
Google::Protobuf::TypeError *TypeError
Google::Protobuf::ParseError *ParseError
Ruby value model ¶
Message field values cross the boundary as a small, fixed set of Go types, so a host (such as go-embedded-ruby) can map its own object graph to and from this package:
protobuf type Go value ------------- -------- bool bool int32/int64/sint*/sfixed* int64 uint32/uint64/fixed* uint64 float float64 double float64 string string bytes []byte enum Symbol (known value) or int64 (unknown number) message *Message (nil when unset) repeated *RepeatedField map *Map
Builder DSL ¶
(*DescriptorPool).Build mirrors the gem's pool.build block:
pool.Build(func(b *protobuf.Builder) {
b.AddMessage("Person", func(m *protobuf.MessageBuilder) {
m.Optional("name", protobuf.String, 1)
m.Optional("id", protobuf.Int32, 2)
m.Repeated("emails", protobuf.String, 3)
m.Map("attrs", protobuf.String, protobuf.String, 4)
})
})
cls := pool.Lookup("Person").(*protobuf.Descriptor).Msgclass()
p := cls.New(map[string]any{"name": "Ada"})
Scope ¶
The runtime + builder are covered faithfully. What is deliberately out of scope (a comment, per the task): the gem's full protoc-generated codegen DSL (the giant serialized-FileDescriptorProto string a .proto compiles to) — this package offers the equivalent builder DSL instead — and proto2 group wire syntax. Well-known types (Any, Timestamp, Duration, Struct, Value, ListValue, FieldMask, the wrappers and Empty) are pre-registered in the generated pool and round-trip through the canonical runtime.
Index ¶
- func AnyIs(any *Message, class *MessageClass) bool
- func Encode(m *Message) ([]byte, error)
- func EncodeJSON(m *Message, opts ...JSONOptions) ([]byte, error)
- type ArgumentError
- type Builder
- type Descriptor
- type DescriptorPool
- type EnumBuilder
- type EnumDescriptor
- type Error
- type FieldDescriptor
- type JSONOptions
- type Map
- func (m *Map) Clear()
- func (m *Map) Delete(key any) bool
- func (m *Map) Dup() *Map
- func (m *Map) Each(fn func(key, val any))
- func (m *Map) Equal(other *Map) bool
- func (m *Map) Get(key any) (any, bool)
- func (m *Map) Has(key any) bool
- func (m *Map) Inspect() string
- func (m *Map) Keys() []any
- func (m *Map) Length() int
- func (m *Map) Set(key, val any) error
- func (m *Map) ToHash() map[any]any
- func (m *Map) Values() []any
- type Message
- func (m *Message) Class() *MessageClass
- func (m *Message) Clone() *Message
- func (m *Message) Dup() *Message
- func (m *Message) Equal(other *Message) bool
- func (m *Message) Get(name string) (any, error)
- func (m *Message) Inspect() string
- func (m *Message) Set(name string, v any) error
- func (m *Message) ToH() map[string]any
- type MessageBuilder
- func (mb *MessageBuilder) Map(name string, keyType, valType Symbol, number int, valTypeName ...string)
- func (mb *MessageBuilder) Oneof(name string, fn func(*OneofBuilder))
- func (mb *MessageBuilder) Optional(name string, typ Symbol, number int, typeName ...string)
- func (mb *MessageBuilder) Repeated(name string, typ Symbol, number int, typeName ...string)
- type MessageClass
- type OneofBuilder
- type ParseError
- type RangeError
- type RepeatedField
- func (r *RepeatedField) At(i int) any
- func (r *RepeatedField) Clear()
- func (r *RepeatedField) Concat(other any) error
- func (r *RepeatedField) Dup() *RepeatedField
- func (r *RepeatedField) Each(fn func(any))
- func (r *RepeatedField) Equal(other *RepeatedField) bool
- func (r *RepeatedField) Inspect() string
- func (r *RepeatedField) Length() int
- func (r *RepeatedField) Push(vals ...any) error
- func (r *RepeatedField) SetAt(i int, v any) error
- func (r *RepeatedField) ToArray() []any
- type Symbol
- type TypeError
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AnyIs ¶
func AnyIs(any *Message, class *MessageClass) bool
AnyIs reports whether the Any holds a message of class, mirroring Google::Protobuf::Any#is?(Klass).
func Encode ¶
Encode serialises a message to the protobuf binary wire format, mirroring Google::Protobuf.encode(msg). The bytes are produced by the canonical google.golang.org/protobuf runtime, so they are wire-compatible with real protobuf. An encoding failure (e.g. an invalid-UTF-8 proto3 string) is reported as an ArgumentError (the gem raises).
func EncodeJSON ¶
func EncodeJSON(m *Message, opts ...JSONOptions) ([]byte, error)
EncodeJSON renders a message as proto3-JSON, mirroring Google::Protobuf.encode_json(msg). The mapping follows the proto3 JSON spec (via protojson). Note protojson deliberately varies insignificant whitespace between runs, so compare decoded values, not raw bytes, for equality.
Types ¶
type ArgumentError ¶
type ArgumentError struct{ Message string }
ArgumentError mirrors MRI raising ::ArgumentError — used here for an unknown field name, an unknown enum symbol, or a malformed builder specification.
func (*ArgumentError) Error ¶
func (e *ArgumentError) Error() string
func (*ArgumentError) RubyClass ¶
func (e *ArgumentError) RubyClass() string
type Builder ¶
type Builder struct {
// contains filtered or unexported fields
}
Builder is the receiver of a Build block, mirroring the object the gem yields to pool.build: add_message / add_enum.
func (*Builder) AddEnum ¶
func (b *Builder) AddEnum(name string, fn func(*EnumBuilder))
AddEnum defines an enum named name, mirroring add_enum. fn receives a *EnumBuilder describing its values.
func (*Builder) AddMessage ¶
func (b *Builder) AddMessage(name string, fn func(*MessageBuilder))
AddMessage defines a message named name, mirroring add_message. fn receives a *MessageBuilder describing its fields.
type Descriptor ¶
type Descriptor struct {
// contains filtered or unexported fields
}
Descriptor wraps a message descriptor, mirroring Google::Protobuf::Descriptor. It yields the message class (Msgclass) and its fields (Each / Lookup).
func (*Descriptor) Each ¶
func (d *Descriptor) Each(fn func(*FieldDescriptor))
Each iterates the message's fields in declaration order, mirroring descriptor.each { |field| … }.
func (*Descriptor) Lookup ¶
func (d *Descriptor) Lookup(name string) *FieldDescriptor
Lookup returns the field named name, or nil, mirroring descriptor.lookup(name).
func (*Descriptor) Msgclass ¶
func (d *Descriptor) Msgclass() *MessageClass
Msgclass returns the message class for this descriptor, mirroring descriptor.msgclass.
func (*Descriptor) Name ¶
func (d *Descriptor) Name() string
Name returns the message's fully-qualified name, mirroring descriptor.name.
type DescriptorPool ¶
type DescriptorPool struct {
// contains filtered or unexported fields
}
DescriptorPool is a registry of protobuf descriptors, mirroring the gem's Google::Protobuf::DescriptorPool. Build compiles a batch of message/enum definitions into it (the pool.build DSL) and Lookup resolves a fully-qualified name to its *Descriptor / *EnumDescriptor.
func GeneratedPool ¶
func GeneratedPool() *DescriptorPool
GeneratedPool returns the process-wide generated pool, mirroring Google::Protobuf::DescriptorPool.generated_pool: the single pool every generated message class registers into.
func NewDescriptorPool ¶
func NewDescriptorPool() *DescriptorPool
NewDescriptorPool returns an empty pool pre-loaded with the well-known-type files (google.protobuf.Timestamp, Duration, Any, Struct, Value, ListValue, FieldMask, the scalar wrappers and Empty), matching the gem: they are always resolvable in a fresh pool.
func (*DescriptorPool) Build ¶
func (p *DescriptorPool) Build(fn func(*Builder)) error
Build compiles one batch of definitions into the pool, mirroring
pool.build do add_message "Foo" do … end add_enum "Bar" do … end end
Every message and enum added by fn is placed in a single synthesised proto3 file so they may reference one another freely. It returns an error (never nil-swallowed) if the batch is malformed or fails to compile.
func (*DescriptorPool) Lookup ¶
func (p *DescriptorPool) Lookup(name string) any
Lookup resolves a fully-qualified name to its descriptor, mirroring pool.lookup(name). It returns a *Descriptor for a message, a *EnumDescriptor for an enum, or nil when the name is unknown.
func (*DescriptorPool) LookupMsgclass ¶
func (p *DescriptorPool) LookupMsgclass(name string) *MessageClass
LookupMsgclass is a convenience for the common case: it resolves name to a message and returns its class, or nil if name is not a message. It is equivalent to pool.lookup(name).msgclass in Ruby.
type EnumBuilder ¶
type EnumBuilder struct {
// contains filtered or unexported fields
}
EnumBuilder describes an enum's values, mirroring the add_enum block.
func (*EnumBuilder) Value ¶
func (eb *EnumBuilder) Value(name Symbol, number int)
Value adds an enum value, mirroring `value :NAME, number`.
type EnumDescriptor ¶
type EnumDescriptor struct {
// contains filtered or unexported fields
}
EnumDescriptor wraps an enum descriptor, mirroring Google::Protobuf::EnumDescriptor.
func (*EnumDescriptor) LookupName ¶
func (e *EnumDescriptor) LookupName(name string) (int, bool)
LookupName returns the number for the value named name, mirroring enum.lookup_name(name). The bool reports whether name is a defined value.
func (*EnumDescriptor) LookupValue ¶
func (e *EnumDescriptor) LookupValue(number int) (Symbol, bool)
LookupValue returns the Symbol name for number, mirroring enum.lookup_value(number). The bool reports whether number is defined.
func (*EnumDescriptor) Name ¶
func (e *EnumDescriptor) Name() string
Name returns the enum's fully-qualified name, mirroring enum.name.
type Error ¶
type Error interface {
error
// RubyClass is the fully-qualified Ruby exception class this error maps to
// (e.g. "Google::Protobuf::TypeError").
RubyClass() string
}
Error is the base of this package's error taxonomy. Every error this package returns satisfies Error and reports, via RubyClass, the Ruby exception class a host (go-embedded-ruby) should raise. It mirrors the exceptions the google-protobuf gem raises.
type FieldDescriptor ¶
type FieldDescriptor struct {
// contains filtered or unexported fields
}
FieldDescriptor wraps a field descriptor, mirroring Google::Protobuf::FieldDescriptor.
func (*FieldDescriptor) Label ¶
func (f *FieldDescriptor) Label() Symbol
Label returns the field's label as a Symbol (:optional or :repeated), mirroring field.label.
func (*FieldDescriptor) Name ¶
func (f *FieldDescriptor) Name() string
Name returns the field name, mirroring field.name.
func (*FieldDescriptor) Number ¶
func (f *FieldDescriptor) Number() int
Number returns the field's tag number, mirroring field.number.
func (*FieldDescriptor) Type ¶
func (f *FieldDescriptor) Type() Symbol
Type returns the field's type as a Symbol (:int32, :string, :message, …), mirroring field.type.
type JSONOptions ¶
type JSONOptions struct {
// EmitDefaults includes fields set to their default value, mirroring
// emit_defaults: true (protojson's EmitUnpopulated).
EmitDefaults bool
// PreserveProtoNames emits/accepts the proto field names rather than the
// lowerCamelCase JSON names, mirroring preserve_proto_fieldnames: true
// (protojson's UseProtoNames / decode's field-name handling).
PreserveProtoNames bool
// IgnoreUnknownFields skips unknown fields on decode, mirroring
// ignore_unknown_fields: true (protojson's DiscardUnknown).
IgnoreUnknownFields bool
}
JSONOptions mirror the keyword options of the gem's encode_json / decode_json.
type Map ¶
type Map struct {
// contains filtered or unexported fields
}
Map is a typed protobuf map, mirroring Google::Protobuf::Map. Keys and values are type-checked against the map's key/value types on insertion. Iteration order is deterministic (keys sorted) so Inspect / Keys / Each are reproducible; protobuf maps are unordered on the wire, so this only affects presentation.
func NewMap ¶
NewMap builds a standalone map with scalar key type k and scalar value type v, mirroring Google::Protobuf::Map.new(:string, :int32). Message/enum value types are not supported standalone (obtain such a map from a message field).
type Message ¶
type Message struct {
// contains filtered or unexported fields
}
Message is a message instance, mirroring an instance of a generated message class. It wraps a dynamicpb dynamic message so binary/JSON encoding go through the canonical runtime.
func AnyPack ¶
AnyPack wraps msg in a new google.protobuf.Any, mirroring Google::Protobuf::Any#pack: it sets type_url to the conventional type.googleapis.com/<full name> and value to the binary encoding of msg.
func AnyUnpack ¶
func AnyUnpack(any *Message, class *MessageClass) (*Message, error)
AnyUnpack decodes the message packed inside the Any as an instance of class, mirroring Google::Protobuf::Any#unpack(Klass). It returns nil when the Any does not hold a message of that type.
func Decode ¶
func Decode(class *MessageClass, data []byte) (*Message, error)
Decode parses binary protobuf bytes into a new instance of class, mirroring Google::Protobuf.decode(Klass, bytes). Malformed input is a ParseError.
func DecodeJSON ¶
func DecodeJSON(class *MessageClass, data []byte, opts ...JSONOptions) (*Message, error)
DecodeJSON parses proto3-JSON into a new instance of class, mirroring Google::Protobuf.decode_json(Klass, json). Malformed input is a ParseError.
func (*Message) Clone ¶
Clone returns a deep copy of the message, mirroring msg.clone. For a protobuf message dup and clone are identical (no singleton/frozen state to preserve).
func (*Message) Equal ¶
Equal reports whether m and other carry the same message contents, mirroring msg == other. Messages of different types are never equal.
func (*Message) Get ¶
Get reads field name, mirroring the generated reader msg.name. Repeated and map fields return their live *RepeatedField / *Map; an unset message field returns nil; scalars return their Ruby value (proto3 default when unset).
func (*Message) Inspect ¶
Inspect returns a debug string, mirroring msg.inspect: <Name: field: value, …>.
type MessageBuilder ¶
type MessageBuilder struct {
// contains filtered or unexported fields
}
MessageBuilder describes a message's fields, mirroring the block add_message yields (optional / repeated / map / oneof).
func (*MessageBuilder) Map ¶
func (mb *MessageBuilder) Map(name string, keyType, valType Symbol, number int, valTypeName ...string)
Map adds a map field, mirroring `map :name, :key_type, :value_type, number [, "ValueTypeName"]`. It synthesises the map-entry message the protobuf format requires.
func (*MessageBuilder) Oneof ¶
func (mb *MessageBuilder) Oneof(name string, fn func(*OneofBuilder))
Oneof adds a oneof group named name, mirroring `oneof :name do … end`. The fields declared in fn become members of the oneof.
func (*MessageBuilder) Optional ¶
func (mb *MessageBuilder) Optional(name string, typ Symbol, number int, typeName ...string)
Optional adds a singular field, mirroring `optional :name, :type, number [, "TypeName"]`. For a :message or :enum field the referenced fully-qualified type name is required as typeName.
type MessageClass ¶
type MessageClass struct {
// contains filtered or unexported fields
}
MessageClass is a generated message class, mirroring the anonymous Class the gem attaches to a Descriptor (descriptor.msgclass). New builds instances.
func WellKnownType ¶
func WellKnownType(shortName string) *MessageClass
WellKnownType returns the message class for a well-known type by its short name (e.g. "Timestamp", "Duration", "Any", "Struct", "Value", "ListValue", "FieldMask", "Empty", "StringValue"), from the generated pool. It returns nil for an unknown name.
func (*MessageClass) Descriptor ¶
func (c *MessageClass) Descriptor() *Descriptor
Descriptor returns the class's *Descriptor, mirroring klass.descriptor.
func (*MessageClass) Name ¶
func (c *MessageClass) Name() string
Name returns the message's fully-qualified name.
func (*MessageClass) New ¶
func (c *MessageClass) New(init ...map[string]any) (*Message, error)
New builds a new message, optionally initialised from a field=>value hash, mirroring MyMsg.new(field: value, …). It returns an error (the gem raises) if an init key is not a field or a value has the wrong type.
type OneofBuilder ¶
type OneofBuilder struct {
// contains filtered or unexported fields
}
OneofBuilder describes the fields inside a oneof.
type ParseError ¶
type ParseError struct{ Message string }
ParseError mirrors the gem's Google::Protobuf::ParseError, raised by Google::Protobuf.decode / decode_json on malformed input.
func (*ParseError) Error ¶
func (e *ParseError) Error() string
func (*ParseError) RubyClass ¶
func (e *ParseError) RubyClass() string
type RangeError ¶
type RangeError struct{ Message string }
RangeError mirrors MRI raising ::RangeError when an integer value does not fit the target field's integer type (e.g. 1<<40 into an int32 field), or when an enum number is out of the valid range.
func (*RangeError) Error ¶
func (e *RangeError) Error() string
func (*RangeError) RubyClass ¶
func (e *RangeError) RubyClass() string
type RepeatedField ¶
type RepeatedField struct {
// contains filtered or unexported fields
}
RepeatedField is a typed, ordered list of protobuf values, mirroring Google::Protobuf::RepeatedField. It offers the gem's core Enumerable surface (Push/<<, [], []=, each, to_a, +, ==, clear). Values are type-checked against the field's element type on insertion (a wrong type raises TypeError).
func NewRepeatedField ¶
func NewRepeatedField(t Symbol, initial ...any) (*RepeatedField, error)
NewRepeatedField builds a standalone repeated field of scalar element type t, mirroring Google::Protobuf::RepeatedField.new(:int32, [1, 2, 3]). Message and enum element types are not supported standalone (obtain such a list from a message field).
func (*RepeatedField) At ¶
func (r *RepeatedField) At(i int) any
At returns the element at index i, mirroring rf[i]. Negative indices count from the end; an out-of-range index returns nil (as Ruby's Array#[] does).
func (*RepeatedField) Clear ¶
func (r *RepeatedField) Clear()
Clear removes all elements, mirroring #clear.
func (*RepeatedField) Concat ¶
func (r *RepeatedField) Concat(other any) error
Concat appends every element of other (a *RepeatedField or []any), mirroring #concat / #+.
func (*RepeatedField) Dup ¶
func (r *RepeatedField) Dup() *RepeatedField
Dup returns a shallow copy with the same element type, mirroring #dup.
func (*RepeatedField) Each ¶
func (r *RepeatedField) Each(fn func(any))
Each iterates the elements in order, mirroring #each.
func (*RepeatedField) Equal ¶
func (r *RepeatedField) Equal(other *RepeatedField) bool
Equal reports whether r and other hold equal elements in the same order, mirroring #==.
func (*RepeatedField) Inspect ¶
func (r *RepeatedField) Inspect() string
Inspect renders the list, mirroring #inspect: [a, b, c].
func (*RepeatedField) Length ¶
func (r *RepeatedField) Length() int
Length returns the number of elements, mirroring #length / #size.
func (*RepeatedField) Push ¶
func (r *RepeatedField) Push(vals ...any) error
Push appends values, mirroring #push / #<<. It type-checks each value.
func (*RepeatedField) SetAt ¶
func (r *RepeatedField) SetAt(i int, v any) error
SetAt writes the element at index i, mirroring rf[i] = value. An out-of-range index is a RangeError (the gem raises IndexError). Negative indices count from the end.
func (*RepeatedField) ToArray ¶
func (r *RepeatedField) ToArray() []any
ToArray returns the elements as a []any, mirroring #to_a.
type Symbol ¶
type Symbol string
Symbol is a Ruby Symbol (`:name`). The builder DSL takes field types as Symbols (`protobuf.Int32` == Ruby `:int32`); enum field values are read back as Symbols (the value's name), matching the gem.
const ( Int32 Symbol = "int32" Int64 Symbol = "int64" Uint32 Symbol = "uint32" Uint64 Symbol = "uint64" Sint32 Symbol = "sint32" Sint64 Symbol = "sint64" Fixed32 Symbol = "fixed32" Fixed64 Symbol = "fixed64" Sfixed32 Symbol = "sfixed32" Sfixed64 Symbol = "sfixed64" Float Symbol = "float" Double Symbol = "double" Bool Symbol = "bool" String Symbol = "string" Bytes Symbol = "bytes" MessageType Symbol = "message" Enum Symbol = "enum" )
Field-type symbols accepted by the builder DSL, mirroring the gem's type symbols (:int32, :string, :message, …).
type TypeError ¶
type TypeError struct{ Message string }
TypeError mirrors the gem's Google::Protobuf::TypeError: a value handed to a field setter (or to a repeated/map container) whose Ruby type does not match the field's protobuf type. In MRI Google::Protobuf::TypeError subclasses the core ::TypeError.
