TUN-813: Clean up cloudflared dependencies

This commit is contained in:
Areg Harutyunyan
2018-07-24 18:04:33 -05:00
parent d06fc520c7
commit 0468866626
3310 changed files with 993 additions and 1223303 deletions

View File

@@ -1,3 +0,0 @@
startup --batch --host_jvm_args=-Xms2500m --host_jvm_args=-Xmx2500m
build --noshow_progress --spawn_strategy=standalone --genrule_strategy=standalone --local_resources=1536,1.5,0.5
test --noshow_progress --test_output=errors --spawn_strategy=standalone --genrule_strategy=standalone --test_strategy=standalone --local_resources=1536,1.5,0.5

View File

@@ -1,19 +0,0 @@
#!/bin/bash
must() {
echo "$@" 1>&2
"$@" || die "FAIL"
}
die() {
echo "$@" 1>&2
exit 1
}
if [[ -z "$USE_BAZEL" || "$USE_BAZEL" -eq "0" ]]; then
must go test -v ./...
else
# On Travis, this will use "$HOME/bin/bazel", but don't assume this
# for local testing of the CI script.
must bazel --bazelrc=_travis/bazelrc test //...
fi

View File

@@ -1,39 +0,0 @@
#!/bin/bash
must() {
echo "$@" 1>&2
"$@" || die "FAIL"
}
die() {
echo "$@" 1>&2
exit 1
}
if [[ -z "$USE_BAZEL" || "$USE_BAZEL" -eq "0" ]]; then
must go get -t ./...
else
BAZEL_VERSION="${BAZEL_VERSION:-0.14.1}"
case "$TRAVIS_OS_NAME" in
linux)
BAZEL_INSTALLER_URL="https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VERSION}/bazel-${BAZEL_VERSION}-installer-linux-x86_64.sh"
SEDI="sed -i"
;;
osx)
BAZEL_INSTALLER_URL="https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VERSION}/bazel-${BAZEL_VERSION}-installer-darwin-x86_64.sh"
SEDI="sed -i ''"
;;
*)
die "unknown OS $TRAVIS_OS_NAME"
;;
esac
must curl -fsSLo /tmp/bazel.sh "$BAZEL_INSTALLER_URL"
must chmod +x /tmp/bazel.sh
must /tmp/bazel.sh --user
rm -f /tmp/bazel.sh
if [[ ! -z "$TRAVIS_GO_VERSION" ]]; then
must $SEDI -e 's/^go_register_toolchains()/go_register_toolchains(go_version="host")/' WORKSPACE
fi
must "$HOME/bin/bazel" --bazelrc=_travis/bazelrc version
must "$HOME/bin/bazel" --bazelrc=_travis/bazelrc fetch //...
fi

View File

@@ -1,31 +0,0 @@
package capnp
import (
"testing"
)
func TestAddressElement(t *testing.T) {
tests := []struct {
a Address
i int32
sz Size
out Address
ok bool
}{
{0, 0, 0, 0, true},
{0, 1, 0, 0, true},
{0, 1, 8, 8, true},
{0, 2, 8, 16, true},
{24, 1, 0, 24, true},
{24, 1, 8, 32, true},
{24, 2, 8, 40, true},
{0, 0x7fffffff, 3, 0, false},
{0xffffffff, 0x7fffffff, 0xffffffff, 0, false},
}
for _, test := range tests {
out, ok := test.a.element(test.i, test.sz)
if ok != test.ok || (ok && out != test.out) {
t.Errorf("%#v.element(%d, %d) = %#v, %t; want %#v, %t", test.a, test.i, test.sz, out, ok, test.out, test.ok)
}
}
}

View File

@@ -1,192 +0,0 @@
package capnp
import (
"bytes"
"encoding/hex"
"testing"
)
func TestCanonicalize(t *testing.T) {
{
// null
b, err := Canonicalize(Struct{})
if err != nil {
t.Fatal("Canonicalize(Struct{}):", err)
}
if want := ([]byte{0, 0, 0, 0, 0, 0, 0, 0}); !bytes.Equal(b, want) {
t.Errorf("Canonicalize(Struct{}) =\n%s\n; want\n%s", hex.Dump(b), hex.Dump(want))
}
}
{
// empty struct
_, seg, _ := NewMessage(SingleSegment(nil))
s, _ := NewStruct(seg, ObjectSize{})
b, err := Canonicalize(s)
if err != nil {
t.Fatal("Canonicalize(empty struct):", err)
}
want := ([]byte{0xfc, 0xff, 0xff, 0xff, 0, 0, 0, 0})
if !bytes.Equal(b, want) {
t.Errorf("Canonicalize(empty struct) =\n%s\n; want\n%s", hex.Dump(b), hex.Dump(want))
}
}
{
// zero data, zero pointer struct
_, seg, _ := NewMessage(SingleSegment(nil))
s, _ := NewStruct(seg, ObjectSize{DataSize: 8, PointerCount: 1})
b, err := Canonicalize(s)
if err != nil {
t.Fatal("Canonicalize(zero data, zero pointer struct):", err)
}
want := ([]byte{0xfc, 0xff, 0xff, 0xff, 0, 0, 0, 0})
if !bytes.Equal(b, want) {
t.Errorf("Canonicalize(zero data, zero pointer struct) =\n%s\n; want\n%s", hex.Dump(b), hex.Dump(want))
}
}
{
// one word data struct
_, seg, _ := NewMessage(SingleSegment(nil))
s, _ := NewStruct(seg, ObjectSize{DataSize: 8, PointerCount: 1})
s.SetUint16(0, 0xbeef)
b, err := Canonicalize(s)
if err != nil {
t.Fatal("Canonicalize(one word data struct):", err)
}
want := ([]byte{
0, 0, 0, 0, 1, 0, 0, 0,
0xef, 0xbe, 0, 0, 0, 0, 0, 0,
})
if !bytes.Equal(b, want) {
t.Errorf("Canonicalize(one word data struct) =\n%s\n; want\n%s", hex.Dump(b), hex.Dump(want))
}
}
{
// two pointers to zero structs
_, seg, _ := NewMessage(SingleSegment(nil))
s, _ := NewStruct(seg, ObjectSize{PointerCount: 2})
e1, _ := NewStruct(seg, ObjectSize{DataSize: 8})
e2, _ := NewStruct(seg, ObjectSize{DataSize: 8})
s.SetPtr(0, e1.ToPtr())
s.SetPtr(1, e2.ToPtr())
b, err := Canonicalize(s)
if err != nil {
t.Fatal("Canonicalize(two pointers to zero structs):", err)
}
want := ([]byte{
0, 0, 0, 0, 0, 0, 2, 0,
0xfc, 0xff, 0xff, 0xff, 0, 0, 0, 0,
0xfc, 0xff, 0xff, 0xff, 0, 0, 0, 0,
})
if !bytes.Equal(b, want) {
t.Errorf("Canonicalize(two pointers to zero structs) =\n%s\n; want\n%s", hex.Dump(b), hex.Dump(want))
}
}
{
// int list
_, seg, _ := NewMessage(SingleSegment(nil))
s, _ := NewStruct(seg, ObjectSize{PointerCount: 1})
l, _ := NewInt8List(seg, 5)
s.SetPtr(0, l.ToPtr())
l.Set(0, 1)
l.Set(1, 2)
l.Set(2, 3)
l.Set(3, 4)
l.Set(4, 5)
b, err := Canonicalize(s)
if err != nil {
t.Fatal("Canonicalize(int list):", err)
}
want := ([]byte{
0, 0, 0, 0, 0, 0, 1, 0,
0x01, 0, 0, 0, 0x2a, 0, 0, 0,
1, 2, 3, 4, 5, 0, 0, 0,
})
if !bytes.Equal(b, want) {
t.Errorf("Canonicalize(int list) =\n%s\n; want\n%s", hex.Dump(b), hex.Dump(want))
}
}
{
// zero int list
_, seg, _ := NewMessage(SingleSegment(nil))
s, _ := NewStruct(seg, ObjectSize{PointerCount: 1})
l, _ := NewInt8List(seg, 5)
s.SetPtr(0, l.ToPtr())
b, err := Canonicalize(s)
if err != nil {
t.Fatal("Canonicalize(zero int list):", err)
}
want := ([]byte{
0, 0, 0, 0, 0, 0, 1, 0,
0x01, 0, 0, 0, 0x2a, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
})
if !bytes.Equal(b, want) {
t.Errorf("Canonicalize(zero int list) =\n%s\n; want\n%s", hex.Dump(b), hex.Dump(want))
}
}
{
// struct list
_, seg, _ := NewMessage(SingleSegment(nil))
s, _ := NewStruct(seg, ObjectSize{PointerCount: 1})
l, _ := NewCompositeList(seg, ObjectSize{DataSize: 8, PointerCount: 1}, 2)
s.SetPtr(0, l.ToPtr())
l.Struct(0).SetUint64(0, 0xdeadbeef)
txt, _ := NewText(seg, "xyzzy")
l.Struct(1).SetPtr(0, txt.ToPtr())
b, err := Canonicalize(s)
if err != nil {
t.Fatal("Canonicalize(struct list):", err)
}
want := ([]byte{
0, 0, 0, 0, 0, 0, 1, 0,
0x01, 0, 0, 0, 0x27, 0, 0, 0,
0x08, 0, 0, 0, 1, 0, 1, 0,
0xef, 0xbe, 0xad, 0xde, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0x01, 0, 0, 0, 0x32, 0, 0, 0,
'x', 'y', 'z', 'z', 'y', 0, 0, 0,
})
if !bytes.Equal(b, want) {
t.Errorf("Canonicalize(struct list) =\n%s\n; want\n%s", hex.Dump(b), hex.Dump(want))
}
}
{
// zero struct list
_, seg, _ := NewMessage(SingleSegment(nil))
s, _ := NewStruct(seg, ObjectSize{PointerCount: 1})
l, _ := NewCompositeList(seg, ObjectSize{DataSize: 16, PointerCount: 2}, 3)
s.SetPtr(0, l.ToPtr())
b, err := Canonicalize(s)
if err != nil {
t.Fatal("Canonicalize(zero struct list):", err)
}
want := ([]byte{
0, 0, 0, 0, 0, 0, 1, 0,
0x01, 0, 0, 0, 0x07, 0, 0, 0,
0x0c, 0, 0, 0, 0, 0, 0, 0,
})
if !bytes.Equal(b, want) {
t.Errorf("Canonicalize(zero struct list) =\n%s\n; want\n%s", hex.Dump(b), hex.Dump(want))
}
}
{
// zero-length struct list
_, seg, _ := NewMessage(SingleSegment(nil))
s, _ := NewStruct(seg, ObjectSize{PointerCount: 1})
l, _ := NewCompositeList(seg, ObjectSize{DataSize: 16, PointerCount: 2}, 0)
s.SetPtr(0, l.ToPtr())
b, err := Canonicalize(s)
if err != nil {
t.Fatal("Canonicalize(zero-length struct list):", err)
}
want := ([]byte{
0, 0, 0, 0, 0, 0, 1, 0,
0x01, 0, 0, 0, 0x07, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
})
if !bytes.Equal(b, want) {
t.Errorf("Canonicalize(zero-length struct list) =\n%s\n; want\n%s", hex.Dump(b), hex.Dump(want))
}
}
}

View File

@@ -1,280 +0,0 @@
package capnp
import (
"bytes"
"errors"
"testing"
)
func TestToInterface(t *testing.T) {
_, seg, err := NewMessage(SingleSegment(nil))
if err != nil {
t.Fatal(err)
}
tests := []struct {
ptr Pointer
in Interface
}{
{nil, Interface{}},
{Struct{}, Interface{}},
{Struct{seg: seg, off: 0, depthLimit: maxDepth}, Interface{}},
{Interface{}, Interface{}},
{Interface{seg, 42}, Interface{seg, 42}},
}
for _, test := range tests {
if in := ToInterface(test.ptr); in != test.in {
t.Errorf("ToInterface(%#v) = %#v; want %#v", test.ptr, in, test.in)
}
}
}
func TestInterface_value(t *testing.T) {
_, seg, err := NewMessage(SingleSegment(nil))
if err != nil {
t.Fatal(err)
}
tests := []struct {
in Interface
val rawPointer
}{
{Interface{}, 0},
{NewInterface(seg, 0), 0x0000000000000003},
{NewInterface(seg, 0xdeadbeef), 0xdeadbeef00000003},
}
for _, test := range tests {
for paddr := Address(0); paddr < 16; paddr++ {
if val := test.in.value(paddr); val != test.val {
t.Errorf("Interface{seg: %p, cap: %d}.value(%v) = %v; want %v", test.in.seg, test.in.cap, paddr, val, test.val)
}
}
}
}
func TestTransform(t *testing.T) {
_, s, err := NewMessage(SingleSegment(nil))
if err != nil {
t.Fatal(err)
}
root, err := NewStruct(s, ObjectSize{PointerCount: 2})
if err != nil {
t.Fatal(err)
}
a, err := NewStruct(s, ObjectSize{DataSize: 8, PointerCount: 1})
if err != nil {
t.Fatal(err)
}
root.SetPointer(1, a)
a.SetUint64(0, 1)
b, err := NewStruct(s, ObjectSize{DataSize: 8})
if err != nil {
t.Fatal(err)
}
b.SetUint64(0, 2)
a.SetPointer(0, b)
dmsg, d, err := NewMessage(SingleSegment(nil))
if err != nil {
t.Fatal(err)
}
da, err := NewStruct(d, ObjectSize{DataSize: 8, PointerCount: 1})
if err != nil {
t.Fatal(err)
}
if err := dmsg.SetRoot(da); err != nil {
t.Fatal(err)
}
da.SetUint64(0, 56)
db, err := NewStruct(d, ObjectSize{DataSize: 8})
if err != nil {
t.Fatal(err)
}
db.SetUint64(0, 78)
da.SetPointer(0, db)
tests := []struct {
p Pointer
transform []PipelineOp
out Pointer
}{
{
root,
nil,
root,
},
{
root,
[]PipelineOp{},
root,
},
{
root,
[]PipelineOp{
{Field: 0},
},
nil,
},
{
root,
[]PipelineOp{
{Field: 0, DefaultValue: mustMarshal(t, dmsg)},
},
da,
},
{
root,
[]PipelineOp{
{Field: 1},
},
a,
},
{
root,
[]PipelineOp{
{Field: 1, DefaultValue: mustMarshal(t, dmsg)},
},
a,
},
{
root,
[]PipelineOp{
{Field: 1},
{Field: 0},
},
b,
},
{
root,
[]PipelineOp{
{Field: 0},
{Field: 0},
},
nil,
},
{
root,
[]PipelineOp{
{Field: 0, DefaultValue: mustMarshal(t, dmsg)},
{Field: 0},
},
db,
},
{
root,
[]PipelineOp{
{Field: 0},
{Field: 0, DefaultValue: mustMarshal(t, dmsg)},
},
da,
},
{
root,
[]PipelineOp{
{Field: 0, DefaultValue: mustMarshal(t, dmsg)},
{Field: 1, DefaultValue: mustMarshal(t, dmsg)},
},
da,
},
}
for _, test := range tests {
out, err := Transform(test.p, test.transform)
if !deepPointerEqual(out, test.out) {
t.Errorf("Transform(%+v, %v) = %+v; want %+v", test.p, test.transform, out, test.out)
}
if err != nil {
t.Errorf("Transform(%+v, %v) error: %v", test.p, test.transform, err)
}
}
}
func TestMethodString(t *testing.T) {
tests := []struct {
m *Method
s string
}{
{
&Method{
InterfaceID: 0x8e5322c1e9282534,
MethodID: 1,
},
"@0x8e5322c1e9282534.@1",
},
{
&Method{
InterfaceID: 0x8e5322c1e9282534,
MethodID: 1,
InterfaceName: "aircraftlib:Echo",
MethodName: "foo",
},
"aircraftlib:Echo.foo",
},
}
for _, test := range tests {
if s := test.m.String(); s != test.s {
t.Errorf("%#v.String() = %q; want %q", test.m, s, test.s)
}
}
}
func TestPipelineOpString(t *testing.T) {
tests := []struct {
op PipelineOp
s string
}{
{
PipelineOp{Field: 4},
"get field 4",
},
{
PipelineOp{Field: 4, DefaultValue: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
"get field 4 with default",
},
}
for _, test := range tests {
if s := test.op.String(); s != test.s {
t.Errorf("%#v.String() = %q; want %q", test.op, s, test.s)
}
}
}
func TestIsUnimplemented(t *testing.T) {
tests := []struct {
e error
ok bool
}{
{nil, false},
{ErrUnimplemented, true},
{errors.New("foo"), false},
{&MethodError{Method: new(Method), Err: ErrUnimplemented}, true},
{&MethodError{Method: new(Method), Err: errors.New("foo")}, false},
}
for _, test := range tests {
if ok := IsUnimplemented(test.e); ok != test.ok {
t.Errorf("IsUnimplemented(%#v) = %t; want %t", test.e, ok, test.ok)
}
}
}
func mustMarshal(t *testing.T, msg *Message) []byte {
data, err := msg.Marshal()
if err != nil {
t.Fatal("Marshal:", err)
}
return data
}
func deepPointerEqual(a, b Pointer) bool {
if a == nil && b == nil {
return true
}
if a == nil || b == nil {
return false
}
msgA, _, _ := NewMessage(SingleSegment(nil))
msgA.SetRoot(a)
abytes, _ := msgA.Marshal()
msgB, _, _ := NewMessage(SingleSegment(nil))
msgB.SetRoot(b)
bbytes, _ := msgB.Marshal()
return bytes.Equal(abytes, bbytes)
}

View File

@@ -1,742 +0,0 @@
package capnp
import (
"bytes"
"encoding/binary"
"fmt"
"testing"
)
func TestSegmentInBounds(t *testing.T) {
tests := []struct {
n int
addr Address
ok bool
}{
{0, 0, false},
{0, 1, false},
{0, 2, false},
{1, 0, true},
{1, 1, false},
{1, 2, false},
{2, 0, true},
{2, 1, true},
{2, 2, false},
}
for _, test := range tests {
seg := &Segment{data: make([]byte, test.n)}
if ok := seg.inBounds(test.addr); ok != test.ok {
t.Errorf("&Segment{data: make([]byte, %d)}.inBounds(%#v) = %t; want %t", test.n, test.addr, ok, test.ok)
}
}
}
func TestSegmentRegionInBounds(t *testing.T) {
tests := []struct {
n int
addr Address
sz Size
ok bool
}{
{0, 0, 0, true}, // zero-sized region <= len is okay
{0, 0, 1, false},
{0, 1, 0, false},
{0, 1, 1, false},
{1, 0, 0, true},
{1, 0, 1, true},
{1, 1, 0, true},
{1, 1, 1, false},
{2, 0, 0, true},
{2, 0, 1, true},
{2, 0, 2, true},
{2, 0, 3, false},
{2, 1, 0, true},
{2, 1, 1, true},
{2, 1, 2, false},
{2, 1, 3, false},
{2, 2, 0, true},
{2, 2, 1, false},
}
for _, test := range tests {
seg := &Segment{data: make([]byte, test.n)}
if ok := seg.regionInBounds(test.addr, test.sz); ok != test.ok {
t.Errorf("&Segment{data: make([]byte, %d)}.regionInBounds(%#v, %#v) = %t; want %t", test.n, test.addr, test.sz, ok, test.ok)
}
}
}
func TestSegmentReadUint8(t *testing.T) {
tests := []struct {
data []byte
addr Address
val uint8
panics bool
}{
{data: []byte{}, addr: 0, panics: true},
{data: []byte{42}, addr: 0, val: 42},
{data: []byte{42}, addr: 1, panics: true},
{data: []byte{1, 42, 2}, addr: 0, val: 1},
{data: []byte{1, 42, 2}, addr: 1, val: 42},
{data: []byte{1, 42, 2}, addr: 2, val: 2},
{data: []byte{1, 42, 2}, addr: 3, panics: true},
}
for _, test := range tests {
seg := &Segment{data: test.data}
var val uint8
err := catchPanic(func() {
val = seg.readUint8(test.addr)
})
if err != nil {
if !test.panics {
t.Errorf("&Segment{data: % x}.readUint8(%v) unexpected panic: %v", test.data, test.addr, err)
}
continue
}
if test.panics {
t.Errorf("&Segment{data: % x}.readUint8(%v) did not panic as expected", test.data, test.addr)
continue
}
if val != test.val {
t.Errorf("&Segment{data: % x}.readUint8(%v) = %#x; want %#x", test.data, test.addr, val, test.val)
}
}
}
func TestSegmentReadUint16(t *testing.T) {
tests := []struct {
data []byte
addr Address
val uint16
panics bool
}{
{data: []byte{}, addr: 0, panics: true},
{data: []byte{0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00}, addr: 0, val: 0},
{data: []byte{0x01, 0x00}, addr: 0, val: 1},
{data: []byte{0x34, 0x12}, addr: 0, val: 0x1234},
{data: []byte{0x34, 0x12, 0x56}, addr: 0, val: 0x1234},
{data: []byte{0x34, 0x12, 0x56}, addr: 1, val: 0x5612},
{data: []byte{0x34, 0x12, 0x56}, addr: 2, panics: true},
}
for _, test := range tests {
seg := &Segment{data: test.data}
var val uint16
err := catchPanic(func() {
val = seg.readUint16(test.addr)
})
if err != nil {
if !test.panics {
t.Errorf("&Segment{data: % x}.readUint16(%v) unexpected panic: %v", test.data, test.addr, err)
}
continue
}
if test.panics {
t.Errorf("&Segment{data: % x}.readUint16(%v) did not panic as expected", test.data, test.addr)
continue
}
if val != test.val {
t.Errorf("&Segment{data: % x}.readUint16(%v) = %#x; want %#x", test.data, test.addr, val, test.val)
}
}
}
func TestSegmentReadUint32(t *testing.T) {
tests := []struct {
data []byte
addr Address
val uint32
panics bool
}{
{data: []byte{}, addr: 0, panics: true},
{data: []byte{0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00, 0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00, 0x00, 0x00}, addr: 0, val: 0},
{data: []byte{0x78, 0x56, 0x34, 0x12}, addr: 0, val: 0x12345678},
{data: []byte{0xff, 0x78, 0x56, 0x34, 0x12, 0xff}, addr: 1, val: 0x12345678},
{data: []byte{0xff, 0x78, 0x56, 0x34, 0x12, 0xff}, addr: 2, val: 0xff123456},
{data: []byte{0xff, 0x78, 0x56, 0x34, 0x12, 0xff}, addr: 3, panics: true},
}
for _, test := range tests {
seg := &Segment{data: test.data}
var val uint32
err := catchPanic(func() {
val = seg.readUint32(test.addr)
})
if err != nil {
if !test.panics {
t.Errorf("&Segment{data: % x}.readUint32(%v) unexpected panic: %v", test.data, test.addr, err)
}
continue
}
if test.panics {
t.Errorf("&Segment{data: % x}.readUint32(%v) did not panic as expected", test.data, test.addr)
continue
}
if val != test.val {
t.Errorf("&Segment{data: % x}.readUint32(%v) = %#x; want %#x", test.data, test.addr, val, test.val)
}
}
}
func TestSegmentReadUint64(t *testing.T) {
tests := []struct {
data []byte
addr Address
val uint64
panics bool
}{
{data: []byte{}, addr: 0, panics: true},
{data: []byte{0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00, 0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00, 0x00, 0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00, 0x00, 0x00, 0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, addr: 0, val: 0},
{data: []byte{0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01}, addr: 0, val: 0x0123456789abcdef},
{data: []byte{0xff, 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01, 0xff}, addr: 0, val: 0x23456789abcdefff},
{data: []byte{0xff, 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01, 0xff}, addr: 1, val: 0x0123456789abcdef},
{data: []byte{0xff, 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01, 0xff}, addr: 2, val: 0xff0123456789abcd},
{data: []byte{0xff, 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01, 0xff}, addr: 3, panics: true},
}
for _, test := range tests {
seg := &Segment{data: test.data}
var val uint64
err := catchPanic(func() {
val = seg.readUint64(test.addr)
})
if err != nil {
if !test.panics {
t.Errorf("&Segment{data: % x}.readUint64(%v) unexpected panic: %v", test.data, test.addr, err)
}
continue
}
if test.panics {
t.Errorf("&Segment{data: % x}.readUint64(%v) did not panic as expected", test.data, test.addr)
continue
}
if val != test.val {
t.Errorf("&Segment{data: % x}.readUint64(%v) = %#x; want %#x", test.data, test.addr, val, test.val)
}
}
}
func TestSegmentWriteUint8(t *testing.T) {
tests := []struct {
data []byte
addr Address
val uint8
out []byte
panics bool
}{
{
data: []byte{},
addr: 0,
val: 0,
panics: true,
},
{
data: []byte{1},
addr: 0,
val: 42,
out: []byte{42},
},
{
data: []byte{42},
addr: 1,
val: 1,
panics: true,
},
{
data: []byte{1, 2, 3},
addr: 0,
val: 0xff,
out: []byte{0xff, 2, 3},
},
{
data: []byte{1, 2, 3},
addr: 1,
val: 0xff,
out: []byte{1, 0xff, 3},
},
{
data: []byte{1, 2, 3},
addr: 2,
val: 0xff,
out: []byte{1, 2, 0xff},
},
{
data: []byte{1, 2, 3},
addr: 3,
val: 0xff,
panics: true,
},
}
for _, test := range tests {
out := make([]byte, len(test.data))
copy(out, test.data)
seg := &Segment{data: out}
err := catchPanic(func() {
seg.writeUint8(test.addr, test.val)
})
if err != nil {
if !test.panics {
t.Errorf("&Segment{data: % x}.writeUint8(%v, %#x) unexpected panic: %v", test.data, test.addr, test.val, err)
}
continue
}
if test.panics {
t.Errorf("&Segment{data: % x}.writeUint8(%v, %#x) did not panic as expected", test.data, test.addr, test.val)
continue
}
if !bytes.Equal(out, test.out) {
t.Errorf("data after &Segment{data: % x}.writeUint8(%v, %#x) = % x; want % x", test.data, test.addr, test.val, out, test.out)
}
}
}
func TestSegmentWriteUint16(t *testing.T) {
tests := []struct {
data []byte
addr Address
val uint16
out []byte
panics bool
}{
{
data: []byte{},
addr: 0,
val: 0,
panics: true,
},
{
data: []byte{1, 2, 3, 4},
addr: 1,
val: 0x1234,
out: []byte{1, 0x34, 0x12, 4},
},
}
for _, test := range tests {
out := make([]byte, len(test.data))
copy(out, test.data)
seg := &Segment{data: out}
err := catchPanic(func() {
seg.writeUint16(test.addr, test.val)
})
if err != nil {
if !test.panics {
t.Errorf("&Segment{data: % x}.writeUint16(%v, %#x) unexpected panic: %v", test.data, test.addr, test.val, err)
}
continue
}
if test.panics {
t.Errorf("&Segment{data: % x}.writeUint16(%v, %#x) did not panic as expected", test.data, test.addr, test.val)
continue
}
if !bytes.Equal(out, test.out) {
t.Errorf("data after &Segment{data: % x}.writeUint16(%v, %#x) = % x; want % x", test.data, test.addr, test.val, out, test.out)
}
}
}
func TestSegmentWriteUint32(t *testing.T) {
tests := []struct {
data []byte
addr Address
val uint32
out []byte
panics bool
}{
{
data: []byte{},
addr: 0,
val: 0,
panics: true,
},
{
data: []byte{1, 2, 3, 4, 5, 6},
addr: 1,
val: 0x01234567,
out: []byte{1, 0x67, 0x45, 0x23, 0x01, 6},
},
}
for _, test := range tests {
out := make([]byte, len(test.data))
copy(out, test.data)
seg := &Segment{data: out}
err := catchPanic(func() {
seg.writeUint32(test.addr, test.val)
})
if err != nil {
if !test.panics {
t.Errorf("&Segment{data: % x}.writeUint32(%v, %#x) unexpected panic: %v", test.data, test.addr, test.val, err)
}
continue
}
if test.panics {
t.Errorf("&Segment{data: % x}.writeUint32(%v, %#x) did not panic as expected", test.data, test.addr, test.val)
continue
}
if !bytes.Equal(out, test.out) {
t.Errorf("data after &Segment{data: % x}.writeUint32(%v, %#x) = % x; want % x", test.data, test.addr, test.val, out, test.out)
}
}
}
func TestSegmentWriteUint64(t *testing.T) {
tests := []struct {
data []byte
addr Address
val uint64
out []byte
panics bool
}{
{
data: []byte{},
addr: 0,
val: 0,
panics: true,
},
{
data: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
addr: 1,
val: 0x0123456789abcdef,
out: []byte{1, 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01, 10},
},
}
for _, test := range tests {
out := make([]byte, len(test.data))
copy(out, test.data)
seg := &Segment{data: out}
err := catchPanic(func() {
seg.writeUint64(test.addr, test.val)
})
if err != nil {
if !test.panics {
t.Errorf("&Segment{data: % x}.writeUint64(%v, %#x) unexpected panic: %v", test.data, test.addr, test.val, err)
}
continue
}
if test.panics {
t.Errorf("&Segment{data: % x}.writeUint64(%v, %#x) did not panic as expected", test.data, test.addr, test.val)
continue
}
if !bytes.Equal(out, test.out) {
t.Errorf("data after &Segment{data: % x}.writeUint64(%v, %#x) = % x; want % x", test.data, test.addr, test.val, out, test.out)
}
}
}
func TestSetPtrCopyListMember(t *testing.T) {
_, seg, err := NewMessage(SingleSegment(nil))
if err != nil {
t.Fatal("NewMessage:", err)
}
root, err := NewRootStruct(seg, ObjectSize{PointerCount: 2})
if err != nil {
t.Fatal("NewRootStruct:", err)
}
plist, err := NewCompositeList(seg, ObjectSize{PointerCount: 1}, 1)
if err != nil {
t.Fatal("NewCompositeList:", err)
}
if err := root.SetPtr(0, plist.ToPtr()); err != nil {
t.Fatal("root.SetPtr(0, plist):", err)
}
sub, err := NewStruct(seg, ObjectSize{DataSize: 8})
if err != nil {
t.Fatal("NewStruct:", err)
}
sub.SetUint64(0, 42)
pl0 := plist.Struct(0)
if err := pl0.SetPtr(0, sub.ToPtr()); err != nil {
t.Fatal("pl0.SetPtr(0, sub.ToPtr()):", err)
}
if err := root.SetPtr(1, pl0.ToPtr()); err != nil {
t.Error("root.SetPtr(1, pl0):", err)
}
p1, err := root.Ptr(1)
if err != nil {
t.Error("root.Ptr(1):", err)
}
s1 := p1.Struct()
if !s1.IsValid() {
t.Error("root.Ptr(1) is not a valid struct")
}
if SamePtr(s1.ToPtr(), pl0.ToPtr()) {
t.Error("list member not copied; points to same object")
}
s1p0, err := s1.Ptr(0)
if err != nil {
t.Error("root.Ptr(1).Struct().Ptr(0):", err)
}
s1s0 := s1p0.Struct()
if !s1s0.IsValid() {
t.Error("root.Ptr(1).Struct().Ptr(0) is not a valid struct")
}
if SamePtr(s1s0.ToPtr(), sub.ToPtr()) {
t.Error("sub-object not copied; points to same object")
}
if got := s1s0.Uint64(0); got != 42 {
t.Errorf("sub-object data = %d; want 42", got)
}
}
func TestSetPtrToZeroSizeStruct(t *testing.T) {
_, seg, err := NewMessage(SingleSegment(nil))
if err != nil {
t.Fatal("NewMessage:", err)
}
root, err := NewRootStruct(seg, ObjectSize{PointerCount: 1})
if err != nil {
t.Fatal("NewRootStruct:", err)
}
sub, err := NewStruct(seg, ObjectSize{})
if err != nil {
t.Fatal("NewStruct:", err)
}
if err := root.SetPtr(0, sub.ToPtr()); err != nil {
t.Fatal("root.SetPtr(0, sub.ToPtr()):", err)
}
ptrSlice := seg.Data()[root.off : root.off+8]
want := []byte{0xfc, 0xff, 0xff, 0xff, 0, 0, 0, 0}
if !bytes.Equal(ptrSlice, want) {
t.Errorf("SetPtr wrote % 02x; want % 02x", ptrSlice, want)
}
}
func TestReadFarPointers(t *testing.T) {
msg := &Message{
// an rpc.capnp Message
Arena: MultiSegment([][]byte{
// Segment 0
{
// Double-far pointer: segment 2, offset 0
0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
},
// Segment 1
{
// (Root) Struct data section
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Struct pointer section
// Double-far pointer: segment 4, offset 0
0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
},
// Segment 2
{
// Far pointer landing pad: segment 1, offset 0
0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
// Far pointer landing pad tag word: struct with 1 word data and 1 pointer
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
},
// Segment 3
{
// (Root>0) Struct data section
0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
0xaa, 0x70, 0x65, 0x21, 0xd7, 0x7b, 0x31, 0xa7,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Struct pointer section
// Far pointer: segment 4, offset 4
0x22, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
// Far pointer: segment 4, offset 7
0x3a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
// Null
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
// Segment 4
{
// Far pointer landing pad: segment 3, offset 0
0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
// Far pointer landing pad tag word: struct with 3 word data and 3 pointer
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00,
// (Root>0>0) Struct data section
0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Struct pointer section
// Null
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Far pointer landing pad: struct pointer: offset -3, 1 word data, 1 pointer
0xf4, 0xff, 0xff, 0xff, 0x01, 0x00, 0x01, 0x00,
// (Root>0>1) Struct pointer section
// Struct pointer: offset 2, 1 word data
0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
// Null
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Far pointer landing pad: struct pointer: offset -3, 2 pointers
0xf4, 0xff, 0xff, 0xff, 0x00, 0x00, 0x02, 0x00,
// (Root>0>1>0) Struct data section
0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
}),
}
rootp, err := msg.RootPtr()
if err != nil {
t.Error("RootPtr:", err)
}
root := rootp.Struct()
if root.Uint16(0) != 2 {
t.Errorf("root.Uint16(0) = %d; want 2", root.Uint16(0))
}
callp, err := root.Ptr(0)
if err != nil {
t.Error("root.Ptr(0):", err)
}
call := callp.Struct()
targetp, err := call.Ptr(0)
if err != nil {
t.Error("root.Ptr(0).Ptr(0):", err)
}
if got := targetp.Struct().Uint32(0); got != 84 {
t.Errorf("root.Ptr(0).Ptr(0).Uint32(0) = %d; want 84", got)
}
paramsp, err := call.Ptr(1)
if err != nil {
t.Error("root.Ptr(0).Ptr(1):", err)
}
contentp, err := paramsp.Struct().Ptr(0)
if err != nil {
t.Error("root.Ptr(0).Ptr(1).Ptr(0):", err)
}
if got := contentp.Struct().Uint64(0); got != 42 {
t.Errorf("root.Ptr(0).Ptr(1).Ptr(0).Uint64(0) = %d; want 42", got)
}
}
func TestWriteFarPointer(t *testing.T) {
// TODO(someday): run same test with a two-word list
msg := &Message{
Arena: MultiSegment([][]byte{
make([]byte, 8),
make([]byte, 0, 24),
}),
}
seg1, err := msg.Segment(1)
if err != nil {
t.Fatal("msg.Segment(1):", err)
}
s, err := NewStruct(seg1, ObjectSize{DataSize: 8, PointerCount: 1})
if err != nil {
t.Fatal("NewStruct(msg.Segment(1), ObjectSize{8, 1}):", err)
}
if s.Segment() != seg1 {
t.Fatalf("struct allocated in segment %d", s.Segment().ID())
}
if err := msg.SetRootPtr(s.ToPtr()); err != nil {
t.Error("msg.SetRootPtr(...):", err)
}
seg0, err := msg.Segment(0)
if err != nil {
t.Fatal("msg.Segment(0):", err)
}
root := rawPointer(binary.LittleEndian.Uint64(seg0.Data()))
if root.pointerType() != farPointer {
t.Fatalf("root (%#016x) type = %v; want %v (farPointer)", root, root.pointerType(), farPointer)
}
if root.farSegment() != 1 {
t.Fatalf("root points to segment %d; want 1", root.farSegment())
}
padAddr := root.farAddress()
if padAddr > Address(len(seg1.Data())-8) {
t.Fatalf("root points to out of bounds address %v; size of segment is %d", padAddr, len(seg1.Data()))
}
pad := rawPointer(binary.LittleEndian.Uint64(seg1.Data()[padAddr:]))
if pad.pointerType() != structPointer {
t.Errorf("landing pad (%#016x) type = %v; want %v (structPointer)", pad, pad.pointerType(), structPointer)
}
if got, ok := pad.offset().resolve(padAddr + 8); !ok || got != s.off {
t.Errorf("landing pad (%#016x @ %v) resolved address = %v, %t; want %v, true", pad, padAddr, got, ok, s.off)
}
if got, want := pad.structSize(), (ObjectSize{DataSize: 8, PointerCount: 1}); got != want {
t.Errorf("landing pad (%#016x) struct size = %v; want %v", pad, got, want)
}
}
func TestWriteDoubleFarPointer(t *testing.T) {
// TODO(someday): run same test with a two-word list
msg := &Message{
Arena: MultiSegment([][]byte{
make([]byte, 8),
make([]byte, 0, 16),
}),
}
seg1, err := msg.Segment(1)
if err != nil {
t.Fatal("msg.Segment(1):", err)
}
s, err := NewStruct(seg1, ObjectSize{DataSize: 8, PointerCount: 1})
if err != nil {
t.Fatal("NewStruct(msg.Segment(1), ObjectSize{8, 1}):", err)
}
if s.Segment() != seg1 {
t.Fatalf("struct allocated in segment %d", s.Segment().ID())
}
if err := msg.SetRootPtr(s.ToPtr()); err != nil {
t.Error("msg.SetRootPtr(...):", err)
}
seg0, err := msg.Segment(0)
if err != nil {
t.Fatal("msg.Segment(0):", err)
}
root := rawPointer(binary.LittleEndian.Uint64(seg0.Data()))
if root.pointerType() != doubleFarPointer {
t.Fatalf("root (%#016x) type = %v; want %v (doubleFarPointer)", root, root.pointerType(), doubleFarPointer)
}
if root.farSegment() == 0 || root.farSegment() == 1 {
t.Fatalf("root points to segment %d; want !=0,1", root.farSegment())
}
padSeg, err := msg.Segment(root.farSegment())
if err != nil {
t.Fatalf("msg.Segment(%d): %v", root.farSegment(), err)
}
padAddr := root.farAddress()
if padAddr > Address(len(padSeg.Data())-16) {
t.Fatalf("root points to out of bounds address %v; size of segment is %d", padAddr, len(padSeg.Data()))
}
pad1 := rawPointer(binary.LittleEndian.Uint64(padSeg.Data()[padAddr:]))
if pad1.pointerType() != farPointer {
t.Errorf("landing pad pointer 1 (%#016x) type = %v; want %v (farPointer)", pad1, pad1.pointerType(), farPointer)
}
if pad1.farSegment() != 1 {
t.Fatalf("landing pad pointer 1 (%#016x) points to segment %d; want 1", pad1, pad1.farSegment())
}
if pad1.farAddress() != s.off {
t.Fatalf("landing pad pointer 1 (%#016x) points to address %v; want %v", pad1, pad1.farAddress(), s.off)
}
pad2 := rawPointer(binary.LittleEndian.Uint64(padSeg.Data()[padAddr+8:]))
if pad2.pointerType() != structPointer {
t.Errorf("landing pad pointer 2 (%#016x) type = %v; want %v (structPointer)", pad2, pad2.pointerType(), structPointer)
}
if pad2.offset() != 0 {
t.Errorf("landing pad pointer 2 (%#016x) offset = %d; want 0", pad2, pad2.offset())
}
if got, want := pad2.structSize(), (ObjectSize{DataSize: 8, PointerCount: 1}); got != want {
t.Errorf("landing pad pointer 2 (%#016x) struct size = %v; want %v", pad2, got, want)
}
}
func catchPanic(f func()) (err error) {
defer func() {
pval := recover()
if pval == nil {
return
}
e, ok := pval.(error)
if !ok {
err = fmt.Errorf("non-error panic: %#v", pval)
return
}
err = e
}()
f()
return nil
}

View File

@@ -1 +0,0 @@
/capnpc-go

View File

@@ -1,36 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"capnpc-go.go",
"fileparts.go",
"nodes.go",
"templateparams.go",
"templates.go",
],
importpath = "zombiezen.com/go/capnproto2/capnpc-go",
visibility = ["//visibility:private"],
deps = [
"//:go_default_library",
"//internal/schema:go_default_library",
],
)
go_binary(
name = "capnpc-go",
embed = [":go_default_library"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = ["capnpc-go_test.go"],
data = glob(["testdata/**"]),
embed = [":go_default_library"],
deps = [
"//:go_default_library",
"//encoding/text:go_default_library",
"//internal/schema:go_default_library",
],
)

File diff suppressed because it is too large Load Diff

View File

@@ -1,471 +0,0 @@
package main
import (
"bytes"
"fmt"
"go/parser"
"go/token"
"io/ioutil"
"path/filepath"
"sort"
"strconv"
"strings"
"testing"
"zombiezen.com/go/capnproto2"
"zombiezen.com/go/capnproto2/encoding/text"
"zombiezen.com/go/capnproto2/internal/schema"
)
func readTestFile(name string) ([]byte, error) {
path := filepath.Join("testdata", name)
return ioutil.ReadFile(path)
}
func mustReadTestFile(t *testing.T, name string) []byte {
data, err := readTestFile(name)
if err != nil {
t.Fatal(err)
}
return data
}
func mustReadGeneratorRequest(t *testing.T, name string) schema.CodeGeneratorRequest {
data := mustReadTestFile(t, name)
msg, err := capnp.Unmarshal(data)
if err != nil {
t.Fatalf("Unmarshaling %s: %v", name, err)
}
req, err := schema.ReadRootCodeGeneratorRequest(msg)
if err != nil {
t.Fatalf("Reading code generator request %s: %v", name, err)
}
return req
}
func TestBuildNodeMap(t *testing.T) {
tests := []struct {
name string
fileID uint64
fileNodes []uint64
}{
{
name: "go.capnp.out",
fileID: 0xd12a1c51fedd6c88,
fileNodes: []uint64{
0xbea97f1023792be0,
0xe130b601260e44b5,
0xc58ad6bd519f935e,
0xa574b41924caefc7,
0xc8768679ec52e012,
0xfa10659ae02f2093,
0xc2b96012172f8df1,
},
},
{
name: "group.capnp.out",
fileID: 0x83c2b5818e83ab19,
fileNodes: []uint64{
0xd119fd352d8ea888, // the struct
0x822357857e5925d4, // the group
},
},
}
for _, test := range tests {
data, err := readTestFile(test.name)
if err != nil {
t.Errorf("readTestFile(%q): %v", test.name, err)
continue
}
msg, err := capnp.Unmarshal(data)
if err != nil {
t.Errorf("Unmarshaling %s: %v", test.name, err)
continue
}
req, err := schema.ReadRootCodeGeneratorRequest(msg)
if err != nil {
t.Errorf("Reading code generator request %s: %v", test.name, err)
continue
}
nodes, err := buildNodeMap(req)
if err != nil {
t.Errorf("%s: buildNodeMap: %v", test.name, err)
}
f := nodes[test.fileID]
if f == nil {
t.Errorf("%s: node map is missing file node @%#x", test.name, test.fileID)
continue
}
if f.Id() != test.fileID {
t.Errorf("%s: node map has ID @%#x for lookup of @%#x", test.name, f.Id(), test.fileID)
}
// Test node.nodes collection
for _, id := range test.fileNodes {
found := false
for _, fn := range f.nodes {
if fn.Id() == id {
found = true
break
}
}
if !found {
t.Errorf("%s: missing @%#x from file nodes", test.name, id)
}
}
// Test map lookup
for _, k := range test.fileNodes {
n := nodes[k]
if n == nil {
t.Errorf("%s: missing @%#x from node map", test.name, k)
}
if n.Id() != k {
t.Errorf("%s: node map has ID @%#x for lookup of @%#x", test.name, n.Id(), k)
}
}
}
}
func TestRemoteScope(t *testing.T) {
type scopeTest struct {
name string
constID uint64
initImports []importSpec
remoteName string
remoteNew string
imports []importSpec
}
tests := []scopeTest{
{
name: "same-file struct",
constID: 0x84efedc75e99768d, // scopes.fooVar
remoteName: "Foo",
remoteNew: "NewFoo",
},
{
name: "different file struct",
constID: 0x836faf1834d91729, // scopes.otherFooVar
remoteName: "otherscopes.Foo",
remoteNew: "otherscopes.NewFoo",
imports: []importSpec{
{name: "otherscopes", path: "zombiezen.com/go/capnproto2/capnpc-go/testdata/otherscopes"},
},
},
{
name: "same-file struct list",
constID: 0xcda2680ec5c921e0, // scopes.fooListVar
remoteName: "Foo_List",
remoteNew: "NewFoo_List",
},
{
name: "different file struct list",
constID: 0x83e7e1b3cd1be338, // scopes.otherFooListVar
remoteName: "otherscopes.Foo_List",
remoteNew: "otherscopes.NewFoo_List",
imports: []importSpec{
{name: "otherscopes", path: "zombiezen.com/go/capnproto2/capnpc-go/testdata/otherscopes"},
},
},
{
name: "built-in Int32 list",
constID: 0xacf3d9917d0bb0f0, // scopes.intList
remoteName: "capnp.Int32List",
remoteNew: "capnp.NewInt32List",
imports: []importSpec{
{name: "capnp", path: "zombiezen.com/go/capnproto2"},
},
},
}
req := mustReadGeneratorRequest(t, "scopes.capnp.out")
nodes, err := buildNodeMap(req)
if err != nil {
t.Fatal("buildNodeMap:", err)
}
collect := func(test scopeTest) (g *generator, typ schema.Type, from *node, ok bool) {
g = newGenerator(0xd68755941d99d05e, nodes, genoptions{})
v := nodes[test.constID]
if v == nil {
t.Errorf("Can't find const @%#x for %s test", test.constID, test.name)
return nil, schema.Type{}, nil, false
}
if v.Which() != schema.Node_Which_const {
t.Errorf("Type of node @%#x in %s test is a %v node; want const. Check the test.", test.constID, test.name, v.Which())
return nil, schema.Type{}, nil, false
}
constType, _ := v.Const().Type()
for _, i := range test.initImports {
g.imports.add(i)
}
return g, constType, v, true
}
for _, test := range tests {
g, typ, from, ok := collect(test)
if !ok {
continue
}
rn, err := g.RemoteTypeName(typ, from)
if err != nil {
t.Errorf("%s: g.RemoteTypeName(nodes[%#x].Const().Type(), nodes[%#x]) error: %v", test.name, test.constID, test.constID, err)
continue
}
if rn != test.remoteName {
t.Errorf("%s: g.RemoteTypeName(nodes[%#x].Const().Type(), nodes[%#x]) = %q; want %q", test.name, test.constID, test.constID, rn, test.remoteName)
continue
}
if !hasExactImports(test.imports, g.imports) {
t.Errorf("%s: g.RemoteTypeName(nodes[%#x].Const().Type(), nodes[%#x]); g.imports = %s; want %s", test.name, test.constID, test.constID, formatImportSpecs(g.imports.usedImports()), formatImportSpecs(test.imports))
continue
}
}
for _, test := range tests {
g, typ, from, ok := collect(test)
if !ok {
continue
}
rn, err := g.RemoteTypeNew(typ, from)
if err != nil {
t.Errorf("%s: g.RemoteTypeNew(nodes[%#x].Const().Type(), nodes[%#x]) error: %v", test.name, test.constID, test.constID, err)
continue
}
if rn != test.remoteNew {
t.Errorf("%s: g.RemoteTypeNew(nodes[%#x].Const().Type(), nodes[%#x]) = %q; want %q", test.name, test.constID, test.constID, rn, test.remoteNew)
continue
}
if !hasExactImports(test.imports, g.imports) {
t.Errorf("%s: g.RemoteTypeNew(nodes[%#x].Const().Type(), nodes[%#x]); g.imports = %s; want %s", test.name, test.constID, test.constID, formatImportSpecs(g.imports.usedImports()), formatImportSpecs(test.imports))
continue
}
}
}
func hasExactImports(specs []importSpec, imp imports) bool {
used := imp.usedImports()
if len(used) != len(specs) {
return false
}
outer:
for i := range specs {
for j := range used {
if specs[i] == used[j] {
continue outer
}
}
return false
}
return true
}
func formatImportSpecs(specs []importSpec) string {
var buf bytes.Buffer
for i, s := range specs {
if i > 0 {
buf.WriteString("; ")
}
buf.WriteString(s.String())
}
return buf.String()
}
func TestDefineConstNodes(t *testing.T) {
req := mustReadGeneratorRequest(t, "const.capnp.out")
nodes, err := buildNodeMap(req)
if err != nil {
t.Fatal("buildNodeMap:", err)
}
g := newGenerator(0xc260cb50ae622e10, nodes, genoptions{})
getCalls := traceGenerator(g)
err = g.defineConstNodes(nodes[0xc260cb50ae622e10].nodes)
if err != nil {
t.Fatal("defineConstNodes:", err)
}
calls := getCalls()
if len(calls) != 1 {
t.Fatalf("defineConstNodes called %d templates; want 1", len(calls))
}
p, ok := calls[0].params.(constantsParams)
if calls[0].name != "constants" || !ok {
t.Fatalf("defineConstNodes rendered %v; want render of constants template", calls[0])
}
if !containsExactlyIDs(p.Consts, 0xda96e2255811b258) {
t.Errorf("defineConstNodes rendered Consts %s", nodeListString(p.Consts))
}
if !containsExactlyIDs(p.Vars, 0xe0a385c7be1fea4d) {
t.Errorf("defineConstNodes rendered Vars %s", nodeListString(p.Vars))
}
}
func TestDefineFile(t *testing.T) {
// Sanity check to make sure codegen produces parseable Go.
const iterations = 3
defaultOptions := genoptions{
promises: true,
schemas: true,
structStrings: true,
}
tests := []struct {
fileID uint64
fname string
opts genoptions
}{
{0x832bcc6686a26d56, "aircraft.capnp.out", defaultOptions},
{0x832bcc6686a26d56, "aircraft.capnp.out", genoptions{
promises: false,
schemas: false,
structStrings: false,
}},
{0x832bcc6686a26d56, "aircraft.capnp.out", genoptions{
promises: true,
schemas: false,
structStrings: false,
}},
{0x832bcc6686a26d56, "aircraft.capnp.out", genoptions{
promises: false,
schemas: true,
structStrings: false,
}},
{0x832bcc6686a26d56, "aircraft.capnp.out", genoptions{
promises: true,
schemas: true,
structStrings: false,
}},
{0x832bcc6686a26d56, "aircraft.capnp.out", genoptions{
promises: false,
schemas: true,
structStrings: true,
}},
{0x83c2b5818e83ab19, "group.capnp.out", defaultOptions},
{0xb312981b2552a250, "rpc.capnp.out", defaultOptions},
{0xd68755941d99d05e, "scopes.capnp.out", defaultOptions},
{0xecd50d792c3d9992, "util.capnp.out", defaultOptions},
}
for _, test := range tests {
data, err := readTestFile(test.fname)
if err != nil {
t.Errorf("reading %s: %v", test.fname, err)
continue
}
msg, err := capnp.Unmarshal(data)
if err != nil {
t.Errorf("Unmarshaling %s: %v", test.fname, err)
continue
}
req, err := schema.ReadRootCodeGeneratorRequest(msg)
if err != nil {
t.Errorf("Reading code generator request %s: %v", test.fname, err)
continue
}
nodes, err := buildNodeMap(req)
if err != nil {
t.Errorf("buildNodeMap %s: %v", test.fname, err)
continue
}
g := newGenerator(test.fileID, nodes, test.opts)
if err := g.defineFile(); err != nil {
t.Errorf("defineFile %s %+v: %v", test.fname, test.opts, err)
continue
}
src := g.generate()
if _, err := parser.ParseFile(token.NewFileSet(), test.fname+".go", src, 0); err != nil {
// TODO(light): log src
t.Errorf("generate %s %+v failed to parse: %v", test.fname, test.opts, err)
}
// Generation should be deterministic between runs.
for i := 0; i < iterations-1; i++ {
g := newGenerator(test.fileID, nodes, test.opts)
if err := g.defineFile(); err != nil {
t.Errorf("defineFile %s %+v [iteration %d]: %v", test.fname, test.opts, i+2, err)
continue
}
src2 := g.generate()
if !bytes.Equal(src, src2) {
t.Errorf("defineFile %s %+v [iteration %d] did not match iteration 1: non-deterministic", test.fname, test.opts, i+2)
}
}
}
}
func TestSchemaVarLiteral(t *testing.T) {
tests := []string{
"",
"foo",
"deadbeefdeadbeef",
"deadbeefdeadbeefdeadbeef",
"\x00\x00",
"\xff\xff",
"\n",
" ~\"\\",
"\xff\xff\x27\xa1\xe3\xf1",
}
for _, test := range tests {
got := schemaVarParams{schema: []byte(test)}.SchemaLiteral()
u, err := strconv.Unquote(strings.Replace(got, "\" +\n\t\"", "", -1))
if err != nil {
t.Errorf("schema literal of %q does not parse: %v\n\tproduced: %s", test, err, got)
} else if u != test {
t.Errorf("schema literal of %q != %s", test, got)
}
}
}
type traceRenderer struct {
renderer
calls []renderCall
}
func traceGenerator(g *generator) (getCalls func() []renderCall) {
tr := &traceRenderer{renderer: g.r}
g.r = tr
return func() []renderCall { return tr.calls }
}
func (tr *traceRenderer) Render(name string, params interface{}) error {
tr.calls = append(tr.calls, renderCall{name, params})
return tr.renderer.Render(name, params)
}
type renderCall struct {
name string
params interface{}
}
func (rc renderCall) String() string {
return fmt.Sprintf("{%q %#v}", rc.name, rc.params)
}
func containsExactlyIDs(nodes []*node, ids ...uint64) bool {
if len(nodes) != len(ids) {
return false
}
sorted := make([]uint64, len(ids))
copy(sorted, ids)
sort.Sort(uint64Slice(sorted))
actual := make([]uint64, len(nodes))
for i := range nodes {
actual[i] = nodes[i].Id()
}
sort.Sort(uint64Slice(actual))
for i := range sorted {
if actual[i] != sorted[i] {
return false
}
}
return true
}
func nodeListString(n []*node) string {
b := new(bytes.Buffer)
e := text.NewEncoder(b)
b.WriteByte('[')
for i, nn := range n {
if i > 0 {
b.WriteByte(' ')
}
e.Encode(0xe682ab4cf923a417, nn.Struct)
}
b.WriteByte(']')
return b.String()
}

View File

@@ -1,194 +0,0 @@
package main
import (
"fmt"
"strconv"
"strings"
"unicode"
"zombiezen.com/go/capnproto2"
)
type staticData struct {
name string
buf []byte
}
func (sd *staticData) init(fileID uint64) {
sd.name = fmt.Sprintf("x_%x", fileID)
sd.buf = make([]byte, 0, 4096)
}
func (sd *staticData) copyData(obj capnp.Ptr) (staticDataRef, error) {
m, _, err := capnp.NewMessage(capnp.SingleSegment(nil))
if err != nil {
return staticDataRef{}, err
}
err = m.SetRootPtr(obj)
if err != nil {
return staticDataRef{}, err
}
data, err := m.Marshal()
if err != nil {
return staticDataRef{}, err
}
ref := staticDataRef{data: sd}
ref.Start = len(sd.buf)
sd.buf = append(sd.buf, data...)
ref.End = len(sd.buf)
return ref, nil
}
type staticDataRef struct {
data *staticData
Start, End int
}
func (ref staticDataRef) IsValid() bool {
return ref.Start < ref.End
}
func (ref staticDataRef) String() string {
return fmt.Sprintf("%s[%d:%d]", ref.data.name, ref.Start, ref.End)
}
type imports struct {
specs []importSpec
used map[string]bool // keyed on import path
}
var capnpImportSpec = importSpec{path: capnpImport, name: "capnp"}
func (i *imports) init() {
i.specs = nil
i.used = make(map[string]bool)
i.reserve(capnpImportSpec)
i.reserve(importSpec{path: schemasImport, name: "schemas"})
i.reserve(importSpec{path: serverImport, name: "server"})
i.reserve(importSpec{path: textImport, name: "text"})
i.reserve(importSpec{path: contextImport, name: "context"})
i.reserve(importSpec{path: "math", name: "math"})
i.reserve(importSpec{path: "strconv", name: "strconv"})
}
func (i *imports) Capnp() string {
return i.add(importSpec{path: capnpImport, name: "capnp"})
}
func (i *imports) Schemas() string {
return i.add(importSpec{path: schemasImport, name: "schemas"})
}
func (i *imports) Server() string {
return i.add(importSpec{path: serverImport, name: "server"})
}
func (i *imports) Text() string {
return i.add(importSpec{path: textImport, name: "text"})
}
func (i *imports) Context() string {
return i.add(importSpec{path: contextImport, name: "context"})
}
func (i *imports) Math() string {
return i.add(importSpec{path: "math", name: "math"})
}
func (i *imports) Strconv() string {
return i.add(importSpec{path: "strconv", name: "strconv"})
}
func (i *imports) usedImports() []importSpec {
specs := make([]importSpec, 0, len(i.specs))
for _, s := range i.specs {
if i.used[s.path] {
specs = append(specs, s)
}
}
return specs
}
func (i *imports) byPath(path string) (spec importSpec, ok bool) {
for _, spec = range i.specs {
if spec.path == path {
return spec, true
}
}
return importSpec{}, false
}
func (i *imports) byName(name string) (spec importSpec, ok bool) {
for _, spec = range i.specs {
if spec.name == name {
return spec, true
}
}
return importSpec{}, false
}
func (i *imports) add(spec importSpec) (name string) {
name = i.reserve(spec)
i.used[spec.path] = true
return name
}
// reserve adds an import spec without marking it as used.
func (i *imports) reserve(spec importSpec) (name string) {
if ispec, ok := i.byPath(spec.path); ok {
return ispec.name
}
if spec.name == "" {
spec.name = pkgFromImport(spec.path)
}
if _, found := i.byName(spec.name); found {
for base, n := spec.name, uint64(2); ; n++ {
spec.name = base + strconv.FormatUint(n, 10)
if _, found = i.byName(spec.name); !found {
break
}
}
}
i.specs = append(i.specs, spec)
return spec.name
}
func pkgFromImport(path string) string {
if i := strings.LastIndex(path, "/"); i != -1 {
path = path[i+1:]
}
p := []rune(path)
n := 0
for _, r := range p {
if isIdent(r) {
p[n] = r
n++
}
}
if n == 0 || !isLower(p[0]) {
return "pkg" + string(p[:n])
}
return string(p[:n])
}
func isLower(r rune) bool {
return 'a' <= r && r <= 'z' || r == '_'
}
func isIdent(r rune) bool {
return isLower(r) || 'A' <= r && r <= 'Z' || r >= 0x80 && unicode.IsLetter(r)
}
type importSpec struct {
path string
name string
}
func (spec importSpec) String() string {
if spec.name == "" {
return strconv.Quote(spec.path)
}
return spec.name + " " + strconv.Quote(spec.path)
}

View File

@@ -1,336 +0,0 @@
package main
import (
"errors"
"fmt"
"strings"
"zombiezen.com/go/capnproto2"
"zombiezen.com/go/capnproto2/internal/schema"
)
type node struct {
schema.Node
pkg string
imp string
nodes []*node // only for file nodes
Name string
}
func (n *node) codeOrderFields() []field {
fields, _ := n.StructNode().Fields()
numFields := fields.Len()
mbrs := make([]field, numFields)
for i := 0; i < numFields; i++ {
f := fields.At(i)
fann, _ := f.Annotations()
fname, _ := f.Name()
fname = parseAnnotations(fann).Rename(fname)
mbrs[f.CodeOrder()] = field{Field: f, Name: fname}
}
return mbrs
}
// DiscriminantOffset returns the byte offset of the struct union discriminant.
func (n *node) DiscriminantOffset() (uint32, error) {
if n == nil {
return 0, errors.New("discriminant offset called on nil node")
}
if n.Which() != schema.Node_Which_structNode {
return 0, fmt.Errorf("discriminant offset called on %v node", n.Which())
}
return n.StructNode().DiscriminantOffset() * 2, nil
}
func (n *node) shortDisplayName() string {
dn, _ := n.DisplayName()
return dn[n.DisplayNamePrefixLength():]
}
// String returns the node's display name.
func (n *node) String() string {
return displayName(n)
}
func displayName(n interface {
DisplayName() (string, error)
}) string {
dn, _ := n.DisplayName()
return dn
}
type field struct {
schema.Field
Name string
}
// HasDiscriminant reports whether the field is in a union.
func (f field) HasDiscriminant() bool {
return f.DiscriminantValue() != schema.Field_noDiscriminant
}
type enumval struct {
schema.Enumerant
Name string
Val int
Tag string
parent *node
}
func makeEnumval(enum *node, i int, e schema.Enumerant) enumval {
eann, _ := e.Annotations()
ann := parseAnnotations(eann)
name, _ := e.Name()
name = ann.Rename(name)
t := ann.Tag(name)
return enumval{e, name, i, t, enum}
}
func (e *enumval) FullName() string {
return e.parent.Name + "_" + e.Name
}
type interfaceMethod struct {
schema.Method
Interface *node
ID int
Name string
OriginalName string
Params *node
Results *node
}
func methodSet(methods []interfaceMethod, n *node, nodes nodeMap) ([]interfaceMethod, error) {
ms, _ := n.Interface().Methods()
for i := 0; i < ms.Len(); i++ {
m := ms.At(i)
mname, _ := m.Name()
mann, _ := m.Annotations()
pn, err := nodes.mustFind(m.ParamStructType())
if err != nil {
return methods, fmt.Errorf("could not find param type for %s.%s", n.shortDisplayName(), mname)
}
rn, err := nodes.mustFind(m.ResultStructType())
if err != nil {
return methods, fmt.Errorf("could not find result type for %s.%s", n.shortDisplayName(), mname)
}
methods = append(methods, interfaceMethod{
Method: m,
Interface: n,
ID: i,
OriginalName: mname,
Name: parseAnnotations(mann).Rename(mname),
Params: pn,
Results: rn,
})
}
// TODO(light): sort added methods by code order
supers, _ := n.Interface().Superclasses()
for i := 0; i < supers.Len(); i++ {
s := supers.At(i)
sn, err := nodes.mustFind(s.Id())
if err != nil {
return methods, fmt.Errorf("could not find superclass %#x of %s", s.Id(), n)
}
methods, err = methodSet(methods, sn, nodes)
if err != nil {
return methods, err
}
}
return methods, nil
}
// Tag types
const (
defaultTag = iota
noTag
customTag
)
type annotations struct {
Doc string
Package string
Import string
TagType int
CustomTag string
Name string
}
func parseAnnotations(list schema.Annotation_List) *annotations {
ann := new(annotations)
for i, n := 0, list.Len(); i < n; i++ {
a := list.At(i)
val, _ := a.Value()
text, _ := val.Text()
switch a.Id() {
case capnp.Doc:
ann.Doc = text
case capnp.Package:
ann.Package = text
case capnp.Import:
ann.Import = text
case capnp.Tag:
ann.TagType = customTag
ann.CustomTag = text
case capnp.Notag:
ann.TagType = noTag
case capnp.Name:
ann.Name = text
}
}
return ann
}
// Tag returns the string value that an enumerant value called name should have.
// An empty string indicates that this enumerant value has no tag.
func (ann *annotations) Tag(name string) string {
switch ann.TagType {
case noTag:
return ""
case customTag:
return ann.CustomTag
case defaultTag:
fallthrough
default:
return name
}
}
// Rename returns the overridden name from the annotations or the given name
// if no annotation was found.
func (ann *annotations) Rename(given string) string {
if ann.Name == "" {
return given
}
return ann.Name
}
type nodeMap map[uint64]*node
func buildNodeMap(req schema.CodeGeneratorRequest) (nodeMap, error) {
rnodes, err := req.Nodes()
if err != nil {
return nil, err
}
nodes := make(nodeMap, rnodes.Len())
var allfiles []*node
for i := 0; i < rnodes.Len(); i++ {
ni := rnodes.At(i)
n := &node{Node: ni}
nodes[n.Id()] = n
if n.Which() == schema.Node_Which_file {
allfiles = append(allfiles, n)
}
}
for _, f := range allfiles {
fann, err := f.Annotations()
if err != nil {
return nil, fmt.Errorf("reading annotations for %v: %v", f, err)
}
ann := parseAnnotations(fann)
f.pkg = ann.Package
f.imp = ann.Import
nnodes, _ := f.NestedNodes()
for i := 0; i < nnodes.Len(); i++ {
nn := nnodes.At(i)
if ni := nodes[nn.Id()]; ni != nil {
nname, _ := nn.Name()
if err := resolveName(nodes, ni, "", nname, f); err != nil {
return nil, err
}
}
}
}
return nodes, nil
}
// resolveName is called as part of building up a node map to populate the name field of n.
func resolveName(nodes nodeMap, n *node, base, name string, file *node) error {
na, err := n.Annotations()
if err != nil {
return fmt.Errorf("reading annotations for %s: %v", n, err)
}
name = parseAnnotations(na).Rename(name)
if base == "" {
n.Name = strings.Title(name)
} else {
n.Name = base + "_" + name
}
n.pkg = file.pkg
n.imp = file.imp
file.nodes = append(file.nodes, n)
nnodes, err := n.NestedNodes()
if err != nil {
return fmt.Errorf("listing nested nodes for %s: %v", n, err)
}
for i := 0; i < nnodes.Len(); i++ {
nn := nnodes.At(i)
ni := nodes[nn.Id()]
if ni == nil {
continue
}
nname, err := nn.Name()
if err != nil {
return fmt.Errorf("reading name of nested node %d in %s: %v", i+1, n, err)
}
if err := resolveName(nodes, ni, n.Name, nname, file); err != nil {
return err
}
}
switch n.Which() {
case schema.Node_Which_structNode:
fields, _ := n.StructNode().Fields()
for i := 0; i < fields.Len(); i++ {
f := fields.At(i)
if f.Which() != schema.Field_Which_group {
continue
}
fa, _ := f.Annotations()
fname, _ := f.Name()
grp := nodes[f.Group().TypeId()]
if grp == nil {
return fmt.Errorf("could not find type information for group %s in %s", fname, n)
}
fname = parseAnnotations(fa).Rename(fname)
if err := resolveName(nodes, grp, n.Name, fname, file); err != nil {
return err
}
}
case schema.Node_Which_interface:
m, _ := n.Interface().Methods()
methodResolve := func(id uint64, mname string, base string, name string) error {
x := nodes[id]
if x == nil {
return fmt.Errorf("could not find type %#x for %s.%s", id, n, mname)
}
if x.ScopeId() != 0 {
return nil
}
return resolveName(nodes, x, base, name, file)
}
for i := 0; i < m.Len(); i++ {
mm := m.At(i)
mname, _ := mm.Name()
mann, _ := mm.Annotations()
base := n.Name + "_" + parseAnnotations(mann).Rename(mname)
if err := methodResolve(mm.ParamStructType(), mname, base, "Params"); err != nil {
return err
}
if err := methodResolve(mm.ResultStructType(), mname, base, "Results"); err != nil {
return err
}
}
}
return nil
}
func (nm nodeMap) mustFind(id uint64) (*node, error) {
n := nm[id]
if n == nil {
return nil, fmt.Errorf("could not find node %#x in schema", id)
}
return n, nil
}

View File

@@ -1,236 +0,0 @@
package main
import (
"bytes"
"fmt"
)
type annotationParams struct {
G *generator
Node *node
}
type constantsParams struct {
G *generator
Consts []*node
Vars []*node
}
type enumParams struct {
G *generator
Node *node
Annotations *annotations
EnumValues []enumval
}
type structTypesParams struct {
G *generator
Node *node
Annotations *annotations
BaseNode *node
}
func (p structTypesParams) IsBase() bool {
return p.Node == p.BaseNode
}
type baseStructFuncsParams struct {
G *generator
Node *node
StringMethod bool
}
type structFuncsParams struct {
G *generator
Node *node
}
type structGroupParams struct {
G *generator
Node *node
Group *node
Field field
}
type structFieldParams struct {
G *generator
Node *node
Field field
Annotations *annotations
FieldType string
}
type (
structFloatFieldParams structUintFieldParams
structInterfaceFieldParams structFieldParams
structVoidFieldParams structFieldParams
structListFieldParams structObjectFieldParams
structPointerFieldParams structObjectFieldParams
structStructFieldParams structObjectFieldParams
)
type structBoolFieldParams struct {
structFieldParams
Default bool
}
type structUintFieldParams struct {
structFieldParams
Bits uint
Default uint64
}
func (p structUintFieldParams) Offset() uint32 {
return p.Field.Slot().Offset() * uint32(p.Bits/8)
}
func (p structFloatFieldParams) Offset() uint32 {
return structUintFieldParams(p).Offset()
}
type structIntFieldParams struct {
structUintFieldParams
EnumName string
}
func (p structIntFieldParams) ReturnType() string {
if p.EnumName != "" {
return p.EnumName
}
return fmt.Sprintf("int%d", p.Bits)
}
type structTextFieldParams struct {
structFieldParams
Default string
}
type structDataFieldParams struct {
structFieldParams
Default []byte
}
type structObjectFieldParams struct {
structFieldParams
TypeNode *node
Default staticDataRef
}
type structListParams struct {
G *generator
Node *node
StringMethod bool
}
type structEnumsParams struct {
G *generator
Node *node
Fields []field
EnumString enumString
}
type promiseParams struct {
G *generator
Node *node
Fields []field
}
type promiseGroupParams struct {
G *generator
Node *node
Field field
Group *node
}
type promiseFieldStructParams struct {
G *generator
Node *node
Field field
Struct *node
Default staticDataRef
}
type promiseFieldAnyPointerParams struct {
G *generator
Node *node
Field field
}
type promiseFieldInterfaceParams struct {
G *generator
Node *node
Field field
Interface *node
}
type interfaceClientParams struct {
G *generator
Node *node
Annotations *annotations
Methods []interfaceMethod
}
type interfaceServerParams struct {
G *generator
Node *node
Annotations *annotations
Methods []interfaceMethod
}
type structValueParams struct {
G *generator
Node *node
Typ *node
Value staticDataRef
}
type pointerValueParams struct {
G *generator
Value staticDataRef
}
type listValueParams struct {
G *generator
Typ string
Value staticDataRef
}
type schemaVarParams struct {
G *generator
FileID uint64
NodeIDs []uint64
schema []byte
}
func (p schemaVarParams) SchemaLiteral() string {
const width = 16
var out bytes.Buffer
out.WriteByte('"')
for i, b := range p.schema {
if i > 0 && i%width == 0 {
out.WriteString("\" +\n\t\"")
}
switch {
case b < ' ' || b > '~':
// unprintable
out.WriteString("\\x")
out.WriteByte(hexdigit(b >> 4))
out.WriteByte(hexdigit(b & 0xf))
case b == '"':
out.WriteString("\\\"")
case b == '\\':
out.WriteString("\\\\")
default:
out.WriteByte(b)
}
}
out.WriteByte('"')
return out.String()
}
func hexdigit(b byte) byte {
if b < 10 {
return b + '0'
}
return (b - 10) + 'a'
}

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +0,0 @@
{{if .Field.HasDiscriminant -}}
if s.Struct.Uint16({{.Node.DiscriminantOffset}}) != {{.Field.DiscriminantValue}} {
panic({{printf "Which() != %s" .Field.Name | printf "%q"}})
}
{{end -}}

View File

@@ -1,9 +0,0 @@
func (s {{.Node.Name}}) Has{{.Field.Name|title}}() bool {
{{if .Field.HasDiscriminant -}}
if s.Struct.Uint16({{.Node.DiscriminantOffset}}) != {{.Field.DiscriminantValue}} {
return false
}
{{end -}}
p, err := s.Struct.Ptr({{.Field.Slot.Offset}})
return p.IsValid() || err != nil
}

View File

@@ -1,4 +0,0 @@
InterfaceID: {{.Interface.Id|printf "%#x"}},
MethodID: {{.ID}},
InterfaceName: {{.Interface.DisplayName|printf "%q"}},
MethodName: {{.OriginalName|printf "%q"}},

View File

@@ -1,3 +0,0 @@
{{if .Field.HasDiscriminant -}}
s.Struct.SetUint16({{.Node.DiscriminantOffset}}, {{.Field.DiscriminantValue}})
{{end -}}

View File

@@ -1,2 +0,0 @@
// {{.Name}}_TypeID is the unique identifier for the type {{.Name}}.
const {{.Name}}_TypeID = {{.Id|printf "%#x"}}

View File

@@ -1 +0,0 @@
const {{.Node.Name}} = uint64({{.Node.Id|printf "%#x"}})

View File

@@ -1,23 +0,0 @@
{{ template "_typeid" .Node }}
func New{{.Node.Name}}(s *{{.G.Capnp}}.Segment) ({{.Node.Name}}, error) {
st, err := {{$.G.Capnp}}.NewStruct(s, {{.G.ObjectSize .Node}})
return {{.Node.Name}}{st}, err
}
func NewRoot{{.Node.Name}}(s *{{.G.Capnp}}.Segment) ({{.Node.Name}}, error) {
st, err := {{.G.Capnp}}.NewRootStruct(s, {{.G.ObjectSize .Node}})
return {{.Node.Name}}{st}, err
}
func ReadRoot{{.Node.Name}}(msg *{{.G.Capnp}}.Message) ({{.Node.Name}}, error) {
root, err := msg.RootPtr()
return {{.Node.Name}}{root.Struct()}, err
}
{{if .StringMethod}}
func (s {{.Node.Name}}) String() string {
str, _ := {{.G.Imports.Text}}.Marshal({{.Node.Id|printf "%#x"}}, s.Struct)
return str
}
{{end}}

View File

@@ -1,14 +0,0 @@
{{with .Consts -}}
// Constants defined in {{$.G.Basename}}.
const (
{{range .}} {{.Name}} = {{$.G.Value . .Const.Type .Const.Value}}
{{end}}
)
{{end}}
{{with .Vars -}}
// Constants defined in {{$.G.Basename}}.
var (
{{range .}} {{.Name}} = {{$.G.Value . .Const.Type .Const.Value}}
{{end}}
)
{{end}}

View File

@@ -1,55 +0,0 @@
{{with .Annotations.Doc -}}
// {{.}}
{{end -}}
type {{.Node.Name}} uint16
{{ template "_typeid" .Node }}
{{with .EnumValues -}}
// Values of {{$.Node.Name}}.
const (
{{range . -}}
{{.FullName}} {{$.Node.Name}} = {{.Val}}
{{end}}
)
// String returns the enum's constant name.
func (c {{$.Node.Name}}) String() string {
switch c {
{{range . -}}
{{if .Tag}}case {{.FullName}}: return {{printf "%q" .Tag}}
{{end}}
{{- end}}
default: return ""
}
}
// {{$.Node.Name}}FromString returns the enum value with a name,
// or the zero value if there's no such value.
func {{$.Node.Name}}FromString(c string) {{$.Node.Name}} {
switch c {
{{range . -}}
{{if .Tag}}case {{printf "%q" .Tag}}: return {{.FullName}}
{{end}}
{{- end}}
default: return 0
}
}
{{end}}
type {{.Node.Name}}_List struct { {{$.G.Capnp}}.List }
func New{{.Node.Name}}_List(s *{{$.G.Capnp}}.Segment, sz int32) ({{.Node.Name}}_List, error) {
l, err := {{.G.Capnp}}.NewUInt16List(s, sz)
return {{.Node.Name}}_List{l.List}, err
}
func (l {{.Node.Name}}_List) At(i int) {{.Node.Name}} {
ul := {{.G.Capnp}}.UInt16List{List: l.List}
return {{.Node.Name}}(ul.At(i))
}
func (l {{.Node.Name}}_List) Set(i int, v {{.Node.Name}}) {
ul := {{.G.Capnp}}.UInt16List{List: l.List}
ul.Set(i, uint16(v))
}

View File

@@ -1,26 +0,0 @@
{{with .Annotations.Doc -}}
// {{.}}
{{end -}}
type {{.Node.Name}} struct { Client {{.G.Capnp}}.Client }
{{ template "_typeid" .Node }}
{{range .Methods -}}
func (c {{$.Node.Name}}) {{.Name|title}}(ctx {{$.G.Imports.Context}}.Context, params func({{$.G.RemoteNodeName .Params $.Node}}) error, opts ...{{$.G.Capnp}}.CallOption) {{$.G.RemoteNodeName .Results $.Node}}_Promise {
if c.Client == nil {
return {{$.G.RemoteNodeName .Results $.Node}}_Promise{Pipeline: {{$.G.Capnp}}.NewPipeline({{$.G.Capnp}}.ErrorAnswer({{$.G.Capnp}}.ErrNullClient))}
}
call := &{{$.G.Capnp}}.Call{
Ctx: ctx,
Method: {{$.G.Capnp}}.Method{
{{template "_interfaceMethod" .}}
},
Options: {{$.G.Capnp}}.NewCallOptions(opts),
}
if params != nil {
call.ParamsSize = {{$.G.ObjectSize .Params}}
call.ParamsFunc = func(s {{$.G.Capnp}}.Struct) error { return params({{$.G.RemoteNodeName .Params $.Node}}{Struct: s}) }
}
return {{$.G.RemoteNodeName .Results $.Node}}_Promise{Pipeline: {{$.G.Capnp}}.NewPipeline(c.Client.Call(call))}
}
{{end}}

View File

@@ -1,40 +0,0 @@
type {{.Node.Name}}_Server interface {
{{range .Methods}}
{{.Name|title}}({{$.G.RemoteNodeName .Interface $.Node}}_{{.Name}}) error
{{end}}
}
func {{.Node.Name}}_ServerToClient(s {{.Node.Name}}_Server) {{.Node.Name}} {
c, _ := s.({{.G.Imports.Server}}.Closer)
return {{.Node.Name}}{Client: {{.G.Imports.Server}}.New({{.Node.Name}}_Methods(nil, s), c)}
}
func {{.Node.Name}}_Methods(methods []{{.G.Imports.Server}}.Method, s {{.Node.Name}}_Server) []{{.G.Imports.Server}}.Method {
if cap(methods) == 0 {
methods = make([]{{.G.Imports.Server}}.Method, 0, {{len .Methods}})
}
{{range .Methods}}
methods = append(methods, {{$.G.Imports.Server}}.Method{
Method: {{$.G.Capnp}}.Method{
{{template "_interfaceMethod" .}}
},
Impl: func(c {{$.G.Imports.Context}}.Context, opts {{$.G.Capnp}}.CallOptions, p, r {{$.G.Capnp}}.Struct) error {
call := {{$.G.RemoteNodeName .Interface $.Node}}_{{.Name}}{c, opts, {{$.G.RemoteNodeName .Params $.Node}}{Struct: p}, {{$.G.RemoteNodeName .Results $.Node}}{Struct: r} }
return s.{{.Name|title}}(call)
},
ResultsSize: {{$.G.ObjectSize .Results}},
})
{{end}}
return methods
}
{{range .Methods -}}
{{if eq .Interface.Id $.Node.Id}}
// {{$.Node.Name}}_{{.Name}} holds the arguments for a server call to {{$.Node.Name}}.{{.Name}}.
type {{$.Node.Name}}_{{.Name}} struct {
Ctx {{$.G.Imports.Context}}.Context
Options {{$.G.Capnp}}.CallOptions
Params {{$.G.RemoteNodeName .Params $.Node}}
Results {{$.G.RemoteNodeName .Results $.Node}}
}
{{end}}
{{- end}}

View File

@@ -1,2 +0,0 @@
{{.Typ}}{List: {{.G.Capnp}}.MustUnmarshalRootPtr({{.Value}}).List()}
{{- /* no EOL */ -}}

View File

@@ -1,2 +0,0 @@
{{.G.Capnp}}.MustUnmarshalRootPtr({{.Value}})
{{- /* no EOL */ -}}

View File

@@ -1,8 +0,0 @@
// {{.Node.Name}}_Promise is a wrapper for a {{.Node.Name}} promised by a client call.
type {{.Node.Name}}_Promise struct { *{{.G.Capnp}}.Pipeline }
func (p {{.Node.Name}}_Promise) Struct() ({{.Node.Name}}, error) {
s, err := p.Pipeline.Struct()
return {{.Node.Name}}{s}, err
}

View File

@@ -1,4 +0,0 @@
func (p {{.Node.Name}}_Promise) {{.Field.Name|title}}() *{{.G.Capnp}}.Pipeline {
return p.Pipeline.GetPipeline({{.Field.Slot.Offset}})
}

View File

@@ -1,4 +0,0 @@
func (p {{.Node.Name}}_Promise) {{.Field.Name|title}}() {{.G.RemoteNodeName .Interface .Node}} {
return {{.G.RemoteNodeName .Interface .Node}}{Client: p.Pipeline.GetPipeline({{.Field.Slot.Offset}}).Client()}
}

View File

@@ -1,4 +0,0 @@
func (p {{.Node.Name}}_Promise) {{.Field.Name|title}}() {{.G.RemoteNodeName .Struct .Node}}_Promise {
return {{.G.RemoteNodeName .Struct .Node}}_Promise{Pipeline: p.Pipeline.{{if .Default.IsValid}}GetPipelineDefault({{.Field.Slot.Offset}}, {{.Default}}){{else}}GetPipeline({{.Field.Slot.Offset}}){{end}} }
}

View File

@@ -1 +0,0 @@
func (p {{.Node.Name}}_Promise) {{.Field.Name|title}}() {{.Group.Name}}_Promise { return {{.Group.Name}}_Promise{p.Pipeline} }

View File

@@ -1,8 +0,0 @@
const schema_{{.FileID|printf "%x"}} = {{.SchemaLiteral}}
func init() {
{{.G.Imports.Schemas}}.Register(schema_{{.FileID|printf "%x"}},
{{- range .NodeIDs}}
{{.|printf "%#x"}},
{{- end}})
}

View File

@@ -1,10 +0,0 @@
func (s {{.Node.Name}}) {{.Field.Name|title}}() bool {
{{template "_checktag" . -}}
return {{if .Default}}!{{end}}s.Struct.Bit({{.Field.Slot.Offset}})
}
func (s {{.Node.Name}}) Set{{.Field.Name|title}}(v bool) {
{{template "_settag" . -}}
s.Struct.SetBit({{.Field.Slot.Offset}}, {{if .Default}}!{{end}}v)
}

View File

@@ -1,22 +0,0 @@
func (s {{.Node.Name}}) {{.Field.Name|title}}() ({{.FieldType}}, error) {
{{template "_checktag" . -}}
p, err := s.Struct.Ptr({{.Field.Slot.Offset}})
{{with .Default -}}
return {{$.FieldType}}(p.DataDefault({{printf "%#v" .}})), err
{{- else -}}
return {{.FieldType}}(p.Data()), err
{{- end}}
}
{{template "_hasfield" .}}
func (s {{.Node.Name}}) Set{{.Field.Name|title}}(v {{.FieldType}}) error {
{{template "_settag" . -}}
{{if .Default -}}
if v == nil {
v = []byte{}
}
{{end -}}
return s.Struct.SetData({{.Field.Slot.Offset}}, v)
}

View File

@@ -1,17 +0,0 @@
type {{.Node.Name}}_Which uint16
const (
{{range .Fields}} {{$.Node.Name}}_Which_{{.Name}} {{$.Node.Name}}_Which = {{.DiscriminantValue}}
{{end}}
)
func (w {{.Node.Name}}_Which) String() string {
const s = {{.EnumString.ValueString|printf "%q"}}
switch w {
{{range $i, $f := .Fields}}case {{$.Node.Name}}_Which_{{.Name}}:
return s{{$.EnumString.SliceFor $i}}
{{end}}
}
return "{{.Node.Name}}_Which(" + {{.G.Imports.Strconv}}.FormatUint(uint64(w), 10) + ")"
}

View File

@@ -1,10 +0,0 @@
func (s {{.Node.Name}}) {{.Field.Name|title}}() float{{.Bits}} {
{{template "_checktag" . -}}
return {{.G.Imports.Math}}.Float{{.Bits}}frombits(s.Struct.Uint{{.Bits}}({{.Offset}}){{with .Default}} ^ {{printf "%#x" .}}{{end}})
}
func (s {{.Node.Name}}) Set{{.Field.Name|title}}(v float{{.Bits}}) {
{{template "_settag" . -}}
s.Struct.SetUint{{.Bits}}({{.Offset}}, {{.G.Imports.Math}}.Float{{.Bits}}bits(v){{with .Default}}^{{printf "%#x" .}}{{end}})
}

View File

@@ -1,5 +0,0 @@
{{if gt .Node.StructNode.DiscriminantCount 0}}
func (s {{.Node.Name}}) Which() {{.Node.Name}}_Which {
return {{.Node.Name}}_Which(s.Struct.Uint16({{.Node.DiscriminantOffset}}))
}
{{end -}}

View File

@@ -1,4 +0,0 @@
func (s {{.Node.Name}}) {{.Field.Name|title}}() {{.Group.Name}} { return {{.Group.Name}}(s) }
{{if .Field.HasDiscriminant}}
func (s {{.Node.Name}}) Set{{.Field.Name|title}}() { {{template "_settag" .}} }
{{end}}

View File

@@ -1,10 +0,0 @@
func (s {{.Node.Name}}) {{.Field.Name|title}}() {{.ReturnType}} {
{{template "_checktag" . -}}
return {{.ReturnType}}(s.Struct.Uint{{.Bits}}({{.Offset}}){{with .Default}} ^ {{.}}{{end}})
}
func (s {{.Node.Name}}) Set{{.Field.Name|title}}(v {{.ReturnType}}) {
{{template "_settag" . -}}
s.Struct.SetUint{{.Bits}}({{.Offset}}, uint{{.Bits}}(v){{with .Default}}^{{.}}{{end}})
}

View File

@@ -1,18 +0,0 @@
func (s {{.Node.Name}}) {{.Field.Name|title}}() {{.FieldType}} {
{{template "_checktag" . -}}
p, _ := s.Struct.Ptr({{.Field.Slot.Offset}})
return {{.FieldType}}{Client: p.Interface().Client()}
}
{{template "_hasfield" .}}
func (s {{.Node.Name}}) Set{{.Field.Name|title}}(v {{.FieldType}}) error {
{{template "_settag" . -}}
if v.Client == nil {
return s.Struct.SetPtr({{.Field.Slot.Offset}}, capnp.Ptr{})
}
seg := s.Segment()
in := {{.G.Capnp}}.NewInterface(seg, seg.Message().AddCap(v.Client))
return s.Struct.SetPtr({{.Field.Slot.Offset}}, in.ToPtr())
}

View File

@@ -1,19 +0,0 @@
// {{.Node.Name}}_List is a list of {{.Node.Name}}.
type {{.Node.Name}}_List struct{ {{.G.Capnp}}.List }
// New{{.Node.Name}} creates a new list of {{.Node.Name}}.
func New{{.Node.Name}}_List(s *{{.G.Capnp}}.Segment, sz int32) ({{.Node.Name}}_List, error) {
l, err := {{.G.Capnp}}.NewCompositeList(s, {{.G.ObjectSize .Node}}, sz)
return {{.Node.Name}}_List{l}, err
}
func (s {{.Node.Name}}_List) At(i int) {{.Node.Name}} { return {{.Node.Name}}{ s.List.Struct(i) } }
func (s {{.Node.Name}}_List) Set(i int, v {{.Node.Name}}) error { return s.List.SetStruct(i, v.Struct) }
{{if .StringMethod}}
func (s {{.Node.Name}}_List) String() string {
str, _ := {{.G.Imports.Text}}.MarshalList({{.Node.Id|printf "%#x"}}, s.List)
return str
}
{{end}}

View File

@@ -1,33 +0,0 @@
func (s {{.Node.Name}}) {{.Field.Name|title}}() ({{.FieldType}}, error) {
{{template "_checktag" . -}}
p, err := s.Struct.Ptr({{.Field.Slot.Offset}})
{{if .Default.IsValid -}}
if err != nil {
return {{.FieldType}}{}, err
}
l, err := p.ListDefault({{.Default}})
return {{.FieldType}}{List: l}, err
{{- else -}}
return {{.FieldType}}{List: p.List()}, err
{{- end}}
}
{{template "_hasfield" .}}
func (s {{.Node.Name}}) Set{{.Field.Name|title}}(v {{.FieldType}}) error {
{{template "_settag" . -}}
return s.Struct.SetPtr({{.Field.Slot.Offset}}, v.List.ToPtr())
}
// New{{.Field.Name|title}} sets the {{.Field.Name}} field to a newly
// allocated {{.FieldType}}, preferring placement in s's segment.
func (s {{.Node.Name}}) New{{.Field.Name|title}}(n int32) ({{.FieldType}}, error) {
{{template "_settag" . -}}
l, err := {{.G.RemoteTypeNew .Field.Slot.Type .Node}}(s.Struct.Segment(), n)
if err != nil {
return {{.FieldType}}{}, err
}
err = s.Struct.SetPtr({{.Field.Slot.Offset}}, l.List.ToPtr())
return l, err
}

View File

@@ -1,37 +0,0 @@
func (s {{.Node.Name}}) {{.Field.Name|title}}() ({{.G.Capnp}}.Pointer, error) {
{{template "_checktag" . -}}
{{if .Default.IsValid -}}
p, err := s.Struct.Pointer({{.Field.Slot.Offset}})
if err != nil {
return nil, err
}
return {{.G.Capnp}}.PointerDefault(p, {{.Default}})
{{- else -}}
return s.Struct.Pointer({{.Field.Slot.Offset}})
{{- end}}
}
{{template "_hasfield" .}}
func (s {{.Node.Name}}) {{.Field.Name|title}}Ptr() ({{.G.Capnp}}.Ptr, error) {
{{if .Default.IsValid -}}
p, err := s.Struct.Ptr({{.Field.Slot.Offset}})
if err != nil {
return nil, err
}
return p.Default({{.Default}})
{{- else -}}
return s.Struct.Ptr({{.Field.Slot.Offset}})
{{- end}}
}
func (s {{.Node.Name}}) Set{{.Field.Name|title}}(v {{.G.Capnp}}.Pointer) error {
{{template "_settag" . -}}
return s.Struct.SetPointer({{.Field.Slot.Offset}}, v)
}
func (s {{.Node.Name}}) Set{{.Field.Name|title}}Ptr(v {{.G.Capnp}}.Ptr) error {
{{template "_settag" . -}}
return s.Struct.SetPtr({{.Field.Slot.Offset}}, v)
}

View File

@@ -1,33 +0,0 @@
func (s {{.Node.Name}}) {{.Field.Name|title}}() ({{.FieldType}}, error) {
{{template "_checktag" . -}}
p, err := s.Struct.Ptr({{.Field.Slot.Offset}})
{{if .Default.IsValid -}}
if err != nil {
return {{.FieldType}}{}, err
}
ss, err := p.StructDefault({{.Default}})
return {{.FieldType}}{Struct: ss}, err
{{- else -}}
return {{.FieldType}}{Struct: p.Struct()}, err
{{- end}}
}
{{template "_hasfield" .}}
func (s {{.Node.Name}}) Set{{.Field.Name|title}}(v {{.FieldType}}) error {
{{template "_settag" . -}}
return s.Struct.SetPtr({{.Field.Slot.Offset}}, v.Struct.ToPtr())
}
// New{{.Field.Name|title}} sets the {{.Field.Name}} field to a newly
// allocated {{.FieldType}} struct, preferring placement in s's segment.
func (s {{.Node.Name}}) New{{.Field.Name|title}}() ({{.FieldType}}, error) {
{{template "_settag" . -}}
ss, err := {{.G.RemoteNodeNew .TypeNode .Node}}(s.Struct.Segment())
if err != nil {
return {{.FieldType}}{}, err
}
err = s.Struct.SetPtr({{.Field.Slot.Offset}}, ss.Struct.ToPtr())
return ss, err
}

View File

@@ -1,30 +0,0 @@
func (s {{.Node.Name}}) {{.Field.Name|title}}() (string, error) {
{{template "_checktag" . -}}
p, err := s.Struct.Ptr({{.Field.Slot.Offset}})
{{with .Default -}}
return p.TextDefault({{printf "%q" .}}), err
{{- else -}}
return p.Text(), err
{{- end}}
}
{{template "_hasfield" .}}
func (s {{.Node.Name}}) {{.Field.Name|title}}Bytes() ([]byte, error) {
p, err := s.Struct.Ptr({{.Field.Slot.Offset}})
{{with .Default -}}
return p.TextBytesDefault({{printf "%q" .}}), err
{{- else -}}
return p.TextBytes(), err
{{- end}}
}
func (s {{.Node.Name}}) Set{{.Field.Name|title}}(v string) error {
{{template "_settag" . -}}
{{if .Default -}}
return s.Struct.SetNewText({{.Field.Slot.Offset}}, v)
{{- else -}}
return s.Struct.SetText({{.Field.Slot.Offset}}, v)
{{- end}}
}

View File

@@ -1,8 +0,0 @@
{{with .Annotations.Doc -}}
// {{.}}
{{end -}}
type {{.Node.Name}} {{if .IsBase -}}
struct{ {{.G.Capnp}}.Struct }
{{- else -}}
{{.BaseNode.Name}}
{{- end}}

View File

@@ -1,10 +0,0 @@
func (s {{.Node.Name}}) {{.Field.Name|title}}() uint{{.Bits}} {
{{template "_checktag" . -}}
return s.Struct.Uint{{.Bits}}({{.Offset}}){{with .Default}} ^ {{.}}{{end}}
}
func (s {{.Node.Name}}) Set{{.Field.Name|title}}(v uint{{.Bits}}) {
{{template "_settag" . -}}
s.Struct.SetUint{{.Bits}}({{.Offset}}, v{{with .Default}}^{{.}}{{end}})
}

View File

@@ -1,2 +0,0 @@
{{.G.RemoteNodeName .Typ .Node}}{Struct: {{.G.Capnp}}.MustUnmarshalRootPtr({{.Value}}).Struct()}
{{- /* no EOL */ -}}

View File

@@ -1,6 +0,0 @@
{{if .Field.HasDiscriminant -}}
func (s {{.Node.Name}}) Set{{.Field.Name|title}}() {
{{template "_settag" .}}
}
{{end -}}

View File

@@ -1,13 +0,0 @@
# Generate scopes.capnp.out with:
# capnp compile -o- scopes.capnp > scopes.capnp.out
# Must run inside this directory to preserve paths.
using Go = import "go.capnp";
@0xc260cb50ae622e10;
$Go.package("const");
$Go.import("zombiezen.com/go/capnproto2/capnpc-go/testdata/const");
const answer @0xda96e2255811b258 :Int64 = 42;
const blob @0xe0a385c7be1fea4d :Data = "\x01\x02\x03";

View File

@@ -1,15 +0,0 @@
# Generate go.capnp.out with:
# capnp compile -o- go.capnp > go.capnp.out
# Must run inside this directory to preserve paths.
@0xd12a1c51fedd6c88;
annotation package(file) :Text;
annotation import(file) :Text;
annotation doc(struct, field, enum) :Text;
annotation tag(enumerant) :Text;
annotation notag(enumerant) :Void;
annotation customtype(field) :Text;
annotation name(struct, field, union, enum, enumerant, interface, method, param, annotation, const, group) :Text;
$package("capnp");

View File

@@ -1,11 +0,0 @@
using Go = import "go.capnp";
@0x83c2b5818e83ab19;
$Go.package("template_fix");
$Go.import("zombiezen.com/go/capnproto2/capnpc-go/testdata/group");
struct SomeMisguidedStruct {
someGroup :group {
someGroupField @0 :UInt64;
}
}

View File

@@ -1,11 +0,0 @@
# File to be imported from scopes.capnp.
using Go = import "go.capnp";
@0x9c339b0568fe60ba;
$Go.package("otherscopes");
$Go.import("zombiezen.com/go/capnproto2/capnpc-go/testdata/otherscopes");
struct Foo @0xd127518fcfe6191d {
}

View File

@@ -1,20 +0,0 @@
# Generate scopes.capnp.out with:
# capnp compile -o- scopes.capnp > scopes.capnp.out
# Must run inside this directory to preserve paths.
using Go = import "go.capnp";
using Other = import "otherscopes.capnp";
@0xd68755941d99d05e;
$Go.package("scopes");
$Go.import("zombiezen.com/go/capnproto2/capnpc-go/testdata/scopes");
struct Foo @0xc8d7b3b4e07f8bd9 {
}
const fooVar @0x84efedc75e99768d :Foo = ();
const otherFooVar @0x836faf1834d91729 :Other.Foo = ();
const fooListVar @0xcda2680ec5c921e0 :List(Foo) = [];
const otherFooListVar @0x83e7e1b3cd1be338 :List(Other.Foo) = [];
const intList @0xacf3d9917d0bb0f0 :List(Int32) = [];

View File

@@ -1,173 +0,0 @@
# Sandstorm - Personal Cloud Sandbox
# Copyright (c) 2014 Sandstorm Development Group, Inc. and contributors
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Derived from sandstorm at 08fafe55995edfe188777eb00b5a2d1826032c59.
# Using Go annotations.
@0xecd50d792c3d9992;
using Go = import "go.capnp";
$Go.package("util");
$Go.import("zombiezen.com/go/capnproto2/capnpc-go/testdata/util");
using DateInNs = Int64;
using DurationInNs = UInt64;
struct KeyValue {
key @0 :Text;
value @1 :Text;
}
struct LocalizedText {
# Text intended to be displayed to a user. May be localized to multiple languages.
#
# TODO(soon): Maybe instead of packing all translations in here, we should have a message code
# and parameter substitutions, with the (message code, locale) -> text map stored elsewhere?
defaultText @0 :Text;
# What to display if no localization matching the user's preferences is available.
localizations @1 :List(Localization);
# Localized versions of the text.
struct Localization {
locale @0 :Text; # IETF BCP 47 locale, e.g. "en" or "en-US".
text @1 :Text; # Localized text.
}
}
interface Handle {
# Arbitrary handle to some resource provided by the platform. May or may not be persistent,
# depending on the use case.
#
# To "drop" a handle means to discard any references. The purpose of a handle is to detect when
# it has been dropped and to free the underlying resource and cancel any ongoing operation at
# that time.
#
# A handle can be persistent. Once you have called `save()` on it to obtain a SturdyRef, dropping
# the live reference will not cancel the operation. You must drop all live references *and*
# explicitly drop any SturdyRef. Every interface which supports restoring SturdyRefs also
# has a corresponding `drop()` method for this purpose.
#
# Unfortunately, there is no way to ensure that a SturdyRef will eventually be deleted. A grain
# could, for example, call `save()` and then simply fail to store the SturdyRef anywhere, causing
# it to be "leaked" until such a time as the grain itself is destroyed. Or worse, a whole server
# could be destroyed in a fire, leaking all SturdyRefs stored therein forever. Apps implementing
# persistent handles must be designed to account for this, probably by giving the owning user
# a way to inspect incoming references and remove them manually. Sandstorm automatically provides
# such an interface for all apps it hosts.
}
interface ByteStream {
# Represents a destination for a stream of bytes. The bytes are ordered, but boundaries between
# messages are not semantically important.
#
# Streams are push-oriented (traditionally, "output streams") rather than pull-oriented ("input
# streams") because this most easily allows multiple packets to be in-flight at once while
# allowing flow control at either end. If we tried to design a pull-oriented stream, it would
# suffer from problems:
# * If we used a naive read() method that returns a simple data blob, you would need to make
# multiple simultaneous calls to deal with network latency. However, those calls could
# potentially return in the wrong order. Although you could restore order by keeping track of
# the order in which the calls were made, this would be a lot of work, and most callers would
# probably fail to do it.
# * We could instead have a read() method that returns a blob as well as a capability to read the
# next blob. You would then make multiple calls using pipelining. Even in this case, though,
# an unpredictable event loop could schedule a pipelined call's return before the parent call.
# Moreover, the interface would be awkward to use and implement. E.g. what happens if you call
# read() twice on the same capability?
write @0 (data :Data);
# Add bytes.
#
# It's safe to make overlapping calls to `write()`, since Cap'n Proto enforces E-Order and so
# the calls will be delivered in order. However, it is a good idea to limit how much data is
# in-flight at a time, so that it doesn't fill up buffers and block other traffic. On the other
# hand, having only one `write()` in flight at a time will not fully utilize the available
# bandwidth if the connection has any significant latency, so parallelizing a few `write()`s is
# a good idea.
#
# Similarly, the implementation of `ByteStream` can delay returning from `write()` as a way to
# hint to the caller that it should hold off on further writes.
done @1 ();
# Call after the last write to indicate that there is no more data. If the `ByteStream` is
# discarded without a call to `done()`, the callee must assume that an error occurred and that
# the data is incomplete.
#
# This will not return until all bytes are successfully written to their final destination.
# It will throw an exception if any error occurs, including if the total number of bytes written
# did not match `expectSize()`.
expectSize @2 (size :UInt64);
# Optionally called to let the receiver know exactly how much data will be written. This should
# normally be called before the first write(), but if called later, `size` indicates how many
# more bytes to expect _after_ the call. It is an error by the caller if more or fewer bytes are
# actually written before `done()`; this also implies that all calls to `expectSize()` must be
# consistent. The caller will ignore any exceptions thrown from this method, therefore it
# is not necessary for the callee to actually implement it.
}
interface Blob @0xe53527a75d90198f {
# Represents a large byte blob.
getSize @0 () -> (size :UInt64);
# Get the total size of the blob. May block if the blob is still being uploaded and the size is
# not yet known.
writeTo @1 (stream :ByteStream, startAtOffset :UInt64 = 0) -> (handle :Handle);
# Write the contents of the blob to `stream`.
getSlice @2 (offset :UInt64, size :UInt32) -> (data :Data);
# Read a slice of the blob starting at the given offset. `size` cannot be greater than Cap'n
# Proto's limit of 2^29-1, and reasonable servers will likely impose far lower limits. If the
# slice would cross past the end of the blob, it is truncated. Otherwise, `data` is always
# exactly `size` bytes (though the caller should check for security purposes).
#
# One technique that makes a lot of sense is to start off by calling e.g. `getSlice(0, 65536)`.
# If the returned data is less than 65536 bytes then you know you got the whole blob, otherwise
# you may want to switch to `writeTo`.
}
interface Assignable(T) {
# An "assignable" -- a mutable memory cell. Supports subscribing to updates.
get @0 () -> (value :T, setter :Setter);
# The returned setter functions the same as you'd get from `asSetter()` except that it will
# become disconnected the next time the Assignable is set by someone else. Thus, you may use this
# to implement optimistic concurrency control.
asGetter @1 () -> (getter :Getter);
# Return a read-only capability for this assignable, co-hosted with the assignable itself for
# performance. If the assignable is persistent, the getter is as well.
asSetter @2 () -> (setter :Setter);
# Return a write-only capability for this assignable, co-hosted with the assignable itself for
# performance. If the assignable is persistent, the setter is as well.
interface Getter {
get @0 () -> (value :T);
subscribe @1 (setter :Setter) -> (handle :Handle);
# Subscribe to updates. Calls the given setter any time the assignable's value changes. Drop
# the returned handle to stop receiving updates. If `setter` is persistent, `handle` will also
# be persistent.
}
interface Setter {
set @0 (value :T) -> ();
}
}

View File

@@ -1,229 +0,0 @@
package text
import (
"bytes"
"io/ioutil"
"path/filepath"
"testing"
"zombiezen.com/go/capnproto2"
"zombiezen.com/go/capnproto2/internal/schema"
"zombiezen.com/go/capnproto2/schemas"
)
func readTestFile(name string) ([]byte, error) {
path := filepath.Join("testdata", name)
return ioutil.ReadFile(path)
}
func TestEncode(t *testing.T) {
tests := []struct {
constID uint64
text string
}{
{0xc0b634e19e5a9a4e, `(key = "42", value = (int32 = -123))`},
{0x967c8fe21790b0fb, `(key = "float", value = (float64 = 3.14))`},
{0xdf35cb2e1f5ea087, `(key = "bool", value = (bool = false))`},
{0xb167974479102805, `(map = [(key = "foo", value = (void = void)), (key = "bar", value = (void = void))])`},
{0x81fdbfdc91779421, `(map = [])`},
{0x8e85252144f61858, `(data = "Hi\xde\xad\xbe\xef\xca\xfe")`},
{0xc21398a8474837ba, `(voidList = [void, void])`},
{0xde82c2eeb3a4b07c, `(boolList = [true, false, true, false])`},
{0xf9e3ffc179272aa2, `(int8List = [1, -2, 3])`},
{0xfc421b96ec6ad2b6, `(int64List = [1, -2, 3])`},
{0xb3034b89d02775a5, `(uint8List = [255, 0, 1])`},
{0x9246c307e46ad03b, `(uint64List = [1, 2, 3])`},
{0xd012128a1a9cb7fc, `(float32List = [0.5, 3.14, -2])`},
{0xf16c386c66d492e2, `(textList = ["foo", "bar", "baz"])`},
{0xe14f4d42aa55de8c, `(dataList = ["\xde\xad\xbe\xef", "\xca\xfe"])`},
{0xe88c91698f7f0b73, `(cheese = gouda)`},
{0x9c51b843b337490b, `(cheeseList = [gouda, cheddar])`},
{0x81e2aadb8bfb237b, `(matrix = [[1, 2, 3], [4, 5, 6]])`},
}
data, err := readTestFile("txt.capnp.out")
if err != nil {
t.Fatal(err)
}
reg := new(schemas.Registry)
err = reg.Register(&schemas.Schema{
Bytes: data,
Nodes: []uint64{
0x8df8bc5abdc060a6,
0xd3602730c572a43b,
},
})
if err != nil {
t.Fatalf("Adding to registry: %v", err)
}
msg, err := capnp.Unmarshal(data)
if err != nil {
t.Fatal("Unmarshaling txt.capnp.out:", err)
}
req, err := schema.ReadRootCodeGeneratorRequest(msg)
if err != nil {
t.Fatal("Reading code generator request txt.capnp.out:", err)
}
nodes, err := req.Nodes()
if err != nil {
t.Fatal(err)
}
nodeMap := make(map[uint64]schema.Node, nodes.Len())
for i := 0; i < nodes.Len(); i++ {
n := nodes.At(i)
nodeMap[n.Id()] = n
}
for _, test := range tests {
c := nodeMap[test.constID]
if !c.IsValid() {
t.Errorf("Can't find node %#x; skipping", test.constID)
continue
}
dn, _ := c.DisplayName()
if c.Which() != schema.Node_Which_const {
t.Errorf("%s @%#x is a %v, not const; skipping", dn, test.constID, c.Which())
continue
}
typ, err := c.Const().Type()
if err != nil {
t.Errorf("(%s @%#x).const.type: %v", dn, test.constID, err)
continue
}
if typ.Which() != schema.Type_Which_structType {
t.Errorf("(%s @%#x).const.type is a %v; want struct", dn, test.constID, typ.Which())
continue
}
tid := typ.StructType().TypeId()
v, err := c.Const().Value()
if err != nil {
t.Errorf("(%s @%#x).const.value: %v", dn, test.constID, err)
continue
}
if v.Which() != schema.Value_Which_structValue {
t.Errorf("(%s @%#x).const.value is a %v; want struct", dn, test.constID, v.Which())
continue
}
sv, err := v.StructValuePtr()
if err != nil {
t.Errorf("(%s @%#x).const.value.struct: %v", dn, test.constID, err)
continue
}
buf := new(bytes.Buffer)
enc := NewEncoder(buf)
enc.UseRegistry(reg)
if err := enc.Encode(tid, sv.Struct()); err != nil {
t.Errorf("Encode(%#x, (%s @%#x).const.value.struct): %v", tid, dn, test.constID, err)
continue
}
if text := buf.String(); text != test.text {
t.Errorf("Encode(%#x, (%s @%#x).const.value.struct) = %q; want %q", tid, dn, test.constID, text, test.text)
continue
}
}
}
func TestEncodeList(t *testing.T) {
tests := []struct {
constID uint64
text string
}{
{0x90c9e81e6418df8e, `[(key = "foo", value = (void = void)), (key = "bar", value = (void = void))]`},
}
data, err := readTestFile("txt.capnp.out")
if err != nil {
t.Fatal(err)
}
reg := new(schemas.Registry)
err = reg.Register(&schemas.Schema{
Bytes: data,
Nodes: []uint64{
0x8df8bc5abdc060a6,
0xd3602730c572a43b,
},
})
if err != nil {
t.Fatalf("Adding to registry: %v", err)
}
msg, err := capnp.Unmarshal(data)
if err != nil {
t.Fatal("Unmarshaling txt.capnp.out:", err)
}
req, err := schema.ReadRootCodeGeneratorRequest(msg)
if err != nil {
t.Fatal("Reading code generator request txt.capnp.out:", err)
}
nodes, err := req.Nodes()
if err != nil {
t.Fatal(err)
}
nodeMap := make(map[uint64]schema.Node, nodes.Len())
for i := 0; i < nodes.Len(); i++ {
n := nodes.At(i)
nodeMap[n.Id()] = n
}
for _, test := range tests {
c := nodeMap[test.constID]
if !c.IsValid() {
t.Errorf("Can't find node %#x; skipping", test.constID)
continue
}
dn, _ := c.DisplayName()
if c.Which() != schema.Node_Which_const {
t.Errorf("%s @%#x is a %v, not const; skipping", dn, test.constID, c.Which())
continue
}
typ, err := c.Const().Type()
if err != nil {
t.Errorf("(%s @%#x).const.type: %v", dn, test.constID, err)
continue
}
if typ.Which() != schema.Type_Which_list {
t.Errorf("(%s @%#x).const.type is a %v; want list", dn, test.constID, typ.Which())
continue
}
etyp, err := typ.List().ElementType()
if err != nil {
t.Errorf("(%s @%#x).const.type.list.element_type: %v", dn, test.constID, err)
continue
}
if etyp.Which() != schema.Type_Which_structType {
t.Errorf("(%s @%#x).const.type is a %v; want struct", dn, test.constID, etyp.Which())
continue
}
tid := etyp.StructType().TypeId()
v, err := c.Const().Value()
if err != nil {
t.Errorf("(%s @%#x).const.value: %v", dn, test.constID, err)
continue
}
if v.Which() != schema.Value_Which_list {
t.Errorf("(%s @%#x).const.value is a %v; want list", dn, test.constID, v.Which())
continue
}
lv, err := v.ListPtr()
if err != nil {
t.Errorf("(%s @%#x).const.value.list: %v", dn, test.constID, err)
continue
}
buf := new(bytes.Buffer)
enc := NewEncoder(buf)
enc.UseRegistry(reg)
if err := enc.EncodeList(tid, lv.List()); err != nil {
t.Errorf("Encode(%#x, (%s @%#x).const.value.list): %v", tid, dn, test.constID, err)
continue
}
if text := buf.String(); text != test.text {
t.Errorf("Encode(%#x, (%s @%#x).const.value.list) = %q; want %q", tid, dn, test.constID, text, test.text)
continue
}
}
}

View File

@@ -1,76 +0,0 @@
@0x8ae03d633330d781;
struct KeyValue @0x8df8bc5abdc060a6 {
key @0 :Text;
value @1 :Value;
}
struct Value @0xd3602730c572a43b {
union {
void @0 :Void;
bool @1 :Bool;
int8 @2 :Int8;
int16 @3 :Int16;
int32 @4 :Int32;
int64 @5 :Int64;
uint8 @6 :UInt8;
uint16 @7 :UInt16;
uint32 @8 :UInt32;
uint64 @9 :UInt64;
float32 @10 :Float32;
float64 @11 :Float64;
text @12 :Text;
data @13 :Data;
cheese @29 :Cheese;
map @14 :List(KeyValue);
voidList @15 :List(Void);
boolList @16 :List(Bool);
int8List @17 :List(Int8);
int16List @18 :List(Int16);
int32List @19 :List(Int32);
int64List @20 :List(Int64);
uint8List @21 :List(UInt8);
uint16List @22 :List(UInt16);
uint32List @23 :List(UInt32);
uint64List @24 :List(UInt64);
float32List @25 :List(Float32);
float64List @26 :List(Float64);
textList @27 :List(Text);
dataList @28 :List(Data);
cheeseList @30 :List(Cheese);
matrix @31 :List(List(Int32));
}
}
enum Cheese {
cheddar @0;
gouda @1;
}
const kv @0xc0b634e19e5a9a4e :KeyValue = (key = "42", value = (int32 = -123));
const floatKv @0x967c8fe21790b0fb :KeyValue = (key = "float", value = (float64 = 3.14));
const boolKv @0xdf35cb2e1f5ea087 :KeyValue = (key = "bool", value = (bool = false));
const mapVal @0xb167974479102805 :Value = (map = [
(key = "foo", value = (void = void)),
(key = "bar", value = (void = void)),
]);
const data @0x8e85252144f61858 :Value = (data = 0x"4869 dead beef cafe");
const emptyMap @0x81fdbfdc91779421 :Value = (map = []);
const voidList @0xc21398a8474837ba :Value = (voidList = [void, void]);
const boolList @0xde82c2eeb3a4b07c :Value = (boolList = [true, false, true, false]);
const int8List @0xf9e3ffc179272aa2 :Value = (int8List = [1, -2, 3]);
const int64List @0xfc421b96ec6ad2b6 :Value = (int64List = [1, -2, 3]);
const uint8List @0xb3034b89d02775a5 :Value = (uint8List = [255, 0, 1]);
const uint64List @0x9246c307e46ad03b :Value = (uint64List = [1, 2, 3]);
const floatList @0xd012128a1a9cb7fc :Value = (float32List = [0.5, 3.14, -2.0]);
const textList @0xf16c386c66d492e2 :Value = (textList = ["foo", "bar", "baz"]);
const dataList @0xe14f4d42aa55de8c :Value = (dataList = [0x"deadbeef", 0x"cafe"]);
const cheese @0xe88c91698f7f0b73 :Value = (cheese = gouda);
const cheeseList @0x9c51b843b337490b :Value = (cheeseList = [gouda, cheddar]);
const matrix @0x81e2aadb8bfb237b :Value = (matrix = [[1, 2, 3], [4, 5, 6]]);
const kvList @0x90c9e81e6418df8e :List(KeyValue) = [
(key = "foo", value = (void = void)),
(key = "bar", value = (void = void)),
];

View File

@@ -1,121 +0,0 @@
package capnp_test
import (
"fmt"
"io/ioutil"
"os"
"zombiezen.com/go/capnproto2"
air "zombiezen.com/go/capnproto2/internal/aircraftlib"
)
func Example() {
// Make a brand new empty message.
msg, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
// If you want runtime-type identification, this is easily obtained. Just
// wrap everything in a struct that contains a single anoymous union (e.g. struct Z).
// Then always set a Z as the root object in you message/first segment.
// The cost of the extra word of storage is usually worth it, as
// then human readable output is easily obtained via a shell command such as
//
// $ cat binary.cpz | capnp decode aircraft.capnp Z
//
// If you need to conserve space, and know your content in advance, it
// isn't necessary to use an anonymous union. Just supply the type name
// in place of 'Z' in the decode command above.
// There can only be one root. Subsequent NewRoot* calls will set the root
// pointer and orphan the previous root.
z, err := air.NewRootZ(seg)
if err != nil {
panic(err)
}
// then non-root objects:
aircraft, err := z.NewAircraft()
if err != nil {
panic(err)
}
b737, err := aircraft.NewB737()
if err != nil {
panic(err)
}
planebase, err := b737.NewBase()
if err != nil {
panic(err)
}
// Set primitive fields
planebase.SetCanFly(true)
planebase.SetName("Henrietta")
planebase.SetRating(100)
planebase.SetMaxSpeed(876) // km/hr
// if we don't set capacity, it will get the default value, in this case 0.
//planebase.SetCapacity(26020) // Liters fuel
// Creating a list
homes, err := planebase.NewHomes(2)
if err != nil {
panic(err)
}
homes.Set(0, air.Airport_jfk)
homes.Set(1, air.Airport_lax)
// Ready to write!
// You can write to memory...
buf, err := msg.Marshal()
if err != nil {
panic(err)
}
_ = buf
// ... or write to an io.Writer.
file, err := ioutil.TempFile("", "go-capnproto")
if err != nil {
panic(err)
}
defer file.Close()
defer os.Remove(file.Name())
err = capnp.NewEncoder(file).Encode(msg)
if err != nil {
panic(err)
}
}
func ExampleUnmarshal() {
msg, s, err := capnp.NewMessage(capnp.SingleSegment(nil))
if err != nil {
fmt.Printf("allocation error %v\n", err)
return
}
d, err := air.NewRootZdate(s)
if err != nil {
fmt.Printf("root error %v\n", err)
return
}
d.SetYear(2004)
d.SetMonth(12)
d.SetDay(7)
data, err := msg.Marshal()
if err != nil {
fmt.Printf("marshal error %v\n", err)
return
}
// Read
msg, err = capnp.Unmarshal(data)
if err != nil {
fmt.Printf("unmarshal error %v\n", err)
return
}
d, err = air.ReadRootZdate(msg)
if err != nil {
fmt.Printf("read root error %v\n", err)
return
}
fmt.Printf("year %d, month %d, day %d\n", d.Year(), d.Month(), d.Day())
// Output:
// year 2004, month 12, day 7
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,110 +0,0 @@
package capnp_test
import (
"bytes"
"encoding/hex"
"fmt"
"path/filepath"
"runtime"
"testing"
"zombiezen.com/go/capnproto2"
air "zombiezen.com/go/capnproto2/internal/aircraftlib"
"zombiezen.com/go/capnproto2/internal/capnptool"
)
const schemaPath = "internal/aircraftlib/aircraft.capnp"
func initNester(t *testing.T, n air.Nester1Capn, strs ...string) {
tl, err := n.NewStrs(int32(len(strs)))
if err != nil {
t.Fatalf("initNester(..., %q): NewStrs: %v", strs, err)
}
for i, s := range strs {
if err := tl.Set(i, s); err != nil {
t.Fatalf("initNester(..., %q): set strs[%d]: %v", strs, i, err)
}
}
}
func zdateFilledMessage(t testing.TB, n int32) *capnp.Message {
msg, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
if err != nil {
t.Fatal(err)
}
z, err := air.NewRootZ(seg)
if err != nil {
t.Fatal(err)
}
list, err := z.NewZdatevec(n)
if err != nil {
t.Fatal(err)
}
for i := 0; i < int(n); i++ {
d, err := air.NewZdate(seg)
if err != nil {
t.Fatal(err)
}
d.SetMonth(12)
d.SetDay(7)
d.SetYear(int16(2004 + i))
list.Set(i, d)
}
return msg
}
func zdataFilledMessage(t testing.TB, n int) *capnp.Message {
msg, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
if err != nil {
t.Fatal(err)
}
z, err := air.NewRootZ(seg)
if err != nil {
t.Fatal(err)
}
d, err := air.NewZdata(seg)
if err != nil {
t.Fatal(err)
}
b := make([]byte, n)
for i := 0; i < len(b); i++ {
b[i] = byte(i)
}
d.SetData(b)
z.SetZdata(d)
return msg
}
// encodeTestMessage encodes the textual Cap'n Proto message to unpacked
// binary using the capnp tool, or returns the fallback if the tool fails.
func encodeTestMessage(typ string, text string, fallback []byte) ([]byte, error) {
tool, err := capnptool.Find()
if err != nil {
// TODO(light): log tool missing
return fallback, nil
}
b, err := tool.Encode(capnptool.Type{SchemaPath: schemaPath, Name: typ}, text)
if err != nil {
return nil, fmt.Errorf("%s value %q encode failed: %v", typ, text, err)
}
if !bytes.Equal(b, fallback) {
return nil, fmt.Errorf("%s value %q =\n%s; fallback is\n%s\nFallback out of date?", typ, text, hex.Dump(b), hex.Dump(fallback))
}
return b, nil
}
// mustEncodeTestMessage encodes the textual Cap'n Proto message to unpacked
// binary using the capnp tool, or returns the fallback if the tool fails.
func mustEncodeTestMessage(t testing.TB, typ string, text string, fallback []byte) []byte {
b, err := encodeTestMessage(typ, text, fallback)
if err != nil {
if _, fname, line, ok := runtime.Caller(1); ok {
t.Fatalf("%s:%d: %v", filepath.Base(fname), line, err)
} else {
t.Fatal(err)
}
}
return b
}

View File

@@ -1,24 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"aircraft.capnp.go",
"generate.go",
],
importpath = "zombiezen.com/go/capnproto2/internal/aircraftlib",
visibility = ["//:__subpackages__"],
deps = [
"//:go_default_library",
"//encoding/text:go_default_library",
"//schemas:go_default_library",
"//server:go_default_library",
"@org_golang_x_net//context:go_default_library",
],
)
filegroup(
name = "schema",
srcs = ["aircraft.capnp"],
visibility = ["//:__subpackages__"],
)

View File

@@ -1,353 +0,0 @@
using Go = import "/go.capnp";
$Go.package("aircraftlib");
$Go.import("zombiezen.com/go/capnproto2/internal/aircraftlib");
@0x832bcc6686a26d56;
const constDate :Zdate = (year = 2015, month = 8, day = 27);
const constList :List(Zdate) = [(year = 2015, month = 8, day = 27), (year = 2015, month = 8, day = 28)];
const constEnum :Airport = jfk;
struct Zdate {
year @0 :Int16;
month @1 :UInt8;
day @2 :UInt8;
}
struct Zdata {
data @0 :Data;
}
enum Airport {
none @0;
jfk @1;
lax @2;
sfo @3;
luv @4;
dfw @5;
test @6;
# test must be last because we use it to count
# the number of elements in the Airport enum.
}
struct PlaneBase {
name @0: Text;
homes @1: List(Airport);
rating @2: Int64;
canFly @3: Bool;
capacity @4: Int64;
maxSpeed @5: Float64;
}
struct B737 {
base @0: PlaneBase;
}
struct A320 {
base @0: PlaneBase;
}
struct F16 {
base @0: PlaneBase;
}
# need a struct with at least two pointers to catch certain bugs
struct Regression {
base @0: PlaneBase;
b0 @1: Float64; # intercept
beta @2: List(Float64);
planes @3: List(Aircraft);
ymu @4: Float64; # y-mean in original space
ysd @5: Float64; # y-standard deviation in original space
}
struct Aircraft {
# so we can restrict
# and specify a Plane is required in
# certain places.
union {
void @0: Void; # @0 will be the default, so always make @0 a Void.
b737 @1: B737;
a320 @2: A320;
f16 @3: F16;
}
}
struct Z {
# Z must contain all types, as this is our
# runtime type identification. It is a thin shim.
union {
void @0: Void; # always first in any union.
zz @1: Z; # any. fyi, this can't be 'z' alone.
f64 @2: Float64;
f32 @3: Float32;
i64 @4: Int64;
i32 @5: Int32;
i16 @6: Int16;
i8 @7: Int8;
u64 @8: UInt64;
u32 @9: UInt32;
u16 @10: UInt16;
u8 @11: UInt8;
bool @12: Bool;
text @13: Text;
blob @14: Data;
f64vec @15: List(Float64);
f32vec @16: List(Float32);
i64vec @17: List(Int64);
i32vec @18: List(Int32);
i16vec @19: List(Int16);
i8vec @20: List(Int8);
u64vec @21: List(UInt64);
u32vec @22: List(UInt32);
u16vec @23: List(UInt16);
u8vec @24: List(UInt8);
boolvec @39: List(Bool);
datavec @40: List(Data);
textvec @41: List(Text);
zvec @25: List(Z);
zvecvec @26: List(List(Z));
zdate @27: Zdate;
zdata @28: Zdata;
aircraftvec @29: List(Aircraft);
aircraft @30: Aircraft;
regression @31: Regression;
planebase @32: PlaneBase;
airport @33: Airport;
b737 @34: B737;
a320 @35: A320;
f16 @36: F16;
zdatevec @37: List(Zdate);
zdatavec @38: List(Zdata);
grp :group {
first @42 :UInt64;
second @43 :UInt64;
}
echo @44 :Echo;
echoBases @45 :EchoBases;
}
}
# tests for Text/List(Text) recusion handling
struct Counter {
size @0: Int64;
words @1: Text;
wordlist @2: List(Text);
bitlist @3: List(Bool);
}
struct Bag {
counter @0: Counter;
}
struct Zserver {
waitingjobs @0: List(Zjob);
}
struct Zjob {
cmd @0: Text;
args @1: List(Text);
}
# versioning test structs
struct VerEmpty {
}
struct VerOneData {
val @0: Int16;
}
struct VerTwoData {
val @0: Int16;
duo @1: Int64;
}
struct VerOnePtr {
ptr @0: VerOneData;
}
struct VerTwoPtr {
ptr1 @0: VerOneData;
ptr2 @1: VerOneData;
}
struct VerTwoDataTwoPtr {
val @0: Int16;
duo @1: Int64;
ptr1 @2: VerOneData;
ptr2 @3: VerOneData;
}
struct HoldsVerEmptyList {
mylist @0: List(VerEmpty);
}
struct HoldsVerOneDataList {
mylist @0: List(VerOneData);
}
struct HoldsVerTwoDataList {
mylist @0: List(VerTwoData);
}
struct HoldsVerOnePtrList {
mylist @0: List(VerOnePtr);
}
struct HoldsVerTwoPtrList {
mylist @0: List(VerTwoPtr);
}
struct HoldsVerTwoTwoList {
mylist @0: List(VerTwoDataTwoPtr);
}
struct HoldsVerTwoTwoPlus {
mylist @0: List(VerTwoTwoPlus);
}
struct VerTwoTwoPlus {
val @0: Int16;
duo @1: Int64;
ptr1 @2: VerTwoDataTwoPtr;
ptr2 @3: VerTwoDataTwoPtr;
tre @4: Int64;
lst3 @5: List(Int64);
}
# text handling
struct HoldsText {
txt @0: Text;
lst @1: List(Text);
lstlst @2: List(List(Text));
}
# test that we avoid unnecessary truncation
struct WrapEmpty {
mightNotBeReallyEmpty @0: VerEmpty;
}
struct Wrap2x2 {
mightNotBeReallyEmpty @0: VerTwoDataTwoPtr;
}
struct Wrap2x2plus {
mightNotBeReallyEmpty @0: VerTwoTwoPlus;
}
# test voids in a union
struct VoidUnion {
union {
a @0 :Void;
b @1 :Void;
}
}
# test List(List(Struct(List)))
struct Nester1Capn {
strs @0: List(Text);
}
struct RWTestCapn {
nestMatrix @0: List(List(Nester1Capn));
}
struct ListStructCapn {
vec @0: List(Nester1Capn);
}
# test interfaces
interface Echo {
echo @0 (in :Text) -> (out :Text);
}
struct Hoth {
base @0 :EchoBase;
}
struct EchoBase {
echo @0 :Echo;
}
# test List(Struct(Interface))
struct EchoBases {
bases @0 :List(EchoBase);
}
# test transforms
struct StackingRoot {
a @1 :StackingA;
aWithDefault @0 :StackingA = (num = 42);
}
struct StackingA {
num @0 :Int32;
b @1 :StackingB;
}
struct StackingB {
num @0 :Int32;
}
interface CallSequence {
getNumber @0 () -> (n :UInt32);
}
# test defaults
struct Defaults {
text @0 :Text = "foo";
data @1 :Data = "bar";
float @2 :Float32 = 3.14;
int @3 :Int32 = -123;
uint @4 :UInt32 = 42;
}
# benchmarks
struct BenchmarkA {
name @0 :Text;
birthDay @1 :Int64;
phone @2 :Text;
siblings @3 :Int32;
spouse @4 :Bool;
money @5 :Float64;
}
struct AllocBenchmark {
fields @0 :List(Field);
struct Field {
stringValue @0 :Text;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +0,0 @@
package aircraftlib
//go:generate capnp compile -I ../../std -ogo aircraft.capnp

View File

@@ -1,8 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["capnptool.go"],
importpath = "zombiezen.com/go/capnproto2/internal/capnptool",
visibility = ["//:__subpackages__"],
)

View File

@@ -1,76 +0,0 @@
// Package capnptool provides an API for calling the capnp tool in tests.
package capnptool
import (
"bytes"
"fmt"
"io"
"os/exec"
"strings"
"sync"
)
// Tool is the path to the capnp command-line tool.
// It can be used from multiple goroutines.
type Tool string
var cache struct {
init sync.Once
tool Tool
err error
}
// Find searches PATH for the capnp tool.
func Find() (Tool, error) {
cache.init.Do(func() {
path, err := exec.LookPath("capnp")
if err != nil {
cache.err = err
return
}
cache.tool = Tool(path)
})
return cache.tool, cache.err
}
// Run executes the tool with the given stdin and arguments returns the stdout.
func (tool Tool) Run(stdin io.Reader, args ...string) ([]byte, error) {
c := exec.Command(string(tool), args...)
c.Stdin = stdin
stderr := new(bytes.Buffer)
c.Stderr = stderr
out, err := c.Output()
if err != nil {
return nil, fmt.Errorf("run `%s`: %v; stderr:\n%s", strings.Join(c.Args, " "), err, stderr)
}
return out, nil
}
// Encode encodes Cap'n Proto text into the binary representation.
func (tool Tool) Encode(typ Type, text string) ([]byte, error) {
return tool.Run(strings.NewReader(text), "encode", typ.SchemaPath, typ.Name)
}
// Decode decodes a Cap'n Proto message into text.
func (tool Tool) Decode(typ Type, r io.Reader) (string, error) {
out, err := tool.Run(r, "decode", "--short", typ.SchemaPath, typ.Name)
if err != nil {
return "", err
}
return string(out), nil
}
// DecodePacked decodes a packed Cap'n Proto message into text.
func (tool Tool) DecodePacked(typ Type, r io.Reader) (string, error) {
out, err := tool.Run(r, "decode", "--short", "--packed", typ.SchemaPath, typ.Name)
if err != nil {
return "", err
}
return string(out), nil
}
// Type is a reference to a Cap'n Proto type in a schema.
type Type struct {
SchemaPath string
Name string
}

View File

@@ -1,193 +0,0 @@
// +build mktemplates
// Build tag so that users who run `go get zombiezen.com/go/capnproto2/...` don't install this command.
// cd internal/cmd/mktemplates && go build -tags=mktemplates
// mktemplates is a command to regenerate capnpc-go/templates.go.
package main
import (
"bytes"
"fmt"
"go/format"
"io"
"io/ioutil"
"os"
"path/filepath"
"sort"
"strings"
"text/template/parse"
)
func main() {
if len(os.Args) != 3 {
fmt.Fprintln(os.Stderr, "usage: mktemplates OUT DIR")
os.Exit(64)
}
dir := os.Args[2]
names, err := listdir(dir)
if err != nil {
fatalln(err)
}
ts := make([]template, len(names))
for i, name := range names {
src, err := ioutil.ReadFile(filepath.Join(dir, name))
if err != nil {
fatalf("reading template %s: %v", name, err)
}
compiled, err := compileTemplate(name, string(src))
if err != nil {
fatalf("compiling template %s: %v", name, err)
}
ts[i] = template{
name: name,
content: compiled,
}
}
genbuf := new(bytes.Buffer)
err = generateGo(genbuf, os.Args, ts)
if err != nil {
fatalln("generating code:", err)
}
code, err := format.Source(genbuf.Bytes())
if err != nil {
fatalln("formatting code:", err)
}
outname := os.Args[1]
out, err := os.Create(outname)
if err != nil {
fatalf("opening destination %s: %v", outname, err)
}
_, err = out.Write(code)
cerr := out.Close()
if err != nil {
fatalf("write to %s: %v", outname, err)
}
if cerr != nil {
fatalln(err)
}
}
func compileTemplate(name, src string) (string, error) {
tset, err := parse.Parse(name, src, "{{", "}}", funcStubs)
if err != nil {
return "", err
}
return tset[name].Root.String(), nil
}
func generateGo(w io.Writer, args []string, ts []template) error {
src := new(bytes.Buffer)
for _, t := range ts {
fmt.Fprintf(src, "{{define %q}}", t.name)
src.WriteString(t.content)
src.WriteString("{{end}}")
}
// TODO(light): collect errors
fmt.Fprintln(w, "// Code generated from templates directory. DO NOT EDIT.")
fmt.Fprintln(w)
fmt.Fprintln(w, "//go:generate", strings.Join(args, " "))
fmt.Fprintln(w)
fmt.Fprintln(w, "package main")
fmt.Fprintln(w, "import (")
fmt.Fprintln(w, "\t\"strings\"")
fmt.Fprintln(w, "\t\"text/template\"")
fmt.Fprintln(w, ")")
fmt.Fprintln(w, "var templates = template.Must(template.New(\"\").Funcs(template.FuncMap{")
fmt.Fprintln(w, "\t\"title\": strings.Title,")
fmt.Fprintf(w, "}).Parse(\n\t%q))\n", src.Bytes())
for _, t := range ts {
if strings.HasPrefix(t.name, "_") {
continue
}
fmt.Fprintf(w, "func render%s(r renderer, p %sParams) error {\n\treturn r.Render(%[2]q, p)\n}\n", strings.Title(t.name), t.name)
}
return nil
}
type template struct {
name string
content string
}
func listdir(name string) ([]string, error) {
f, err := os.Open(name)
if err != nil {
return nil, err
}
defer f.Close()
names, err := f.Readdirnames(-1)
if err != nil {
return nil, err
}
n := 0
for _, name := range names {
if !strings.HasPrefix(name, ".") {
names[n] = name
n++
}
}
names = names[:n]
sort.Strings(names)
return names, nil
}
func fatalln(args ...interface{}) {
var buf bytes.Buffer
buf.WriteString("mktemplates: ")
fmt.Fprintln(&buf, args...)
os.Stderr.Write(buf.Bytes())
os.Exit(1)
}
func fatalf(format string, args ...interface{}) {
var buf bytes.Buffer
buf.WriteString("mktemplates: ")
fmt.Fprintf(&buf, format, args...)
if !bytes.HasSuffix(buf.Bytes(), []byte{'\n'}) {
buf.Write([]byte{'\n'})
}
os.Stderr.Write(buf.Bytes())
os.Exit(1)
}
var funcStubs = map[string]interface{}{
// Built-ins
"and": variadicBoolStub,
"call": func(interface{}, ...interface{}) (interface{}, error) { return nil, nil },
"eq": func(arg0 interface{}, args ...interface{}) (bool, error) { return false, nil },
"ge": cmpStub,
"gt": cmpStub,
"html": escaperStub,
"index": func(interface{}, ...interface{}) (interface{}, error) { return nil, nil },
"js": escaperStub,
"le": cmpStub,
"len": func(interface{}) (int, error) { return 0, nil },
"lt": cmpStub,
"ne": cmpStub,
"not": func(interface{}) bool { return false },
"or": variadicBoolStub,
"print": fmt.Sprint,
"printf": fmt.Sprintf,
"println": fmt.Sprintln,
"urlquery": escaperStub,
// App-specific
"title": strings.Title,
}
func variadicBoolStub(arg0 interface{}, args ...interface{}) interface{} {
return arg0
}
func cmpStub(interface{}, interface{}) (bool, error) {
return false, nil
}
func escaperStub(...interface{}) string {
return ""
}
func importStub() string {
return ""
}

View File

@@ -1,24 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["doc.go"],
importpath = "zombiezen.com/go/capnproto2/internal/demo",
visibility = ["//:__subpackages__"],
)
go_test(
name = "go_default_test",
srcs = [
"book_test.go",
"hash_test.go",
],
embed = [":go_default_library"],
deps = [
"//:go_default_library",
"//internal/demo/books:go_default_library",
"//internal/demo/hashes:go_default_library",
"//rpc:go_default_library",
"@org_golang_x_net//context:go_default_library",
],
)

View File

@@ -1,61 +0,0 @@
package demo_test
import (
"fmt"
"io"
"zombiezen.com/go/capnproto2"
"zombiezen.com/go/capnproto2/internal/demo/books"
)
func Example_book() {
r, w := io.Pipe()
go writer(w)
reader(r)
// Output:
// "War and Peace" has 1440 pages
}
func writer(out io.Writer) {
// Make a brand new empty message. A Message allocates Cap'n Proto structs.
msg, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
if err != nil {
panic(err)
}
// Create a new Book struct. Every message must have a root struct.
book, err := books.NewRootBook(seg)
if err != nil {
panic(err)
}
book.SetTitle("War and Peace")
book.SetPageCount(1440)
// Write the message to stdout.
err = capnp.NewEncoder(out).Encode(msg)
if err != nil {
panic(err)
}
}
func reader(in io.Reader) {
// Read the message from stdin.
msg, err := capnp.NewDecoder(in).Decode()
if err != nil {
panic(err)
}
// Extract the root struct from the message.
book, err := books.ReadRootBook(msg)
if err != nil {
panic(err)
}
// Access fields from the struct.
title, err := book.Title()
if err != nil {
panic(err)
}
pageCount := book.PageCount()
fmt.Printf("%q has %d pages\n", title, pageCount)
}

View File

@@ -1,16 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"books.capnp.go",
"gen.go",
],
importpath = "zombiezen.com/go/capnproto2/internal/demo/books",
visibility = ["//:__subpackages__"],
deps = [
"//:go_default_library",
"//encoding/text:go_default_library",
"//schemas:go_default_library",
],
)

View File

@@ -1,12 +0,0 @@
using Go = import "/go.capnp";
@0x85d3acc39d94e0f8;
$Go.package("books");
$Go.import("zombiezen.com/go/capnproto2/internal/demo/books");
struct Book {
title @0 :Text;
# Title of the book.
pageCount @1 :Int32;
# Number of pages in the book.
}

View File

@@ -1,104 +0,0 @@
// Code generated by capnpc-go. DO NOT EDIT.
package books
import (
capnp "zombiezen.com/go/capnproto2"
text "zombiezen.com/go/capnproto2/encoding/text"
schemas "zombiezen.com/go/capnproto2/schemas"
)
type Book struct{ capnp.Struct }
// Book_TypeID is the unique identifier for the type Book.
const Book_TypeID = 0x8100cc88d7d4d47c
func NewBook(s *capnp.Segment) (Book, error) {
st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1})
return Book{st}, err
}
func NewRootBook(s *capnp.Segment) (Book, error) {
st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1})
return Book{st}, err
}
func ReadRootBook(msg *capnp.Message) (Book, error) {
root, err := msg.RootPtr()
return Book{root.Struct()}, err
}
func (s Book) String() string {
str, _ := text.Marshal(0x8100cc88d7d4d47c, s.Struct)
return str
}
func (s Book) Title() (string, error) {
p, err := s.Struct.Ptr(0)
return p.Text(), err
}
func (s Book) HasTitle() bool {
p, err := s.Struct.Ptr(0)
return p.IsValid() || err != nil
}
func (s Book) TitleBytes() ([]byte, error) {
p, err := s.Struct.Ptr(0)
return p.TextBytes(), err
}
func (s Book) SetTitle(v string) error {
return s.Struct.SetText(0, v)
}
func (s Book) PageCount() int32 {
return int32(s.Struct.Uint32(0))
}
func (s Book) SetPageCount(v int32) {
s.Struct.SetUint32(0, uint32(v))
}
// Book_List is a list of Book.
type Book_List struct{ capnp.List }
// NewBook creates a new list of Book.
func NewBook_List(s *capnp.Segment, sz int32) (Book_List, error) {
l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}, sz)
return Book_List{l}, err
}
func (s Book_List) At(i int) Book { return Book{s.List.Struct(i)} }
func (s Book_List) Set(i int, v Book) error { return s.List.SetStruct(i, v.Struct) }
func (s Book_List) String() string {
str, _ := text.MarshalList(0x8100cc88d7d4d47c, s.List)
return str
}
// Book_Promise is a wrapper for a Book promised by a client call.
type Book_Promise struct{ *capnp.Pipeline }
func (p Book_Promise) Struct() (Book, error) {
s, err := p.Pipeline.Struct()
return Book{s}, err
}
const schema_85d3acc39d94e0f8 = "x\xda\x12\x88w`2d\xdd\xcf\xc8\xc0\x10(\xc2\xca" +
"\xb6\xbf\xe6\xca\x95\xeb\x1dg\x1a\x03y\x18\x19\xff\xffx" +
"0e\xee\xe15\x97[\x19X\x19\xd9\x19\x18\x04\x8fv" +
"\x09\x9e\x05\xd1'\xcb\x19t\xff'\xe5\xe7g\x17\xeb%" +
"'2\x16\xe4\x15X9\xe5\xe7g30\x0402\x06" +
"r0\xb300\xb0020\x08j\x1a10\x04\xaa" +
"03\x06\x1a0122\x8a0\x82\xc4t\x83\x18\x18" +
"\x02u\x98\x19\x03-\x98\x18\xe5K2KrR\x19y" +
"\x18\x98\x18y\x18\x18\xff\x17$\xa6\xa7:\xe7\x97\xe61" +
"0\x960\xb2001\xb200\x02\x02\x00\x00\xff\xff" +
"F\xa9$\xae"
func init() {
schemas.Register(schema_85d3acc39d94e0f8,
0x8100cc88d7d4d47c)
}

View File

@@ -1,3 +0,0 @@
//go:generate capnp compile -I ../../../std -ogo books.capnp
package books

View File

@@ -1,2 +0,0 @@
// Package demo contains example tests.
package demo

View File

@@ -1,93 +0,0 @@
package demo_test
import (
"crypto/sha1"
"fmt"
"hash"
"net"
"golang.org/x/net/context"
"zombiezen.com/go/capnproto2/internal/demo/hashes"
"zombiezen.com/go/capnproto2/rpc"
)
// hashFactory is a local implementation of HashFactory.
type hashFactory struct{}
func (hf hashFactory) NewSha1(call hashes.HashFactory_newSha1) error {
// Create a new locally implemented Hash capability.
hs := hashes.Hash_ServerToClient(hashServer{sha1.New()})
// Notice that methods can return other interfaces.
return call.Results.SetHash(hs)
}
// hashServer is a local implementation of Hash.
type hashServer struct {
h hash.Hash
}
func (hs hashServer) Write(call hashes.Hash_write) error {
data, err := call.Params.Data()
if err != nil {
return err
}
_, err = hs.h.Write(data)
if err != nil {
return err
}
return nil
}
func (hs hashServer) Sum(call hashes.Hash_sum) error {
s := hs.h.Sum(nil)
return call.Results.SetHash(s)
}
func server(c net.Conn) error {
// Create a new locally implemented HashFactory.
main := hashes.HashFactory_ServerToClient(hashFactory{})
// Listen for calls, using the HashFactory as the bootstrap interface.
conn := rpc.NewConn(rpc.StreamTransport(c), rpc.MainInterface(main.Client))
// Wait for connection to abort.
err := conn.Wait()
return err
}
func client(ctx context.Context, c net.Conn) error {
// Create a connection that we can use to get the HashFactory.
conn := rpc.NewConn(rpc.StreamTransport(c))
defer conn.Close()
// Get the "bootstrap" interface. This is the capability set with
// rpc.MainInterface on the remote side.
hf := hashes.HashFactory{Client: conn.Bootstrap(ctx)}
// Now we can call methods on hf, and they will be sent over c.
s := hf.NewSha1(ctx, nil).Hash()
// s refers to a remote Hash. Method calls are delivered in order.
s.Write(ctx, func(p hashes.Hash_write_Params) error {
err := p.SetData([]byte("Hello, "))
return err
})
s.Write(ctx, func(p hashes.Hash_write_Params) error {
err := p.SetData([]byte("World!"))
return err
})
result, err := s.Sum(ctx, nil).Struct()
if err != nil {
return err
}
sha1Val, err := result.Hash()
if err != nil {
return err
}
fmt.Printf("sha1: %x\n", sha1Val)
return nil
}
func Example_hash() {
c1, c2 := net.Pipe()
go server(c1)
client(context.Background(), c2)
// Output:
// sha1: 0a0a9f2a6772942557ab5355d76af442f8f65e01
}

View File

@@ -1,18 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"gen.go",
"hash.capnp.go",
],
importpath = "zombiezen.com/go/capnproto2/internal/demo/hashes",
visibility = ["//:__subpackages__"],
deps = [
"//:go_default_library",
"//encoding/text:go_default_library",
"//schemas:go_default_library",
"//server:go_default_library",
"@org_golang_x_net//context:go_default_library",
],
)

View File

@@ -1,3 +0,0 @@
//go:generate capnp compile -I ../../../std -ogo hash.capnp
package hashes

View File

@@ -1,13 +0,0 @@
using Go = import "/go.capnp";
@0xdb8274f9144abc7e;
$Go.package("hashes");
$Go.import("zombiezen.com/go/capnproto2/internal/demo/hashes");
interface HashFactory {
newSha1 @0 () -> (hash :Hash);
}
interface Hash {
write @0 (data :Data) -> ();
sum @1 () -> (hash :Data);
}

View File

@@ -1,605 +0,0 @@
// Code generated by capnpc-go. DO NOT EDIT.
package hashes
import (
context "golang.org/x/net/context"
capnp "zombiezen.com/go/capnproto2"
text "zombiezen.com/go/capnproto2/encoding/text"
schemas "zombiezen.com/go/capnproto2/schemas"
server "zombiezen.com/go/capnproto2/server"
)
type HashFactory struct{ Client capnp.Client }
// HashFactory_TypeID is the unique identifier for the type HashFactory.
const HashFactory_TypeID = 0xaead580f97fddabc
func (c HashFactory) NewSha1(ctx context.Context, params func(HashFactory_newSha1_Params) error, opts ...capnp.CallOption) HashFactory_newSha1_Results_Promise {
if c.Client == nil {
return HashFactory_newSha1_Results_Promise{Pipeline: capnp.NewPipeline(capnp.ErrorAnswer(capnp.ErrNullClient))}
}
call := &capnp.Call{
Ctx: ctx,
Method: capnp.Method{
InterfaceID: 0xaead580f97fddabc,
MethodID: 0,
InterfaceName: "hash.capnp:HashFactory",
MethodName: "newSha1",
},
Options: capnp.NewCallOptions(opts),
}
if params != nil {
call.ParamsSize = capnp.ObjectSize{DataSize: 0, PointerCount: 0}
call.ParamsFunc = func(s capnp.Struct) error { return params(HashFactory_newSha1_Params{Struct: s}) }
}
return HashFactory_newSha1_Results_Promise{Pipeline: capnp.NewPipeline(c.Client.Call(call))}
}
type HashFactory_Server interface {
NewSha1(HashFactory_newSha1) error
}
func HashFactory_ServerToClient(s HashFactory_Server) HashFactory {
c, _ := s.(server.Closer)
return HashFactory{Client: server.New(HashFactory_Methods(nil, s), c)}
}
func HashFactory_Methods(methods []server.Method, s HashFactory_Server) []server.Method {
if cap(methods) == 0 {
methods = make([]server.Method, 0, 1)
}
methods = append(methods, server.Method{
Method: capnp.Method{
InterfaceID: 0xaead580f97fddabc,
MethodID: 0,
InterfaceName: "hash.capnp:HashFactory",
MethodName: "newSha1",
},
Impl: func(c context.Context, opts capnp.CallOptions, p, r capnp.Struct) error {
call := HashFactory_newSha1{c, opts, HashFactory_newSha1_Params{Struct: p}, HashFactory_newSha1_Results{Struct: r}}
return s.NewSha1(call)
},
ResultsSize: capnp.ObjectSize{DataSize: 0, PointerCount: 1},
})
return methods
}
// HashFactory_newSha1 holds the arguments for a server call to HashFactory.newSha1.
type HashFactory_newSha1 struct {
Ctx context.Context
Options capnp.CallOptions
Params HashFactory_newSha1_Params
Results HashFactory_newSha1_Results
}
type HashFactory_newSha1_Params struct{ capnp.Struct }
// HashFactory_newSha1_Params_TypeID is the unique identifier for the type HashFactory_newSha1_Params.
const HashFactory_newSha1_Params_TypeID = 0x92b20ad1a58ca0ca
func NewHashFactory_newSha1_Params(s *capnp.Segment) (HashFactory_newSha1_Params, error) {
st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0})
return HashFactory_newSha1_Params{st}, err
}
func NewRootHashFactory_newSha1_Params(s *capnp.Segment) (HashFactory_newSha1_Params, error) {
st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0})
return HashFactory_newSha1_Params{st}, err
}
func ReadRootHashFactory_newSha1_Params(msg *capnp.Message) (HashFactory_newSha1_Params, error) {
root, err := msg.RootPtr()
return HashFactory_newSha1_Params{root.Struct()}, err
}
func (s HashFactory_newSha1_Params) String() string {
str, _ := text.Marshal(0x92b20ad1a58ca0ca, s.Struct)
return str
}
// HashFactory_newSha1_Params_List is a list of HashFactory_newSha1_Params.
type HashFactory_newSha1_Params_List struct{ capnp.List }
// NewHashFactory_newSha1_Params creates a new list of HashFactory_newSha1_Params.
func NewHashFactory_newSha1_Params_List(s *capnp.Segment, sz int32) (HashFactory_newSha1_Params_List, error) {
l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}, sz)
return HashFactory_newSha1_Params_List{l}, err
}
func (s HashFactory_newSha1_Params_List) At(i int) HashFactory_newSha1_Params {
return HashFactory_newSha1_Params{s.List.Struct(i)}
}
func (s HashFactory_newSha1_Params_List) Set(i int, v HashFactory_newSha1_Params) error {
return s.List.SetStruct(i, v.Struct)
}
func (s HashFactory_newSha1_Params_List) String() string {
str, _ := text.MarshalList(0x92b20ad1a58ca0ca, s.List)
return str
}
// HashFactory_newSha1_Params_Promise is a wrapper for a HashFactory_newSha1_Params promised by a client call.
type HashFactory_newSha1_Params_Promise struct{ *capnp.Pipeline }
func (p HashFactory_newSha1_Params_Promise) Struct() (HashFactory_newSha1_Params, error) {
s, err := p.Pipeline.Struct()
return HashFactory_newSha1_Params{s}, err
}
type HashFactory_newSha1_Results struct{ capnp.Struct }
// HashFactory_newSha1_Results_TypeID is the unique identifier for the type HashFactory_newSha1_Results.
const HashFactory_newSha1_Results_TypeID = 0xea3e50f7663f7bdf
func NewHashFactory_newSha1_Results(s *capnp.Segment) (HashFactory_newSha1_Results, error) {
st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1})
return HashFactory_newSha1_Results{st}, err
}
func NewRootHashFactory_newSha1_Results(s *capnp.Segment) (HashFactory_newSha1_Results, error) {
st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1})
return HashFactory_newSha1_Results{st}, err
}
func ReadRootHashFactory_newSha1_Results(msg *capnp.Message) (HashFactory_newSha1_Results, error) {
root, err := msg.RootPtr()
return HashFactory_newSha1_Results{root.Struct()}, err
}
func (s HashFactory_newSha1_Results) String() string {
str, _ := text.Marshal(0xea3e50f7663f7bdf, s.Struct)
return str
}
func (s HashFactory_newSha1_Results) Hash() Hash {
p, _ := s.Struct.Ptr(0)
return Hash{Client: p.Interface().Client()}
}
func (s HashFactory_newSha1_Results) HasHash() bool {
p, err := s.Struct.Ptr(0)
return p.IsValid() || err != nil
}
func (s HashFactory_newSha1_Results) SetHash(v Hash) error {
if v.Client == nil {
return s.Struct.SetPtr(0, capnp.Ptr{})
}
seg := s.Segment()
in := capnp.NewInterface(seg, seg.Message().AddCap(v.Client))
return s.Struct.SetPtr(0, in.ToPtr())
}
// HashFactory_newSha1_Results_List is a list of HashFactory_newSha1_Results.
type HashFactory_newSha1_Results_List struct{ capnp.List }
// NewHashFactory_newSha1_Results creates a new list of HashFactory_newSha1_Results.
func NewHashFactory_newSha1_Results_List(s *capnp.Segment, sz int32) (HashFactory_newSha1_Results_List, error) {
l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}, sz)
return HashFactory_newSha1_Results_List{l}, err
}
func (s HashFactory_newSha1_Results_List) At(i int) HashFactory_newSha1_Results {
return HashFactory_newSha1_Results{s.List.Struct(i)}
}
func (s HashFactory_newSha1_Results_List) Set(i int, v HashFactory_newSha1_Results) error {
return s.List.SetStruct(i, v.Struct)
}
func (s HashFactory_newSha1_Results_List) String() string {
str, _ := text.MarshalList(0xea3e50f7663f7bdf, s.List)
return str
}
// HashFactory_newSha1_Results_Promise is a wrapper for a HashFactory_newSha1_Results promised by a client call.
type HashFactory_newSha1_Results_Promise struct{ *capnp.Pipeline }
func (p HashFactory_newSha1_Results_Promise) Struct() (HashFactory_newSha1_Results, error) {
s, err := p.Pipeline.Struct()
return HashFactory_newSha1_Results{s}, err
}
func (p HashFactory_newSha1_Results_Promise) Hash() Hash {
return Hash{Client: p.Pipeline.GetPipeline(0).Client()}
}
type Hash struct{ Client capnp.Client }
// Hash_TypeID is the unique identifier for the type Hash.
const Hash_TypeID = 0xf29f97dd675a9431
func (c Hash) Write(ctx context.Context, params func(Hash_write_Params) error, opts ...capnp.CallOption) Hash_write_Results_Promise {
if c.Client == nil {
return Hash_write_Results_Promise{Pipeline: capnp.NewPipeline(capnp.ErrorAnswer(capnp.ErrNullClient))}
}
call := &capnp.Call{
Ctx: ctx,
Method: capnp.Method{
InterfaceID: 0xf29f97dd675a9431,
MethodID: 0,
InterfaceName: "hash.capnp:Hash",
MethodName: "write",
},
Options: capnp.NewCallOptions(opts),
}
if params != nil {
call.ParamsSize = capnp.ObjectSize{DataSize: 0, PointerCount: 1}
call.ParamsFunc = func(s capnp.Struct) error { return params(Hash_write_Params{Struct: s}) }
}
return Hash_write_Results_Promise{Pipeline: capnp.NewPipeline(c.Client.Call(call))}
}
func (c Hash) Sum(ctx context.Context, params func(Hash_sum_Params) error, opts ...capnp.CallOption) Hash_sum_Results_Promise {
if c.Client == nil {
return Hash_sum_Results_Promise{Pipeline: capnp.NewPipeline(capnp.ErrorAnswer(capnp.ErrNullClient))}
}
call := &capnp.Call{
Ctx: ctx,
Method: capnp.Method{
InterfaceID: 0xf29f97dd675a9431,
MethodID: 1,
InterfaceName: "hash.capnp:Hash",
MethodName: "sum",
},
Options: capnp.NewCallOptions(opts),
}
if params != nil {
call.ParamsSize = capnp.ObjectSize{DataSize: 0, PointerCount: 0}
call.ParamsFunc = func(s capnp.Struct) error { return params(Hash_sum_Params{Struct: s}) }
}
return Hash_sum_Results_Promise{Pipeline: capnp.NewPipeline(c.Client.Call(call))}
}
type Hash_Server interface {
Write(Hash_write) error
Sum(Hash_sum) error
}
func Hash_ServerToClient(s Hash_Server) Hash {
c, _ := s.(server.Closer)
return Hash{Client: server.New(Hash_Methods(nil, s), c)}
}
func Hash_Methods(methods []server.Method, s Hash_Server) []server.Method {
if cap(methods) == 0 {
methods = make([]server.Method, 0, 2)
}
methods = append(methods, server.Method{
Method: capnp.Method{
InterfaceID: 0xf29f97dd675a9431,
MethodID: 0,
InterfaceName: "hash.capnp:Hash",
MethodName: "write",
},
Impl: func(c context.Context, opts capnp.CallOptions, p, r capnp.Struct) error {
call := Hash_write{c, opts, Hash_write_Params{Struct: p}, Hash_write_Results{Struct: r}}
return s.Write(call)
},
ResultsSize: capnp.ObjectSize{DataSize: 0, PointerCount: 0},
})
methods = append(methods, server.Method{
Method: capnp.Method{
InterfaceID: 0xf29f97dd675a9431,
MethodID: 1,
InterfaceName: "hash.capnp:Hash",
MethodName: "sum",
},
Impl: func(c context.Context, opts capnp.CallOptions, p, r capnp.Struct) error {
call := Hash_sum{c, opts, Hash_sum_Params{Struct: p}, Hash_sum_Results{Struct: r}}
return s.Sum(call)
},
ResultsSize: capnp.ObjectSize{DataSize: 0, PointerCount: 1},
})
return methods
}
// Hash_write holds the arguments for a server call to Hash.write.
type Hash_write struct {
Ctx context.Context
Options capnp.CallOptions
Params Hash_write_Params
Results Hash_write_Results
}
// Hash_sum holds the arguments for a server call to Hash.sum.
type Hash_sum struct {
Ctx context.Context
Options capnp.CallOptions
Params Hash_sum_Params
Results Hash_sum_Results
}
type Hash_write_Params struct{ capnp.Struct }
// Hash_write_Params_TypeID is the unique identifier for the type Hash_write_Params.
const Hash_write_Params_TypeID = 0xdffe94ae546cdee3
func NewHash_write_Params(s *capnp.Segment) (Hash_write_Params, error) {
st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1})
return Hash_write_Params{st}, err
}
func NewRootHash_write_Params(s *capnp.Segment) (Hash_write_Params, error) {
st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1})
return Hash_write_Params{st}, err
}
func ReadRootHash_write_Params(msg *capnp.Message) (Hash_write_Params, error) {
root, err := msg.RootPtr()
return Hash_write_Params{root.Struct()}, err
}
func (s Hash_write_Params) String() string {
str, _ := text.Marshal(0xdffe94ae546cdee3, s.Struct)
return str
}
func (s Hash_write_Params) Data() ([]byte, error) {
p, err := s.Struct.Ptr(0)
return []byte(p.Data()), err
}
func (s Hash_write_Params) HasData() bool {
p, err := s.Struct.Ptr(0)
return p.IsValid() || err != nil
}
func (s Hash_write_Params) SetData(v []byte) error {
return s.Struct.SetData(0, v)
}
// Hash_write_Params_List is a list of Hash_write_Params.
type Hash_write_Params_List struct{ capnp.List }
// NewHash_write_Params creates a new list of Hash_write_Params.
func NewHash_write_Params_List(s *capnp.Segment, sz int32) (Hash_write_Params_List, error) {
l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}, sz)
return Hash_write_Params_List{l}, err
}
func (s Hash_write_Params_List) At(i int) Hash_write_Params {
return Hash_write_Params{s.List.Struct(i)}
}
func (s Hash_write_Params_List) Set(i int, v Hash_write_Params) error {
return s.List.SetStruct(i, v.Struct)
}
func (s Hash_write_Params_List) String() string {
str, _ := text.MarshalList(0xdffe94ae546cdee3, s.List)
return str
}
// Hash_write_Params_Promise is a wrapper for a Hash_write_Params promised by a client call.
type Hash_write_Params_Promise struct{ *capnp.Pipeline }
func (p Hash_write_Params_Promise) Struct() (Hash_write_Params, error) {
s, err := p.Pipeline.Struct()
return Hash_write_Params{s}, err
}
type Hash_write_Results struct{ capnp.Struct }
// Hash_write_Results_TypeID is the unique identifier for the type Hash_write_Results.
const Hash_write_Results_TypeID = 0x80ac741ec7fb8f65
func NewHash_write_Results(s *capnp.Segment) (Hash_write_Results, error) {
st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0})
return Hash_write_Results{st}, err
}
func NewRootHash_write_Results(s *capnp.Segment) (Hash_write_Results, error) {
st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0})
return Hash_write_Results{st}, err
}
func ReadRootHash_write_Results(msg *capnp.Message) (Hash_write_Results, error) {
root, err := msg.RootPtr()
return Hash_write_Results{root.Struct()}, err
}
func (s Hash_write_Results) String() string {
str, _ := text.Marshal(0x80ac741ec7fb8f65, s.Struct)
return str
}
// Hash_write_Results_List is a list of Hash_write_Results.
type Hash_write_Results_List struct{ capnp.List }
// NewHash_write_Results creates a new list of Hash_write_Results.
func NewHash_write_Results_List(s *capnp.Segment, sz int32) (Hash_write_Results_List, error) {
l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}, sz)
return Hash_write_Results_List{l}, err
}
func (s Hash_write_Results_List) At(i int) Hash_write_Results {
return Hash_write_Results{s.List.Struct(i)}
}
func (s Hash_write_Results_List) Set(i int, v Hash_write_Results) error {
return s.List.SetStruct(i, v.Struct)
}
func (s Hash_write_Results_List) String() string {
str, _ := text.MarshalList(0x80ac741ec7fb8f65, s.List)
return str
}
// Hash_write_Results_Promise is a wrapper for a Hash_write_Results promised by a client call.
type Hash_write_Results_Promise struct{ *capnp.Pipeline }
func (p Hash_write_Results_Promise) Struct() (Hash_write_Results, error) {
s, err := p.Pipeline.Struct()
return Hash_write_Results{s}, err
}
type Hash_sum_Params struct{ capnp.Struct }
// Hash_sum_Params_TypeID is the unique identifier for the type Hash_sum_Params.
const Hash_sum_Params_TypeID = 0xe74bb2d0190cf89c
func NewHash_sum_Params(s *capnp.Segment) (Hash_sum_Params, error) {
st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0})
return Hash_sum_Params{st}, err
}
func NewRootHash_sum_Params(s *capnp.Segment) (Hash_sum_Params, error) {
st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0})
return Hash_sum_Params{st}, err
}
func ReadRootHash_sum_Params(msg *capnp.Message) (Hash_sum_Params, error) {
root, err := msg.RootPtr()
return Hash_sum_Params{root.Struct()}, err
}
func (s Hash_sum_Params) String() string {
str, _ := text.Marshal(0xe74bb2d0190cf89c, s.Struct)
return str
}
// Hash_sum_Params_List is a list of Hash_sum_Params.
type Hash_sum_Params_List struct{ capnp.List }
// NewHash_sum_Params creates a new list of Hash_sum_Params.
func NewHash_sum_Params_List(s *capnp.Segment, sz int32) (Hash_sum_Params_List, error) {
l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}, sz)
return Hash_sum_Params_List{l}, err
}
func (s Hash_sum_Params_List) At(i int) Hash_sum_Params { return Hash_sum_Params{s.List.Struct(i)} }
func (s Hash_sum_Params_List) Set(i int, v Hash_sum_Params) error {
return s.List.SetStruct(i, v.Struct)
}
func (s Hash_sum_Params_List) String() string {
str, _ := text.MarshalList(0xe74bb2d0190cf89c, s.List)
return str
}
// Hash_sum_Params_Promise is a wrapper for a Hash_sum_Params promised by a client call.
type Hash_sum_Params_Promise struct{ *capnp.Pipeline }
func (p Hash_sum_Params_Promise) Struct() (Hash_sum_Params, error) {
s, err := p.Pipeline.Struct()
return Hash_sum_Params{s}, err
}
type Hash_sum_Results struct{ capnp.Struct }
// Hash_sum_Results_TypeID is the unique identifier for the type Hash_sum_Results.
const Hash_sum_Results_TypeID = 0xd093963b95a4e107
func NewHash_sum_Results(s *capnp.Segment) (Hash_sum_Results, error) {
st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1})
return Hash_sum_Results{st}, err
}
func NewRootHash_sum_Results(s *capnp.Segment) (Hash_sum_Results, error) {
st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1})
return Hash_sum_Results{st}, err
}
func ReadRootHash_sum_Results(msg *capnp.Message) (Hash_sum_Results, error) {
root, err := msg.RootPtr()
return Hash_sum_Results{root.Struct()}, err
}
func (s Hash_sum_Results) String() string {
str, _ := text.Marshal(0xd093963b95a4e107, s.Struct)
return str
}
func (s Hash_sum_Results) Hash() ([]byte, error) {
p, err := s.Struct.Ptr(0)
return []byte(p.Data()), err
}
func (s Hash_sum_Results) HasHash() bool {
p, err := s.Struct.Ptr(0)
return p.IsValid() || err != nil
}
func (s Hash_sum_Results) SetHash(v []byte) error {
return s.Struct.SetData(0, v)
}
// Hash_sum_Results_List is a list of Hash_sum_Results.
type Hash_sum_Results_List struct{ capnp.List }
// NewHash_sum_Results creates a new list of Hash_sum_Results.
func NewHash_sum_Results_List(s *capnp.Segment, sz int32) (Hash_sum_Results_List, error) {
l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}, sz)
return Hash_sum_Results_List{l}, err
}
func (s Hash_sum_Results_List) At(i int) Hash_sum_Results { return Hash_sum_Results{s.List.Struct(i)} }
func (s Hash_sum_Results_List) Set(i int, v Hash_sum_Results) error {
return s.List.SetStruct(i, v.Struct)
}
func (s Hash_sum_Results_List) String() string {
str, _ := text.MarshalList(0xd093963b95a4e107, s.List)
return str
}
// Hash_sum_Results_Promise is a wrapper for a Hash_sum_Results promised by a client call.
type Hash_sum_Results_Promise struct{ *capnp.Pipeline }
func (p Hash_sum_Results_Promise) Struct() (Hash_sum_Results, error) {
s, err := p.Pipeline.Struct()
return Hash_sum_Results{s}, err
}
const schema_db8274f9144abc7e = "x\xda\x84\x92?h\x13a\x18\xc6\x9f\xe7\xbb;\xaf\xa8" +
"G\xfaq\x05\xe9bP\"\x82\xd8\xe2\xb5[\x05\x13\x1c" +
"Tt\xb9\x8b\x0e\xe2\xf6QO#$\xb5\xe4.\x14\x11" +
"\xff\xd0\xc5E\x10\xb4\xdaE\xd0A7\xed\xd0Q\xba\x8a" +
"(\x08u\xb4\x12\x8b:\x08\xdd\xec\xa2\xa5\xd4\x93\xef\x92" +
"k\x02!v\xfb\xe0y\xdf\xe7\x9e\xf7w\xcf\xe0fI" +
"x\xd6a\x13\x08\x8eY\xbb\x92\xf0\xc1\xe6\xbb\xfd\xf1\xab" +
"\xbb\x90\x83\x04L\x1bp7\xb8\x0e3\xf9\xf0\xfc\xfe\xcb" +
"O\xbb\x17\x1fB\xeek\x0b\xe3M\x8e\x11f\xb2\xb4\xb2" +
"5\x9f\xbb\xf8z\x01r\x8f\x91\xdc^:;\xb4\x11\xcf" +
"~\x01\xe8\xbe\xe5\x1b\xf7#\xb5\xc5{\x9ev\x7f\xe9W" +
"b\x7f{\xf1\xf8\xf8\x93G\xcb-\x7f+U?\xf3;" +
"\xe86Y\x04\x93\x1f_\xab\x17\x16\xe6\xfe\xaev\xeb[" +
"\\\x03]\x0a\xad?\xfd\xb3wxy\xf1\xdc\xcf\xae|" +
"\x07\xc4\x0a\xccd\xf5f\xf1\xcao\xff\xc4Z+_\xba" +
"8n\x89\x09\x82\xae\x93nzs\x97\xae6\xe7\x9f\xad" +
"\xf7\xc4\x1c\x11\xb3\xae'\xb4\xd3\x88\xb8\xe7\xde\x126\x8e" +
"&\x15\x15UF'\xd5\xb4\x98\x9a\x9e8\xa3\xdf3\xf5" +
"kqX(\x87\xf9\xa8Q\x8d\xa3m\xddh\xeb\xa7\xd4" +
"d|\xbd~ct*\x9c9_Q^\xc1\xcf\xab\xba" +
"\xaau\xe6\x98\xcd\x15[\x83>\x19\x98\x86\x05lse" +
"v\x80\x94'!\xa4e\xdfi{\x95\xe8\x93\xbd\x81\xa2" +
"F\xadP\x0e\xa3\x86]\x8d\xa3\xc04L\xc0$ \x9d" +
"#@0`0\x18\x12\xcc\xe9%:\x10t\xc0~'" +
"\xf9*\xa7\x93\xf6\xb3\xb8\xacb\xd5\xdfB\x87\xf0U]" +
"\x19\xb5\x9d\x91\x94\x8ba\xca\xee\xbfae\xe77\x81\x94" +
"]\xdf\xcc\x08B\xa3\x1bH\xd1e]aVZ\xe9\x8d" +
"A\xc8C6;=aV89|\x10B:v>" +
"=\xbbD;j\xd4R\xb4\xff\x02\x00\x00\xff\xff<." +
"\xe3\xa6"
func init() {
schemas.Register(schema_db8274f9144abc7e,
0x80ac741ec7fb8f65,
0x92b20ad1a58ca0ca,
0xaead580f97fddabc,
0xd093963b95a4e107,
0xdffe94ae546cdee3,
0xe74bb2d0190cf89c,
0xea3e50f7663f7bdf,
0xf29f97dd675a9431)
}

View File

@@ -1,123 +0,0 @@
package fulfiller
import (
"errors"
"testing"
"zombiezen.com/go/capnproto2"
)
func TestFulfiller_NewShouldBeUnresolved(t *testing.T) {
f := new(Fulfiller)
if a := f.Peek(); a != nil {
t.Errorf("f.Peek() = %v; want nil", a)
}
select {
case <-f.Done():
t.Error("Done closed early")
default:
// success
}
}
func TestFulfiller_FulfillShouldResolve(t *testing.T) {
f := new(Fulfiller)
st := newStruct(t, capnp.ObjectSize{})
f.Fulfill(st)
select {
case <-f.Done():
default:
t.Error("Done still closed after Fulfill")
}
ret, err := f.Struct()
if err != nil {
t.Errorf("f.Struct() error: %v", err)
}
if ret != st {
t.Errorf("f.Struct() = %v; want %v", ret, st)
}
}
func TestFulfiller_RejectShouldResolve(t *testing.T) {
f := new(Fulfiller)
e := errors.New("failure and rejection")
f.Reject(e)
select {
case <-f.Done():
default:
t.Error("Done still closed after Reject")
}
ret, err := f.Struct()
if err != e {
t.Errorf("f.Struct() error = %v; want %v", err, e)
}
if capnp.IsValid(ret) {
t.Errorf("f.Struct() = %v; want null", ret)
}
}
func TestFulfiller_QueuedCallsDeliveredInOrder(t *testing.T) {
f := new(Fulfiller)
oc := new(orderClient)
result := newStruct(t, capnp.ObjectSize{PointerCount: 1})
in := result.Segment().Message().AddCap(oc)
result.SetPointer(0, capnp.NewInterface(result.Segment(), in))
ans1 := f.PipelineCall([]capnp.PipelineOp{{Field: 0}}, new(capnp.Call))
ans2 := f.PipelineCall([]capnp.PipelineOp{{Field: 0}}, new(capnp.Call))
f.Fulfill(result)
ans3 := f.PipelineCall([]capnp.PipelineOp{{Field: 0}}, new(capnp.Call))
ans3.Struct()
ans4 := f.PipelineCall([]capnp.PipelineOp{{Field: 0}}, new(capnp.Call))
check := func(a capnp.Answer, n uint64) {
r, err := a.Struct()
if r.Uint64(0) != n {
t.Errorf("r%d = %d; want %d", n+1, r.Uint64(0), n)
}
if err != nil {
t.Errorf("err%d = %v", n+1, err)
}
}
check(ans1, 0)
check(ans2, 1)
check(ans3, 2)
check(ans4, 3)
}
func newStruct(t *testing.T, sz capnp.ObjectSize) capnp.Struct {
_, s, err := capnp.NewMessage(capnp.SingleSegment(nil))
if err != nil {
t.Fatal(err)
}
st, err := capnp.NewStruct(s, sz)
if err != nil {
t.Fatal(err)
}
return st
}
type orderClient int
func (oc *orderClient) Call(cl *capnp.Call) capnp.Answer {
_, s, err := capnp.NewMessage(capnp.SingleSegment(nil))
if err != nil {
return capnp.ErrorAnswer(err)
}
st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8})
if err != nil {
return capnp.ErrorAnswer(err)
}
st.SetUint64(0, uint64(*oc))
*oc++
return capnp.ImmediateAnswer(st)
}
func (oc *orderClient) Close() error {
return nil
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More