mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-28 00:29:58 +00:00
TUN-528: Move cloudflared into a separate repo
This commit is contained in:
541
vendor/zombiezen.com/go/capnproto2/capability.go
generated
vendored
Normal file
541
vendor/zombiezen.com/go/capnproto2/capability.go
generated
vendored
Normal file
@@ -0,0 +1,541 @@
|
||||
package capnp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// An Interface is a reference to a client in a message's capability table.
|
||||
type Interface struct {
|
||||
seg *Segment
|
||||
cap CapabilityID
|
||||
}
|
||||
|
||||
// NewInterface creates a new interface pointer. No allocation is
|
||||
// performed; s is only used for Segment()'s return value.
|
||||
func NewInterface(s *Segment, cap CapabilityID) Interface {
|
||||
return Interface{
|
||||
seg: s,
|
||||
cap: cap,
|
||||
}
|
||||
}
|
||||
|
||||
// ToInterface converts p to an Interface.
|
||||
//
|
||||
// Deprecated: Use Ptr.Interface.
|
||||
func ToInterface(p Pointer) Interface {
|
||||
if !IsValid(p) {
|
||||
return Interface{}
|
||||
}
|
||||
i, ok := p.underlying().(Interface)
|
||||
if !ok {
|
||||
return Interface{}
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
// ToPtr converts the interface to a generic pointer.
|
||||
func (p Interface) ToPtr() Ptr {
|
||||
return Ptr{
|
||||
seg: p.seg,
|
||||
lenOrCap: uint32(p.cap),
|
||||
flags: interfacePtrFlag,
|
||||
}
|
||||
}
|
||||
|
||||
// Segment returns the segment this pointer came from.
|
||||
func (i Interface) Segment() *Segment {
|
||||
return i.seg
|
||||
}
|
||||
|
||||
// IsValid returns whether the interface is valid.
|
||||
func (i Interface) IsValid() bool {
|
||||
return i.seg != nil
|
||||
}
|
||||
|
||||
// HasData is always true.
|
||||
func (i Interface) HasData() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Capability returns the capability ID of the interface.
|
||||
func (i Interface) Capability() CapabilityID {
|
||||
return i.cap
|
||||
}
|
||||
|
||||
// value returns a raw interface pointer with the capability ID.
|
||||
func (i Interface) value(paddr Address) rawPointer {
|
||||
if i.seg == nil {
|
||||
return 0
|
||||
}
|
||||
return rawInterfacePointer(i.cap)
|
||||
}
|
||||
|
||||
func (i Interface) underlying() Pointer {
|
||||
return i
|
||||
}
|
||||
|
||||
// Client returns the client stored in the message's capability table
|
||||
// or nil if the pointer is invalid.
|
||||
func (i Interface) Client() Client {
|
||||
if i.seg == nil {
|
||||
return nil
|
||||
}
|
||||
tab := i.seg.msg.CapTable
|
||||
if int64(i.cap) >= int64(len(tab)) {
|
||||
return nil
|
||||
}
|
||||
return tab[i.cap]
|
||||
}
|
||||
|
||||
// ErrNullClient is returned from a call made on a null client pointer.
|
||||
var ErrNullClient = errors.New("capnp: call on null client")
|
||||
|
||||
// A CapabilityID is an index into a message's capability table.
|
||||
type CapabilityID uint32
|
||||
|
||||
// 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.
|
||||
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
|
||||
}
|
||||
|
||||
// The Call type holds the record for an outgoing interface 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
|
||||
}
|
||||
|
||||
// Copy clones a call, ensuring that its Params are placed.
|
||||
// If Call.ParamsFunc is nil, then the same Call will be returned.
|
||||
func (call *Call) Copy(s *Segment) (*Call, error) {
|
||||
if call.ParamsFunc == nil {
|
||||
return call, nil
|
||||
}
|
||||
p, err := call.PlaceParams(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Call{
|
||||
Ctx: call.Ctx,
|
||||
Method: call.Method,
|
||||
Params: p,
|
||||
Options: call.Options,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// PlaceParams returns the parameters struct, allocating it inside
|
||||
// segment s as necessary. If s is nil, a new single-segment message
|
||||
// is allocated.
|
||||
func (call *Call) PlaceParams(s *Segment) (Struct, error) {
|
||||
if call.ParamsFunc == nil {
|
||||
return call.Params, nil
|
||||
}
|
||||
if s == nil {
|
||||
var err error
|
||||
_, s, err = NewMessage(SingleSegment(nil))
|
||||
if err != nil {
|
||||
return Struct{}, err
|
||||
}
|
||||
}
|
||||
p, err := NewStruct(s, call.ParamsSize)
|
||||
if err != nil {
|
||||
return Struct{}, nil
|
||||
}
|
||||
err = call.ParamsFunc(p)
|
||||
return p, err
|
||||
}
|
||||
|
||||
// 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.
|
||||
type CallOptions struct {
|
||||
m map[interface{}]interface{}
|
||||
}
|
||||
|
||||
// NewCallOptions builds a CallOptions value from a list of individual options.
|
||||
func NewCallOptions(opts []CallOption) CallOptions {
|
||||
co := CallOptions{make(map[interface{}]interface{})}
|
||||
for _, o := range opts {
|
||||
o.f(co)
|
||||
}
|
||||
return co
|
||||
}
|
||||
|
||||
// Value retrieves the value associated with the options for this key,
|
||||
// or nil if no value is associated with this key.
|
||||
func (co CallOptions) Value(key interface{}) interface{} {
|
||||
return co.m[key]
|
||||
}
|
||||
|
||||
// With creates a copy of the CallOptions value with other options applied.
|
||||
func (co CallOptions) With(opts []CallOption) CallOptions {
|
||||
newopts := CallOptions{make(map[interface{}]interface{})}
|
||||
for k, v := range co.m {
|
||||
newopts.m[k] = v
|
||||
}
|
||||
for _, o := range opts {
|
||||
o.f(newopts)
|
||||
}
|
||||
return newopts
|
||||
}
|
||||
|
||||
// A CallOption is a function that modifies options on an interface call.
|
||||
type CallOption struct {
|
||||
f func(CallOptions)
|
||||
}
|
||||
|
||||
// SetOptionValue returns a call option that associates a value to an
|
||||
// option key. This can be retrieved later with CallOptions.Value.
|
||||
func SetOptionValue(key, value interface{}) CallOption {
|
||||
return CallOption{func(co CallOptions) {
|
||||
co.m[key] = value
|
||||
}}
|
||||
}
|
||||
|
||||
// An Answer is the deferred result of a client call, which is usually wrapped by a Pipeline.
|
||||
type Answer interface {
|
||||
// Struct waits until the call is finished and returns the result.
|
||||
Struct() (Struct, error)
|
||||
|
||||
// The following methods are the same as in Client except with
|
||||
// an added transform parameter -- a path to the interface to use.
|
||||
|
||||
PipelineCall(transform []PipelineOp, call *Call) Answer
|
||||
PipelineClose(transform []PipelineOp) error
|
||||
}
|
||||
|
||||
// A Pipeline is a generic wrapper for an answer.
|
||||
type Pipeline struct {
|
||||
answer Answer
|
||||
parent *Pipeline
|
||||
op PipelineOp
|
||||
}
|
||||
|
||||
// NewPipeline returns a new pipeline based on an answer.
|
||||
func NewPipeline(ans Answer) *Pipeline {
|
||||
return &Pipeline{answer: ans}
|
||||
}
|
||||
|
||||
// Answer returns the answer the pipeline is derived from.
|
||||
func (p *Pipeline) Answer() Answer {
|
||||
return p.answer
|
||||
}
|
||||
|
||||
// Transform returns the operations needed to transform the root answer
|
||||
// into the value p represents.
|
||||
func (p *Pipeline) Transform() []PipelineOp {
|
||||
n := 0
|
||||
for q := p; q.parent != nil; q = q.parent {
|
||||
n++
|
||||
}
|
||||
xform := make([]PipelineOp, n)
|
||||
for i, q := n-1, p; q.parent != nil; i, q = i-1, q.parent {
|
||||
xform[i] = q.op
|
||||
}
|
||||
return xform
|
||||
}
|
||||
|
||||
// Struct waits until the answer is resolved and returns the struct
|
||||
// this pipeline represents.
|
||||
func (p *Pipeline) Struct() (Struct, error) {
|
||||
s, err := p.answer.Struct()
|
||||
if err != nil {
|
||||
return Struct{}, err
|
||||
}
|
||||
ptr, err := TransformPtr(s.ToPtr(), p.Transform())
|
||||
if err != nil {
|
||||
return Struct{}, err
|
||||
}
|
||||
return ptr.Struct(), nil
|
||||
}
|
||||
|
||||
// Client returns the client version of p.
|
||||
func (p *Pipeline) Client() *PipelineClient {
|
||||
return (*PipelineClient)(p)
|
||||
}
|
||||
|
||||
// GetPipeline returns a derived pipeline which yields the pointer field given.
|
||||
func (p *Pipeline) GetPipeline(off uint16) *Pipeline {
|
||||
return p.GetPipelineDefault(off, nil)
|
||||
}
|
||||
|
||||
// GetPipelineDefault returns a derived pipeline which yields the pointer field given,
|
||||
// defaulting to the value given.
|
||||
func (p *Pipeline) GetPipelineDefault(off uint16, def []byte) *Pipeline {
|
||||
return &Pipeline{
|
||||
answer: p.answer,
|
||||
parent: p,
|
||||
op: PipelineOp{
|
||||
Field: off,
|
||||
DefaultValue: def,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// PipelineClient implements Client by calling to the pipeline's answer.
|
||||
type PipelineClient Pipeline
|
||||
|
||||
func (pc *PipelineClient) transform() []PipelineOp {
|
||||
return (*Pipeline)(pc).Transform()
|
||||
}
|
||||
|
||||
// Call calls Answer.PipelineCall with the pipeline's transform.
|
||||
func (pc *PipelineClient) Call(call *Call) Answer {
|
||||
return pc.answer.PipelineCall(pc.transform(), call)
|
||||
}
|
||||
|
||||
// Close calls Answer.PipelineClose with the pipeline's transform.
|
||||
func (pc *PipelineClient) Close() error {
|
||||
return pc.answer.PipelineClose(pc.transform())
|
||||
}
|
||||
|
||||
// A PipelineOp describes a step in transforming a pipeline.
|
||||
// It maps closely with the PromisedAnswer.Op struct in rpc.capnp.
|
||||
type PipelineOp struct {
|
||||
Field uint16
|
||||
DefaultValue []byte
|
||||
}
|
||||
|
||||
// String returns a human-readable description of op.
|
||||
func (op PipelineOp) String() string {
|
||||
s := make([]byte, 0, 32)
|
||||
s = append(s, "get field "...)
|
||||
s = strconv.AppendInt(s, int64(op.Field), 10)
|
||||
if op.DefaultValue == nil {
|
||||
return string(s)
|
||||
}
|
||||
s = append(s, " with default"...)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
// A Method identifies a method along with an optional human-readable
|
||||
// description of the 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
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (m *Method) String() string {
|
||||
buf := make([]byte, 0, 128)
|
||||
if m.InterfaceName == "" {
|
||||
buf = append(buf, '@', '0', 'x')
|
||||
buf = strconv.AppendUint(buf, m.InterfaceID, 16)
|
||||
} else {
|
||||
buf = append(buf, m.InterfaceName...)
|
||||
}
|
||||
buf = append(buf, '.')
|
||||
if m.MethodName == "" {
|
||||
buf = append(buf, '@')
|
||||
buf = strconv.AppendUint(buf, uint64(m.MethodID), 10)
|
||||
} else {
|
||||
buf = append(buf, m.MethodName...)
|
||||
}
|
||||
return string(buf)
|
||||
}
|
||||
|
||||
// Transform applies a sequence of pipeline operations to a pointer
|
||||
// and returns the result.
|
||||
//
|
||||
// Deprecated: Use TransformPtr.
|
||||
func Transform(p Pointer, transform []PipelineOp) (Pointer, error) {
|
||||
pp, err := TransformPtr(toPtr(p), transform)
|
||||
return pp.toPointer(), err
|
||||
}
|
||||
|
||||
// TransformPtr applies a sequence of pipeline operations to a pointer
|
||||
// and returns the result.
|
||||
func TransformPtr(p Ptr, transform []PipelineOp) (Ptr, error) {
|
||||
n := len(transform)
|
||||
if n == 0 {
|
||||
return p, nil
|
||||
}
|
||||
s := p.Struct()
|
||||
for _, op := range transform[:n-1] {
|
||||
field, err := s.Ptr(op.Field)
|
||||
if err != nil {
|
||||
return Ptr{}, err
|
||||
}
|
||||
s, err = field.StructDefault(op.DefaultValue)
|
||||
if err != nil {
|
||||
return Ptr{}, err
|
||||
}
|
||||
}
|
||||
op := transform[n-1]
|
||||
p, err := s.Ptr(op.Field)
|
||||
if err != nil {
|
||||
return Ptr{}, err
|
||||
}
|
||||
if op.DefaultValue != nil {
|
||||
p, err = p.Default(op.DefaultValue)
|
||||
}
|
||||
return p, err
|
||||
}
|
||||
|
||||
type immediateAnswer struct {
|
||||
s Struct
|
||||
}
|
||||
|
||||
// ImmediateAnswer returns an Answer that accesses s.
|
||||
func ImmediateAnswer(s Struct) Answer {
|
||||
return immediateAnswer{s}
|
||||
}
|
||||
|
||||
func (ans immediateAnswer) Struct() (Struct, error) {
|
||||
return ans.s, nil
|
||||
}
|
||||
|
||||
func (ans immediateAnswer) findClient(transform []PipelineOp) Client {
|
||||
p, err := TransformPtr(ans.s.ToPtr(), transform)
|
||||
if err != nil {
|
||||
return ErrorClient(err)
|
||||
}
|
||||
return p.Interface().Client()
|
||||
}
|
||||
|
||||
func (ans immediateAnswer) PipelineCall(transform []PipelineOp, call *Call) Answer {
|
||||
c := ans.findClient(transform)
|
||||
if c == nil {
|
||||
return ErrorAnswer(ErrNullClient)
|
||||
}
|
||||
return c.Call(call)
|
||||
}
|
||||
|
||||
func (ans immediateAnswer) PipelineClose(transform []PipelineOp) error {
|
||||
c := ans.findClient(transform)
|
||||
if c == nil {
|
||||
return ErrNullClient
|
||||
}
|
||||
return c.Close()
|
||||
}
|
||||
|
||||
type errorAnswer struct {
|
||||
e error
|
||||
}
|
||||
|
||||
// ErrorAnswer returns a Answer that always returns error e.
|
||||
func ErrorAnswer(e error) Answer {
|
||||
return errorAnswer{e}
|
||||
}
|
||||
|
||||
func (ans errorAnswer) Struct() (Struct, error) {
|
||||
return Struct{}, ans.e
|
||||
}
|
||||
|
||||
func (ans errorAnswer) PipelineCall([]PipelineOp, *Call) Answer {
|
||||
return ans
|
||||
}
|
||||
|
||||
func (ans errorAnswer) PipelineClose([]PipelineOp) error {
|
||||
return ans.e
|
||||
}
|
||||
|
||||
// IsFixedAnswer reports whether an answer was created by
|
||||
// ImmediateAnswer or ErrorAnswer.
|
||||
func IsFixedAnswer(ans Answer) bool {
|
||||
switch ans.(type) {
|
||||
case immediateAnswer:
|
||||
return true
|
||||
case errorAnswer:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
type errorClient struct {
|
||||
e error
|
||||
}
|
||||
|
||||
// ErrorClient returns a Client that always returns error e.
|
||||
func ErrorClient(e error) Client {
|
||||
return errorClient{e}
|
||||
}
|
||||
|
||||
func (ec errorClient) Call(*Call) Answer {
|
||||
return ErrorAnswer(ec.e)
|
||||
}
|
||||
|
||||
func (ec errorClient) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsErrorClient reports whether c was created with ErrorClient.
|
||||
func IsErrorClient(c Client) bool {
|
||||
_, ok := c.(errorClient)
|
||||
return ok
|
||||
}
|
||||
|
||||
// MethodError is an error on an associated method.
|
||||
type MethodError struct {
|
||||
Method *Method
|
||||
Err error
|
||||
}
|
||||
|
||||
// Error returns the method name concatenated with the error string.
|
||||
func (e *MethodError) Error() string {
|
||||
return e.Method.String() + ": " + e.Err.Error()
|
||||
}
|
||||
|
||||
// ErrUnimplemented is the error returned when a method is called on
|
||||
// a server that does not implement the method.
|
||||
var ErrUnimplemented = errors.New("capnp: method not implemented")
|
||||
|
||||
// IsUnimplemented reports whether e indicates an unimplemented method error.
|
||||
func IsUnimplemented(e error) bool {
|
||||
if me, ok := e.(*MethodError); ok {
|
||||
e = me.Err
|
||||
}
|
||||
return e == ErrUnimplemented
|
||||
}
|
Reference in New Issue
Block a user