Skip to content

Commit

Permalink
Avoid use of fmt in the main package.
Browse files Browse the repository at this point in the history
This adds a String() method to ClientHook so we can avoid using fmt for
that, then removes the last use of fmt in the main package, per capnproto#364.

Before closing that issue, I think I'd still like to get it out of the
flowcontrol package hierarchy at least, and maybe elsewhere if
practical.
  • Loading branch information
zenhack committed Feb 19, 2023
1 parent 285a677 commit f9f1b3d
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 5 deletions.
7 changes: 7 additions & 0 deletions answer.go
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,13 @@ func (pc PipelineClient) Brand() Brand {
func (pc PipelineClient) Shutdown() {
}

func (pc PipelineClient) String() string {
return "PipelineClient{transform: " +
str.Slice(pc.transform) +
", promise: 0x" + str.PtrToHex(pc.p) +
"}"
}

// A PipelineOp describes a step in transforming a pipeline.
// It maps closely with the PromisedAnswer.Op struct in rpc.capnp.
type PipelineOp struct {
Expand Down
12 changes: 9 additions & 3 deletions capability.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package capnp
import (
"context"
"errors"
"fmt"
"runtime"
"strconv"
"sync"
Expand Down Expand Up @@ -606,9 +605,9 @@ func (c Client) String() string {
}
var s string
if c.h.isResolved() {
s = fmt.Sprintf("<client %T@%p>", c.h.ClientHook, c.h)
s = "<client " + c.h.ClientHook.String() + ">"
} else {
s = fmt.Sprintf("<unresolved client %T@%p>", c.h.ClientHook, c.h)
s = "<unresolved client " + c.h.ClientHook.String() + ">"
}
c.h.mu.Unlock()
c.mu.Unlock()
Expand Down Expand Up @@ -876,6 +875,9 @@ type ClientHook interface {
// Shutdown is undefined. It is expected for the ClientHook to reject
// any outstanding call futures.
Shutdown()

// String formats the hook as a string (same as fmt.Stringer)
String() string
}

// Send is the input to ClientHook.Send.
Expand Down Expand Up @@ -1049,4 +1051,8 @@ func (ec errorClient) Brand() Brand {
func (ec errorClient) Shutdown() {
}

func (ec errorClient) String() string {
return "errorClient{" + ec.e.Error() + "}"
}

var closedSignal = make(chan struct{})
32 changes: 30 additions & 2 deletions internal/str/str.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
// of environments that care about minimizing executable size.
package str

import "strconv"
import (
"strconv"
"strings"

"unsafe" // Only for formatting pointers as integers; we don't actually do anything unsafe.
)

// Utod formats unsigned integers as decimals.
func Utod[T Uint](n T) string {
Expand All @@ -19,6 +24,10 @@ func UToHex[T Uint](n T) string {
return strconv.FormatUint(uint64(n), 16)
}

func PtrToHex[T any](p *T) string {
return UToHex(uintptr(unsafe.Pointer(p)))
}

// ZeroPad pads value to the left with zeros, making the resulting string
// count bytes long.
func ZeroPad(count int, value string) string {
Expand All @@ -34,8 +43,27 @@ func ZeroPad(count int, value string) string {
return string(buf)
}

// Slice formats a slice of values which themselves implement Stringer.
func Slice[T Stringer](s []T) string {
var b strings.Builder
b.WriteRune('{')
for i, v := range s {
if i > 0 {
b.WriteString(", ")
}
b.WriteString(v.String())
}
b.WriteRune('}')
return b.String()
}

// Stringer is equivalent to fmt.Stringer
type Stringer interface {
String() string
}

type Uint interface {
~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uint
~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uint | ~uintptr
}

type Int interface {
Expand Down
4 changes: 4 additions & 0 deletions rpc/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@ type embargo struct {
lifted chan struct{}
}

func (e embargo) String() string {
return "embargo{c: " + e.c.String() + ", 0x" + str.PtrToHex(e.p) + "}"
}

// embargo creates a new embargoed client, stealing the reference.
//
// The caller must be holding onto c.mu.
Expand Down
5 changes: 5 additions & 0 deletions rpc/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"

"capnproto.org/go/capnp/v3"
"capnproto.org/go/capnp/v3/internal/str"
"capnproto.org/go/capnp/v3/internal/syncutil"
rpccp "capnproto.org/go/capnp/v3/std/capnp/rpc"
)
Expand Down Expand Up @@ -84,6 +85,10 @@ type importClient struct {
generation uint64
}

func (ic *importClient) String() string {
return "importClient{c: 0x" + str.PtrToHex(ic.c) + ", id: " + str.Utod(ic.id) + "}"
}

func (ic *importClient) Send(ctx context.Context, s capnp.Send) (*capnp.Answer, capnp.ReleaseFunc) {
return withLockedConn2(ic.c, func(c *lockedConn) (*capnp.Answer, capnp.ReleaseFunc) {
if !c.startTask() {
Expand Down
4 changes: 4 additions & 0 deletions rpc/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,10 @@ type bootstrapClient struct {
cancel context.CancelFunc
}

func (bc bootstrapClient) String() string {
return "bootstrapClient{c: " + bc.c.String() + "}"
}

func (bc bootstrapClient) Send(ctx context.Context, s capnp.Send) (*capnp.Answer, capnp.ReleaseFunc) {
return bc.c.SendCall(ctx, s)
}
Expand Down
5 changes: 5 additions & 0 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"capnproto.org/go/capnp/v3"
"capnproto.org/go/capnp/v3/exc"
"capnproto.org/go/capnp/v3/exp/mpsc"
"capnproto.org/go/capnp/v3/internal/str"
)

// A Method describes a single capability method on a server object.
Expand Down Expand Up @@ -104,6 +105,10 @@ type Server struct {
HandleUnknownMethod func(m capnp.Method) *Method
}

func (s *Server) String() string {
return "*Server@0x" + str.PtrToHex(s)
}

// New returns a client hook that makes calls to a set of methods.
// If shutdown is nil then the server's shutdown is a no-op. The server
// guarantees message delivery order by blocking each call on the
Expand Down

0 comments on commit f9f1b3d

Please sign in to comment.