Skip to content

Commit

Permalink
util/slicesx: add FirstElementEqual and LastElementEqual
Browse files Browse the repository at this point in the history
And update a few callers as examples of motivation. (there are a
couple others, but these are the ones where it's prettier)

Updates #cleanup

Change-Id: Ic8c5cb7af0a59c6e790a599136b591ebe16d38eb
Signed-off-by: Brad Fitzpatrick <[email protected]>
  • Loading branch information
bradfitz committed Sep 12, 2024
1 parent 910462a commit cec779e
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 4 deletions.
3 changes: 2 additions & 1 deletion derp/derp_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import (
"tailscale.com/types/key"
"tailscale.com/types/logger"
"tailscale.com/util/set"
"tailscale.com/util/slicesx"
"tailscale.com/version"
)

Expand Down Expand Up @@ -1323,7 +1324,7 @@ func (s *Server) noteClientActivity(c *sclient) {
cs.activeClient.Store(c)
}

if sh := dup.sendHistory; len(sh) != 0 && sh[len(sh)-1] == c {
if slicesx.LastEqual(dup.sendHistory, c) {
// The client c was the last client to make activity
// in this set and it was already recorded. Nothing to
// do.
Expand Down
3 changes: 2 additions & 1 deletion ssh/tailssh/tailssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import (
"tailscale.com/util/clientmetric"
"tailscale.com/util/httpm"
"tailscale.com/util/mak"
"tailscale.com/util/slicesx"
)

var (
Expand Down Expand Up @@ -330,7 +331,7 @@ func (c *conn) nextAuthMethodCallback(cm gossh.ConnMetadata, prevErrors []error)
switch {
case c.anyPasswordIsOkay:
nextMethod = append(nextMethod, "password")
case len(prevErrors) > 0 && prevErrors[len(prevErrors)-1] == errPubKeyRequired:
case slicesx.LastEqual(prevErrors, errPubKeyRequired):
nextMethod = append(nextMethod, "publickey")
}

Expand Down
6 changes: 4 additions & 2 deletions util/linuxfw/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import (
"fmt"
"strings"
"unicode"

"tailscale.com/util/slicesx"
)

func formatMaybePrintable(b []byte) string {
// Remove a single trailing null, if any
if len(b) > 0 && b[len(b)-1] == 0 {
// Remove a single trailing null, if any.
if slicesx.LastEqual(b, 0) {
b = b[:len(b)-1]
}

Expand Down
12 changes: 12 additions & 0 deletions util/slicesx/slicesx.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,15 @@ func CutSuffix[E comparable](s, suffix []E) (after []E, found bool) {
}
return s[:len(s)-len(suffix)], true
}

// FirstEqual reports whether len(s) > 0 and
// its first element == v.
func FirstEqual[T comparable](s []T, v T) bool {
return len(s) > 0 && s[0] == v
}

// LastEqual reports whether len(s) > 0 and
// its last element == v.
func LastEqual[T comparable](s []T, v T) bool {
return len(s) > 0 && s[len(s)-1] == v
}
25 changes: 25 additions & 0 deletions util/slicesx/slicesx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,28 @@ func TestCutSuffix(t *testing.T) {
})
}
}

func TestFirstLastEqual(t *testing.T) {
tests := []struct {
name string
in string
v byte
f func([]byte, byte) bool
want bool
}{
{"first-empty", "", 'f', FirstEqual[byte], false},
{"first-true", "foo", 'f', FirstEqual[byte], true},
{"first-false", "foo", 'b', FirstEqual[byte], false},
{"last-empty", "", 'f', LastEqual[byte], false},
{"last-true", "bar", 'r', LastEqual[byte], true},
{"last-false", "bar", 'o', LastEqual[byte], false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.f([]byte(tt.in), tt.v); got != tt.want {
t.Errorf("got %v; want %v", got, tt.want)
}
})
}

}

0 comments on commit cec779e

Please sign in to comment.