Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kill the struct wrapper around Client #279

Merged
merged 4 commits into from
Aug 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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