Skip to content

Commit

Permalink
Merge pull request #279 from zenhack/kill-client-struct-wrappers
Browse files Browse the repository at this point in the history
Kill the struct wrapper around Client
  • Loading branch information
lthibault authored Aug 1, 2022
2 parents ecf31e6 + 1b0596d commit fe8fc11
Show file tree
Hide file tree
Showing 16 changed files with 211 additions and 157 deletions.
7 changes: 6 additions & 1 deletion capability.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
22 changes: 16 additions & 6 deletions capnpc-go/templates/interfaceClient
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{{with .Annotations.Doc -}}
// {{.}}
{{end -}}
type {{.Node.Name}} struct { capnp.Client }
type {{.Node.Name}} capnp.Client

{{ template "_typeid" .Node }}

Expand All @@ -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()
}
2 changes: 1 addition & 1 deletion capnpc-go/templates/interfaceServer
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion capnpc-go/templates/promiseFieldInterface
Original file line number Diff line number Diff line change
@@ -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())
}

6 changes: 3 additions & 3 deletions capnpc-go/templates/structInterfaceField
Original file line number Diff line number Diff line change
@@ -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())
}

98 changes: 64 additions & 34 deletions internal/aircraftlib/aircraft.capnp.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions list.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())
}

Expand Down
Loading

0 comments on commit fe8fc11

Please sign in to comment.