Skip to content

Commit cec779e

Browse files
committed
util/slicesx: add FirstElementEqual and LastElementEqual
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 <bradfitz@tailscale.com>
1 parent 910462a commit cec779e

File tree

5 files changed

+45
-4
lines changed

5 files changed

+45
-4
lines changed

derp/derp_server.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import (
4747
"tailscale.com/types/key"
4848
"tailscale.com/types/logger"
4949
"tailscale.com/util/set"
50+
"tailscale.com/util/slicesx"
5051
"tailscale.com/version"
5152
)
5253

@@ -1323,7 +1324,7 @@ func (s *Server) noteClientActivity(c *sclient) {
13231324
cs.activeClient.Store(c)
13241325
}
13251326

1326-
if sh := dup.sendHistory; len(sh) != 0 && sh[len(sh)-1] == c {
1327+
if slicesx.LastEqual(dup.sendHistory, c) {
13271328
// The client c was the last client to make activity
13281329
// in this set and it was already recorded. Nothing to
13291330
// do.

ssh/tailssh/tailssh.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import (
4545
"tailscale.com/util/clientmetric"
4646
"tailscale.com/util/httpm"
4747
"tailscale.com/util/mak"
48+
"tailscale.com/util/slicesx"
4849
)
4950

5051
var (
@@ -330,7 +331,7 @@ func (c *conn) nextAuthMethodCallback(cm gossh.ConnMetadata, prevErrors []error)
330331
switch {
331332
case c.anyPasswordIsOkay:
332333
nextMethod = append(nextMethod, "password")
333-
case len(prevErrors) > 0 && prevErrors[len(prevErrors)-1] == errPubKeyRequired:
334+
case slicesx.LastEqual(prevErrors, errPubKeyRequired):
334335
nextMethod = append(nextMethod, "publickey")
335336
}
336337

util/linuxfw/helpers.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ import (
1010
"fmt"
1111
"strings"
1212
"unicode"
13+
14+
"tailscale.com/util/slicesx"
1315
)
1416

1517
func formatMaybePrintable(b []byte) string {
16-
// Remove a single trailing null, if any
17-
if len(b) > 0 && b[len(b)-1] == 0 {
18+
// Remove a single trailing null, if any.
19+
if slicesx.LastEqual(b, 0) {
1820
b = b[:len(b)-1]
1921
}
2022

util/slicesx/slicesx.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,15 @@ func CutSuffix[E comparable](s, suffix []E) (after []E, found bool) {
136136
}
137137
return s[:len(s)-len(suffix)], true
138138
}
139+
140+
// FirstEqual reports whether len(s) > 0 and
141+
// its first element == v.
142+
func FirstEqual[T comparable](s []T, v T) bool {
143+
return len(s) > 0 && s[0] == v
144+
}
145+
146+
// LastEqual reports whether len(s) > 0 and
147+
// its last element == v.
148+
func LastEqual[T comparable](s []T, v T) bool {
149+
return len(s) > 0 && s[len(s)-1] == v
150+
}

util/slicesx/slicesx_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,28 @@ func TestCutSuffix(t *testing.T) {
197197
})
198198
}
199199
}
200+
201+
func TestFirstLastEqual(t *testing.T) {
202+
tests := []struct {
203+
name string
204+
in string
205+
v byte
206+
f func([]byte, byte) bool
207+
want bool
208+
}{
209+
{"first-empty", "", 'f', FirstEqual[byte], false},
210+
{"first-true", "foo", 'f', FirstEqual[byte], true},
211+
{"first-false", "foo", 'b', FirstEqual[byte], false},
212+
{"last-empty", "", 'f', LastEqual[byte], false},
213+
{"last-true", "bar", 'r', LastEqual[byte], true},
214+
{"last-false", "bar", 'o', LastEqual[byte], false},
215+
}
216+
for _, tt := range tests {
217+
t.Run(tt.name, func(t *testing.T) {
218+
if got := tt.f([]byte(tt.in), tt.v); got != tt.want {
219+
t.Errorf("got %v; want %v", got, tt.want)
220+
}
221+
})
222+
}
223+
224+
}

0 commit comments

Comments
 (0)