diff --git a/capability.go b/capability.go index 4831324c..3d1a8fcb 100644 --- a/capability.go +++ b/capability.go @@ -104,7 +104,12 @@ func (id CapabilityID) GoString() string { // A Client is a reference to a Cap'n Proto capability. // The zero value is a null capability reference. // It is safe to use from multiple goroutines. -type Client struct { +type Client ClientKind + +// The underlying type of Client. We expose this so that +// we can use ~ClientKind as a constraint in generics to +// capture any capability type. +type ClientKind = struct { *client } diff --git a/capnpc-go/templates/interfaceClient b/capnpc-go/templates/interfaceClient index 1410006a..7c434354 100644 --- a/capnpc-go/templates/interfaceClient +++ b/capnpc-go/templates/interfaceClient @@ -1,7 +1,7 @@ {{with .Annotations.Doc -}} // {{.}} {{end -}} -type {{.Node.Name}} struct { capnp.Client } +type {{.Node.Name}} capnp.Client {{ template "_typeid" .Node }} @@ -16,17 +16,27 @@ func (c {{$.Node.Name}}) {{.Name|title}}(ctx {{$.G.Imports.Context}}.Context, pa s.ArgsSize = {{$.G.ObjectSize .Params}} s.PlaceArgs = func(s capnp.Struct) error { return params({{$.G.RemoteNodeName .Params $.Node}}{Struct: s}) } } - ans, release := c.Client.SendCall(ctx, s) + ans, release := capnp.Client(c).SendCall(ctx, s) return {{$.G.RemoteNodeName .Results $.Node}}_Future{Future: ans.Future()}, release } {{end}} func (c {{$.Node.Name}}) AddRef() {{$.Node.Name}} { - return {{$.Node.Name}} { - Client: c.Client.AddRef(), - } + return {{$.Node.Name}}(capnp.Client(c).AddRef()) +} + +func (c {{$.Node.Name}}) Release() { + capnp.Client(c).Release() +} + +func (c {{$.Node.Name}}) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Client(c).EncodeAsPtr(seg) } func ({{$.Node.Name}}) DecodeFromPtr(p capnp.Ptr) {{$.Node.Name}} { - return {{$.Node.Name}}{ Client: capnp.Client{}.DecodeFromPtr(p) } + return {{$.Node.Name}}(capnp.Client{}.DecodeFromPtr(p)) +} + +func (c {{$.Node.Name}}) IsValid() bool { + return capnp.Client(c).IsValid() } diff --git a/capnpc-go/templates/interfaceServer b/capnpc-go/templates/interfaceServer index c1e1bb8c..4473d03b 100644 --- a/capnpc-go/templates/interfaceServer +++ b/capnpc-go/templates/interfaceServer @@ -14,7 +14,7 @@ func {{.Node.Name}}_NewServer(s {{.Node.Name}}_Server) *{{.G.Imports.Server}}.Se // {{.Node.Name}}_ServerToClient creates a new Client from an implementation of {{.Node.Name}}_Server. // The caller is responsible for calling Release on the returned Client. func {{.Node.Name}}_ServerToClient(s {{.Node.Name}}_Server) {{.Node.Name}} { - return {{.Node.Name}}{Client: capnp.NewClient({{.Node.Name}}_NewServer(s))} + return {{.Node.Name}}(capnp.NewClient({{.Node.Name}}_NewServer(s))) } // {{.Node.Name}}_Methods appends Methods to a slice that invoke the methods on s. diff --git a/capnpc-go/templates/promiseFieldInterface b/capnpc-go/templates/promiseFieldInterface index 3ac1df41..990587b7 100644 --- a/capnpc-go/templates/promiseFieldInterface +++ b/capnpc-go/templates/promiseFieldInterface @@ -1,4 +1,4 @@ func (p {{.Node.Name}}_Future) {{.Field.Name|title}}() {{.G.RemoteNodeName .Interface .Node}} { - return {{.G.RemoteNodeName .Interface .Node}}{Client: p.Future.Field({{.Field.Slot.Offset}}, nil).Client()} + return {{.G.RemoteNodeName .Interface .Node}}(p.Future.Field({{.Field.Slot.Offset}}, nil).Client()) } diff --git a/capnpc-go/templates/structInterfaceField b/capnpc-go/templates/structInterfaceField index 2742fb33..bfaebfbf 100644 --- a/capnpc-go/templates/structInterfaceField +++ b/capnpc-go/templates/structInterfaceField @@ -1,18 +1,18 @@ func (s {{.Node.Name}}) {{.Field.Name|title}}() {{.FieldType}} { {{template "_checktag" . -}} p, _ := s.Struct.Ptr({{.Field.Slot.Offset}}) - return {{.FieldType}}{Client: p.Interface().Client()} + return {{.FieldType}}(p.Interface().Client()) } {{template "_hasfield" .}} func (s {{.Node.Name}}) Set{{.Field.Name|title}}(v {{.FieldType}}) error { {{template "_settag" . -}} - if !v.Client.IsValid() { + if !v.IsValid() { return s.Struct.SetPtr({{.Field.Slot.Offset}}, capnp.Ptr{}) } seg := s.Segment() - in := capnp.NewInterface(seg, seg.Message().AddCap(v.Client)) + in := capnp.NewInterface(seg, seg.Message().AddCap(capnp.Client(v))) return s.Struct.SetPtr({{.Field.Slot.Offset}}, in.ToPtr()) } diff --git a/internal/aircraftlib/aircraft.capnp.go b/internal/aircraftlib/aircraft.capnp.go index 6ce45ee8..30a274ec 100644 --- a/internal/aircraftlib/aircraft.capnp.go +++ b/internal/aircraftlib/aircraft.capnp.go @@ -2165,7 +2165,7 @@ func (s Z) Echo() Echo { panic("Which() != echo") } p, _ := s.Struct.Ptr(0) - return Echo{Client: p.Interface().Client()} + return Echo(p.Interface().Client()) } func (s Z) HasEcho() bool { @@ -2177,11 +2177,11 @@ func (s Z) HasEcho() bool { func (s Z) SetEcho(v Echo) error { s.Struct.SetUint16(0, 43) - if !v.Client.IsValid() { + if !v.IsValid() { return s.Struct.SetPtr(0, capnp.Ptr{}) } seg := s.Segment() - in := capnp.NewInterface(seg, seg.Message().AddCap(v.Client)) + in := capnp.NewInterface(seg, seg.Message().AddCap(capnp.Client(v))) return s.Struct.SetPtr(0, in.ToPtr()) } @@ -2363,7 +2363,7 @@ func (p Z_grp_Future) Struct() (Z_grp, error) { } func (p Z_Future) Echo() Echo { - return Echo{Client: p.Future.Field(0, nil).Client()} + return Echo(p.Future.Field(0, nil).Client()) } func (p Z_Future) AnyPtr() *capnp.Future { @@ -4427,7 +4427,7 @@ func (p ListStructCapn_Future) Struct() (ListStructCapn, error) { return ListStructCapn{s}, err } -type Echo struct{ capnp.Client } +type Echo capnp.Client // Echo_TypeID is the unique identifier for the type Echo. const Echo_TypeID = 0x8e5322c1e9282534 @@ -4445,18 +4445,28 @@ func (c Echo) Echo(ctx context.Context, params func(Echo_echo_Params) error) (Ec s.ArgsSize = capnp.ObjectSize{DataSize: 0, PointerCount: 1} s.PlaceArgs = func(s capnp.Struct) error { return params(Echo_echo_Params{Struct: s}) } } - ans, release := c.Client.SendCall(ctx, s) + ans, release := capnp.Client(c).SendCall(ctx, s) return Echo_echo_Results_Future{Future: ans.Future()}, release } func (c Echo) AddRef() Echo { - return Echo{ - Client: c.Client.AddRef(), - } + return Echo(capnp.Client(c).AddRef()) +} + +func (c Echo) Release() { + capnp.Client(c).Release() +} + +func (c Echo) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Client(c).EncodeAsPtr(seg) } func (Echo) DecodeFromPtr(p capnp.Ptr) Echo { - return Echo{Client: capnp.Client{}.DecodeFromPtr(p)} + return Echo(capnp.Client{}.DecodeFromPtr(p)) +} + +func (c Echo) IsValid() bool { + return capnp.Client(c).IsValid() } // A Echo_Server is a Echo with a local implementation. @@ -4473,7 +4483,7 @@ func Echo_NewServer(s Echo_Server) *server.Server { // Echo_ServerToClient creates a new Client from an implementation of Echo_Server. // The caller is responsible for calling Release on the returned Client. func Echo_ServerToClient(s Echo_Server) Echo { - return Echo{Client: capnp.NewClient(Echo_NewServer(s))} + return Echo(capnp.NewClient(Echo_NewServer(s))) } // Echo_Methods appends Methods to a slice that invoke the methods on s. @@ -4753,7 +4763,7 @@ func (EchoBase) DecodeFromPtr(p capnp.Ptr) EchoBase { } func (s EchoBase) Echo() Echo { p, _ := s.Struct.Ptr(0) - return Echo{Client: p.Interface().Client()} + return Echo(p.Interface().Client()) } func (s EchoBase) HasEcho() bool { @@ -4761,11 +4771,11 @@ func (s EchoBase) HasEcho() bool { } func (s EchoBase) SetEcho(v Echo) error { - if !v.Client.IsValid() { + if !v.IsValid() { return s.Struct.SetPtr(0, capnp.Ptr{}) } seg := s.Segment() - in := capnp.NewInterface(seg, seg.Message().AddCap(v.Client)) + in := capnp.NewInterface(seg, seg.Message().AddCap(capnp.Client(v))) return s.Struct.SetPtr(0, in.ToPtr()) } @@ -4787,7 +4797,7 @@ func (p EchoBase_Future) Struct() (EchoBase, error) { } func (p EchoBase_Future) Echo() Echo { - return Echo{Client: p.Future.Field(0, nil).Client()} + return Echo(p.Future.Field(0, nil).Client()) } type StackingRoot struct{ capnp.Struct } @@ -5029,7 +5039,7 @@ func (p StackingB_Future) Struct() (StackingB, error) { return StackingB{s}, err } -type CallSequence struct{ capnp.Client } +type CallSequence capnp.Client // CallSequence_TypeID is the unique identifier for the type CallSequence. const CallSequence_TypeID = 0xabaedf5f7817c820 @@ -5047,18 +5057,28 @@ func (c CallSequence) GetNumber(ctx context.Context, params func(CallSequence_ge s.ArgsSize = capnp.ObjectSize{DataSize: 0, PointerCount: 0} s.PlaceArgs = func(s capnp.Struct) error { return params(CallSequence_getNumber_Params{Struct: s}) } } - ans, release := c.Client.SendCall(ctx, s) + ans, release := capnp.Client(c).SendCall(ctx, s) return CallSequence_getNumber_Results_Future{Future: ans.Future()}, release } func (c CallSequence) AddRef() CallSequence { - return CallSequence{ - Client: c.Client.AddRef(), - } + return CallSequence(capnp.Client(c).AddRef()) +} + +func (c CallSequence) Release() { + capnp.Client(c).Release() +} + +func (c CallSequence) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Client(c).EncodeAsPtr(seg) } func (CallSequence) DecodeFromPtr(p capnp.Ptr) CallSequence { - return CallSequence{Client: capnp.Client{}.DecodeFromPtr(p)} + return CallSequence(capnp.Client{}.DecodeFromPtr(p)) +} + +func (c CallSequence) IsValid() bool { + return capnp.Client(c).IsValid() } // A CallSequence_Server is a CallSequence with a local implementation. @@ -5075,7 +5095,7 @@ func CallSequence_NewServer(s CallSequence_Server) *server.Server { // CallSequence_ServerToClient creates a new Client from an implementation of CallSequence_Server. // The caller is responsible for calling Release on the returned Client. func CallSequence_ServerToClient(s CallSequence_Server) CallSequence { - return CallSequence{Client: capnp.NewClient(CallSequence_NewServer(s))} + return CallSequence(capnp.NewClient(CallSequence_NewServer(s))) } // CallSequence_Methods appends Methods to a slice that invoke the methods on s. @@ -5225,7 +5245,7 @@ func (p CallSequence_getNumber_Results_Future) Struct() (CallSequence_getNumber_ return CallSequence_getNumber_Results{s}, err } -type Pipeliner struct{ capnp.Client } +type Pipeliner capnp.Client // Pipeliner_TypeID is the unique identifier for the type Pipeliner. const Pipeliner_TypeID = 0xd6514008f0f84ebc @@ -5243,7 +5263,7 @@ func (c Pipeliner) NewPipeliner(ctx context.Context, params func(Pipeliner_newPi s.ArgsSize = capnp.ObjectSize{DataSize: 0, PointerCount: 0} s.PlaceArgs = func(s capnp.Struct) error { return params(Pipeliner_newPipeliner_Params{Struct: s}) } } - ans, release := c.Client.SendCall(ctx, s) + ans, release := capnp.Client(c).SendCall(ctx, s) return Pipeliner_newPipeliner_Results_Future{Future: ans.Future()}, release } func (c Pipeliner) GetNumber(ctx context.Context, params func(CallSequence_getNumber_Params) error) (CallSequence_getNumber_Results_Future, capnp.ReleaseFunc) { @@ -5259,18 +5279,28 @@ func (c Pipeliner) GetNumber(ctx context.Context, params func(CallSequence_getNu s.ArgsSize = capnp.ObjectSize{DataSize: 0, PointerCount: 0} s.PlaceArgs = func(s capnp.Struct) error { return params(CallSequence_getNumber_Params{Struct: s}) } } - ans, release := c.Client.SendCall(ctx, s) + ans, release := capnp.Client(c).SendCall(ctx, s) return CallSequence_getNumber_Results_Future{Future: ans.Future()}, release } func (c Pipeliner) AddRef() Pipeliner { - return Pipeliner{ - Client: c.Client.AddRef(), - } + return Pipeliner(capnp.Client(c).AddRef()) +} + +func (c Pipeliner) Release() { + capnp.Client(c).Release() +} + +func (c Pipeliner) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Client(c).EncodeAsPtr(seg) } func (Pipeliner) DecodeFromPtr(p capnp.Ptr) Pipeliner { - return Pipeliner{Client: capnp.Client{}.DecodeFromPtr(p)} + return Pipeliner(capnp.Client{}.DecodeFromPtr(p)) +} + +func (c Pipeliner) IsValid() bool { + return capnp.Client(c).IsValid() } // A Pipeliner_Server is a Pipeliner with a local implementation. @@ -5289,7 +5319,7 @@ func Pipeliner_NewServer(s Pipeliner_Server) *server.Server { // Pipeliner_ServerToClient creates a new Client from an implementation of Pipeliner_Server. // The caller is responsible for calling Release on the returned Client. func Pipeliner_ServerToClient(s Pipeliner_Server) Pipeliner { - return Pipeliner{Client: capnp.NewClient(Pipeliner_NewServer(s))} + return Pipeliner(capnp.NewClient(Pipeliner_NewServer(s))) } // Pipeliner_Methods appends Methods to a slice that invoke the methods on s. @@ -5440,7 +5470,7 @@ func (s Pipeliner_newPipeliner_Results) SetExtra(v capnp.Ptr) error { func (s Pipeliner_newPipeliner_Results) Pipeliner() Pipeliner { p, _ := s.Struct.Ptr(1) - return Pipeliner{Client: p.Interface().Client()} + return Pipeliner(p.Interface().Client()) } func (s Pipeliner_newPipeliner_Results) HasPipeliner() bool { @@ -5448,11 +5478,11 @@ func (s Pipeliner_newPipeliner_Results) HasPipeliner() bool { } func (s Pipeliner_newPipeliner_Results) SetPipeliner(v Pipeliner) error { - if !v.Client.IsValid() { + if !v.IsValid() { return s.Struct.SetPtr(1, capnp.Ptr{}) } seg := s.Segment() - in := capnp.NewInterface(seg, seg.Message().AddCap(v.Client)) + in := capnp.NewInterface(seg, seg.Message().AddCap(capnp.Client(v))) return s.Struct.SetPtr(1, in.ToPtr()) } @@ -5478,7 +5508,7 @@ func (p Pipeliner_newPipeliner_Results_Future) Extra() *capnp.Future { } func (p Pipeliner_newPipeliner_Results_Future) Pipeliner() Pipeliner { - return Pipeliner{Client: p.Future.Field(1, nil).Client()} + return Pipeliner(p.Future.Field(1, nil).Client()) } type Defaults struct{ capnp.Struct } diff --git a/list.go b/list.go index fd182f25..e44cad9b 100644 --- a/list.go +++ b/list.go @@ -1145,23 +1145,24 @@ func (s StructList[T]) String() string { } func (StructList[T]) DecodeFromPtr(p Ptr) StructList[T] { - return StructList[T]{ List: List{}.DecodeFromPtr(p) } + return StructList[T]{List: List{}.DecodeFromPtr(p)} } -type CapList[T ~struct{ Client }] PointerList +// A list of some Cap'n Proto capability type T. +type CapList[T ~ClientKind] PointerList func (c CapList[T]) At(i int) (T, error) { ptr, err := PointerList(c).At(i) if err != nil { return T{}, err } - return T{Client: ptr.Interface().Client()}, nil + return T(ptr.Interface().Client()), nil } func (c CapList[T]) Set(i int, v T) error { pl := PointerList(c) seg := pl.List.Segment() - capId := seg.Message().AddCap(struct{ Client }(v).Client) + capId := seg.Message().AddCap(Client(v)) return pl.Set(i, NewInterface(seg, capId).ToPtr()) } diff --git a/pogs/extract.go b/pogs/extract.go index e6a27665..331ef270 100644 --- a/pogs/extract.go +++ b/pogs/extract.go @@ -231,13 +231,8 @@ func (e *extracter) extractField(val reflect.Value, s capnp.Struct, f schema.Fie if err != nil { return err } - if val.Type() != clientType { - // Must be a struct wrapper. - val = val.FieldByName("Client") - } - client := p.Interface().Client() - val.Set(reflect.ValueOf(client)) + val.Set(reflect.ValueOf(client).Convert(val.Type())) case schema.Type_Which_anyPointer: p, err := s.Ptr(uint16(f.Slot().Offset())) if err != nil { @@ -387,25 +382,16 @@ func (e *extracter) extractList(val reflect.Value, typ schema.Type, l capnp.List } } case schema.Type_Which_interface: - if val.Type().Elem() == clientType { - for i := 0; i < n; i++ { - p, err := capnp.PointerList{List: l}.At(i) - // TODO(light): collect errors and finish - if err != nil { - return err - } - val.Index(i).Set(reflect.ValueOf(p.Interface().Client())) - } - } else { - // Must be a struct wrapper. - for i := 0; i < n; i++ { - p, err := capnp.PointerList{List: l}.At(i) - // TODO(light): collect errors and finish - if err != nil { - return err - } - val.Index(i).FieldByName("Client").Set(reflect.ValueOf(p.Interface().Client())) + elemType := val.Type().Elem() + for i := 0; i < n; i++ { + p, err := capnp.PointerList{List: l}.At(i) + // TODO(light): collect errors and finish + if err != nil { + return err } + val.Index(i).Set( + reflect.ValueOf(p.Interface().Client()).Convert(elemType), + ) } case schema.Type_Which_anyPointer: // Schemas aren't allowed to have List(AnyPointer). @@ -444,23 +430,7 @@ func isTypeMatch(r reflect.Type, s schema.Type) bool { e, _ := s.List().ElementType() return r.Kind() == reflect.Slice && isTypeMatch(r.Elem(), e) case schema.Type_Which_interface: - if r == clientType { - return true - } - - // Otherwise, the type must be a struct with one element named - // "Client" of type capnp.Client. - if r.Kind() != reflect.Struct { - return false - } - if r.NumField() != 1 { - return false - } - field, ok := r.FieldByName("Client") - if !ok { - return false - } - return field.Type == clientType + return reflect.Zero(clientType).CanConvert(r) case schema.Type_Which_anyPointer: if r == ptrType { return true diff --git a/pogs/insert.go b/pogs/insert.go index 2d34786b..f9d1e0b2 100644 --- a/pogs/insert.go +++ b/pogs/insert.go @@ -235,7 +235,7 @@ func (ins *inserter) insertField(s capnp.Struct, f schema.Field, val reflect.Val case listType: return s.SetPtr(off, val.Interface().(capnp.List).ToPtr()) case clientType: - c := val.Interface().(capnp.Client) + c := val.Convert(clientType).Interface().(capnp.Client) if !c.IsValid() { return s.SetPtr(off, capnp.Ptr{}) } @@ -251,10 +251,7 @@ func (ins *inserter) insertField(s capnp.Struct, f schema.Field, val reflect.Val } func capPtr(seg *capnp.Segment, val reflect.Value) capnp.Ptr { - client, ok := val.Interface().(capnp.Client) - if !ok { - client = val.FieldByName("Client").Interface().(capnp.Client) - } + client := val.Convert(clientType).Interface().(capnp.Client) if !client.IsValid() { return capnp.Ptr{} } diff --git a/pogs/pogs_test.go b/pogs/pogs_test.go index d15bee07..54636ce9 100644 --- a/pogs/pogs_test.go +++ b/pogs/pogs_test.go @@ -161,13 +161,13 @@ var goodTests = []Z{ {Which: air.Z_Which_airport, Airport: air.Airport_lax}, {Which: air.Z_Which_grp, Grp: &ZGroup{First: 123, Second: 456}}, {Which: air.Z_Which_echo, Echo: air.Echo{}}, - {Which: air.Z_Which_echo, Echo: air.Echo{Client: capnp.ErrorClient(errors.New("boo"))}}, + {Which: air.Z_Which_echo, Echo: air.Echo(capnp.ErrorClient(errors.New("boo")))}, {Which: air.Z_Which_echoes, Echoes: []air.Echo{ - {Client: capnp.Client{}}, - {Client: capnp.ErrorClient(errors.New("boo"))}, - {Client: capnp.Client{}}, - {Client: capnp.ErrorClient(errors.New("boo"))}, - {Client: capnp.Client{}}, + {}, + air.Echo(capnp.ErrorClient(errors.New("boo"))), + {}, + air.Echo(capnp.ErrorClient(errors.New("boo"))), + {}, }}, {Which: air.Z_Which_anyPtr, AnyPtr: capnp.Ptr{}}, {Which: air.Z_Which_anyPtr, AnyPtr: newTestStruct().ToPtr()}, @@ -1212,7 +1212,7 @@ func zfill(c air.Z, g *Z) error { return err } for i, ee := range g.Echoes { - if !ee.Client.IsValid() { + if !ee.IsValid() { continue } err := e.Set(i, ee) diff --git a/rpc/bench_test.go b/rpc/bench_test.go index e5039fe8..ebab4b11 100644 --- a/rpc/bench_test.go +++ b/rpc/bench_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "capnproto.org/go/capnp/v3" "capnproto.org/go/capnp/v3/rpc" testcp "capnproto.org/go/capnp/v3/rpc/internal/testcapnp" "capnproto.org/go/capnp/v3/rpc/transport" @@ -14,7 +15,7 @@ func BenchmarkPingPong(b *testing.B) { srv := testcp.PingPong_ServerToClient(pingPongServer{}) conn1 := rpc.NewConn(rpc.NewTransport(p2), &rpc.Options{ ErrorReporter: testErrorReporter{tb: b}, - BootstrapClient: srv.Client, + BootstrapClient: capnp.Client(srv), }) defer func() { <-conn1.Done() @@ -32,8 +33,8 @@ func BenchmarkPingPong(b *testing.B) { }() ctx := context.Background() - client := testcp.PingPong{Client: conn2.Bootstrap(ctx)} - defer client.Client.Release() + client := testcp.PingPong(conn2.Bootstrap(ctx)) + defer client.Release() b.ResetTimer() for i := 0; i < b.N; i++ { diff --git a/rpc/flow_test.go b/rpc/flow_test.go index 9a26706c..45a3ee9e 100644 --- a/rpc/flow_test.go +++ b/rpc/flow_test.go @@ -83,7 +83,7 @@ func TestFixedFlowLimit(t *testing.T) { bootstrap := testcapnp.StreamTest_ServerToClient(slowStreamTestServer{}) conn := NewConn(serverTrans, &Options{ - BootstrapClient: bootstrap.Client, + BootstrapClient: capnp.Client(bootstrap), }) defer conn.Close() <-ctx.Done() @@ -97,7 +97,7 @@ func TestFixedFlowLimit(t *testing.T) { conn := NewConn(trans, nil) defer conn.Close() - client := testcapnp.StreamTest{Client: conn.Bootstrap(ctx)} + client := testcapnp.StreamTest(conn.Bootstrap(ctx)) defer client.Release() // Make a decently sized payload, so we can expect the size of the @@ -106,7 +106,7 @@ func TestFixedFlowLimit(t *testing.T) { // Rig up the flow control, then send calls as fast as the limiter will // let us: - client.Client.SetFlowLimiter(flowcontrol.NewFixedLimiter(limit)) + capnp.Client(client).SetFlowLimiter(flowcontrol.NewFixedLimiter(limit)) for ctx.Err() == nil { client.Push(ctx, func(p testcapnp.StreamTest_push_Params) error { return p.SetData(data) diff --git a/rpc/internal/testcapnp/test.capnp.go b/rpc/internal/testcapnp/test.capnp.go index 1dca94db..c16572cf 100644 --- a/rpc/internal/testcapnp/test.capnp.go +++ b/rpc/internal/testcapnp/test.capnp.go @@ -11,7 +11,7 @@ import ( context "context" ) -type PingPong struct{ capnp.Client } +type PingPong capnp.Client // PingPong_TypeID is the unique identifier for the type PingPong. const PingPong_TypeID = 0xf004c474c2f8ee7a @@ -29,18 +29,28 @@ func (c PingPong) EchoNum(ctx context.Context, params func(PingPong_echoNum_Para s.ArgsSize = capnp.ObjectSize{DataSize: 8, PointerCount: 0} s.PlaceArgs = func(s capnp.Struct) error { return params(PingPong_echoNum_Params{Struct: s}) } } - ans, release := c.Client.SendCall(ctx, s) + ans, release := capnp.Client(c).SendCall(ctx, s) return PingPong_echoNum_Results_Future{Future: ans.Future()}, release } func (c PingPong) AddRef() PingPong { - return PingPong{ - Client: c.Client.AddRef(), - } + return PingPong(capnp.Client(c).AddRef()) +} + +func (c PingPong) Release() { + capnp.Client(c).Release() +} + +func (c PingPong) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Client(c).EncodeAsPtr(seg) } func (PingPong) DecodeFromPtr(p capnp.Ptr) PingPong { - return PingPong{Client: capnp.Client{}.DecodeFromPtr(p)} + return PingPong(capnp.Client{}.DecodeFromPtr(p)) +} + +func (c PingPong) IsValid() bool { + return capnp.Client(c).IsValid() } // A PingPong_Server is a PingPong with a local implementation. @@ -57,7 +67,7 @@ func PingPong_NewServer(s PingPong_Server) *server.Server { // PingPong_ServerToClient creates a new Client from an implementation of PingPong_Server. // The caller is responsible for calling Release on the returned Client. func PingPong_ServerToClient(s PingPong_Server) PingPong { - return PingPong{Client: capnp.NewClient(PingPong_NewServer(s))} + return PingPong(capnp.NewClient(PingPong_NewServer(s))) } // PingPong_Methods appends Methods to a slice that invoke the methods on s. @@ -214,7 +224,7 @@ func (p PingPong_echoNum_Results_Future) Struct() (PingPong_echoNum_Results, err return PingPong_echoNum_Results{s}, err } -type StreamTest struct{ capnp.Client } +type StreamTest capnp.Client // StreamTest_TypeID is the unique identifier for the type StreamTest. const StreamTest_TypeID = 0xbb3ca85b01eea465 @@ -232,18 +242,28 @@ func (c StreamTest) Push(ctx context.Context, params func(StreamTest_push_Params s.ArgsSize = capnp.ObjectSize{DataSize: 0, PointerCount: 1} s.PlaceArgs = func(s capnp.Struct) error { return params(StreamTest_push_Params{Struct: s}) } } - ans, release := c.Client.SendCall(ctx, s) + ans, release := capnp.Client(c).SendCall(ctx, s) return stream.StreamResult_Future{Future: ans.Future()}, release } func (c StreamTest) AddRef() StreamTest { - return StreamTest{ - Client: c.Client.AddRef(), - } + return StreamTest(capnp.Client(c).AddRef()) +} + +func (c StreamTest) Release() { + capnp.Client(c).Release() +} + +func (c StreamTest) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Client(c).EncodeAsPtr(seg) } func (StreamTest) DecodeFromPtr(p capnp.Ptr) StreamTest { - return StreamTest{Client: capnp.Client{}.DecodeFromPtr(p)} + return StreamTest(capnp.Client{}.DecodeFromPtr(p)) +} + +func (c StreamTest) IsValid() bool { + return capnp.Client(c).IsValid() } // A StreamTest_Server is a StreamTest with a local implementation. @@ -260,7 +280,7 @@ func StreamTest_NewServer(s StreamTest_Server) *server.Server { // StreamTest_ServerToClient creates a new Client from an implementation of StreamTest_Server. // The caller is responsible for calling Release on the returned Client. func StreamTest_ServerToClient(s StreamTest_Server) StreamTest { - return StreamTest{Client: capnp.NewClient(StreamTest_NewServer(s))} + return StreamTest(capnp.NewClient(StreamTest_NewServer(s))) } // StreamTest_Methods appends Methods to a slice that invoke the methods on s. @@ -369,7 +389,7 @@ func (p StreamTest_push_Params_Future) Struct() (StreamTest_push_Params, error) return StreamTest_push_Params{s}, err } -type CapArgsTest struct{ capnp.Client } +type CapArgsTest capnp.Client // CapArgsTest_TypeID is the unique identifier for the type CapArgsTest. const CapArgsTest_TypeID = 0xb86bce7f916a10cc @@ -387,7 +407,7 @@ func (c CapArgsTest) Call(ctx context.Context, params func(CapArgsTest_call_Para s.ArgsSize = capnp.ObjectSize{DataSize: 0, PointerCount: 1} s.PlaceArgs = func(s capnp.Struct) error { return params(CapArgsTest_call_Params{Struct: s}) } } - ans, release := c.Client.SendCall(ctx, s) + ans, release := capnp.Client(c).SendCall(ctx, s) return CapArgsTest_call_Results_Future{Future: ans.Future()}, release } func (c CapArgsTest) Self(ctx context.Context, params func(CapArgsTest_self_Params) error) (CapArgsTest_self_Results_Future, capnp.ReleaseFunc) { @@ -403,18 +423,28 @@ func (c CapArgsTest) Self(ctx context.Context, params func(CapArgsTest_self_Para s.ArgsSize = capnp.ObjectSize{DataSize: 0, PointerCount: 0} s.PlaceArgs = func(s capnp.Struct) error { return params(CapArgsTest_self_Params{Struct: s}) } } - ans, release := c.Client.SendCall(ctx, s) + ans, release := capnp.Client(c).SendCall(ctx, s) return CapArgsTest_self_Results_Future{Future: ans.Future()}, release } func (c CapArgsTest) AddRef() CapArgsTest { - return CapArgsTest{ - Client: c.Client.AddRef(), - } + return CapArgsTest(capnp.Client(c).AddRef()) +} + +func (c CapArgsTest) Release() { + capnp.Client(c).Release() +} + +func (c CapArgsTest) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Client(c).EncodeAsPtr(seg) } func (CapArgsTest) DecodeFromPtr(p capnp.Ptr) CapArgsTest { - return CapArgsTest{Client: capnp.Client{}.DecodeFromPtr(p)} + return CapArgsTest(capnp.Client{}.DecodeFromPtr(p)) +} + +func (c CapArgsTest) IsValid() bool { + return capnp.Client(c).IsValid() } // A CapArgsTest_Server is a CapArgsTest with a local implementation. @@ -433,7 +463,7 @@ func CapArgsTest_NewServer(s CapArgsTest_Server) *server.Server { // CapArgsTest_ServerToClient creates a new Client from an implementation of CapArgsTest_Server. // The caller is responsible for calling Release on the returned Client. func CapArgsTest_ServerToClient(s CapArgsTest_Server) CapArgsTest { - return CapArgsTest{Client: capnp.NewClient(CapArgsTest_NewServer(s))} + return CapArgsTest(capnp.NewClient(CapArgsTest_NewServer(s))) } // CapArgsTest_Methods appends Methods to a slice that invoke the methods on s. @@ -702,7 +732,7 @@ func (CapArgsTest_self_Results) DecodeFromPtr(p capnp.Ptr) CapArgsTest_self_Resu } func (s CapArgsTest_self_Results) Self() CapArgsTest { p, _ := s.Struct.Ptr(0) - return CapArgsTest{Client: p.Interface().Client()} + return CapArgsTest(p.Interface().Client()) } func (s CapArgsTest_self_Results) HasSelf() bool { @@ -710,11 +740,11 @@ func (s CapArgsTest_self_Results) HasSelf() bool { } func (s CapArgsTest_self_Results) SetSelf(v CapArgsTest) error { - if !v.Client.IsValid() { + if !v.IsValid() { return s.Struct.SetPtr(0, capnp.Ptr{}) } seg := s.Segment() - in := capnp.NewInterface(seg, seg.Message().AddCap(v.Client)) + in := capnp.NewInterface(seg, seg.Message().AddCap(capnp.Client(v))) return s.Struct.SetPtr(0, in.ToPtr()) } @@ -736,7 +766,7 @@ func (p CapArgsTest_self_Results_Future) Struct() (CapArgsTest_self_Results, err } func (p CapArgsTest_self_Results_Future) Self() CapArgsTest { - return CapArgsTest{Client: p.Future.Field(0, nil).Client()} + return CapArgsTest(p.Future.Field(0, nil).Client()) } const schema_ef12a34b9807e19c = "x\xda\x94\x93Mh\xd3`\x18\xc7\x9f\xa7\xef\x9b\xa5C" + diff --git a/rpc/receiveranswer_test.go b/rpc/receiveranswer_test.go index 145b9589..0085cfc0 100644 --- a/rpc/receiveranswer_test.go +++ b/rpc/receiveranswer_test.go @@ -66,7 +66,7 @@ func TestBootstrapReceiverAnswerRpc(t *testing.T) { serverConn := NewConn( NewStreamTransport(cServer), &Options{ - BootstrapClient: testcapnp.CapArgsTest_ServerToClient(srv).Client, + BootstrapClient: capnp.Client(testcapnp.CapArgsTest_ServerToClient(srv)), }, ) defer serverConn.Close() @@ -75,10 +75,10 @@ func TestBootstrapReceiverAnswerRpc(t *testing.T) { defer clientConn.Close() ctx := context.Background() - c := testcapnp.CapArgsTest{Client: clientConn.Bootstrap(ctx)} + c := testcapnp.CapArgsTest(clientConn.Bootstrap(ctx)) res, rel := c.Call(ctx, func(p testcapnp.CapArgsTest_call_Params) error { - return p.SetCap(c.Client.AddRef()) + return p.SetCap(capnp.Client(c.AddRef())) }) defer rel() c.Release() @@ -105,7 +105,7 @@ func TestCallReceiverAnswerRpc(t *testing.T) { serverConn := NewConn( NewStreamTransport(cServer), &Options{ - BootstrapClient: testcapnp.CapArgsTest_ServerToClient(srv).Client, + BootstrapClient: capnp.Client(testcapnp.CapArgsTest_ServerToClient(srv)), }, ) defer serverConn.Close() @@ -114,14 +114,14 @@ func TestCallReceiverAnswerRpc(t *testing.T) { defer clientConn.Close() ctx := context.Background() - bs := testcapnp.CapArgsTest{Client: clientConn.Bootstrap(ctx)} + bs := testcapnp.CapArgsTest(clientConn.Bootstrap(ctx)) defer bs.Release() selfRes, rel := bs.Self(ctx, nil) defer rel() self := selfRes.Self() callRes, rel := self.Call(ctx, func(p testcapnp.CapArgsTest_call_Params) error { - return p.SetCap(self.Client.AddRef()) + return p.SetCap(capnp.Client(self.AddRef())) }) self.Release() defer rel() @@ -149,7 +149,7 @@ func TestBootstrapReceiverAnswer(t *testing.T) { conn := NewConn( NewStreamTransport(cServer), &Options{ - BootstrapClient: testcapnp.CapArgsTest_ServerToClient(srv).Client, + BootstrapClient: capnp.Client(testcapnp.CapArgsTest_ServerToClient(srv)), }, ) defer conn.Close() @@ -216,7 +216,7 @@ func TestCallReceiverAnswer(t *testing.T) { conn := NewConn( NewStreamTransport(cServer), &Options{ - BootstrapClient: testcapnp.CapArgsTest_ServerToClient(srv).Client, + BootstrapClient: capnp.Client(testcapnp.CapArgsTest_ServerToClient(srv)), }, ) defer conn.Close() diff --git a/server/server_test.go b/server/server_test.go index 63321de0..8a2d2c50 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -39,7 +39,7 @@ func (errorEchoImpl) Echo(_ context.Context, call air.Echo_echo) error { func TestServerCall(t *testing.T) { t.Run("Success", func(t *testing.T) { echo := air.Echo_ServerToClient(echoImpl{}) - defer echo.Client.Release() + defer echo.Release() ans, finish := echo.Echo(context.Background(), func(p air.Echo_echo_Params) error { err := p.SetIn("foo") @@ -58,7 +58,7 @@ func TestServerCall(t *testing.T) { }) t.Run("Error", func(t *testing.T) { echo := air.Echo_ServerToClient(errorEchoImpl{}) - defer echo.Client.Release() + defer echo.Release() ans, finish := echo.Echo(context.Background(), func(p air.Echo_echo_Params) error { err := p.SetIn("foo") @@ -71,8 +71,8 @@ func TestServerCall(t *testing.T) { } }) t.Run("Unimplemented", func(t *testing.T) { - echo := air.Echo{Client: capnp.NewClient(server.New(nil, nil, nil))} - defer echo.Client.Release() + echo := air.Echo(capnp.NewClient(server.New(nil, nil, nil))) + defer echo.Release() ans, finish := echo.Echo(context.Background(), func(p air.Echo_echo_Params) error { err := p.SetIn("foo") @@ -145,19 +145,19 @@ func TestServerCallOrder(t *testing.T) { check(call3, 3) check(call4, 4) }) - test.seq.Client.Release() + test.seq.Release() } } func TestServerShutdown(t *testing.T) { wait := make(chan struct{}) echo := air.Echo_ServerToClient(blockingEchoImpl{wait}) - defer echo.Client.Release() + defer echo.Release() ctx, cancel := context.WithCancel(context.Background()) defer cancel() call, finish := echo.Echo(ctx, nil) defer finish() - echo.Client.Release() + echo.Release() select { case <-call.Done(): if _, err := call.Struct(); err == nil { diff --git a/std/capnp/persistent/persistent.capnp.go b/std/capnp/persistent/persistent.capnp.go index c8ea8821..1444bad9 100644 --- a/std/capnp/persistent/persistent.capnp.go +++ b/std/capnp/persistent/persistent.capnp.go @@ -12,7 +12,7 @@ import ( const PersistentAnnotation = uint64(0xf622595091cafb67) -type Persistent struct{ capnp.Client } +type Persistent capnp.Client // Persistent_TypeID is the unique identifier for the type Persistent. const Persistent_TypeID = 0xc8cb212fcd9f5691 @@ -30,18 +30,28 @@ func (c Persistent) Save(ctx context.Context, params func(Persistent_SaveParams) s.ArgsSize = capnp.ObjectSize{DataSize: 0, PointerCount: 1} s.PlaceArgs = func(s capnp.Struct) error { return params(Persistent_SaveParams{Struct: s}) } } - ans, release := c.Client.SendCall(ctx, s) + ans, release := capnp.Client(c).SendCall(ctx, s) return Persistent_SaveResults_Future{Future: ans.Future()}, release } func (c Persistent) AddRef() Persistent { - return Persistent{ - Client: c.Client.AddRef(), - } + return Persistent(capnp.Client(c).AddRef()) +} + +func (c Persistent) Release() { + capnp.Client(c).Release() +} + +func (c Persistent) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { + return capnp.Client(c).EncodeAsPtr(seg) } func (Persistent) DecodeFromPtr(p capnp.Ptr) Persistent { - return Persistent{Client: capnp.Client{}.DecodeFromPtr(p)} + return Persistent(capnp.Client{}.DecodeFromPtr(p)) +} + +func (c Persistent) IsValid() bool { + return capnp.Client(c).IsValid() } // A Persistent_Server is a Persistent with a local implementation. @@ -58,7 +68,7 @@ func Persistent_NewServer(s Persistent_Server) *server.Server { // Persistent_ServerToClient creates a new Client from an implementation of Persistent_Server. // The caller is responsible for calling Release on the returned Client. func Persistent_ServerToClient(s Persistent_Server) Persistent { - return Persistent{Client: capnp.NewClient(Persistent_NewServer(s))} + return Persistent(capnp.NewClient(Persistent_NewServer(s))) } // Persistent_Methods appends Methods to a slice that invoke the methods on s.