capnp

package module
v2.0.0+incompatible Latest Latest
Warning

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

Go to latest
Published: Sep 20, 2015 License: MIT Imports: 9 Imported by: 0

README

Cap'n Proto bindings for Go

Build Status GoDoc

go-capnproto consists of:

  • a Go code generator for Cap'n Proto
  • a Go package that provides runtime support
  • a Go package that implements the RPC protocol

Getting started

You will need the capnp tool to compile schemas into Go. This package has been tested with Cap'n Proto 0.5.0.

# first: be sure you have your GOPATH env variable setup.
$ go get -u -t zombiezen.com/go/capnproto2/...
$ go test -v zombiezen.com/go/capnproto2/...

Then read the Getting Started guide.

API Compatibility

Consider this package's API as beta software, since the Cap'n Proto spec is not final. In the spirit of the Go 1 compatibility guarantee, I will make every effort to avoid making breaking API changes. The major cases where I reserve the right to make breaking changes are:

  • Security.
  • Changes in the Cap'n Proto specification.
  • Bugs.

Documentation

See the docs on godoc.org.

What is Cap'n Proto?

The best cerealization...

https://capnproto.org/

License

MIT - see LICENSE file

Documentation

Overview

Package capnp is a Cap'n Proto library for Go. https://capnproto.org/

Generating code

capnpc-go provides the compiler backend for capnp.

# First, install capnpc-go to $PATH.
go install zombiezen.com/go/capnproto2/capnpc-go
# Then, generate Go files.
capnp compile -ogo *.capnp

capnpc-go requires two annotations for all files: package and import. package is needed to know what package to place at the head of the generated file and what identifier to use when referring to the type from another package. import should be the fully qualified import path and is used to generate import statement from other packages and to detect when two types are in the same package. For example:

using Go = import "zombiezen.com/go/capnproto2/go.capnp";
$Go.package("main");
$Go.import("zombiezen.com/go/capnproto2/example");

For adding documentation comments to the generated code, there's the doc annotation. This annotation adds the comment to a struct, enum or field so that godoc will pick it up. For example:

struct Zdate $Go.doc("Zdate represents a calendar date") {
  year  @0   :Int16;
  month @1   :UInt8;
  day   @2   :UInt8 ;
}

Messages and Segments

In Cap'n Proto, the unit of communication is a message. A message consists of one or more segments -- contiguous blocks of memory. This allows large messages to be split up and loaded independently or lazily. Typically you will use one segment per message. Logically, a message is organized in a tree of objects, with the root always being a struct (as opposed to a list or primitive). Messages can be read from and written to a stream.

Pointers

The interface for accessing a Cap'n Proto object is Pointer. This can refer to a struct, a list, or an interface. Pointers have value semantics and refer to data in a single segment. All of the concrete pointer types have a notion of "valid". An invalid pointer will return the default value from any accessor and panic when any setter is called.

Data accessors and setters (i.e. struct primitive fields and list elements) do not return errors, but pointer accessors and setters do. There are a reasons that a read or write of a pointer can fail, but the most common are bad pointers or allocation failures. For accessors, an invalid object will be returned in case of an error.

Since Go doesn't have generics, wrapper types provide type safety on lists. This package provides lists of basic types, and capnpc-go generates list wrappers for named types. However, if you need to use deeper nesting of lists (e.g. List(List(UInt8))), you will need to use a PointerList and wrap the elements.

Structs

For the following schema:

struct Foo {
  num @0 :UInt32;
  bar @1 :Foo;
}

capnpc-go will generate:

// Foo is a pointer to a Foo struct in a segment.
// Member functions are provided to get/set members in the
// struct.
type Foo struct{ capnp.Struct }

// NewFoo creates a new orphaned Foo struct, preferring placement in
// s.  If there isn't enough space, then another segment in the
// message will be used or allocated.  You can set a field of type Foo
// to this new message, but usually you will want to use the
// NewBar()-style method shown below.
func NewFoo(s *capnp.Segment) (Foo, error)

// NewRootFoo creates a new Foo struct and sets the message's root to
// it.
func NewRootFoo(s *capnp.Segment) (Foo, error)

// ReadRootFoo reads the message's root pointer and converts it to a
// Foo struct.
func ReadRootFoo(msg *capnp.Message) (Foo, error)

// Num returns the value of the num field.
func (s Foo) Num() uint32

// SetNum sets the value of the num field to v.
func (s Foo) SetNum(v uint32)

// Bar returns the value of the bar field.  This can return an error
// if the pointer goes beyond the segment's range, the segment fails
// to load, or the pointer recursion limit has been reached.
func (s Foo) Bar() (Foo, error)

// SetBar sets the value of the bar field to v.
func (s Foo) SetBar(v Foo) error

// NewBar sets the bar field to a newly allocated Foo struct,
// preferring placement in s's segment.
func (s Foo) NewBar() (Foo, error)

// Foo_List is a value with pointer semantics. It is created for all
// structs, and is used for List(Foo) in the capnp file.
type Foo_List struct{ capnp.List }

// NewFoo_List creates a new orphaned List(Foo), preferring placement
// in s. This can then be added to a message by using a Set function
// which takes a Foo_List. sz specifies the number of elements in the
// list.  The list's size cannot be changed after creation.
func NewFoo_List(s *capnp.Segment, sz int32) Foo_List

// Len returns the number of elements in the list.
func (s Foo_List) Len() int

// At returns a pointer to the i'th element. If i is an invalid index,
// this will return an invalid Foo (all getters will return default
// values, setters will fail).
func (s Foo_List) At(i int) Foo

// Foo_Promise is a promise for a Foo.  Methods are provided to get
// promises of struct and interface fields.
type Foo_Promise struct{ *capnp.Pipeline }

// Get waits until the promise is resolved and returns the result.
func (p Foo_Promise) Get() (Foo, error)

// Bar returns a promise for that bar field.
func (p Foo_Promise) Bar() Foo_Promise

Groups

For each group a typedef is created with a different method set for just the groups fields:

struct Foo {
	group :Group {
		field @0 :Bool;
	}
}

generates the following:

type Foo struct{ capnp.Struct }
type Foo_group Foo

func (s Foo) Group() Foo_group
func (s Foo_group) Field() bool

That way the following may be used to access a field in a group:

var f Foo
value := f.Group().Field()

Note that group accessors just convert the type and so have no overhead.

Unions

Named unions are treated as a group with an inner unnamed union. Unnamed unions generate an enum Type_Which and a corresponding Which() function:

struct Foo {
	union {
		a @0 :Bool;
		b @1 :Bool;
	}
}

generates the following:

type Foo_Which uint16

const (
	Foo_Which_a Foo_Which = 0
	Foo_Which_b Foo_Which = 1
)

func (s Foo) A() bool
func (s Foo) B() bool
func (s Foo) SetA(v bool)
func (s Foo) SetB(v bool)
func (s Foo) Which() Foo_Which

Which() should be checked before using the getters, and the default case must always be handled.

Setters for single values will set the union discriminator as well as set the value.

For voids in unions, there is a void setter that just sets the discriminator. For example:

struct Foo {
	union {
		a @0 :Void;
		b @1 :Void;
	}
}

generates the following:

func (s Foo) SetA() // Set that we are using A
func (s Foo) SetB() // Set that we are using B

Similarly, for groups in unions, there is a group setter that just sets the discriminator. This must be called before the group getter can be used to set values. For example:

struct Foo {
	union {
		a :group {
			v :Bool
		}
		b :group {
			v :Bool
		}
	}
}

and in usage:

f.SetA()         // Set that we are using group A
f.A().SetV(true) // then we can use the group A getter to set the inner values

Enums

capnpc-go generates enum values as constants. For example in the capnp file:

enum ElementSize {
  empty @0;
  bit @1;
  byte @2;
  twoBytes @3;
  fourBytes @4;
  eightBytes @5;
  pointer @6;
  inlineComposite @7;
}

In the generated capnp.go file:

type ElementSize uint16

const (
	ElementSize_empty           ElementSize = 0
	ElementSize_bit             ElementSize = 1
	ElementSize_byte            ElementSize = 2
	ElementSize_twoBytes        ElementSize = 3
	ElementSize_fourBytes       ElementSize = 4
	ElementSize_eightBytes      ElementSize = 5
	ElementSize_pointer         ElementSize = 6
	ElementSize_inlineComposite ElementSize = 7
)

In addition an enum.String() function is generated that will convert the constants to a string for debugging or logging purposes. By default, the enum name is used as the tag value, but the tags can be customized with a $Go.tag or $Go.notag annotation.

For example:

enum ElementSize {
	empty @0           $Go.tag("void");
	bit @1             $Go.tag("1 bit");
	byte @2            $Go.tag("8 bits");
	inlineComposite @7 $Go.notag;
}

In the generated go file:

func (c ElementSize) String() string {
	switch c {
	case ElementSize_empty:
		return "void"
	case ElementSize_bit:
		return "1 bit"
	case ElementSize_byte:
		return "8 bits"
	default:
		return ""
	}
}

Interfaces

capnpc-go generates type-safe Client wrappers for interfaces. For parameter lists and result lists, structs are generated as described above with the names Interface_method_Params and Interface_method_Results, unless a single struct type is used. For example, for this interface:

interface Calculator {
	evaluate @0 (expression :Expression) -> (value :Value);
}

capnpc-go generates the following Go code (along with the structs Calculator_evaluate_Params and Calculator_evaluate_Results):

// Calculator is a client to a Calculator interface.
type Calculator struct{ Client capnp.Client }

// Evaluate calls `evaluate` on the client.  params is called on a newly
// allocated Calculator_evaluate_Params struct to fill in the parameters.
func (c Calculator) Evaluate(
	ctx context.Context,
	params func(Calculator_evaluate_Params) error,
	opts ...capnp.CallOption) *Calculator_evaluate_Results_Promise

capnpc-go also generates code to implement the interface:

// A Calculator_Server implements the Calculator interface.
type Calculator_Server interface {
	Evaluate(Calculator_evaluate_Call) error
}

// Calculator_evaluate_Call holds the arguments for a Calculator.evaluate server call.
type Calculator_evaluate_Call struct {
	Ctx     context.Context
	Options capnp.CallOptions
	Params  Calculator_evaluate_Params
	Results Calculator_evaluate_Results
}

// Calculator_ServerToClient is equivalent to calling:
// NewCalculator(capnp.NewServer(Calculator_Methods(nil, s), s))
// If s does not implement the Close method, then nil is used.
func Calculator_ServerToClient(s Calculator_Server) Calculator

// Calculator_Methods appends methods from Calculator that call to server and
// returns the methods.  If methods is nil or the capacity of the underlying
// slice is too small, a new slice is returned.
func Calculator_Methods(methods []server.Method, s Calculator_Server) []server.Method

Since a single capability may want to implement many interfaces, you can use multiple *_Methods functions to build a single slice to send to NewServer.

An example of combining the client/server code to communicate with a locally implemented Calculator:

var srv Calculator_Server
calc := Calculator_ServerToClient(srv)
result := calc.Evaluate(ctx, func(params Calculator_evaluate_Params) {
	params.SetExpression(expr)
})
val := result.Value().Get()

A note about message ordering: when implementing a server method, you are responsible for acknowledging delivery of a method call. Failure to do so can cause deadlocks. See the server.Ack function for more details.

Example
// Make a brand new empty message.
msg, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))

// If you want runtime-type identification, this is easily obtained. Just
// wrap everything in a struct that contains a single anoymous union (e.g. struct Z).
// Then always set a Z as the root object in you message/first segment.
// The cost of the extra word of storage is usually worth it, as
// then human readable output is easily obtained via a shell command such as
//
// $ cat binary.cpz | capnp decode aircraft.capnp Z
//
// If you need to conserve space, and know your content in advance, it
// isn't necessary to use an anonymous union. Just supply the type name
// in place of 'Z' in the decode command above.

// There can only be one root.  Subsequent NewRoot* calls will set the root
// pointer and orphan the previous root.
z, err := air.NewRootZ(seg)
if err != nil {
	panic(err)
}

// then non-root objects:
aircraft, err := z.NewAircraft()
if err != nil {
	panic(err)
}
b737, err := aircraft.NewB737()
if err != nil {
	panic(err)
}
planebase, err := b737.NewBase()
if err != nil {
	panic(err)
}

// Set primitive fields
planebase.SetCanFly(true)
planebase.SetName("Henrietta")
planebase.SetRating(100)
planebase.SetMaxSpeed(876) // km/hr
// if we don't set capacity, it will get the default value, in this case 0.
//planebase.SetCapacity(26020) // Liters fuel

// Creating a list
homes, err := air.NewAirport_List(seg, 2)
if err != nil {
	panic(err)
}
homes.Set(0, air.Airport_jfk)
homes.Set(1, air.Airport_lax)
// Setting a list field
planebase.SetHomes(homes)

// Ready to write!

// You can write to memory...
buf, err := msg.Marshal()
if err != nil {
	panic(err)
}
_ = buf

// ... or write to an io.Writer.
file, err := ioutil.TempFile("", "go-capnproto")
if err != nil {
	panic(err)
}
defer file.Close()
defer os.Remove(file.Name())
err = capnp.NewEncoder(file).Encode(msg)
if err != nil {
	panic(err)
}

// Read back and view that file in human readable format. Defined in util_test.go
text, err := CapnFileToText(file.Name(), schemaPath, "")
if err != nil {
	panic(err)
}
fmt.Printf("here is our aircraft:\n")
fmt.Printf("%s\n", text)
Output:

here is our aircraft:
(aircraft = (b737 = (base = (name = "Henrietta", homes = [jfk, lax], rating = 100, canFly = true, capacity = 0, maxSpeed = 876))))

Index

Examples

Constants

View Source
const (
	Package    = uint64(0xbea97f1023792be0)
	Import     = uint64(0xe130b601260e44b5)
	Doc        = uint64(0xc58ad6bd519f935e)
	Tag        = uint64(0xa574b41924caefc7)
	Notag      = uint64(0xc8768679ec52e012)
	Customtype = uint64(0xfa10659ae02f2093)
	Name       = uint64(0xc2b96012172f8df1)
)

go.capnp annotation values.

Variables

View Source
var ErrNullClient = errors.New("capnp: call on null client")

ErrNullClient is returned from a call made on a null client pointer.

View Source
var ErrUnimplemented = errors.New("capnp: method not implemented")

ErrUnimplemented is the error returned when a method is called on a server that does not implement the method.

Functions

func HasData

func HasData(p Pointer) bool

HasData returns true if the pointer is valid and has non-zero size.

func IsErrorClient

func IsErrorClient(c Client) bool

IsErrorClient reports whether c was created with ErrorClient.

func IsFixedAnswer

func IsFixedAnswer(ans Answer) bool

IsFixedAnswer reports whether an answer was created by ImmediateAnswer or ErrorAnswer.

func IsUnimplemented

func IsUnimplemented(e error) bool

IsUnimplemented reports whether e indicates an unimplemented method error.

func IsValid

func IsValid(p Pointer) bool

IsValid reports whether p is non-nil and valid.

func NewMessage

func NewMessage(arena Arena) (msg *Message, first *Segment, err error)

NewMessage creates a message with a new root and returns the first segment. It is an error to call NewMessage on an arena with data in it.

func ToData

func ToData(p Pointer) []byte

ToData attempts to convert p into Data, returning nil if p is not a valid 1-byte list pointer.

func ToDataDefault

func ToDataDefault(p Pointer, def []byte) []byte

ToDataDefault attempts to convert p into Data, returning def if p is not a valid 1-byte list pointer.

func ToText

func ToText(p Pointer) string

ToText attempts to convert p into Text, returning an empty string if p is not a valid 1-byte list pointer.

func ToTextDefault

func ToTextDefault(p Pointer, def string) string

ToTextDefault attempts to convert p into Text, returning def if p is not a valid 1-byte list pointer.

Types

type Address

type Address uint32

An Address is an index inside a segment's data (in bytes).

func (Address) GoString

func (addr Address) GoString() string

GoString returns the address in hex format.

func (Address) String

func (addr Address) String() string

String returns the address in hex format.

type Answer

type Answer interface {
	// Struct waits until the call is finished and returns the result.
	Struct() (Struct, error)

	PipelineCall(transform []PipelineOp, call *Call) Answer
	PipelineClose(transform []PipelineOp) error
}

An Answer is the deferred result of a client call, which is usually wrapped by a Pipeline.

func ErrorAnswer

func ErrorAnswer(e error) Answer

ErrorAnswer returns a Answer that always returns error e.

func ImmediateAnswer

func ImmediateAnswer(s Struct) Answer

ImmediateAnswer returns an Answer that accesses s.

type Arena

type Arena interface {
	// NumSegments returns the number of segments in the arena.
	// This must not be larger than 1<<32.
	NumSegments() int64

	// Data loads the data for the segment with the given ID.
	Data(id SegmentID) ([]byte, error)

	// Allocate allocates a byte slice such that cap(data) - len(data) >= minsz.
	// segs is a map of already loaded segments keyed by ID.  The arena may
	// return an existing segment's ID, in which case the arena is responsible
	// for copying the existing data to the returned byte slice.  Allocate must
	// not modify the segments passed into it.
	Allocate(minsz Size, segs map[SegmentID]*Segment) (SegmentID, []byte, error)
}

An Arena loads and allocates segments for a Message. Segment IDs must be tightly packed in the range [0, NumSegments()).

func MultiSegment

func MultiSegment(b [][]byte) Arena

MultiSegment returns a new arena that allocates new segments when they are full. b can be used to populate the buffer for reading or to reserve memory of a specific size.

func SingleSegment

func SingleSegment(b []byte) Arena

SingleSegment returns a new arena with an expanding single-segment buffer. b can be used to populate the segment for reading or to reserve memory of a specific size. A SingleSegment arena does not return errors unless you attempt to access another segment.

type BitList

type BitList struct{ List }

A BitList is a reference to a list of booleans.

func NewBitList

func NewBitList(s *Segment, n int32) (BitList, error)

NewBitList creates a new bit list, preferring placement in s.

func (BitList) At

func (p BitList) At(i int) bool

At returns the i'th bit.

func (BitList) Set

func (p BitList) Set(i int, v bool)

Set sets the i'th bit to v.

type BitOffset

type BitOffset uint32

BitOffset is an offset in bits from the beginning of a struct's data section.

func (BitOffset) GoString

func (bit BitOffset) GoString() string

GoString returns the offset as a Go expression.

func (BitOffset) String

func (bit BitOffset) String() string

String returns the offset in the format "bit X".

type Call

type Call struct {
	// Ctx is the context of the call.
	Ctx context.Context

	// Method is the interface ID and method ID, along with the optional name,
	// of the method to call.
	Method Method

	// Params is a struct containing parameters for the call.
	// This should be set when the RPC system receives a call for an
	// exported interface.  It is mutually exclusive with ParamsFunc
	// and ParamsSize.
	Params Struct
	// ParamsFunc is a function that populates an allocated struct with
	// the parameters for the call.  ParamsSize determines the size of the
	// struct to allocate.  This is used when application code is using a
	// client.  These settings should be set together; they are mutually
	// exclusive with Params.
	ParamsFunc func(Struct) error
	ParamsSize ObjectSize

	// Options passes RPC-specific options for the call.
	Options CallOptions
}

The Call type holds the record for an outgoing interface call.

func (*Call) Copy

func (call *Call) Copy(s *Segment) (*Call, error)

Copy clones a call, ensuring that its Params are placed. If Call.ParamsFunc is nil, then the same Call will be returned.

func (*Call) PlaceParams

func (call *Call) PlaceParams(s *Segment) (Struct, error)

PlaceParams returns the parameters struct, allocating it inside segment s as necessary. If s is nil, a new single-segment message is allocated.

type CallOption

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

A CallOption is a function that modifies options on an interface call.

func SetOptionValue

func SetOptionValue(key, value interface{}) CallOption

SetOptionValue returns a call option that associates a value to an option key. This can be retrieved later with CallOptions.Value.

type CallOptions

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

CallOptions holds RPC-specific options for an interface call. Its usage is similar to the values in context.Context, but is only used for a single call: its values are not intended to propagate to other callees. An example of an option would be the Call.sendResultsTo field in rpc.capnp.

func NewCallOptions

func NewCallOptions(opts []CallOption) CallOptions

NewCallOptions builds a CallOptions value from a list of individual options.

func (CallOptions) Value

func (co CallOptions) Value(key interface{}) interface{}

Value retrieves the value associated with the options for this key, or nil if no value is associated with this key.

func (CallOptions) With

func (co CallOptions) With(opts []CallOption) CallOptions

With creates a copy of the CallOptions value with other options applied.

type CapabilityID

type CapabilityID uint32

A CapabilityID is an index into a message's capability table.

func (CapabilityID) GoString

func (id CapabilityID) GoString() string

GoString returns the ID as a Go expression.

func (CapabilityID) String

func (id CapabilityID) String() string

String returns the ID in the format "capability X".

type Client

type Client interface {
	// Call starts executing a method and returns an answer that will hold
	// the resulting struct.  The call's parameters must be placed before
	// Call() returns.
	//
	// Calls are delivered to the capability in the order they are made.
	// This guarantee is based on the concept of a capability
	// acknowledging delivery of a call: this is specific to an
	// implementation of Client.  A type that implements Client must
	// guarantee that if foo() then bar() is called on a client, that
	// acknowledging foo() happens before acknowledging bar().
	Call(call *Call) Answer

	// Close releases any resources associated with this client.
	// No further calls to the client should be made after calling Close.
	Close() error
}

A Client represents an Cap'n Proto interface type. It is safe to use from multiple goroutines.

Generally, only RPC protocol implementers should provide types that implement Client: call ordering guarantees, promises, and synchronization are tricky to get right. Prefer creating a server that wraps another interface than trying to implement Client.

func ErrorClient

func ErrorClient(e error) Client

ErrorClient returns a Client that always returns error e.

type DataList

type DataList struct{ List }

DataList is an array of pointers to data.

func NewDataList

func NewDataList(s *Segment, n int32) (DataList, error)

NewDataList allocates a new list of data pointers, preferring placement in s.

func (DataList) At

func (l DataList) At(i int) ([]byte, error)

At returns the i'th data in the list.

func (DataList) Set

func (l DataList) Set(i int, v []byte) error

Set sets the i'th data in the list to v.

type DataOffset

type DataOffset uint32

DataOffset is an offset in bytes from the beginning of a struct's data section.

func (DataOffset) GoString

func (off DataOffset) GoString() string

GoString returns the offset as a Go expression.

func (DataOffset) String

func (off DataOffset) String() string

String returns the offset in the format "+X bytes".

type Decoder

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

A Decoder represents a framer that deserializes a particular Cap'n Proto input stream.

func NewDecoder

func NewDecoder(r io.Reader) *Decoder

NewDecoder creates a new Cap'n Proto framer that reads from r.

func NewPackedDecoder

func NewPackedDecoder(r io.Reader) *Decoder

NewPackedDecoder creates a new Cap'n Proto framer that reads from a packed stream r.

func (*Decoder) Decode

func (d *Decoder) Decode() (*Message, error)

Decode reads a message from the decoder stream.

type Encoder

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

An Encoder represents a framer for serializing a particular Cap'n Proto stream.

func NewEncoder

func NewEncoder(w io.Writer) *Encoder

NewEncoder creates a new Cap'n Proto framer that writes to w.

func NewPackedEncoder

func NewPackedEncoder(w io.Writer) *Encoder

NewPackedEncoder creates a new Cap'n Proto framer that writes to a packed stream w.

func (*Encoder) Encode

func (e *Encoder) Encode(m *Message) error

Encode writes a message to the encoder stream.

type Float32List

type Float32List struct{ List }

Float32List is an array of Float32 values.

func NewFloat32List

func NewFloat32List(s *Segment, n int32) (Float32List, error)

NewFloat32List creates a new list of Float32, preferring placement in s.

func (Float32List) At

func (l Float32List) At(i int) float32

At returns the i'th element.

func (Float32List) Set

func (l Float32List) Set(i int, v float32)

Set sets the i'th element to v.

type Float64List

type Float64List struct{ List }

Float64List is an array of Float64 values.

func NewFloat64List

func NewFloat64List(s *Segment, n int32) (Float64List, error)

NewFloat64List creates a new list of Float64, preferring placement in s.

func (Float64List) At

func (l Float64List) At(i int) float64

At returns the i'th element.

func (Float64List) Set

func (l Float64List) Set(i int, v float64)

Set sets the i'th element to v.

type Int16List

type Int16List struct{ List }

Int16List is an array of Int16 values.

func NewInt16List

func NewInt16List(s *Segment, n int32) (Int16List, error)

NewInt16List creates a new list of Int16, preferring placement in s.

func (Int16List) At

func (l Int16List) At(i int) int16

At returns the i'th element.

func (Int16List) Set

func (l Int16List) Set(i int, v int16)

Set sets the i'th element to v.

type Int32List

type Int32List struct{ List }

Int32List is an array of Int32 values.

func NewInt32List

func NewInt32List(s *Segment, n int32) (Int32List, error)

NewInt32List creates a new list of Int32, preferring placement in s.

func (Int32List) At

func (l Int32List) At(i int) int32

At returns the i'th element.

func (Int32List) Set

func (l Int32List) Set(i int, v int32)

Set sets the i'th element to v.

type Int64List

type Int64List struct{ List }

Int64List is an array of Int64 values.

func NewInt64List

func NewInt64List(s *Segment, n int32) (Int64List, error)

NewInt64List creates a new list of Int64, preferring placement in s.

func (Int64List) At

func (l Int64List) At(i int) int64

At returns the i'th element.

func (Int64List) Set

func (l Int64List) Set(i int, v int64)

Set sets the i'th element to v.

type Int8List

type Int8List struct{ List }

Int8List is an array of Int8 values.

func NewInt8List

func NewInt8List(s *Segment, n int32) (Int8List, error)

NewInt8List creates a new list of Int8, preferring placement in s.

func (Int8List) At

func (l Int8List) At(i int) int8

At returns the i'th element.

func (Int8List) Set

func (l Int8List) Set(i int, v int8)

Set sets the i'th element to v.

type Interface

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

An Interface is a reference to a client in a message's capability table.

func NewInterface

func NewInterface(s *Segment, cap CapabilityID) Interface

NewInterface creates a new interface pointer. No allocation is performed; s is only used for Segment()'s return value.

func ToInterface

func ToInterface(p Pointer) Interface

ToInterface attempts to convert p into an interface. If p is not a valid interface, then ToInterface returns an invalid Interface.

func (Interface) Capability

func (i Interface) Capability() CapabilityID

Capability returns the capability ID of the interface.

func (Interface) Client

func (i Interface) Client() Client

Client returns the client stored in the message's capability table or nil if the pointer is invalid.

func (Interface) HasData

func (i Interface) HasData() bool

HasData is always true.

func (Interface) Segment

func (i Interface) Segment() *Segment

Segment returns the segment this pointer came from.

type List

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

A List is a reference to an array of values.

func NewCompositeList

func NewCompositeList(s *Segment, sz ObjectSize, n int32) (List, error)

NewCompositeList creates a new composite list, preferring placement in s.

func ToList

func ToList(p Pointer) List

ToList attempts to convert p into a list. If p is not a valid list, then it returns an invalid List.

func ToListDefault

func ToListDefault(p Pointer, def []byte) (List, error)

ToListDefault attempts to convert p into a struct, reading the default value from def if p is not a struct.

func (List) Address

func (p List) Address() Address

Address returns the address the pointer references.

func (List) HasData

func (p List) HasData() bool

HasData reports whether the list's total size is non-zero.

func (List) Len

func (p List) Len() int

Len returns the length of the list.

func (List) Segment

func (p List) Segment() *Segment

Segment returns the segment this pointer references.

func (List) SetStruct

func (p List) SetStruct(i int, s Struct) error

SetStruct set the i'th element to the value in s.

func (List) Struct

func (p List) Struct(i int) Struct

Struct returns the i'th element as a struct.

type Message

type Message struct {
	Arena Arena

	// CapTable is the indexed list of the clients referenced in the
	// message.  Capability pointers inside the message will use this table
	// to map pointers to Clients.  The table is usually populated by the
	// RPC system.
	//
	// See https://capnproto.org/encoding.html#capabilities-interfaces for
	// more details on the capability table.
	CapTable []Client
	// contains filtered or unexported fields
}

A Message is a tree of Cap'n Proto objects, split into one or more segments of contiguous memory. The only required field is Arena.

func Unmarshal

func Unmarshal(data []byte) (*Message, error)

Unmarshal reads an unpacked serialized stream into a message. No copying is performed, so the objects in the returned message read directly from data.

Example
msg, s, err := capnp.NewMessage(capnp.SingleSegment(nil))
if err != nil {
	fmt.Printf("allocation error %v\n", err)
	return
}
d, err := air.NewRootZdate(s)
if err != nil {
	fmt.Printf("root error %v\n", err)
	return
}
d.SetYear(2004)
d.SetMonth(12)
d.SetDay(7)
data, err := msg.Marshal()
if err != nil {
	fmt.Printf("marshal error %v\n", err)
	return
}

// Read
msg, err = capnp.Unmarshal(data)
if err != nil {
	fmt.Printf("unmarshal error %v\n", err)
	return
}
d, err = air.ReadRootZdate(msg)
if err != nil {
	fmt.Printf("read root error %v\n", err)
	return
}
fmt.Printf("year %d, month %d, day %d\n", d.Year(), d.Month(), d.Day())
Output:

year 2004, month 12, day 7

func (*Message) AddCap

func (m *Message) AddCap(c Client) CapabilityID

AddCap appends a capability to the message's capability table and returns its ID.

func (*Message) Marshal

func (m *Message) Marshal() ([]byte, error)

Marshal concatenates the segments in the message into a single byte slice including framing.

func (*Message) MarshalPacked

func (m *Message) MarshalPacked() ([]byte, error)

MarshalPacked marshals the message in packed form.

func (*Message) NumSegments

func (m *Message) NumSegments() int64

NumSegments returns the number of segments in the message.

func (*Message) Root

func (m *Message) Root() (Pointer, error)

Root returns the pointer to the message's root object.

func (*Message) Segment

func (m *Message) Segment(id SegmentID) (*Segment, error)

Segment returns the segment with the given ID.

func (*Message) SetRoot

func (m *Message) SetRoot(p Pointer) error

SetRoot sets the message's root object to p.

type Method

type Method struct {
	InterfaceID uint64
	MethodID    uint16

	// Canonical name of the interface.  May be empty.
	InterfaceName string
	// Method name as it appears in the schema.  May be empty.
	MethodName string
}

A Method identifies a method along with an optional human-readable description of the method.

func (*Method) String

func (m *Method) String() string

String returns a formatted string containing the interface name or the method name if present, otherwise it uses the raw IDs. This is suitable for use in error messages and logs.

type MethodError

type MethodError struct {
	Method *Method
	Err    error
}

MethodError is an error on an associated method.

func (*MethodError) Error

func (me *MethodError) Error() string

Error returns the method name concatenated with the error string.

type ObjectSize

type ObjectSize struct {
	DataSize     Size
	PointerCount uint16
}

ObjectSize records section sizes for a struct or list.

func (ObjectSize) GoString

func (sz ObjectSize) GoString() string

GoString formats the ObjectSize as a keyed struct literal.

func (ObjectSize) String

func (sz ObjectSize) String() string

String returns a short, human readable representation of the object size.

type Pipeline

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

A Pipeline is a generic wrapper for an answer.

func NewPipeline

func NewPipeline(ans Answer) *Pipeline

NewPipeline returns a new pipeline based on an answer.

func (*Pipeline) Answer

func (p *Pipeline) Answer() Answer

Answer returns the answer the pipeline is derived from.

func (*Pipeline) Client

func (p *Pipeline) Client() *PipelineClient

Client returns the client version of p.

func (*Pipeline) GetPipeline

func (p *Pipeline) GetPipeline(off uint16) *Pipeline

GetPipeline returns a derived pipeline which yields the pointer field given.

func (*Pipeline) GetPipelineDefault

func (p *Pipeline) GetPipelineDefault(off uint16, def []byte) *Pipeline

GetPipelineDefault returns a derived pipeline which yields the pointer field given, defaulting to the value given.

func (*Pipeline) Struct

func (p *Pipeline) Struct() (Struct, error)

Struct waits until the answer is resolved and returns the struct this pipeline represents.

func (*Pipeline) Transform

func (p *Pipeline) Transform() []PipelineOp

Transform returns the operations needed to transform the root answer into the value p represents.

type PipelineClient

type PipelineClient Pipeline

PipelineClient implements Client by calling to the pipeline's answer.

func (*PipelineClient) Call

func (pc *PipelineClient) Call(call *Call) Answer

func (*PipelineClient) Close

func (pc *PipelineClient) Close() error

type PipelineOp

type PipelineOp struct {
	Field        uint16
	DefaultValue []byte
}

A PipelineOp describes a step in transforming a pipeline. It maps closely with the PromisedAnswer.Op struct in rpc.capnp.

func (PipelineOp) String

func (op PipelineOp) String() string

String returns a human-readable description of op.

type Pointer

type Pointer interface {
	// Segment returns the segment this pointer points into.
	// If nil, then this is an invalid pointer.
	Segment() *Segment

	// HasData reports whether the object referenced by the pointer has
	// non-zero size.
	HasData() bool
	// contains filtered or unexported methods
}

A Pointer is a reference to a Cap'n Proto struct, list, or interface.

func MustUnmarshalRoot

func MustUnmarshalRoot(data []byte) Pointer

MustUnmarshalRoot reads an unpacked serialized stream and returns its root pointer. If there is any error, it panics.

func PointerDefault

func PointerDefault(p Pointer, def []byte) (Pointer, error)

PointerDefault returns p if it is valid, otherwise it unmarshals def.

func Transform

func Transform(p Pointer, transform []PipelineOp) (Pointer, error)

Transform applies a sequence of pipeline operations to a pointer and returns the result.

type PointerList

type PointerList struct{ List }

A PointerList is a reference to an array of pointers.

func NewPointerList

func NewPointerList(s *Segment, n int32) (PointerList, error)

NewPointerList allocates a new list of pointers, preferring placement in s.

func (PointerList) At

func (p PointerList) At(i int) (Pointer, error)

At returns the i'th pointer in the list.

func (PointerList) Set

func (p PointerList) Set(i int, v Pointer) error

Set sets the i'th pointer in the list to v.

type Segment

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

A Segment is an allocation arena for Cap'n Proto objects. It is part of a Message, which can contain other segments that reference each other.

func (*Segment) Data

func (s *Segment) Data() []byte

Data returns the raw byte slice for the segment.

func (*Segment) ID

func (s *Segment) ID() SegmentID

ID returns the segment's ID.

func (*Segment) Message

func (s *Segment) Message() *Message

Message returns the message that contains s.

type SegmentID

type SegmentID uint32

A SegmentID is a numeric identifier for a Segment.

type Size

type Size uint32

A Size is a size (in bytes).

func (Size) GoString

func (sz Size) GoString() string

GoString returns the size as a Go expression.

func (Size) String

func (sz Size) String() string

String returns the size in the format "X bytes".

type Struct

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

Struct is a pointer to a struct.

func NewRootStruct

func NewRootStruct(s *Segment, sz ObjectSize) (Struct, error)

NewRootStruct creates a new struct, preferring placement in s, then sets the message's root to the new struct.

func NewStruct

func NewStruct(s *Segment, sz ObjectSize) (Struct, error)

NewStruct creates a new struct, preferring placement in s.

func ToStruct

func ToStruct(p Pointer) Struct

ToStruct attempts to convert p into a struct. If p is not a valid struct, then it returns an invalid Struct.

func ToStructDefault

func ToStructDefault(p Pointer, def []byte) (Struct, error)

ToStructDefault attempts to convert p into a struct, reading the default value from def if p is not a struct.

func (Struct) Address

func (p Struct) Address() Address

Address returns the address the pointer references.

func (Struct) Bit

func (p Struct) Bit(n BitOffset) bool

Bit returns the bit that is n bits from the start of the struct.

func (Struct) HasData

func (p Struct) HasData() bool

HasData reports whether the struct has a non-zero size.

func (Struct) Pointer

func (p Struct) Pointer(i uint16) (Pointer, error)

Pointer returns the i'th pointer in the struct.

func (Struct) Segment

func (p Struct) Segment() *Segment

Segment returns the segment this pointer came from.

func (Struct) SetBit

func (p Struct) SetBit(n BitOffset, v bool)

SetBit sets the bit that is n bits from the start of the struct to v.

func (Struct) SetPointer

func (p Struct) SetPointer(i uint16, src Pointer) error

SetPointer sets the i'th pointer in the struct to src.

func (Struct) SetUint16

func (p Struct) SetUint16(off DataOffset, v uint16)

SetUint16 sets the 16-bit integer that is off bytes from the start of the struct to v.

func (Struct) SetUint32

func (p Struct) SetUint32(off DataOffset, v uint32)

SetUint32 sets the 32-bit integer that is off bytes from the start of the struct to v.

func (Struct) SetUint64

func (p Struct) SetUint64(off DataOffset, v uint64)

SetUint64 sets the 64-bit integer that is off bytes from the start of the struct to v.

func (Struct) SetUint8

func (p Struct) SetUint8(off DataOffset, v uint8)

SetUint8 sets the 8-bit integer that is off bytes from the start of the struct to v.

func (Struct) Uint16

func (p Struct) Uint16(off DataOffset) uint16

Uint16 returns a 16-bit integer from the struct's data section.

func (Struct) Uint32

func (p Struct) Uint32(off DataOffset) uint32

Uint32 returns a 32-bit integer from the struct's data section.

func (Struct) Uint64

func (p Struct) Uint64(off DataOffset) uint64

Uint64 returns a 64-bit integer from the struct's data section.

func (Struct) Uint8

func (p Struct) Uint8(off DataOffset) uint8

Uint8 returns an 8-bit integer from the struct's data section.

type TextList

type TextList struct{ List }

TextList is an array of pointers to strings.

func NewTextList

func NewTextList(s *Segment, n int32) (TextList, error)

NewTextList allocates a new list of text pointers, preferring placement in s.

func (TextList) At

func (l TextList) At(i int) (string, error)

At returns the i'th string in the list.

func (TextList) Set

func (l TextList) Set(i int, v string) error

Set sets the i'th string in the list to v.

type UInt16List

type UInt16List struct{ List }

A UInt16List is an array of UInt16 values.

func NewUInt16List

func NewUInt16List(s *Segment, n int32) (UInt16List, error)

NewUInt16List creates a new list of UInt16, preferring placement in s.

func (UInt16List) At

func (l UInt16List) At(i int) uint16

At returns the i'th element.

func (UInt16List) Set

func (l UInt16List) Set(i int, v uint16)

Set sets the i'th element to v.

type UInt32List

type UInt32List struct{ List }

UInt32List is an array of UInt32 values.

func NewUInt32List

func NewUInt32List(s *Segment, n int32) (UInt32List, error)

NewUInt32List creates a new list of UInt32, preferring placement in s.

func (UInt32List) At

func (l UInt32List) At(i int) uint32

At returns the i'th element.

func (UInt32List) Set

func (l UInt32List) Set(i int, v uint32)

Set sets the i'th element to v.

type UInt64List

type UInt64List struct{ List }

UInt64List is an array of UInt64 values.

func NewUInt64List

func NewUInt64List(s *Segment, n int32) (UInt64List, error)

NewUInt64List creates a new list of UInt64, preferring placement in s.

func (UInt64List) At

func (l UInt64List) At(i int) uint64

At returns the i'th element.

func (UInt64List) Set

func (l UInt64List) Set(i int, v uint64)

Set sets the i'th element to v.

type UInt8List

type UInt8List struct{ List }

A UInt8List is an array of UInt8 values.

func NewData

func NewData(s *Segment, v []byte) (UInt8List, error)

NewData creates a new list of UInt8 from a byte slice.

func NewText

func NewText(s *Segment, v string) (UInt8List, error)

NewText creates a new list of UInt8 from a string.

func NewUInt8List

func NewUInt8List(s *Segment, n int32) (UInt8List, error)

NewUInt8List creates a new list of UInt8, preferring placement in s.

func (UInt8List) At

func (l UInt8List) At(i int) uint8

At returns the i'th element.

func (UInt8List) Set

func (l UInt8List) Set(i int, v uint8)

Set sets the i'th element to v.

type VoidList

type VoidList struct{ List }

A VoidList is a list of zero-sized elements.

func NewVoidList

func NewVoidList(s *Segment, n int32) VoidList

NewVoidList creates a list of voids. No allocation is performed; s is only used for Segment()'s return value.

Directories

Path Synopsis
capnpc-go is the Cap'n proto code generator for Go.
capnpc-go is the Cap'n proto code generator for Go.
internal
fulfiller
Package fulfiller provides a type that implements capnp.Answer that resolves by calling setter methods.
Package fulfiller provides a type that implements capnp.Answer that resolves by calling setter methods.
packed
Package packed provides functions to read and write the "packed" compression scheme described at https://capnproto.org/encoding.html#packing.
Package packed provides functions to read and write the "packed" compression scheme described at https://capnproto.org/encoding.html#packing.
queue
Package queue implements a generic queue using a ring buffer.
Package queue implements a generic queue using a ring buffer.
rpc
Package rpc implements the Cap'n Proto RPC protocol.
Package rpc implements the Cap'n Proto RPC protocol.
internal/logtransport
Package logtransport provides a transport that logs all of its messages.
Package logtransport provides a transport that logs all of its messages.
internal/logutil
Package logutil provides functions that can print to a logger.
Package logutil provides functions that can print to a logger.
internal/pipetransport
Package pipetransport provides in-memory implementations of rpc.Transport for testing.
Package pipetransport provides in-memory implementations of rpc.Transport for testing.
internal/refcount
Package refcount implements a reference-counting client.
Package refcount implements a reference-counting client.
Package server provides runtime support for implementing Cap'n Proto interfaces locally.
Package server provides runtime support for implementing Cap'n Proto interfaces locally.

Jump to

Keyboard shortcuts

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