Merge branch 'feature/v0.4' into develop
Conflicts: capnp/capnp.pyx capnp/capnp_cpp.pxd capnp/schema_cpp.pxd setup.py
This commit is contained in:
18
capnp/async_cpp.pxd
Normal file
18
capnp/async_cpp.pxd
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# schema.capnp.cpp.pyx
|
||||||
|
# distutils: language = c++
|
||||||
|
# distutils: extra_compile_args = --std=c++11
|
||||||
|
|
||||||
|
from cpython.ref cimport PyObject
|
||||||
|
|
||||||
|
cdef extern from "kj/exception.h" namespace " ::kj":
|
||||||
|
cdef cppclass Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
cdef extern from "kj/async.h" namespace " ::kj":
|
||||||
|
cdef cppclass Promise[T]:
|
||||||
|
Promise()
|
||||||
|
Promise(Promise)
|
||||||
|
T wait()
|
||||||
|
|
||||||
|
ctypedef Promise[PyObject *] PyPromise
|
||||||
|
ctypedef Promise[void] VoidPromise
|
||||||
149
capnp/capabilityHelper.h
Normal file
149
capnp/capabilityHelper.h
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "capnp/dynamic.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
#include "Python.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void wrap_remote_call(PyObject * func, capnp::Response<capnp::DynamicStruct> &);
|
||||||
|
PyObject * wrap_dynamic_struct_reader(capnp::DynamicStruct::Reader &);
|
||||||
|
::kj::Promise<void> * call_server_method(PyObject * py_server, char * name, capnp::CallContext< capnp::DynamicStruct, capnp::DynamicStruct> & context);
|
||||||
|
PyObject * wrap_kj_exception(kj::Exception &);
|
||||||
|
PyObject * wrap_kj_exception_for_reraise(kj::Exception &);
|
||||||
|
PyObject * get_exception_info(PyObject *, PyObject *, PyObject *);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reraise_kj_exception() {
|
||||||
|
try {
|
||||||
|
if (PyErr_Occurred())
|
||||||
|
; // let the latest Python exn pass through and ignore the current one
|
||||||
|
else
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (kj::Exception& exn) {
|
||||||
|
auto obj = wrap_kj_exception_for_reraise(exn);
|
||||||
|
PyErr_SetObject((PyObject*)obj->ob_type, obj);
|
||||||
|
}
|
||||||
|
catch (const std::exception& exn) {
|
||||||
|
PyErr_SetString(PyExc_RuntimeError, exn.what());
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_py_error() {
|
||||||
|
PyObject * err = PyErr_Occurred();
|
||||||
|
if(err) {
|
||||||
|
PyObject * ptype, *pvalue, *ptraceback;
|
||||||
|
PyErr_Fetch(&ptype, &pvalue, &ptraceback);
|
||||||
|
|
||||||
|
PyObject * info = get_exception_info(ptype, pvalue, ptraceback);
|
||||||
|
|
||||||
|
PyObject * py_filename = PyTuple_GetItem(info, 0);
|
||||||
|
kj::String filename(kj::heapString(PyBytes_AsString(py_filename)));
|
||||||
|
|
||||||
|
PyObject * py_line = PyTuple_GetItem(info, 1);
|
||||||
|
int line = PyInt_AsLong(py_line);
|
||||||
|
|
||||||
|
PyObject * py_description = PyTuple_GetItem(info, 2);
|
||||||
|
kj::String description(kj::heapString(PyBytes_AsString(py_description)));
|
||||||
|
|
||||||
|
Py_DECREF(ptype);
|
||||||
|
Py_DECREF(pvalue);
|
||||||
|
Py_DECREF(ptraceback);
|
||||||
|
Py_DECREF(info);
|
||||||
|
PyErr_Clear();
|
||||||
|
|
||||||
|
throw kj::Exception(kj::Exception::Nature::OTHER, kj::Exception::Durability::PERMANENT, kj::mv(filename), line, kj::mv(description));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject * wrapPyFunc(PyObject * func, PyObject * arg) {
|
||||||
|
PyObject * result = PyObject_CallFunctionObjArgs(func, arg, NULL);
|
||||||
|
Py_DECREF(func);
|
||||||
|
|
||||||
|
check_py_error();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wrapRemoteCall(PyObject * func, capnp::Response<capnp::DynamicStruct> & arg) {
|
||||||
|
wrap_remote_call(func, arg);
|
||||||
|
|
||||||
|
check_py_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
::kj::Promise<PyObject *> evalLater(kj::EventLoop & loop, PyObject * func) {
|
||||||
|
return loop.evalLater([func]() { return wrapPyFunc(func, NULL); } );
|
||||||
|
}
|
||||||
|
|
||||||
|
::kj::Promise<PyObject *> there(kj::EventLoop & loop, kj::Promise<PyObject *> & promise, PyObject * func, PyObject * error_func) {
|
||||||
|
if(error_func == Py_None)
|
||||||
|
return loop.there(kj::mv(promise), [func](PyObject * arg) { return wrapPyFunc(func, arg); } );
|
||||||
|
else
|
||||||
|
return loop.there(kj::mv(promise), [func](PyObject * arg) { return wrapPyFunc(func, arg); }
|
||||||
|
, [error_func](kj::Exception arg) { return wrapPyFunc(error_func, wrap_kj_exception(arg)); } );
|
||||||
|
}
|
||||||
|
|
||||||
|
::kj::Promise<PyObject *> then(kj::Promise<PyObject *> & promise, PyObject * func, PyObject * error_func) {
|
||||||
|
if(error_func == Py_None)
|
||||||
|
return promise.then([func](PyObject * arg) { return wrapPyFunc(func, arg); } );
|
||||||
|
else
|
||||||
|
return promise.then([func](PyObject * arg) { return wrapPyFunc(func, arg); }
|
||||||
|
, [error_func](kj::Exception arg) { return wrapPyFunc(error_func, wrap_kj_exception(arg)); } );
|
||||||
|
}
|
||||||
|
|
||||||
|
::kj::Promise<void> then(::capnp::RemotePromise< ::capnp::DynamicStruct> & promise, PyObject * func, PyObject * error_func) {
|
||||||
|
if(error_func == Py_None)
|
||||||
|
return promise.then([func](capnp::Response<capnp::DynamicStruct>&& arg) { wrapRemoteCall(func, arg); } );
|
||||||
|
else
|
||||||
|
return promise.then([func](capnp::Response<capnp::DynamicStruct>&& arg) { wrapRemoteCall(func, arg); }
|
||||||
|
, [error_func](kj::Exception arg) { wrapPyFunc(error_func, wrap_kj_exception(arg)); } );
|
||||||
|
}
|
||||||
|
|
||||||
|
class PythonInterfaceDynamicImpl final: public capnp::DynamicCapability::Server {
|
||||||
|
public:
|
||||||
|
PyObject * py_server;
|
||||||
|
|
||||||
|
PythonInterfaceDynamicImpl(capnp::InterfaceSchema & schema, PyObject * _py_server)
|
||||||
|
: capnp::DynamicCapability::Server(schema), py_server(_py_server) {
|
||||||
|
Py_INCREF(_py_server);
|
||||||
|
}
|
||||||
|
|
||||||
|
~PythonInterfaceDynamicImpl() {
|
||||||
|
Py_DECREF(py_server);
|
||||||
|
}
|
||||||
|
|
||||||
|
kj::Promise<void> call(capnp::InterfaceSchema::Method method,
|
||||||
|
capnp::CallContext< capnp::DynamicStruct, capnp::DynamicStruct> context) {
|
||||||
|
auto methodName = method.getProto().getName();
|
||||||
|
|
||||||
|
kj::Promise<void> * promise = call_server_method(py_server, const_cast<char *>(methodName.cStr()), context);
|
||||||
|
|
||||||
|
check_py_error();
|
||||||
|
|
||||||
|
if(promise == nullptr)
|
||||||
|
return kj::READY_NOW;
|
||||||
|
|
||||||
|
kj::Promise<void> ret(kj::mv(*promise));
|
||||||
|
delete promise;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
capnp::DynamicCapability::Client new_client(capnp::InterfaceSchema & schema, PyObject * server, kj::EventLoop & loop) {
|
||||||
|
return capnp::DynamicCapability::Client(kj::heap<PythonInterfaceDynamicImpl>(schema, server), loop);
|
||||||
|
}
|
||||||
|
capnp::DynamicValue::Reader new_server(capnp::InterfaceSchema & schema, PyObject * server) {
|
||||||
|
return capnp::DynamicValue::Reader(kj::heap<PythonInterfaceDynamicImpl>(schema, server));
|
||||||
|
}
|
||||||
|
|
||||||
|
capnp::Capability::Client server_to_client(capnp::InterfaceSchema & schema, PyObject * server) {
|
||||||
|
return kj::heap<PythonInterfaceDynamicImpl>(schema, server);
|
||||||
|
}
|
||||||
|
|
||||||
|
::kj::Promise<PyObject *> convert_to_pypromise(capnp::RemotePromise<capnp::DynamicStruct> & promise) {
|
||||||
|
return promise.then([](capnp::Response<capnp::DynamicStruct>&& response) { return wrap_dynamic_struct_reader(response); } );
|
||||||
|
}
|
||||||
1006
capnp/capnp.pyx
1006
capnp/capnp.pyx
File diff suppressed because it is too large
Load Diff
@@ -1,24 +1,43 @@
|
|||||||
# schema.capnp.cpp.pyx
|
# schema.capnp.cpp.pyx
|
||||||
# distutils: language = c++
|
# distutils: language = c++
|
||||||
# distutils: extra_compile_args = --std=c++11
|
# distutils: extra_compile_args = --std=c++11
|
||||||
from schema_cpp cimport Node, Data, StructNode, EnumNode
|
from schema_cpp cimport Node, Data, StructNode, EnumNode, InterfaceNode, MessageBuilder, MessageReader
|
||||||
|
from async_cpp cimport PyPromise, VoidPromise, Promise
|
||||||
|
|
||||||
|
from cpython.ref cimport PyObject
|
||||||
from libc.stdint cimport *
|
from libc.stdint cimport *
|
||||||
ctypedef unsigned int uint
|
ctypedef unsigned int uint
|
||||||
from libcpp cimport bool as cbool
|
from libcpp cimport bool as cbool
|
||||||
|
|
||||||
|
cdef extern from "capabilityHelper.h":
|
||||||
|
void reraise_kj_exception()
|
||||||
|
|
||||||
cdef extern from "capnp/common.h" namespace " ::capnp":
|
cdef extern from "capnp/common.h" namespace " ::capnp":
|
||||||
enum Void:
|
enum Void:
|
||||||
VOID " ::capnp::VOID"
|
VOID " ::capnp::VOID"
|
||||||
cdef cppclass word:
|
|
||||||
pass
|
|
||||||
|
|
||||||
cdef extern from "kj/string.h" namespace " ::kj":
|
cdef extern from "kj/string.h" namespace " ::kj":
|
||||||
cdef cppclass StringPtr:
|
cdef cppclass StringPtr:
|
||||||
StringPtr(char *)
|
StringPtr(char *)
|
||||||
|
char* cStr()
|
||||||
cdef cppclass String:
|
cdef cppclass String:
|
||||||
char* cStr()
|
char* cStr()
|
||||||
|
|
||||||
|
cdef extern from "kj/exception.h" namespace " ::kj":
|
||||||
|
cdef cppclass Exception:
|
||||||
|
Exception(Exception)
|
||||||
|
char* getFile()
|
||||||
|
int getLine()
|
||||||
|
int getNature()
|
||||||
|
int getDurability()
|
||||||
|
StringPtr getDescription()
|
||||||
|
|
||||||
|
cdef extern from "kj/memory.h" namespace " ::kj":
|
||||||
|
cdef cppclass Own[T]:
|
||||||
|
T& operator*()
|
||||||
|
Own[TwoPartyVatNetwork] makeTwoPartyVatNetwork" ::kj::heap< ::capnp::TwoPartyVatNetwork>"(EventLoop &, AsyncIoStream& stream, Side)
|
||||||
|
Own[PromiseFulfillerPair] copyPromiseFulfillerPair" ::kj::heap< ::kj::PromiseFulfillerPair<void> >"(PromiseFulfillerPair&)
|
||||||
|
|
||||||
cdef extern from "kj/string-tree.h" namespace " ::kj":
|
cdef extern from "kj/string-tree.h" namespace " ::kj":
|
||||||
cdef cppclass StringTree:
|
cdef cppclass StringTree:
|
||||||
String flatten()
|
String flatten()
|
||||||
@@ -32,31 +51,42 @@ cdef extern from "kj/common.h" namespace " ::kj":
|
|||||||
size_t size()
|
size_t size()
|
||||||
T& operator[](size_t index)
|
T& operator[](size_t index)
|
||||||
|
|
||||||
# Cython can't handle ArrayPtr[word] as a function argument
|
|
||||||
cdef cppclass WordArrayPtr " ::kj::ArrayPtr< ::capnp::word>":
|
|
||||||
WordArrayPtr()
|
|
||||||
WordArrayPtr(word *, size_t size)
|
|
||||||
size_t size()
|
|
||||||
word& operator[](size_t index)
|
|
||||||
|
|
||||||
cdef extern from "kj/array.h" namespace " ::kj":
|
cdef extern from "kj/array.h" namespace " ::kj":
|
||||||
cdef cppclass Array[T]:
|
cdef cppclass Array[T]:
|
||||||
T* begin()
|
T* begin()
|
||||||
size_t size()
|
size_t size()
|
||||||
|
|
||||||
# Cython can't handle Array[word] as a function argument
|
cdef extern from "kj/async-io.h" namespace " ::kj":
|
||||||
cdef cppclass WordArray " ::kj::Array< ::capnp::word>":
|
cdef cppclass AsyncIoStream:
|
||||||
word* begin()
|
pass
|
||||||
size_t size()
|
|
||||||
|
Own[AsyncIoStream] AsyncIoStream_wrapFd" ::kj::AsyncIoStream::wrapFd"(int)
|
||||||
|
|
||||||
cdef extern from "capnp/schema.h" namespace " ::capnp":
|
cdef extern from "capnp/schema.h" namespace " ::capnp":
|
||||||
cdef cppclass Schema:
|
cdef cppclass Schema:
|
||||||
Node.Reader getProto() except +
|
Node.Reader getProto() except +reraise_kj_exception
|
||||||
StructSchema asStruct() except +
|
StructSchema asStruct() except +reraise_kj_exception
|
||||||
EnumSchema asEnum() except +
|
EnumSchema asEnum() except +reraise_kj_exception
|
||||||
ConstSchema asConst() except +
|
ConstSchema asConst() except +reraise_kj_exception
|
||||||
Schema getDependency(uint64_t id) except +
|
Schema getDependency(uint64_t id) except +reraise_kj_exception
|
||||||
#InterfaceSchema asInterface() const;
|
InterfaceSchema asInterface() except +reraise_kj_exception
|
||||||
|
|
||||||
|
cdef cppclass InterfaceSchema(Schema):
|
||||||
|
cppclass Method:
|
||||||
|
InterfaceNode.Method.Reader getProto()
|
||||||
|
InterfaceSchema getContainingInterface()
|
||||||
|
uint16_t getOrdinal()
|
||||||
|
uint getIndex()
|
||||||
|
|
||||||
|
cppclass MethodList:
|
||||||
|
uint size()
|
||||||
|
Method operator[](uint index)
|
||||||
|
|
||||||
|
MethodList getMethods()
|
||||||
|
Maybe[Method] findMethodByName(StringPtr name)
|
||||||
|
Method getMethodByName(StringPtr name)
|
||||||
|
bint extends(InterfaceSchema other)
|
||||||
|
# kj::Maybe<InterfaceSchema> findSuperclass(uint64_t typeId) const;
|
||||||
|
|
||||||
cdef cppclass StructSchema(Schema):
|
cdef cppclass StructSchema(Schema):
|
||||||
cppclass Field:
|
cppclass Field:
|
||||||
@@ -103,6 +133,8 @@ cdef extern from "capnp/dynamic.h" namespace " ::capnp":
|
|||||||
pass
|
pass
|
||||||
cppclass Builder:
|
cppclass Builder:
|
||||||
pass
|
pass
|
||||||
|
cppclass Pipeline:
|
||||||
|
pass
|
||||||
|
|
||||||
enum Type:
|
enum Type:
|
||||||
TYPE_UNKNOWN " ::capnp::DynamicValue::UNKNOWN"
|
TYPE_UNKNOWN " ::capnp::DynamicValue::UNKNOWN"
|
||||||
@@ -116,34 +148,110 @@ cdef extern from "capnp/dynamic.h" namespace " ::capnp":
|
|||||||
TYPE_LIST " ::capnp::DynamicValue::LIST"
|
TYPE_LIST " ::capnp::DynamicValue::LIST"
|
||||||
TYPE_ENUM " ::capnp::DynamicValue::ENUM"
|
TYPE_ENUM " ::capnp::DynamicValue::ENUM"
|
||||||
TYPE_STRUCT " ::capnp::DynamicValue::STRUCT"
|
TYPE_STRUCT " ::capnp::DynamicValue::STRUCT"
|
||||||
TYPE_INTERFACE " ::capnp::DynamicValue::INTERFACE"
|
TYPE_CAPABILITY " ::capnp::DynamicValue::CAPABILITY"
|
||||||
TYPE_OBJECT " ::capnp::DynamicValue::OBJECT"
|
TYPE_OBJECT " ::capnp::DynamicValue::OBJECT"
|
||||||
|
|
||||||
cdef cppclass DynamicStruct:
|
cdef cppclass DynamicStruct:
|
||||||
cppclass Reader:
|
cppclass Reader:
|
||||||
DynamicValueForward.Reader get(char *) except +ValueError
|
DynamicValueForward.Reader get(char *) except +reraise_kj_exception
|
||||||
bint has(char *) except +ValueError
|
bint has(char *) except +reraise_kj_exception
|
||||||
StructSchema getSchema()
|
StructSchema getSchema()
|
||||||
Maybe[StructSchema.Field] which()
|
Maybe[StructSchema.Field] which()
|
||||||
cppclass Builder:
|
cppclass Builder:
|
||||||
Builder()
|
Builder()
|
||||||
Builder(Builder &)
|
Builder(Builder &)
|
||||||
DynamicValueForward.Builder get(char *) except +ValueError
|
DynamicValueForward.Builder get(char *) except +reraise_kj_exception
|
||||||
bint has(char *) except +ValueError
|
bint has(char *) except +reraise_kj_exception
|
||||||
void set(char *, DynamicValueForward.Reader) except +ValueError
|
void set(char *, DynamicValueForward.Reader) except +reraise_kj_exception
|
||||||
DynamicValueForward.Builder init(char *, uint size) except +ValueError
|
DynamicValueForward.Builder init(char *, uint size) except +reraise_kj_exception
|
||||||
DynamicValueForward.Builder init(char *) except +ValueError
|
DynamicValueForward.Builder init(char *) except +reraise_kj_exception
|
||||||
StructSchema getSchema()
|
StructSchema getSchema()
|
||||||
Maybe[StructSchema.Field] which()
|
Maybe[StructSchema.Field] which()
|
||||||
void adopt(char *, DynamicOrphan) except +ValueError
|
void adopt(char *, DynamicOrphan) except +reraise_kj_exception
|
||||||
DynamicOrphan disown(char *)
|
DynamicOrphan disown(char *)
|
||||||
DynamicStruct.Reader asReader()
|
DynamicStruct.Reader asReader()
|
||||||
DynamicStruct.Builder getObject(char *, StructSchema)
|
cppclass Pipeline:
|
||||||
|
Pipeline()
|
||||||
|
Pipeline(Pipeline &)
|
||||||
|
DynamicValueForward.Pipeline get(char *)
|
||||||
|
StructSchema getSchema()
|
||||||
|
|
||||||
|
cdef extern from "capnp/dynamic.h" namespace " ::capnp":
|
||||||
|
cdef cppclass DynamicCapability:
|
||||||
|
cppclass Client:
|
||||||
|
Client()
|
||||||
|
Client(Client&)
|
||||||
|
Client upcast(InterfaceSchema requestedSchema)
|
||||||
|
DynamicCapability.Client castAs"castAs< ::capnp::DynamicCapability>"(InterfaceSchema)
|
||||||
|
InterfaceSchema getSchema()
|
||||||
|
Request newRequest(char * methodName, uint firstSegmentWordSize)
|
||||||
|
|
||||||
|
cdef extern from "capnp/capability.h" namespace " ::capnp":
|
||||||
|
cdef cppclass Response" ::capnp::Response< ::capnp::DynamicStruct>"(DynamicStruct.Reader):
|
||||||
|
Response(Response)
|
||||||
|
cdef cppclass RemotePromise" ::capnp::RemotePromise< ::capnp::DynamicStruct>"(Promise[Response], DynamicStruct.Pipeline):
|
||||||
|
RemotePromise(RemotePromise)
|
||||||
|
cdef cppclass Capability:
|
||||||
|
cppclass Client:
|
||||||
|
Client(Client&)
|
||||||
|
DynamicCapability.Client castAs"castAs< ::capnp::DynamicCapability>"(InterfaceSchema)
|
||||||
|
|
||||||
|
cdef extern from "capnp/rpc-twoparty.h" namespace " ::capnp":
|
||||||
|
cdef cppclass RpcSystem" ::capnp::RpcSystem<capnp::rpc::twoparty::SturdyRefHostId>":
|
||||||
|
RpcSystem(RpcSystem&&)
|
||||||
|
enum Side" ::capnp::rpc::twoparty::Side":
|
||||||
|
CLIENT" ::capnp::rpc::twoparty::Side::CLIENT"
|
||||||
|
SERVER" ::capnp::rpc::twoparty::Side::SERVER"
|
||||||
|
cdef cppclass TwoPartyVatNetwork:
|
||||||
|
TwoPartyVatNetwork(EventLoop &, AsyncIoStream& stream, Side)
|
||||||
|
RpcSystem makeRpcServer(TwoPartyVatNetwork&, PyRestorer&, EventLoop&)
|
||||||
|
RpcSystem makeRpcClient(TwoPartyVatNetwork&, EventLoop&)
|
||||||
|
|
||||||
|
cdef extern from "capnp/dynamic.h" namespace " ::capnp":
|
||||||
|
cdef cppclass Request" ::capnp::Request< ::capnp::DynamicStruct, ::capnp::DynamicStruct>":
|
||||||
|
Request()
|
||||||
|
Request(Request &)
|
||||||
|
DynamicValueForward.Builder get(char *) except +reraise_kj_exception
|
||||||
|
bint has(char *) except +reraise_kj_exception
|
||||||
|
void set(char *, DynamicValueForward.Reader) except +reraise_kj_exception
|
||||||
|
DynamicValueForward.Builder init(char *, uint size) except +reraise_kj_exception
|
||||||
|
DynamicValueForward.Builder init(char *) except +reraise_kj_exception
|
||||||
|
StructSchema getSchema()
|
||||||
|
Maybe[StructSchema.Field] which()
|
||||||
|
RemotePromise send()
|
||||||
|
|
||||||
|
cdef extern from "capnp/object.h" namespace " ::capnp":
|
||||||
|
cdef cppclass ObjectPointer:
|
||||||
|
cppclass Reader:
|
||||||
|
DynamicStruct.Reader getAs"getAs< ::capnp::DynamicStruct>"(StructSchema)
|
||||||
|
cppclass Builder:
|
||||||
|
Builder(Builder)
|
||||||
|
DynamicStruct.Builder getAs"getAs< ::capnp::DynamicStruct>"(StructSchema)
|
||||||
|
|
||||||
cdef extern from "fixMaybe.h":
|
cdef extern from "fixMaybe.h":
|
||||||
EnumSchema.Enumerant fixMaybe(Maybe[EnumSchema.Enumerant]) except +ValueError
|
EnumSchema.Enumerant fixMaybe(Maybe[EnumSchema.Enumerant]) except +reraise_kj_exception
|
||||||
char * getEnumString(DynamicStruct.Reader val)
|
char * getEnumString(DynamicStruct.Reader val)
|
||||||
char * getEnumString(DynamicStruct.Builder val)
|
char * getEnumString(DynamicStruct.Builder val)
|
||||||
|
char * getEnumString(Request val)
|
||||||
|
|
||||||
|
cdef extern from "capabilityHelper.h":
|
||||||
|
PyPromise evalLater(EventLoop &, PyObject * func)
|
||||||
|
PyPromise there(EventLoop & loop, PyPromise & promise, PyObject * func, PyObject * error_func)
|
||||||
|
PyPromise then(PyPromise & promise, PyObject * func, PyObject * error_func)
|
||||||
|
VoidPromise then(RemotePromise & promise, PyObject * func, PyObject * error_func)
|
||||||
|
cppclass PythonInterfaceDynamicImpl:
|
||||||
|
PythonInterfaceDynamicImpl(PyObject *)
|
||||||
|
DynamicCapability.Client new_client(InterfaceSchema&, PyObject *, EventLoop&)
|
||||||
|
DynamicValueForward.Reader new_server(InterfaceSchema&, PyObject *)
|
||||||
|
Capability.Client server_to_client(InterfaceSchema&, PyObject *)
|
||||||
|
PyPromise convert_to_pypromise(RemotePromise&)
|
||||||
|
|
||||||
|
cdef extern from "rpcHelper.h":
|
||||||
|
cdef cppclass PyRestorer:
|
||||||
|
PyRestorer(PyObject *, StructSchema&)
|
||||||
|
Capability.Client restoreHelper(RpcSystem&, MessageBuilder&)
|
||||||
|
Capability.Client restoreHelper(RpcSystem&, MessageReader&)
|
||||||
|
RpcSystem makeRpcClientWithRestorer(TwoPartyVatNetwork&, EventLoop&, PyRestorer&)
|
||||||
|
|
||||||
cdef extern from "capnp/dynamic.h" namespace " ::capnp":
|
cdef extern from "capnp/dynamic.h" namespace " ::capnp":
|
||||||
cdef cppclass DynamicEnum:
|
cdef cppclass DynamicEnum:
|
||||||
@@ -159,16 +267,16 @@ cdef extern from "capnp/dynamic.h" namespace " ::capnp":
|
|||||||
|
|
||||||
cdef cppclass DynamicList:
|
cdef cppclass DynamicList:
|
||||||
cppclass Reader:
|
cppclass Reader:
|
||||||
DynamicValueForward.Reader operator[](uint) except +ValueError
|
DynamicValueForward.Reader operator[](uint) except +reraise_kj_exception
|
||||||
uint size()
|
uint size()
|
||||||
cppclass Builder:
|
cppclass Builder:
|
||||||
Builder()
|
Builder()
|
||||||
Builder(Builder &)
|
Builder(Builder &)
|
||||||
DynamicValueForward.Builder operator[](uint) except +ValueError
|
DynamicValueForward.Builder operator[](uint) except +reraise_kj_exception
|
||||||
uint size()
|
uint size()
|
||||||
void set(uint index, DynamicValueForward.Reader value) except +ValueError
|
void set(uint index, DynamicValueForward.Reader value) except +reraise_kj_exception
|
||||||
DynamicValueForward.Builder init(uint index, uint size) except +ValueError
|
DynamicValueForward.Builder init(uint index, uint size) except +reraise_kj_exception
|
||||||
void adopt(uint, DynamicOrphan) except +ValueError
|
void adopt(uint, DynamicOrphan) except +reraise_kj_exception
|
||||||
DynamicOrphan disown(uint)
|
DynamicOrphan disown(uint)
|
||||||
StructSchema getStructElementType'getSchema().getStructElementType'()
|
StructSchema getStructElementType'getSchema().getStructElementType'()
|
||||||
|
|
||||||
@@ -193,39 +301,88 @@ cdef extern from "capnp/dynamic.h" namespace " ::capnp":
|
|||||||
Reader(DynamicList.Reader& value)
|
Reader(DynamicList.Reader& value)
|
||||||
Reader(DynamicEnum value)
|
Reader(DynamicEnum value)
|
||||||
Reader(DynamicStruct.Reader& value)
|
Reader(DynamicStruct.Reader& value)
|
||||||
|
Reader(DynamicCapability.Client& value)
|
||||||
|
Reader(PythonInterfaceDynamicImpl& value)
|
||||||
Type getType()
|
Type getType()
|
||||||
int64_t asInt"as<int64_t>"()
|
int64_t asInt"as<int64_t>"()
|
||||||
uint64_t asUint"as<uint64_t>"()
|
uint64_t asUint"as<uint64_t>"()
|
||||||
bint asBool"as<bool>"()
|
bint asBool"as<bool>"()
|
||||||
double asDouble"as<double>"()
|
double asDouble"as<double>"()
|
||||||
char * asText"as< ::capnp::Text>().cStr"()
|
String asText"as< ::capnp::Text>"()
|
||||||
DynamicList.Reader asList"as< ::capnp::DynamicList>"()
|
DynamicList.Reader asList"as< ::capnp::DynamicList>"()
|
||||||
DynamicStruct.Reader asStruct"as< ::capnp::DynamicStruct>"()
|
DynamicStruct.Reader asStruct"as< ::capnp::DynamicStruct>"()
|
||||||
DynamicObject.Reader asObject"as< ::capnp::DynamicObject>"()
|
ObjectPointer.Reader asObject"as< ::capnp::ObjectPointer>"()
|
||||||
|
DynamicCapability.Client asCapability"as< ::capnp::DynamicCapability>"()
|
||||||
DynamicEnum asEnum"as< ::capnp::DynamicEnum>"()
|
DynamicEnum asEnum"as< ::capnp::DynamicEnum>"()
|
||||||
Data.Reader asData"as< ::capnp::Data>"()
|
Data.Reader asData"as< ::capnp::Data>"()
|
||||||
|
|
||||||
cppclass Builder:
|
cppclass Builder:
|
||||||
Builder()
|
|
||||||
Type getType()
|
Type getType()
|
||||||
int64_t asInt"as<int64_t>"()
|
int64_t asInt"as<int64_t>"()
|
||||||
uint64_t asUint"as<uint64_t>"()
|
uint64_t asUint"as<uint64_t>"()
|
||||||
bint asBool"as<bool>"()
|
bint asBool"as<bool>"()
|
||||||
double asDouble"as<double>"()
|
double asDouble"as<double>"()
|
||||||
char * asText"as< ::capnp::Text>().cStr"()
|
String asText"as< ::capnp::Text>"()
|
||||||
DynamicList.Builder asList"as< ::capnp::DynamicList>"()
|
DynamicList.Builder asList"as< ::capnp::DynamicList>"()
|
||||||
DynamicStruct.Builder asStruct"as< ::capnp::DynamicStruct>"()
|
DynamicStruct.Builder asStruct"as< ::capnp::DynamicStruct>"()
|
||||||
|
ObjectPointer.Builder asObject"as< ::capnp::ObjectPointer>"()
|
||||||
|
DynamicCapability.Client asCapability"as< ::capnp::DynamicCapability>"()
|
||||||
DynamicEnum asEnum"as< ::capnp::DynamicEnum>"()
|
DynamicEnum asEnum"as< ::capnp::DynamicEnum>"()
|
||||||
Data.Builder asData"as< ::capnp::Data>"()
|
Data.Builder asData"as< ::capnp::Data>"()
|
||||||
|
|
||||||
|
cppclass Pipeline:
|
||||||
|
Pipeline(Pipeline)
|
||||||
|
DynamicCapability.Client asCapability"releaseAs< ::capnp::DynamicCapability>"()
|
||||||
|
DynamicStruct.Pipeline asStruct"releaseAs< ::capnp::DynamicStruct>"()
|
||||||
|
Type getType()
|
||||||
|
|
||||||
cdef extern from "capnp/schema-parser.h" namespace " ::capnp":
|
cdef extern from "capnp/schema-parser.h" namespace " ::capnp":
|
||||||
cdef cppclass ParsedSchema(Schema):
|
cdef cppclass ParsedSchema(Schema):
|
||||||
ParsedSchema getNested(char * name) except +
|
ParsedSchema getNested(char * name) except +reraise_kj_exception
|
||||||
cdef cppclass SchemaParser:
|
cdef cppclass SchemaParser:
|
||||||
SchemaParser()
|
SchemaParser()
|
||||||
ParsedSchema parseDiskFile(char * displayName, char * diskPath, ArrayPtr[StringPtr] importPath) except +
|
ParsedSchema parseDiskFile(char * displayName, char * diskPath, ArrayPtr[StringPtr] importPath) except +reraise_kj_exception
|
||||||
|
|
||||||
cdef extern from "capnp/orphan.h" namespace " ::capnp":
|
cdef extern from "capnp/orphan.h" namespace " ::capnp":
|
||||||
cdef cppclass DynamicOrphan" ::capnp::Orphan< ::capnp::DynamicValue>":
|
cdef cppclass DynamicOrphan" ::capnp::Orphan< ::capnp::DynamicValue>":
|
||||||
DynamicValue.Builder get()
|
DynamicValue.Builder get()
|
||||||
DynamicValue.Reader getReader()
|
DynamicValue.Reader getReader()
|
||||||
|
|
||||||
|
cdef extern from "capnp/capability.h" namespace " ::capnp":
|
||||||
|
cdef cppclass CallContext' ::capnp::CallContext< ::capnp::DynamicStruct, ::capnp::DynamicStruct>':
|
||||||
|
CallContext(CallContext&)
|
||||||
|
DynamicStruct.Reader getParams() except +reraise_kj_exception
|
||||||
|
void releaseParams()
|
||||||
|
|
||||||
|
DynamicStruct.Builder getResults(uint firstSegmentWordSize)
|
||||||
|
DynamicStruct.Builder initResults(uint firstSegmentWordSize)
|
||||||
|
void setResults(DynamicStruct.Reader value)
|
||||||
|
# void adoptResults(Orphan<Results>&& value);
|
||||||
|
# Orphanage getResultsOrphanage(uint firstSegmentWordSize = 0);
|
||||||
|
void allowAsyncCancellation(bint allow = true)
|
||||||
|
bint isCanceled()
|
||||||
|
|
||||||
|
cdef extern from "kj/async.h" namespace " ::kj":
|
||||||
|
cdef cppclass EventLoop:
|
||||||
|
EventLoop()
|
||||||
|
# Promise[void] yield_end'yield'()
|
||||||
|
object wait(PyPromise) except +reraise_kj_exception
|
||||||
|
Response wait_remote'wait'(RemotePromise)
|
||||||
|
void wait_void'wait'(VoidPromise)
|
||||||
|
object there(PyPromise) except +reraise_kj_exception
|
||||||
|
PyPromise evalLater(PyObject * func)
|
||||||
|
PyPromise there(PyPromise, PyObject * func)
|
||||||
|
cdef cppclass SimpleEventLoop(EventLoop):
|
||||||
|
pass
|
||||||
|
cdef cppclass PromiseFulfiller:
|
||||||
|
pass
|
||||||
|
cdef cppclass PromiseFulfillerPair" ::kj::PromiseFulfillerPair<void>":
|
||||||
|
VoidPromise promise
|
||||||
|
Own[PromiseFulfiller] fulfiller
|
||||||
|
PromiseFulfillerPair newPromiseAndFulfiller" ::kj::newPromiseAndFulfiller<void>"()
|
||||||
|
PromiseFulfillerPair newPromiseAndFulfiller" ::kj::newPromiseAndFulfiller<void>"(EventLoop&)
|
||||||
|
|
||||||
|
cdef extern from "kj/async-unix.h" namespace " ::kj":
|
||||||
|
cdef cppclass UnixEventLoop(EventLoop):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ T fixMaybe(::kj::Maybe<T> val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const char * getEnumString(T val) {
|
const char * getEnumString(T & val) {
|
||||||
|
|
||||||
auto maybe_val = val.which();
|
auto maybe_val = val.which();
|
||||||
KJ_IF_MAYBE(new_val, maybe_val) {
|
KJ_IF_MAYBE(new_val, maybe_val) {
|
||||||
|
|||||||
59
capnp/rpcHelper.h
Normal file
59
capnp/rpcHelper.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "capnp/dynamic.h"
|
||||||
|
#include "capnp/rpc-twoparty.h"
|
||||||
|
#include "Python.h"
|
||||||
|
#include "capabilityHelper.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
capnp::Capability::Client * call_py_restorer(PyObject *, capnp::DynamicStruct::Reader &);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PyRestorer final: public capnp::SturdyRefRestorer<capnp::ObjectPointer> {
|
||||||
|
public:
|
||||||
|
PyRestorer(PyObject * _py_restorer, capnp::StructSchema& _schema): py_restorer(_py_restorer), schema(_schema) {
|
||||||
|
// We don't need to incref/decref, since this C++ class will be owned by the Python wrapper class, and we'll make sure the python class doesn't refcount to 0 elsewhere.
|
||||||
|
// Py_INCREF(py_restorer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ~PyRestorer() {
|
||||||
|
// Py_DECREF(py_restorer);
|
||||||
|
// }
|
||||||
|
|
||||||
|
capnp::Capability::Client restore(capnp::ObjectPointer::Reader objectId) override {
|
||||||
|
auto reader = objectId.getAs<capnp::DynamicStruct>(schema);
|
||||||
|
capnp::Capability::Client * ret = call_py_restorer(py_restorer, reader);
|
||||||
|
check_py_error();
|
||||||
|
capnp::Capability::Client stack_ret(*ret);
|
||||||
|
delete ret;
|
||||||
|
|
||||||
|
return stack_ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PyObject * py_restorer;
|
||||||
|
capnp::StructSchema schema;
|
||||||
|
};
|
||||||
|
|
||||||
|
capnp::Capability::Client restoreHelper(capnp::RpcSystem<capnp::rpc::twoparty::SturdyRefHostId>& client, capnp::MessageBuilder & objectId) { capnp::MallocMessageBuilder hostIdMessage(8);
|
||||||
|
auto hostId = hostIdMessage.initRoot<capnp::rpc::twoparty::SturdyRefHostId>();
|
||||||
|
hostId.setSide(capnp::rpc::twoparty::Side::SERVER);
|
||||||
|
return client.restore(hostId, objectId.getRoot<capnp::ObjectPointer>());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
capnp::Capability::Client restoreHelper(capnp::RpcSystem<capnp::rpc::twoparty::SturdyRefHostId>& client, capnp::MessageReader & objectId) { capnp::MallocMessageBuilder hostIdMessage(8);
|
||||||
|
auto hostId = hostIdMessage.initRoot<capnp::rpc::twoparty::SturdyRefHostId>();
|
||||||
|
hostId.setSide(capnp::rpc::twoparty::Side::SERVER);
|
||||||
|
return client.restore(hostId, objectId.getRoot<capnp::ObjectPointer>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename SturdyRefHostId, typename ProvisionId,
|
||||||
|
typename RecipientId, typename ThirdPartyCapId, typename JoinAnswer>
|
||||||
|
capnp::RpcSystem<SturdyRefHostId> makeRpcClientWithRestorer(
|
||||||
|
capnp::VatNetwork<SturdyRefHostId, ProvisionId, RecipientId, ThirdPartyCapId, JoinAnswer>& network,
|
||||||
|
const kj::EventLoop& eventLoop, PyRestorer& restorer) {
|
||||||
|
using namespace capnp;
|
||||||
|
return RpcSystem<SturdyRefHostId>(network,
|
||||||
|
kj::Maybe<SturdyRefRestorer<ObjectPointer>&>(restorer), eventLoop);
|
||||||
|
}
|
||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
from libc.stdint cimport *
|
from libc.stdint cimport *
|
||||||
from capnp_cpp cimport DynamicOrphan
|
from capnp_cpp cimport DynamicOrphan
|
||||||
cimport capnp_cpp
|
|
||||||
ctypedef unsigned int uint
|
ctypedef unsigned int uint
|
||||||
ctypedef uint8_t UInt8
|
ctypedef uint8_t UInt8
|
||||||
ctypedef uint16_t UInt16
|
ctypedef uint16_t UInt16
|
||||||
@@ -689,28 +688,49 @@ cdef extern from "capnp/message.h" namespace " ::capnp":
|
|||||||
MallocMessageBuilder(int)
|
MallocMessageBuilder(int)
|
||||||
|
|
||||||
cdef cppclass FlatMessageBuilder(MessageBuilder):
|
cdef cppclass FlatMessageBuilder(MessageBuilder):
|
||||||
FlatMessageBuilder(capnp_cpp.WordArrayPtr array)
|
FlatMessageBuilder(WordArrayPtr array)
|
||||||
FlatMessageBuilder(capnp_cpp.WordArrayPtr array, ReaderOptions)
|
FlatMessageBuilder(WordArrayPtr array, ReaderOptions)
|
||||||
|
|
||||||
enum Void:
|
enum Void:
|
||||||
VOID
|
VOID
|
||||||
|
|
||||||
|
cdef extern from "capnp/common.h" namespace " ::capnp":
|
||||||
|
cdef cppclass word:
|
||||||
|
pass
|
||||||
|
|
||||||
|
cdef extern from "kj/common.h" namespace " ::kj":
|
||||||
|
# Cython can't handle ArrayPtr[word] as a function argument
|
||||||
|
cdef cppclass WordArrayPtr " ::kj::ArrayPtr< ::capnp::word>":
|
||||||
|
WordArrayPtr()
|
||||||
|
WordArrayPtr(word *, size_t size)
|
||||||
|
size_t size()
|
||||||
|
word& operator[](size_t index)
|
||||||
|
|
||||||
|
cdef extern from "kj/array.h" namespace " ::kj":
|
||||||
|
# Cython can't handle Array[word] as a function argument
|
||||||
|
cdef cppclass WordArray " ::kj::Array< ::capnp::word>":
|
||||||
|
word* begin()
|
||||||
|
size_t size()
|
||||||
|
|
||||||
|
cdef extern from "capabilityHelper.h":
|
||||||
|
void reraise_kj_exception()
|
||||||
|
|
||||||
cdef extern from "capnp/serialize.h" namespace " ::capnp":
|
cdef extern from "capnp/serialize.h" namespace " ::capnp":
|
||||||
cdef cppclass StreamFdMessageReader(MessageReader):
|
cdef cppclass StreamFdMessageReader(MessageReader):
|
||||||
StreamFdMessageReader(int) except +
|
StreamFdMessageReader(int) except +reraise_kj_exception
|
||||||
StreamFdMessageReader(int, ReaderOptions) except +
|
StreamFdMessageReader(int, ReaderOptions) except +reraise_kj_exception
|
||||||
|
|
||||||
cdef cppclass FlatArrayMessageReader(MessageReader):
|
cdef cppclass FlatArrayMessageReader(MessageReader):
|
||||||
FlatArrayMessageReader(capnp_cpp.WordArrayPtr array) except +
|
FlatArrayMessageReader(WordArrayPtr array) except +reraise_kj_exception
|
||||||
FlatArrayMessageReader(capnp_cpp.WordArrayPtr array, ReaderOptions) except +
|
FlatArrayMessageReader(WordArrayPtr array, ReaderOptions) except +reraise_kj_exception
|
||||||
|
|
||||||
void writeMessageToFd(int, MessageBuilder&) except +
|
void writeMessageToFd(int, MessageBuilder&) except +reraise_kj_exception
|
||||||
|
|
||||||
capnp_cpp.WordArray messageToFlatArray(MessageBuilder &)
|
WordArray messageToFlatArray(MessageBuilder &)
|
||||||
|
|
||||||
cdef extern from "capnp/serialize-packed.h" namespace " ::capnp":
|
cdef extern from "capnp/serialize-packed.h" namespace " ::capnp":
|
||||||
cdef cppclass PackedFdMessageReader(MessageReader):
|
cdef cppclass PackedFdMessageReader(MessageReader):
|
||||||
PackedFdMessageReader(int) except +
|
PackedFdMessageReader(int) except +reraise_kj_exception
|
||||||
PackedFdMessageReader(int, ReaderOptions) except +
|
PackedFdMessageReader(int, ReaderOptions) except +reraise_kj_exception
|
||||||
|
|
||||||
void writePackedMessageToFd(int, MessageBuilder&) except +
|
void writePackedMessageToFd(int, MessageBuilder&) except +reraise_kj_exception
|
||||||
|
|||||||
27
examples/c++.capnp
Normal file
27
examples/c++.capnp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
|
# and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
@0xbdf87d7bb8304e81;
|
||||||
|
$namespace("capnp::annotations");
|
||||||
|
|
||||||
|
annotation namespace(file): Text;
|
||||||
58
examples/example_capability.capnp
Normal file
58
examples/example_capability.capnp
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
# Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
|
# and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
@0xd508eefec2dc42b8;
|
||||||
|
|
||||||
|
interface TestInterface {
|
||||||
|
foo @0 (i :UInt32, j :Bool) -> (x: Text);
|
||||||
|
bar @1 () -> ();
|
||||||
|
# baz @2 (s: TestAllTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TestExtends extends(TestInterface) {
|
||||||
|
qux @0 ();
|
||||||
|
# corge @1 TestAllTypes -> ();
|
||||||
|
# grault @2 () -> TestAllTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TestPipeline {
|
||||||
|
getCap @0 (n: UInt32, inCap :TestInterface) -> (s: Text, outBox :Box);
|
||||||
|
testPointers @1 (cap :TestInterface, obj :Object, list :List(TestInterface)) -> ();
|
||||||
|
|
||||||
|
struct Box {
|
||||||
|
cap @0 :TestInterface;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestSturdyRefHostId {
|
||||||
|
host @0 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestSturdyRefObjectId {
|
||||||
|
tag @0 :Tag;
|
||||||
|
enum Tag {
|
||||||
|
testInterface @0;
|
||||||
|
testExtends @1;
|
||||||
|
testPipeline @2;
|
||||||
|
}
|
||||||
|
}
|
||||||
37
examples/example_capability.py
Normal file
37
examples/example_capability.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import capnp
|
||||||
|
import example_capability_capnp as capability
|
||||||
|
import socket
|
||||||
|
|
||||||
|
class Server:
|
||||||
|
def __init__(self, val=1):
|
||||||
|
self.val = val
|
||||||
|
|
||||||
|
def foo(self, context):
|
||||||
|
context.results.x = str(context.params.i * 5 + self.val)
|
||||||
|
|
||||||
|
def example_simple_rpc():
|
||||||
|
def _restore(ref_id):
|
||||||
|
return capability.TestInterface.new_server(Server(100))
|
||||||
|
|
||||||
|
loop = capnp.EventLoop()
|
||||||
|
|
||||||
|
read, write = socket.socketpair(socket.AF_UNIX)
|
||||||
|
read_stream = capnp.FdAsyncIoStream(read.fileno())
|
||||||
|
write_stream = capnp.FdAsyncIoStream(write.fileno())
|
||||||
|
|
||||||
|
restorer = capnp.Restorer(capability.TestSturdyRefObjectId, _restore)
|
||||||
|
server = capnp.RpcServer(loop, write_stream, restorer)
|
||||||
|
client = capnp.RpcClient(loop, read_stream)
|
||||||
|
|
||||||
|
ref = capability.TestSturdyRefObjectId.new_message()
|
||||||
|
cap = client.restore(ref.as_reader())
|
||||||
|
cap = cap.cast_as(capability.TestInterface)
|
||||||
|
|
||||||
|
remote = cap.foo(i=5)
|
||||||
|
response = loop.wait(remote)
|
||||||
|
|
||||||
|
assert response.x == '125'
|
||||||
|
|
||||||
|
example_simple_rpc()
|
||||||
59
examples/example_client.cpp
Normal file
59
examples/example_client.cpp
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#include "capnp/rpc-twoparty.h"
|
||||||
|
#include <kj/async-unix.h>
|
||||||
|
#include <kj/thread.h>
|
||||||
|
#include "test.capnp.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
using namespace capnp;
|
||||||
|
using namespace capnproto_test::capnp;
|
||||||
|
using namespace kj;
|
||||||
|
|
||||||
|
Capability::Client getPersistentCap(RpcSystem<rpc::twoparty::SturdyRefHostId>& client,
|
||||||
|
rpc::twoparty::Side side,
|
||||||
|
test::TestSturdyRefObjectId::Tag tag) {
|
||||||
|
// Create the SturdyRefHostId.
|
||||||
|
MallocMessageBuilder hostIdMessage(8);
|
||||||
|
auto hostId = hostIdMessage.initRoot<rpc::twoparty::SturdyRefHostId>();
|
||||||
|
hostId.setSide(side);
|
||||||
|
|
||||||
|
// Create the SturdyRefObjectId.
|
||||||
|
MallocMessageBuilder objectIdMessage(8);
|
||||||
|
objectIdMessage.initRoot<test::TestSturdyRefObjectId>().setTag(tag);
|
||||||
|
|
||||||
|
// Connect to the remote capability.
|
||||||
|
return client.restore(hostId, objectIdMessage.getRoot<ObjectPointer>());
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
kj::UnixEventLoop loop;
|
||||||
|
auto result = loop.evalLater([&]() {
|
||||||
|
auto network = Network::newSystemNetwork();
|
||||||
|
auto address = loop.wait(network->parseRemoteAddress("127.0.0.1:49999"));
|
||||||
|
auto stream = loop.wait(address->connect());
|
||||||
|
TwoPartyVatNetwork vat(loop, *stream, rpc::twoparty::Side::CLIENT);
|
||||||
|
auto rpcClient = makeRpcClient(vat, loop);
|
||||||
|
|
||||||
|
// Request the particular capability from the server.
|
||||||
|
auto client = getPersistentCap(rpcClient, rpc::twoparty::Side::SERVER,
|
||||||
|
test::TestSturdyRefObjectId::Tag::TEST_INTERFACE).castAs<test::TestInterface>();
|
||||||
|
|
||||||
|
auto request1 = client.fooRequest();
|
||||||
|
request1.setI(5);
|
||||||
|
auto promise1 = request1.send();
|
||||||
|
auto response1 = loop.wait(kj::mv(promise1));
|
||||||
|
|
||||||
|
assert ("125" == response1.getX());
|
||||||
|
});
|
||||||
|
|
||||||
|
loop.wait(kj::mv(result));
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
26
examples/example_client.py
Normal file
26
examples/example_client.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import capnp
|
||||||
|
import test_capnp
|
||||||
|
import socket
|
||||||
|
|
||||||
|
def example_client():
|
||||||
|
loop = capnp.EventLoop()
|
||||||
|
|
||||||
|
c = socket.create_connection(('localhost', 49999))
|
||||||
|
read_stream = capnp.FdAsyncIoStream(c.fileno())
|
||||||
|
|
||||||
|
client = capnp.RpcClient(loop, read_stream)
|
||||||
|
|
||||||
|
ref = test_capnp.TestSturdyRefObjectId.new_message()
|
||||||
|
ref.tag = 'testInterface'
|
||||||
|
cap = client.restore(ref)
|
||||||
|
cap = cap.cast_as(test_capnp.TestInterface)
|
||||||
|
|
||||||
|
remote = cap.foo(i=5)
|
||||||
|
response = loop.wait(remote)
|
||||||
|
|
||||||
|
assert response.x == '125'
|
||||||
|
c.close()
|
||||||
|
|
||||||
|
example_client()
|
||||||
190
examples/example_server.cpp
Normal file
190
examples/example_server.cpp
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
#include <boost/asio.hpp>
|
||||||
|
#include "capnp/rpc-twoparty.h"
|
||||||
|
#include <kj/async-unix.h>
|
||||||
|
#include <kj/thread.h>
|
||||||
|
#include "test.capnp.h"
|
||||||
|
|
||||||
|
using namespace capnp;
|
||||||
|
using namespace capnproto_test::capnp;
|
||||||
|
using namespace kj;
|
||||||
|
|
||||||
|
class TestInterfaceImpl final: public test::TestInterface::Server {
|
||||||
|
public:
|
||||||
|
TestInterfaceImpl(int& callCount);
|
||||||
|
|
||||||
|
::kj::Promise<void> foo(
|
||||||
|
test::TestInterface::FooParams::Reader params,
|
||||||
|
test::TestInterface::FooResults::Builder result) override;
|
||||||
|
|
||||||
|
::kj::Promise<void> bazAdvanced(
|
||||||
|
::capnp::CallContext<test::TestInterface::BazParams,
|
||||||
|
test::TestInterface::BazResults> context) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int& callCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TestExtendsImpl final: public test::TestExtends::Server {
|
||||||
|
public:
|
||||||
|
TestExtendsImpl(int& callCount);
|
||||||
|
|
||||||
|
::kj::Promise<void> foo(
|
||||||
|
test::TestInterface::FooParams::Reader params,
|
||||||
|
test::TestInterface::FooResults::Builder result) override;
|
||||||
|
|
||||||
|
::kj::Promise<void> graultAdvanced(
|
||||||
|
::capnp::CallContext<test::TestExtends::GraultParams, test::TestAllTypes> context) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int& callCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TestPipelineImpl final: public test::TestPipeline::Server {
|
||||||
|
public:
|
||||||
|
TestPipelineImpl(int& callCount);
|
||||||
|
|
||||||
|
::kj::Promise<void> getCapAdvanced(
|
||||||
|
capnp::CallContext<test::TestPipeline::GetCapParams,
|
||||||
|
test::TestPipeline::GetCapResults> context) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int& callCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
TestInterfaceImpl::TestInterfaceImpl(int& callCount): callCount(callCount) {}
|
||||||
|
|
||||||
|
::kj::Promise<void> TestInterfaceImpl::foo(
|
||||||
|
test::TestInterface::FooParams::Reader params,
|
||||||
|
test::TestInterface::FooResults::Builder result) {
|
||||||
|
++callCount;
|
||||||
|
result.setX("foo");
|
||||||
|
return kj::READY_NOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
::kj::Promise<void> TestInterfaceImpl::bazAdvanced(
|
||||||
|
::capnp::CallContext<test::TestInterface::BazParams,
|
||||||
|
test::TestInterface::BazResults> context) {
|
||||||
|
++callCount;
|
||||||
|
auto params = context.getParams();
|
||||||
|
// checkTestMessage(params.getS());
|
||||||
|
context.releaseParams();
|
||||||
|
|
||||||
|
return kj::READY_NOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestExtendsImpl::TestExtendsImpl(int& callCount): callCount(callCount) {}
|
||||||
|
|
||||||
|
::kj::Promise<void> TestExtendsImpl::foo(
|
||||||
|
test::TestInterface::FooParams::Reader params,
|
||||||
|
test::TestInterface::FooResults::Builder result) {
|
||||||
|
++callCount;
|
||||||
|
result.setX("bar");
|
||||||
|
return kj::READY_NOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
::kj::Promise<void> TestExtendsImpl::graultAdvanced(
|
||||||
|
::capnp::CallContext<test::TestExtends::GraultParams, test::TestAllTypes> context) {
|
||||||
|
++callCount;
|
||||||
|
context.releaseParams();
|
||||||
|
|
||||||
|
// initTestMessage(context.getResults());
|
||||||
|
|
||||||
|
return kj::READY_NOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestPipelineImpl::TestPipelineImpl(int& callCount): callCount(callCount) {}
|
||||||
|
|
||||||
|
::kj::Promise<void> TestPipelineImpl::getCapAdvanced(
|
||||||
|
capnp::CallContext<test::TestPipeline::GetCapParams,
|
||||||
|
test::TestPipeline::GetCapResults> context) {
|
||||||
|
++callCount;
|
||||||
|
|
||||||
|
auto params = context.getParams();
|
||||||
|
|
||||||
|
auto cap = params.getInCap();
|
||||||
|
context.releaseParams();
|
||||||
|
|
||||||
|
auto request = cap.fooRequest();
|
||||||
|
request.setI(123);
|
||||||
|
request.setJ(true);
|
||||||
|
|
||||||
|
return request.send().then(
|
||||||
|
[this,context](capnp::Response<test::TestInterface::FooResults>&& response) mutable {
|
||||||
|
|
||||||
|
auto result = context.getResults();
|
||||||
|
result.setS("bar");
|
||||||
|
result.initOutBox().setCap(kj::heap<TestExtendsImpl>(callCount));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TestRestorer final: public SturdyRefRestorer<test::TestSturdyRefObjectId> {
|
||||||
|
public:
|
||||||
|
TestRestorer(int& callCount): callCount(callCount) {}
|
||||||
|
|
||||||
|
Capability::Client restore(test::TestSturdyRefObjectId::Reader objectId) override {
|
||||||
|
switch (objectId.getTag()) {
|
||||||
|
case test::TestSturdyRefObjectId::Tag::TEST_INTERFACE:
|
||||||
|
return kj::heap<TestInterfaceImpl>(callCount);
|
||||||
|
// case test::TestSturdyRefObjectId::Tag::TEST_EXTENDS:
|
||||||
|
// return Capability::Client(newBrokenCap("No TestExtends implemented."));
|
||||||
|
case test::TestSturdyRefObjectId::Tag::TEST_PIPELINE:
|
||||||
|
return kj::heap<TestPipelineImpl>(callCount);
|
||||||
|
}
|
||||||
|
KJ_UNREACHABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int& callCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
void runServer(kj::Promise<void> quit, kj::Own<kj::AsyncIoStream> stream, int& callCount) {
|
||||||
|
// Set up the server.
|
||||||
|
kj::UnixEventLoop eventLoop;
|
||||||
|
TwoPartyVatNetwork network(eventLoop, *stream, rpc::twoparty::Side::SERVER);
|
||||||
|
TestRestorer restorer(callCount);
|
||||||
|
auto server = makeRpcServer(network, restorer, eventLoop);
|
||||||
|
|
||||||
|
// Wait until quit promise is fulfilled.
|
||||||
|
eventLoop.wait(kj::mv(quit));
|
||||||
|
}
|
||||||
|
|
||||||
|
Capability::Client getPersistentCap(RpcSystem<rpc::twoparty::SturdyRefHostId>& client,
|
||||||
|
rpc::twoparty::Side side,
|
||||||
|
test::TestSturdyRefObjectId::Tag tag) {
|
||||||
|
// Create the SturdyRefHostId.
|
||||||
|
MallocMessageBuilder hostIdMessage(8);
|
||||||
|
auto hostId = hostIdMessage.initRoot<rpc::twoparty::SturdyRefHostId>();
|
||||||
|
hostId.setSide(side);
|
||||||
|
|
||||||
|
// Create the SturdyRefObjectId.
|
||||||
|
MallocMessageBuilder objectIdMessage(8);
|
||||||
|
objectIdMessage.initRoot<test::TestSturdyRefObjectId>().setTag(tag);
|
||||||
|
|
||||||
|
// Connect to the remote capability.
|
||||||
|
return client.restore(hostId, objectIdMessage.getRoot<ObjectPointer>());
|
||||||
|
}
|
||||||
|
|
||||||
|
using boost::asio::ip::tcp;
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int callCount(0);
|
||||||
|
boost::asio::io_service io_service;
|
||||||
|
|
||||||
|
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 49999));
|
||||||
|
tcp::socket socket(io_service);
|
||||||
|
acceptor.accept(socket);
|
||||||
|
|
||||||
|
kj::Own<AsyncIoStream> stream(AsyncIoStream::wrapFd(socket.native_handle()));
|
||||||
|
auto quitter = kj::newPromiseAndFulfiller<void>();
|
||||||
|
runServer(kj::mv(quitter.promise), kj::mv(stream), callCount);
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
39
examples/example_server.py
Normal file
39
examples/example_server.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import capnp
|
||||||
|
import test_capnp
|
||||||
|
|
||||||
|
import socket
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
class Server:
|
||||||
|
def __init__(self, val=1):
|
||||||
|
self.val = val
|
||||||
|
|
||||||
|
def foo(self, context):
|
||||||
|
context.results.x = str(context.params.i * 5 + self.val)
|
||||||
|
|
||||||
|
def restore(ref_id):
|
||||||
|
return test_capnp.TestInterface.new_server(Server(100))
|
||||||
|
|
||||||
|
def example_server(host='localhost', port=49999):
|
||||||
|
backlog = 1
|
||||||
|
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
s.bind((host,port))
|
||||||
|
s.listen(backlog)
|
||||||
|
|
||||||
|
loop = capnp.EventLoop()
|
||||||
|
while 1:
|
||||||
|
try:
|
||||||
|
(clientsocket, address) = s.accept()
|
||||||
|
stream = capnp.FdAsyncIoStream(clientsocket.fileno())
|
||||||
|
restorer = capnp.Restorer(test_capnp.TestSturdyRefObjectId, restore)
|
||||||
|
server = capnp.RpcServer(loop, stream, restorer)
|
||||||
|
|
||||||
|
waiter = capnp.PromiseFulfillerPair()
|
||||||
|
loop.wait(waiter)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
example_server()
|
||||||
613
examples/test.capnp
Normal file
613
examples/test.capnp
Normal file
@@ -0,0 +1,613 @@
|
|||||||
|
# Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
|
# and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
@0xd508eebdc2dc42b8;
|
||||||
|
|
||||||
|
using Cxx = import "c++.capnp";
|
||||||
|
|
||||||
|
# Use a namespace likely to cause trouble if the generated code doesn't use fully-qualified
|
||||||
|
# names for stuff in the capnproto namespace.
|
||||||
|
$Cxx.namespace("capnproto_test::capnp::test");
|
||||||
|
|
||||||
|
enum TestEnum {
|
||||||
|
foo @0;
|
||||||
|
bar @1;
|
||||||
|
baz @2;
|
||||||
|
qux @3;
|
||||||
|
quux @4;
|
||||||
|
corge @5;
|
||||||
|
grault @6;
|
||||||
|
garply @7;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestAllTypes {
|
||||||
|
voidField @0 : Void;
|
||||||
|
boolField @1 : Bool;
|
||||||
|
int8Field @2 : Int8;
|
||||||
|
int16Field @3 : Int16;
|
||||||
|
int32Field @4 : Int32;
|
||||||
|
int64Field @5 : Int64;
|
||||||
|
uInt8Field @6 : UInt8;
|
||||||
|
uInt16Field @7 : UInt16;
|
||||||
|
uInt32Field @8 : UInt32;
|
||||||
|
uInt64Field @9 : UInt64;
|
||||||
|
float32Field @10 : Float32;
|
||||||
|
float64Field @11 : Float64;
|
||||||
|
textField @12 : Text;
|
||||||
|
dataField @13 : Data;
|
||||||
|
structField @14 : TestAllTypes;
|
||||||
|
enumField @15 : TestEnum;
|
||||||
|
interfaceField @16 : Void; # TODO
|
||||||
|
|
||||||
|
voidList @17 : List(Void);
|
||||||
|
boolList @18 : List(Bool);
|
||||||
|
int8List @19 : List(Int8);
|
||||||
|
int16List @20 : List(Int16);
|
||||||
|
int32List @21 : List(Int32);
|
||||||
|
int64List @22 : List(Int64);
|
||||||
|
uInt8List @23 : List(UInt8);
|
||||||
|
uInt16List @24 : List(UInt16);
|
||||||
|
uInt32List @25 : List(UInt32);
|
||||||
|
uInt64List @26 : List(UInt64);
|
||||||
|
float32List @27 : List(Float32);
|
||||||
|
float64List @28 : List(Float64);
|
||||||
|
textList @29 : List(Text);
|
||||||
|
dataList @30 : List(Data);
|
||||||
|
structList @31 : List(TestAllTypes);
|
||||||
|
enumList @32 : List(TestEnum);
|
||||||
|
interfaceList @33 : List(Void); # TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestDefaults {
|
||||||
|
voidField @0 : Void = void;
|
||||||
|
boolField @1 : Bool = true;
|
||||||
|
int8Field @2 : Int8 = -123;
|
||||||
|
int16Field @3 : Int16 = -12345;
|
||||||
|
int32Field @4 : Int32 = -12345678;
|
||||||
|
int64Field @5 : Int64 = -123456789012345;
|
||||||
|
uInt8Field @6 : UInt8 = 234;
|
||||||
|
uInt16Field @7 : UInt16 = 45678;
|
||||||
|
uInt32Field @8 : UInt32 = 3456789012;
|
||||||
|
uInt64Field @9 : UInt64 = 12345678901234567890;
|
||||||
|
float32Field @10 : Float32 = 1234.5;
|
||||||
|
float64Field @11 : Float64 = -123e45;
|
||||||
|
textField @12 : Text = "foo";
|
||||||
|
dataField @13 : Data = "bar";
|
||||||
|
structField @14 : TestAllTypes = (
|
||||||
|
voidField = void,
|
||||||
|
boolField = true,
|
||||||
|
int8Field = -12,
|
||||||
|
int16Field = 3456,
|
||||||
|
int32Field = -78901234,
|
||||||
|
int64Field = 56789012345678,
|
||||||
|
uInt8Field = 90,
|
||||||
|
uInt16Field = 1234,
|
||||||
|
uInt32Field = 56789012,
|
||||||
|
uInt64Field = 345678901234567890,
|
||||||
|
float32Field = -1.25e-10,
|
||||||
|
float64Field = 345,
|
||||||
|
textField = "baz",
|
||||||
|
dataField = "qux",
|
||||||
|
structField = (
|
||||||
|
textField = "nested",
|
||||||
|
structField = (textField = "really nested")),
|
||||||
|
enumField = baz,
|
||||||
|
# interfaceField can't have a default
|
||||||
|
|
||||||
|
voidList = [void, void, void],
|
||||||
|
boolList = [false, true, false, true, true],
|
||||||
|
int8List = [12, -34, -0x80, 0x7f],
|
||||||
|
int16List = [1234, -5678, -0x8000, 0x7fff],
|
||||||
|
int32List = [12345678, -90123456, -0x80000000, 0x7fffffff],
|
||||||
|
int64List = [123456789012345, -678901234567890, -0x8000000000000000, 0x7fffffffffffffff],
|
||||||
|
uInt8List = [12, 34, 0, 0xff],
|
||||||
|
uInt16List = [1234, 5678, 0, 0xffff],
|
||||||
|
uInt32List = [12345678, 90123456, 0, 0xffffffff],
|
||||||
|
uInt64List = [123456789012345, 678901234567890, 0, 0xffffffffffffffff],
|
||||||
|
float32List = [0, 1234567, 1e37, -1e37, 1e-37, -1e-37],
|
||||||
|
float64List = [0, 123456789012345, 1e306, -1e306, 1e-306, -1e-306],
|
||||||
|
textList = ["quux", "corge", "grault"],
|
||||||
|
dataList = ["garply", "waldo", "fred"],
|
||||||
|
structList = [
|
||||||
|
(textField = "x structlist 1"),
|
||||||
|
(textField = "x structlist 2"),
|
||||||
|
(textField = "x structlist 3")],
|
||||||
|
enumList = [qux, bar, grault]
|
||||||
|
# interfaceList can't have a default
|
||||||
|
);
|
||||||
|
enumField @15 : TestEnum = corge;
|
||||||
|
interfaceField @16 : Void; # TODO
|
||||||
|
|
||||||
|
voidList @17 : List(Void) = [void, void, void, void, void, void];
|
||||||
|
boolList @18 : List(Bool) = [true, false, false, true];
|
||||||
|
int8List @19 : List(Int8) = [111, -111];
|
||||||
|
int16List @20 : List(Int16) = [11111, -11111];
|
||||||
|
int32List @21 : List(Int32) = [111111111, -111111111];
|
||||||
|
int64List @22 : List(Int64) = [1111111111111111111, -1111111111111111111];
|
||||||
|
uInt8List @23 : List(UInt8) = [111, 222] ;
|
||||||
|
uInt16List @24 : List(UInt16) = [33333, 44444];
|
||||||
|
uInt32List @25 : List(UInt32) = [3333333333];
|
||||||
|
uInt64List @26 : List(UInt64) = [11111111111111111111];
|
||||||
|
float32List @27 : List(Float32) = [5555.5, inf, -inf, nan];
|
||||||
|
float64List @28 : List(Float64) = [7777.75, inf, -inf, nan];
|
||||||
|
textList @29 : List(Text) = ["plugh", "xyzzy", "thud"];
|
||||||
|
dataList @30 : List(Data) = ["oops", "exhausted", "rfc3092"];
|
||||||
|
structList @31 : List(TestAllTypes) = [
|
||||||
|
(textField = "structlist 1"),
|
||||||
|
(textField = "structlist 2"),
|
||||||
|
(textField = "structlist 3")];
|
||||||
|
enumList @32 : List(TestEnum) = [foo, garply];
|
||||||
|
interfaceList @33 : List(Void); # TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestObject {
|
||||||
|
objectField @0 :Object;
|
||||||
|
|
||||||
|
# Do not add any other fields here! Some tests rely on objectField being the last pointer
|
||||||
|
# in the struct.
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestOutOfOrder {
|
||||||
|
foo @3 :Text;
|
||||||
|
bar @2 :Text;
|
||||||
|
baz @8 :Text;
|
||||||
|
qux @0 :Text;
|
||||||
|
quux @6 :Text;
|
||||||
|
corge @4 :Text;
|
||||||
|
grault @1 :Text;
|
||||||
|
garply @7 :Text;
|
||||||
|
waldo @5 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestUnion {
|
||||||
|
union0 @0! :union {
|
||||||
|
# Pack union 0 under ideal conditions: there is no unused padding space prior to it.
|
||||||
|
u0f0s0 @4: Void;
|
||||||
|
u0f0s1 @5: Bool;
|
||||||
|
u0f0s8 @6: Int8;
|
||||||
|
u0f0s16 @7: Int16;
|
||||||
|
u0f0s32 @8: Int32;
|
||||||
|
u0f0s64 @9: Int64;
|
||||||
|
u0f0sp @10: Text;
|
||||||
|
|
||||||
|
# Pack more stuff into union0 -- should go in same space.
|
||||||
|
u0f1s0 @11: Void;
|
||||||
|
u0f1s1 @12: Bool;
|
||||||
|
u0f1s8 @13: Int8;
|
||||||
|
u0f1s16 @14: Int16;
|
||||||
|
u0f1s32 @15: Int32;
|
||||||
|
u0f1s64 @16: Int64;
|
||||||
|
u0f1sp @17: Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Pack one bit in order to make pathological situation for union1.
|
||||||
|
bit0 @18: Bool;
|
||||||
|
|
||||||
|
union1 @1! :union {
|
||||||
|
# Pack pathologically bad case. Each field takes up new space.
|
||||||
|
u1f0s0 @19: Void;
|
||||||
|
u1f0s1 @20: Bool;
|
||||||
|
u1f1s1 @21: Bool;
|
||||||
|
u1f0s8 @22: Int8;
|
||||||
|
u1f1s8 @23: Int8;
|
||||||
|
u1f0s16 @24: Int16;
|
||||||
|
u1f1s16 @25: Int16;
|
||||||
|
u1f0s32 @26: Int32;
|
||||||
|
u1f1s32 @27: Int32;
|
||||||
|
u1f0s64 @28: Int64;
|
||||||
|
u1f1s64 @29: Int64;
|
||||||
|
u1f0sp @30: Text;
|
||||||
|
u1f1sp @31: Text;
|
||||||
|
|
||||||
|
# Pack more stuff into union1 -- each should go into the same space as corresponding u1f0s*.
|
||||||
|
u1f2s0 @32: Void;
|
||||||
|
u1f2s1 @33: Bool;
|
||||||
|
u1f2s8 @34: Int8;
|
||||||
|
u1f2s16 @35: Int16;
|
||||||
|
u1f2s32 @36: Int32;
|
||||||
|
u1f2s64 @37: Int64;
|
||||||
|
u1f2sp @38: Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fill in the rest of that bitfield from earlier.
|
||||||
|
bit2 @39: Bool;
|
||||||
|
bit3 @40: Bool;
|
||||||
|
bit4 @41: Bool;
|
||||||
|
bit5 @42: Bool;
|
||||||
|
bit6 @43: Bool;
|
||||||
|
bit7 @44: Bool;
|
||||||
|
|
||||||
|
# Interleave two unions to be really annoying.
|
||||||
|
# Also declare in reverse order to make sure union discriminant values are sorted by field number
|
||||||
|
# and not by declaration order.
|
||||||
|
union2 @2! :union {
|
||||||
|
u2f0s64 @54: Int64;
|
||||||
|
u2f0s32 @52: Int32;
|
||||||
|
u2f0s16 @50: Int16;
|
||||||
|
u2f0s8 @47: Int8;
|
||||||
|
u2f0s1 @45: Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
union3 @3! :union {
|
||||||
|
u3f0s64 @55: Int64;
|
||||||
|
u3f0s32 @53: Int32;
|
||||||
|
u3f0s16 @51: Int16;
|
||||||
|
u3f0s8 @48: Int8;
|
||||||
|
u3f0s1 @46: Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte0 @49: UInt8;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestUnnamedUnion {
|
||||||
|
before @0 :Text;
|
||||||
|
|
||||||
|
union {
|
||||||
|
foo @1 :UInt16;
|
||||||
|
bar @3 :UInt32;
|
||||||
|
}
|
||||||
|
|
||||||
|
middle @2 :UInt16;
|
||||||
|
|
||||||
|
after @4 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestUnionInUnion {
|
||||||
|
# There is no reason to ever do this.
|
||||||
|
outer :union {
|
||||||
|
inner :union {
|
||||||
|
foo @0 :Int32;
|
||||||
|
bar @1 :Int32;
|
||||||
|
}
|
||||||
|
baz @2 :Int32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestGroups {
|
||||||
|
groups :union {
|
||||||
|
foo :group {
|
||||||
|
corge @0 :Int32;
|
||||||
|
grault @2 :Int64;
|
||||||
|
garply @8 :Text;
|
||||||
|
}
|
||||||
|
bar :group {
|
||||||
|
corge @3 :Int32;
|
||||||
|
grault @4 :Text;
|
||||||
|
garply @5 :Int64;
|
||||||
|
}
|
||||||
|
baz :group {
|
||||||
|
corge @1 :Int32;
|
||||||
|
grault @6 :Text;
|
||||||
|
garply @7 :Text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestInterleavedGroups {
|
||||||
|
group1 :group {
|
||||||
|
foo @0 :UInt32;
|
||||||
|
bar @2 :UInt64;
|
||||||
|
union {
|
||||||
|
qux @4 :UInt16;
|
||||||
|
corge :group {
|
||||||
|
grault @6 :UInt64;
|
||||||
|
garply @8 :UInt16;
|
||||||
|
plugh @14 :Text;
|
||||||
|
xyzzy @16 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
fred @12 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
waldo @10 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
group2 :group {
|
||||||
|
foo @1 :UInt32;
|
||||||
|
bar @3 :UInt64;
|
||||||
|
union {
|
||||||
|
qux @5 :UInt16;
|
||||||
|
corge :group {
|
||||||
|
grault @7 :UInt64;
|
||||||
|
garply @9 :UInt16;
|
||||||
|
plugh @15 :Text;
|
||||||
|
xyzzy @17 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
fred @13 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
waldo @11 :Text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestUnionDefaults {
|
||||||
|
s16s8s64s8Set @0 :TestUnion =
|
||||||
|
(union0 = (u0f0s16 = 321), union1 = (u1f0s8 = 123), union2 = (u2f0s64 = 12345678901234567),
|
||||||
|
union3 = (u3f0s8 = 55));
|
||||||
|
s0sps1s32Set @1 :TestUnion =
|
||||||
|
(union0 = (u0f1s0 = void), union1 = (u1f0sp = "foo"), union2 = (u2f0s1 = true),
|
||||||
|
union3 = (u3f0s32 = 12345678));
|
||||||
|
|
||||||
|
unnamed1 @2 :TestUnnamedUnion = (foo = 123);
|
||||||
|
unnamed2 @3 :TestUnnamedUnion = (bar = 321, before = "foo", after = "bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestNestedTypes {
|
||||||
|
enum NestedEnum {
|
||||||
|
foo @0;
|
||||||
|
bar @1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NestedStruct {
|
||||||
|
enum NestedEnum {
|
||||||
|
baz @0;
|
||||||
|
qux @1;
|
||||||
|
quux @2;
|
||||||
|
}
|
||||||
|
|
||||||
|
outerNestedEnum @0 :TestNestedTypes.NestedEnum = bar;
|
||||||
|
innerNestedEnum @1 :NestedEnum = quux;
|
||||||
|
}
|
||||||
|
|
||||||
|
nestedStruct @0 :NestedStruct;
|
||||||
|
|
||||||
|
outerNestedEnum @1 :NestedEnum = bar;
|
||||||
|
innerNestedEnum @2 :NestedStruct.NestedEnum = quux;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestUsing {
|
||||||
|
using OuterNestedEnum = TestNestedTypes.NestedEnum;
|
||||||
|
using TestNestedTypes.NestedStruct.NestedEnum;
|
||||||
|
|
||||||
|
outerNestedEnum @1 :OuterNestedEnum = bar;
|
||||||
|
innerNestedEnum @0 :NestedEnum = quux;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestLists {
|
||||||
|
# Small structs, when encoded as list, will be encoded as primitive lists rather than struct
|
||||||
|
# lists, to save space.
|
||||||
|
struct Struct0 { f @0 :Void; }
|
||||||
|
struct Struct1 { f @0 :Bool; }
|
||||||
|
struct Struct8 { f @0 :UInt8; }
|
||||||
|
struct Struct16 { f @0 :UInt16; }
|
||||||
|
struct Struct32 { f @0 :UInt32; }
|
||||||
|
struct Struct64 { f @0 :UInt64; }
|
||||||
|
struct StructP { f @0 :Text; }
|
||||||
|
|
||||||
|
# Versions of the above which cannot be encoded as primitive lists.
|
||||||
|
struct Struct0c { f @0 :Void; pad @1 :Text; }
|
||||||
|
struct Struct1c { f @0 :Bool; pad @1 :Text; }
|
||||||
|
struct Struct8c { f @0 :UInt8; pad @1 :Text; }
|
||||||
|
struct Struct16c { f @0 :UInt16; pad @1 :Text; }
|
||||||
|
struct Struct32c { f @0 :UInt32; pad @1 :Text; }
|
||||||
|
struct Struct64c { f @0 :UInt64; pad @1 :Text; }
|
||||||
|
struct StructPc { f @0 :Text; pad @1 :UInt64; }
|
||||||
|
|
||||||
|
list0 @0 :List(Struct0);
|
||||||
|
list1 @1 :List(Struct1);
|
||||||
|
list8 @2 :List(Struct8);
|
||||||
|
list16 @3 :List(Struct16);
|
||||||
|
list32 @4 :List(Struct32);
|
||||||
|
list64 @5 :List(Struct64);
|
||||||
|
listP @6 :List(StructP);
|
||||||
|
|
||||||
|
int32ListList @7 :List(List(Int32));
|
||||||
|
textListList @8 :List(List(Text));
|
||||||
|
structListList @9 :List(List(TestAllTypes));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestFieldZeroIsBit {
|
||||||
|
bit @0 :Bool;
|
||||||
|
secondBit @1 :Bool = true;
|
||||||
|
thirdField @2 :UInt8 = 123;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestListDefaults {
|
||||||
|
lists @0 :TestLists = (
|
||||||
|
list0 = [(f = void), (f = void)],
|
||||||
|
list1 = [(f = true), (f = false), (f = true), (f = true)],
|
||||||
|
list8 = [(f = 123), (f = 45)],
|
||||||
|
list16 = [(f = 12345), (f = 6789)],
|
||||||
|
list32 = [(f = 123456789), (f = 234567890)],
|
||||||
|
list64 = [(f = 1234567890123456), (f = 2345678901234567)],
|
||||||
|
listP = [(f = "foo"), (f = "bar")],
|
||||||
|
int32ListList = [[1, 2, 3], [4, 5], [12341234]],
|
||||||
|
textListList = [["foo", "bar"], ["baz"], ["qux", "corge"]],
|
||||||
|
structListList = [[(int32Field = 123), (int32Field = 456)], [(int32Field = 789)]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestLateUnion {
|
||||||
|
# Test what happens if the unions are not the first ordinals in the struct. At one point this
|
||||||
|
# was broken for the dynamic API.
|
||||||
|
|
||||||
|
foo @0 :Int32;
|
||||||
|
bar @1 :Text;
|
||||||
|
baz @2 :Int16;
|
||||||
|
|
||||||
|
theUnion @3! :union {
|
||||||
|
qux @4 :Text;
|
||||||
|
corge @5 :List(Int32);
|
||||||
|
grault @6 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
|
anotherUnion @7! :union {
|
||||||
|
qux @8 :Text;
|
||||||
|
corge @9 :List(Int32);
|
||||||
|
grault @10 :Float32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestOldVersion {
|
||||||
|
# A subset of TestNewVersion.
|
||||||
|
old1 @0 :Int64;
|
||||||
|
old2 @1 :Text;
|
||||||
|
old3 @2 :TestOldVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestNewVersion {
|
||||||
|
# A superset of TestOldVersion.
|
||||||
|
old1 @0 :Int64;
|
||||||
|
old2 @1 :Text;
|
||||||
|
old3 @2 :TestNewVersion;
|
||||||
|
new1 @3 :Int64 = 987;
|
||||||
|
new2 @4 :Text = "baz";
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestStructUnion {
|
||||||
|
un @0! :union {
|
||||||
|
allTypes @1 :TestAllTypes;
|
||||||
|
object @2 :TestObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestEmptyStruct {}
|
||||||
|
|
||||||
|
struct TestConstants {
|
||||||
|
const voidConst :Void = void;
|
||||||
|
const boolConst :Bool = true;
|
||||||
|
const int8Const :Int8 = -123;
|
||||||
|
const int16Const :Int16 = -12345;
|
||||||
|
const int32Const :Int32 = -12345678;
|
||||||
|
const int64Const :Int64 = -123456789012345;
|
||||||
|
const uint8Const :UInt8 = 234;
|
||||||
|
const uint16Const :UInt16 = 45678;
|
||||||
|
const uint32Const :UInt32 = 3456789012;
|
||||||
|
const uint64Const :UInt64 = 12345678901234567890;
|
||||||
|
const float32Const :Float32 = 1234.5;
|
||||||
|
const float64Const :Float64 = -123e45;
|
||||||
|
const textConst :Text = "foo";
|
||||||
|
const dataConst :Data = "bar";
|
||||||
|
const structConst :TestAllTypes = (
|
||||||
|
voidField = void,
|
||||||
|
boolField = true,
|
||||||
|
int8Field = -12,
|
||||||
|
int16Field = 3456,
|
||||||
|
int32Field = -78901234,
|
||||||
|
int64Field = 56789012345678,
|
||||||
|
uInt8Field = 90,
|
||||||
|
uInt16Field = 1234,
|
||||||
|
uInt32Field = 56789012,
|
||||||
|
uInt64Field = 345678901234567890,
|
||||||
|
float32Field = -1.25e-10,
|
||||||
|
float64Field = 345,
|
||||||
|
textField = "baz",
|
||||||
|
dataField = "qux",
|
||||||
|
structField = (
|
||||||
|
textField = "nested",
|
||||||
|
structField = (textField = "really nested")),
|
||||||
|
enumField = baz,
|
||||||
|
# interfaceField can't have a default
|
||||||
|
|
||||||
|
voidList = [void, void, void],
|
||||||
|
boolList = [false, true, false, true, true],
|
||||||
|
int8List = [12, -34, -0x80, 0x7f],
|
||||||
|
int16List = [1234, -5678, -0x8000, 0x7fff],
|
||||||
|
int32List = [12345678, -90123456, -0x80000000, 0x7fffffff],
|
||||||
|
int64List = [123456789012345, -678901234567890, -0x8000000000000000, 0x7fffffffffffffff],
|
||||||
|
uInt8List = [12, 34, 0, 0xff],
|
||||||
|
uInt16List = [1234, 5678, 0, 0xffff],
|
||||||
|
uInt32List = [12345678, 90123456, 0, 0xffffffff],
|
||||||
|
uInt64List = [123456789012345, 678901234567890, 0, 0xffffffffffffffff],
|
||||||
|
float32List = [0, 1234567, 1e37, -1e37, 1e-37, -1e-37],
|
||||||
|
float64List = [0, 123456789012345, 1e306, -1e306, 1e-306, -1e-306],
|
||||||
|
textList = ["quux", "corge", "grault"],
|
||||||
|
dataList = ["garply", "waldo", "fred"],
|
||||||
|
structList = [
|
||||||
|
(textField = "x structlist 1"),
|
||||||
|
(textField = "x structlist 2"),
|
||||||
|
(textField = "x structlist 3")],
|
||||||
|
enumList = [qux, bar, grault]
|
||||||
|
# interfaceList can't have a default
|
||||||
|
);
|
||||||
|
const enumConst :TestEnum = corge;
|
||||||
|
|
||||||
|
const voidListConst :List(Void) = [void, void, void, void, void, void];
|
||||||
|
const boolListConst :List(Bool) = [true, false, false, true];
|
||||||
|
const int8ListConst :List(Int8) = [111, -111];
|
||||||
|
const int16ListConst :List(Int16) = [11111, -11111];
|
||||||
|
const int32ListConst :List(Int32) = [111111111, -111111111];
|
||||||
|
const int64ListConst :List(Int64) = [1111111111111111111, -1111111111111111111];
|
||||||
|
const uint8ListConst :List(UInt8) = [111, 222] ;
|
||||||
|
const uint16ListConst :List(UInt16) = [33333, 44444];
|
||||||
|
const uint32ListConst :List(UInt32) = [3333333333];
|
||||||
|
const uint64ListConst :List(UInt64) = [11111111111111111111];
|
||||||
|
const float32ListConst :List(Float32) = [5555.5, inf, -inf, nan];
|
||||||
|
const float64ListConst :List(Float64) = [7777.75, inf, -inf, nan];
|
||||||
|
const textListConst :List(Text) = ["plugh", "xyzzy", "thud"];
|
||||||
|
const dataListConst :List(Data) = ["oops", "exhausted", "rfc3092"];
|
||||||
|
const structListConst :List(TestAllTypes) = [
|
||||||
|
(textField = "structlist 1"),
|
||||||
|
(textField = "structlist 2"),
|
||||||
|
(textField = "structlist 3")];
|
||||||
|
const enumListConst :List(TestEnum) = [foo, garply];
|
||||||
|
}
|
||||||
|
|
||||||
|
const globalInt :UInt32 = 12345;
|
||||||
|
const globalText :Text = "foobar";
|
||||||
|
const globalStruct :TestAllTypes = (int32Field = 54321);
|
||||||
|
const derivedConstant :TestAllTypes = (
|
||||||
|
uInt32Field = .globalInt,
|
||||||
|
textField = TestConstants.textConst,
|
||||||
|
structField = TestConstants.structConst,
|
||||||
|
int16List = TestConstants.int16ListConst,
|
||||||
|
structList = TestConstants.structListConst);
|
||||||
|
|
||||||
|
interface TestInterface {
|
||||||
|
foo @0 (i :UInt32, j :Bool) -> (x: Text);
|
||||||
|
bar @1 () -> ();
|
||||||
|
baz @2 (s: TestAllTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TestExtends extends(TestInterface) {
|
||||||
|
qux @0 ();
|
||||||
|
corge @1 TestAllTypes -> ();
|
||||||
|
grault @2 () -> TestAllTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TestPipeline {
|
||||||
|
getCap @0 (n: UInt32, inCap :TestInterface) -> (s: Text, outBox :Box);
|
||||||
|
testPointers @1 (cap :TestInterface, obj :Object, list :List(TestInterface)) -> ();
|
||||||
|
|
||||||
|
struct Box {
|
||||||
|
cap @0 :TestInterface;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestSturdyRefHostId {
|
||||||
|
host @0 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestSturdyRefObjectId {
|
||||||
|
tag @0 :Tag;
|
||||||
|
enum Tag {
|
||||||
|
testInterface @0;
|
||||||
|
testExtends @1;
|
||||||
|
testPipeline @2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestProvisionId {}
|
||||||
|
struct TestRecipientId {}
|
||||||
|
struct TestThirdPartyCapId {}
|
||||||
|
struct TestJoinAnswer {}
|
||||||
9007
examples/test.capnp.c++
Normal file
9007
examples/test.capnp.c++
Normal file
File diff suppressed because it is too large
Load Diff
16936
examples/test.capnp.h
Normal file
16936
examples/test.capnp.h
Normal file
File diff suppressed because it is too large
Load Diff
44
scripts/capnp-json.py
Executable file
44
scripts/capnp-json.py
Executable file
@@ -0,0 +1,44 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import capnp
|
||||||
|
|
||||||
|
def parse_args():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("command")
|
||||||
|
parser.add_argument("schema_file")
|
||||||
|
parser.add_argument("struct_name")
|
||||||
|
parser.add_argument("-d", "--defaults", help="include default values in json output", action="store_true")
|
||||||
|
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
def encode(schema_file, struct_name, **kwargs):
|
||||||
|
schema = capnp.load(schema_file)
|
||||||
|
|
||||||
|
struct_schema = getattr(schema, struct_name)
|
||||||
|
|
||||||
|
struct_dict = json.load(sys.stdin)
|
||||||
|
struct = struct_schema.from_dict(struct_dict)
|
||||||
|
|
||||||
|
struct.write(sys.stdout)
|
||||||
|
|
||||||
|
def decode(schema_file, struct_name, defaults):
|
||||||
|
schema = capnp.load(schema_file)
|
||||||
|
|
||||||
|
struct_schema = getattr(schema, struct_name)
|
||||||
|
struct = struct_schema.read(sys.stdin)
|
||||||
|
|
||||||
|
json.dump(struct.to_dict(defaults), sys.stdout)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = parse_args()
|
||||||
|
|
||||||
|
command = args.command
|
||||||
|
kwargs = vars(args)
|
||||||
|
del kwargs['command']
|
||||||
|
|
||||||
|
globals()[command](**kwargs) # hacky way to get defined functions, and call function with name=command
|
||||||
|
|
||||||
|
main()
|
||||||
10
setup.py
10
setup.py
@@ -11,15 +11,15 @@ if Cython.__version__ < '0.19.1':
|
|||||||
import pkg_resources
|
import pkg_resources
|
||||||
setuptools_version = pkg_resources.get_distribution("setuptools").version
|
setuptools_version = pkg_resources.get_distribution("setuptools").version
|
||||||
if setuptools_version < '0.8':
|
if setuptools_version < '0.8':
|
||||||
raise RuntimeError('Old setuptools installed (%s). Please run `pip install -U setuptools`. Running `pip install capnp` will not work alone, since setuptools needs to be upgraded before installing anything else.' % setuptools_version)
|
raise RuntimeError('Old setuptools installed (%s). Please run `pip install -U setuptools`. Running `pip install pycapnp` will not work alone, since setuptools needs to be upgraded before installing anything else.' % setuptools_version)
|
||||||
|
|
||||||
from distutils.core import setup
|
from distutils.core import setup
|
||||||
import os
|
import os
|
||||||
|
|
||||||
MAJOR = 0
|
MAJOR = 0
|
||||||
MINOR = 3
|
MINOR = 4
|
||||||
MICRO = 18
|
MICRO = 0
|
||||||
VERSION = '%d.%d.%d' % (MAJOR, MINOR, MICRO)
|
VERSION = '%d.%d.%d-dev' % (MAJOR, MINOR, MICRO)
|
||||||
|
|
||||||
def write_version_py(filename=None):
|
def write_version_py(filename=None):
|
||||||
cnt = """\
|
cnt = """\
|
||||||
@@ -54,7 +54,7 @@ setup(
|
|||||||
'cython > 0.19',
|
'cython > 0.19',
|
||||||
'setuptools >= 0.8'],
|
'setuptools >= 0.8'],
|
||||||
# PyPi info
|
# PyPi info
|
||||||
description='A cython wrapping of the C++ capnproto library',
|
description="A cython wrapping of the C++ Cap'n Proto library",
|
||||||
long_description=long_description,
|
long_description=long_description,
|
||||||
license='BSD',
|
license='BSD',
|
||||||
author="Jason Paryani",
|
author="Jason Paryani",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
( boolField = true,
|
( voidField = void,
|
||||||
|
boolField = true,
|
||||||
int8Field = -123,
|
int8Field = -123,
|
||||||
int16Field = -12345,
|
int16Field = -12345,
|
||||||
int32Field = -12345678,
|
int32Field = -12345678,
|
||||||
@@ -12,6 +13,7 @@
|
|||||||
textField = "foo",
|
textField = "foo",
|
||||||
dataField = "bar",
|
dataField = "bar",
|
||||||
structField = (
|
structField = (
|
||||||
|
voidField = void,
|
||||||
boolField = true,
|
boolField = true,
|
||||||
int8Field = -12,
|
int8Field = -12,
|
||||||
int16Field = 3456,
|
int16Field = 3456,
|
||||||
@@ -26,10 +28,39 @@
|
|||||||
textField = "baz",
|
textField = "baz",
|
||||||
dataField = "qux",
|
dataField = "qux",
|
||||||
structField = (
|
structField = (
|
||||||
|
voidField = void,
|
||||||
|
boolField = false,
|
||||||
|
int8Field = 0,
|
||||||
|
int16Field = 0,
|
||||||
|
int32Field = 0,
|
||||||
|
int64Field = 0,
|
||||||
|
uInt8Field = 0,
|
||||||
|
uInt16Field = 0,
|
||||||
|
uInt32Field = 0,
|
||||||
|
uInt64Field = 0,
|
||||||
|
float32Field = 0,
|
||||||
|
float64Field = 0,
|
||||||
textField = "nested",
|
textField = "nested",
|
||||||
structField = (
|
structField = (
|
||||||
textField = "really nested" ) ),
|
voidField = void,
|
||||||
|
boolField = false,
|
||||||
|
int8Field = 0,
|
||||||
|
int16Field = 0,
|
||||||
|
int32Field = 0,
|
||||||
|
int64Field = 0,
|
||||||
|
uInt8Field = 0,
|
||||||
|
uInt16Field = 0,
|
||||||
|
uInt32Field = 0,
|
||||||
|
uInt64Field = 0,
|
||||||
|
float32Field = 0,
|
||||||
|
float64Field = 0,
|
||||||
|
textField = "really nested",
|
||||||
|
enumField = foo,
|
||||||
|
interfaceField = void ),
|
||||||
|
enumField = foo,
|
||||||
|
interfaceField = void ),
|
||||||
enumField = baz,
|
enumField = baz,
|
||||||
|
interfaceField = void,
|
||||||
voidList = [void, void, void],
|
voidList = [void, void, void],
|
||||||
boolList = [false, true, false, true, true],
|
boolList = [false, true, false, true, true],
|
||||||
int8List = [12, -34, -128, 127],
|
int8List = [12, -34, -128, 127],
|
||||||
@@ -45,11 +76,54 @@
|
|||||||
textList = ["quux", "corge", "grault"],
|
textList = ["quux", "corge", "grault"],
|
||||||
dataList = ["garply", "waldo", "fred"],
|
dataList = ["garply", "waldo", "fred"],
|
||||||
structList = [
|
structList = [
|
||||||
( textField = "x structlist 1" ),
|
( voidField = void,
|
||||||
( textField = "x structlist 2" ),
|
boolField = false,
|
||||||
( textField = "x structlist 3" ) ],
|
int8Field = 0,
|
||||||
|
int16Field = 0,
|
||||||
|
int32Field = 0,
|
||||||
|
int64Field = 0,
|
||||||
|
uInt8Field = 0,
|
||||||
|
uInt16Field = 0,
|
||||||
|
uInt32Field = 0,
|
||||||
|
uInt64Field = 0,
|
||||||
|
float32Field = 0,
|
||||||
|
float64Field = 0,
|
||||||
|
textField = "x structlist 1",
|
||||||
|
enumField = foo,
|
||||||
|
interfaceField = void ),
|
||||||
|
( voidField = void,
|
||||||
|
boolField = false,
|
||||||
|
int8Field = 0,
|
||||||
|
int16Field = 0,
|
||||||
|
int32Field = 0,
|
||||||
|
int64Field = 0,
|
||||||
|
uInt8Field = 0,
|
||||||
|
uInt16Field = 0,
|
||||||
|
uInt32Field = 0,
|
||||||
|
uInt64Field = 0,
|
||||||
|
float32Field = 0,
|
||||||
|
float64Field = 0,
|
||||||
|
textField = "x structlist 2",
|
||||||
|
enumField = foo,
|
||||||
|
interfaceField = void ),
|
||||||
|
( voidField = void,
|
||||||
|
boolField = false,
|
||||||
|
int8Field = 0,
|
||||||
|
int16Field = 0,
|
||||||
|
int32Field = 0,
|
||||||
|
int64Field = 0,
|
||||||
|
uInt8Field = 0,
|
||||||
|
uInt16Field = 0,
|
||||||
|
uInt32Field = 0,
|
||||||
|
uInt64Field = 0,
|
||||||
|
float32Field = 0,
|
||||||
|
float64Field = 0,
|
||||||
|
textField = "x structlist 3",
|
||||||
|
enumField = foo,
|
||||||
|
interfaceField = void ) ],
|
||||||
enumList = [qux, bar, grault] ),
|
enumList = [qux, bar, grault] ),
|
||||||
enumField = corge,
|
enumField = corge,
|
||||||
|
interfaceField = void,
|
||||||
voidList = [void, void, void, void, void, void],
|
voidList = [void, void, void, void, void, void],
|
||||||
boolList = [true, false, false, true],
|
boolList = [true, false, false, true],
|
||||||
int8List = [111, -111],
|
int8List = [111, -111],
|
||||||
@@ -65,7 +139,49 @@
|
|||||||
textList = ["plugh", "xyzzy", "thud"],
|
textList = ["plugh", "xyzzy", "thud"],
|
||||||
dataList = ["oops", "exhausted", "rfc3092"],
|
dataList = ["oops", "exhausted", "rfc3092"],
|
||||||
structList = [
|
structList = [
|
||||||
( textField = "structlist 1" ),
|
( voidField = void,
|
||||||
( textField = "structlist 2" ),
|
boolField = false,
|
||||||
( textField = "structlist 3" ) ],
|
int8Field = 0,
|
||||||
|
int16Field = 0,
|
||||||
|
int32Field = 0,
|
||||||
|
int64Field = 0,
|
||||||
|
uInt8Field = 0,
|
||||||
|
uInt16Field = 0,
|
||||||
|
uInt32Field = 0,
|
||||||
|
uInt64Field = 0,
|
||||||
|
float32Field = 0,
|
||||||
|
float64Field = 0,
|
||||||
|
textField = "structlist 1",
|
||||||
|
enumField = foo,
|
||||||
|
interfaceField = void ),
|
||||||
|
( voidField = void,
|
||||||
|
boolField = false,
|
||||||
|
int8Field = 0,
|
||||||
|
int16Field = 0,
|
||||||
|
int32Field = 0,
|
||||||
|
int64Field = 0,
|
||||||
|
uInt8Field = 0,
|
||||||
|
uInt16Field = 0,
|
||||||
|
uInt32Field = 0,
|
||||||
|
uInt64Field = 0,
|
||||||
|
float32Field = 0,
|
||||||
|
float64Field = 0,
|
||||||
|
textField = "structlist 2",
|
||||||
|
enumField = foo,
|
||||||
|
interfaceField = void ),
|
||||||
|
( voidField = void,
|
||||||
|
boolField = false,
|
||||||
|
int8Field = 0,
|
||||||
|
int16Field = 0,
|
||||||
|
int32Field = 0,
|
||||||
|
int64Field = 0,
|
||||||
|
uInt8Field = 0,
|
||||||
|
uInt16Field = 0,
|
||||||
|
uInt32Field = 0,
|
||||||
|
uInt64Field = 0,
|
||||||
|
float32Field = 0,
|
||||||
|
float64Field = 0,
|
||||||
|
textField = "structlist 3",
|
||||||
|
enumField = foo,
|
||||||
|
interfaceField = void ) ],
|
||||||
enumList = [foo, garply] )
|
enumList = [foo, garply] )
|
||||||
|
|||||||
56
test/test_capability.capnp
Normal file
56
test/test_capability.capnp
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
|
# and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
@0xd508eefec2dc42b8;
|
||||||
|
|
||||||
|
interface TestInterface {
|
||||||
|
foo @0 (i :UInt32, j :Bool) -> (x: Text);
|
||||||
|
bar @1 () -> ();
|
||||||
|
# baz @2 (s: TestAllTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TestExtends extends(TestInterface) {
|
||||||
|
qux @0 ();
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TestPipeline {
|
||||||
|
getCap @0 (n: UInt32, inCap :TestInterface) -> (s: Text, outBox :Box);
|
||||||
|
testPointers @1 (cap :TestInterface, obj :Object, list :List(TestInterface)) -> ();
|
||||||
|
|
||||||
|
struct Box {
|
||||||
|
cap @0 :TestInterface;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestSturdyRefHostId {
|
||||||
|
host @0 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestSturdyRefObjectId {
|
||||||
|
tag @0 :Tag;
|
||||||
|
enum Tag {
|
||||||
|
testInterface @0;
|
||||||
|
testExtends @1;
|
||||||
|
testPipeline @2;
|
||||||
|
}
|
||||||
|
}
|
||||||
167
test/test_capability.py
Normal file
167
test/test_capability.py
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
import pytest
|
||||||
|
import capnp
|
||||||
|
import os
|
||||||
|
|
||||||
|
this_dir = os.path.dirname(__file__)
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def capability():
|
||||||
|
return capnp.load(os.path.join(this_dir, 'test_capability.capnp'))
|
||||||
|
|
||||||
|
class Server:
|
||||||
|
def __init__(self, val=1):
|
||||||
|
self.val = val
|
||||||
|
|
||||||
|
def foo(self, context):
|
||||||
|
context.results.x = str(context.params.i * 5 + self.val)
|
||||||
|
|
||||||
|
class PipelineServer:
|
||||||
|
def getCap(self, context):
|
||||||
|
def _then(response):
|
||||||
|
context.results.s = response.x + '_foo'
|
||||||
|
context.results.outBox.cap = capability().TestInterface.new_server(Server(100))
|
||||||
|
|
||||||
|
return context.params.inCap.foo(i=context.params.n).then(_then)
|
||||||
|
|
||||||
|
def test_client(capability):
|
||||||
|
loop = capnp.EventLoop()
|
||||||
|
|
||||||
|
client = capability.TestInterface.new_client(Server(), loop)
|
||||||
|
|
||||||
|
req = client._request('foo')
|
||||||
|
req.i = 5
|
||||||
|
|
||||||
|
remote = req.send()
|
||||||
|
response = loop.wait(remote)
|
||||||
|
|
||||||
|
assert response.x == '26'
|
||||||
|
|
||||||
|
req = client.foo_request()
|
||||||
|
req.i = 5
|
||||||
|
|
||||||
|
remote = req.send()
|
||||||
|
response = loop.wait(remote)
|
||||||
|
|
||||||
|
assert response.x == '26'
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
client.foo2_request()
|
||||||
|
|
||||||
|
req = client.foo_request()
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
req.i = 'foo'
|
||||||
|
|
||||||
|
req = client.foo_request()
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
req.baz = 1
|
||||||
|
|
||||||
|
def test_simple_client(capability):
|
||||||
|
loop = capnp.EventLoop()
|
||||||
|
|
||||||
|
client = capability.TestInterface.new_client(Server(), loop)
|
||||||
|
|
||||||
|
remote = client._send('foo', i=5)
|
||||||
|
response = loop.wait(remote)
|
||||||
|
|
||||||
|
assert response.x == '26'
|
||||||
|
|
||||||
|
|
||||||
|
remote = client.foo(i=5)
|
||||||
|
response = loop.wait(remote)
|
||||||
|
|
||||||
|
assert response.x == '26'
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
remote = client.foo(i='foo')
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
remote = client.foo2(i=5)
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
remote = client.foo(baz=5)
|
||||||
|
|
||||||
|
def test_pipeline(capability):
|
||||||
|
loop = capnp.EventLoop()
|
||||||
|
|
||||||
|
client = capability.TestPipeline.new_client(PipelineServer(), loop)
|
||||||
|
foo_client = capability.TestInterface.new_client(Server(), loop)
|
||||||
|
|
||||||
|
remote = client.getCap(n=5, inCap=foo_client)
|
||||||
|
|
||||||
|
outCap = remote.outBox.cap
|
||||||
|
pipelinePromise = outCap.foo(i=10)
|
||||||
|
|
||||||
|
response = loop.wait(pipelinePromise)
|
||||||
|
assert response.x == '150'
|
||||||
|
|
||||||
|
response = loop.wait(remote)
|
||||||
|
assert response.s == '26_foo'
|
||||||
|
|
||||||
|
class BadServer:
|
||||||
|
def __init__(self, val=1):
|
||||||
|
self.val = val
|
||||||
|
|
||||||
|
def foo(self, context):
|
||||||
|
context.results.x = str(context.params.i * 5 + self.val)
|
||||||
|
context.results.x2 = 5 # raises exception
|
||||||
|
|
||||||
|
def test_exception_client(capability):
|
||||||
|
loop = capnp.EventLoop()
|
||||||
|
|
||||||
|
client = capability.TestInterface.new_client(BadServer(), loop)
|
||||||
|
|
||||||
|
remote = client._send('foo', i=5)
|
||||||
|
with pytest.raises(capnp.KjException):
|
||||||
|
loop.wait(remote)
|
||||||
|
|
||||||
|
class BadPipelineServer:
|
||||||
|
def getCap(self, context):
|
||||||
|
def _then(response):
|
||||||
|
context.results.s = response.x + '_foo'
|
||||||
|
context.results.outBox.cap = capability().TestInterface.new_server(Server(100))
|
||||||
|
def _error(error):
|
||||||
|
raise Exception('test was a success')
|
||||||
|
|
||||||
|
return context.params.inCap.foo(i=context.params.n).then(_then, _error)
|
||||||
|
|
||||||
|
def test_exception_chain(capability):
|
||||||
|
loop = capnp.EventLoop()
|
||||||
|
|
||||||
|
client = capability.TestPipeline.new_client(BadPipelineServer(), loop)
|
||||||
|
foo_client = capability.TestInterface.new_client(BadServer(), loop)
|
||||||
|
|
||||||
|
remote = client.getCap(n=5, inCap=foo_client)
|
||||||
|
|
||||||
|
try:
|
||||||
|
loop.wait(remote)
|
||||||
|
except Exception as e:
|
||||||
|
assert 'test was a success' in str(e)
|
||||||
|
|
||||||
|
def test_pipeline_exception(capability):
|
||||||
|
loop = capnp.EventLoop()
|
||||||
|
|
||||||
|
client = capability.TestPipeline.new_client(BadPipelineServer(), loop)
|
||||||
|
foo_client = capability.TestInterface.new_client(BadServer(), loop)
|
||||||
|
|
||||||
|
remote = client.getCap(n=5, inCap=foo_client)
|
||||||
|
|
||||||
|
outCap = remote.outBox.cap
|
||||||
|
pipelinePromise = outCap.foo(i=10)
|
||||||
|
|
||||||
|
with pytest.raises(Exception):
|
||||||
|
loop.wait(pipelinePromise)
|
||||||
|
|
||||||
|
with pytest.raises(Exception):
|
||||||
|
loop.wait(remote)
|
||||||
|
|
||||||
|
def test_casting(capability):
|
||||||
|
loop = capnp.EventLoop()
|
||||||
|
|
||||||
|
client = capability.TestExtends.new_client(Server(), loop)
|
||||||
|
client2 = client.upcast(capability.TestInterface)
|
||||||
|
client3 = client2.cast_as(capability.TestInterface)
|
||||||
|
|
||||||
|
with pytest.raises(Exception):
|
||||||
|
client.upcast(capability.TestPipeline)
|
||||||
40
test/test_rpc.py
Normal file
40
test/test_rpc.py
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import pytest
|
||||||
|
import capnp
|
||||||
|
import os
|
||||||
|
import socket
|
||||||
|
|
||||||
|
this_dir = os.path.dirname(__file__)
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def capability():
|
||||||
|
return capnp.load(os.path.join(this_dir, 'test_capability.capnp'))
|
||||||
|
|
||||||
|
class Server:
|
||||||
|
def __init__(self, val=1):
|
||||||
|
self.val = val
|
||||||
|
|
||||||
|
def foo(self, context):
|
||||||
|
context.results.x = str(context.params.i * 5 + self.val)
|
||||||
|
|
||||||
|
def test_simple_rpc(capability):
|
||||||
|
def _restore(ref_id):
|
||||||
|
return capability.TestInterface.new_server(Server(100))
|
||||||
|
|
||||||
|
loop = capnp.EventLoop()
|
||||||
|
|
||||||
|
read, write = socket.socketpair(socket.AF_UNIX)
|
||||||
|
read_stream = capnp.FdAsyncIoStream(read.fileno())
|
||||||
|
write_stream = capnp.FdAsyncIoStream(write.fileno())
|
||||||
|
|
||||||
|
restorer = capnp.Restorer(capability.TestSturdyRefObjectId, _restore)
|
||||||
|
server = capnp.RpcServer(loop, write_stream, restorer)
|
||||||
|
client = capnp.RpcClient(loop, read_stream)
|
||||||
|
|
||||||
|
ref = capability.TestSturdyRefObjectId.new_message()
|
||||||
|
cap = client.restore(ref)
|
||||||
|
cap = cap.cast_as(capability.TestInterface)
|
||||||
|
|
||||||
|
remote = cap.foo(i=5)
|
||||||
|
response = loop.wait(remote)
|
||||||
|
|
||||||
|
assert response.x == '125'
|
||||||
Reference in New Issue
Block a user