types/result, util/lineiter: add package for a result type, use it

This adds a new generic result type (motivated by golang/go#70084) to
try it out, and uses it in the new lineutil package (replacing the old
lineread package), changing that package to return iterators:
sometimes over []byte (when the input is all in memory), but sometimes
iterators over results of []byte, if errors might happen at runtime.

Updates #12912
Updates golang/go#70084

Change-Id: Iacdc1070e661b5fb163907b1e8b07ac7d51d3f83
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2024-11-04 20:49:40 -08:00
committed by Brad Fitzpatrick
parent 809a6eba80
commit 01185e436f
20 changed files with 290 additions and 139 deletions

View File

@@ -4,14 +4,13 @@
package netmon
import (
"errors"
"io"
"net/netip"
"os/exec"
"testing"
"go4.org/mem"
"tailscale.com/util/lineread"
"tailscale.com/util/lineiter"
"tailscale.com/version"
)
@@ -73,31 +72,34 @@ func likelyHomeRouterIPDarwinExec() (ret netip.Addr, netif string, ok bool) {
defer io.Copy(io.Discard, stdout) // clear the pipe to prevent hangs
var f []mem.RO
lineread.Reader(stdout, func(lineb []byte) error {
for lr := range lineiter.Reader(stdout) {
lineb, err := lr.Value()
if err != nil {
break
}
line := mem.B(lineb)
if !mem.Contains(line, mem.S("default")) {
return nil
continue
}
f = mem.AppendFields(f[:0], line)
if len(f) < 4 || !f[0].EqualString("default") {
return nil
continue
}
ipm, flagsm, netifm := f[1], f[2], f[3]
if !mem.Contains(flagsm, mem.S("G")) {
return nil
continue
}
if mem.Contains(flagsm, mem.S("I")) {
return nil
continue
}
ip, err := netip.ParseAddr(string(mem.Append(nil, ipm)))
if err == nil && ip.IsPrivate() {
ret = ip
netif = netifm.StringCopy()
// We've found what we're looking for.
return errStopReadingNetstatTable
break
}
return nil
})
}
return ret, netif, ret.IsValid()
}
@@ -110,5 +112,3 @@ func TestFetchRoutingTable(t *testing.T) {
}
}
}
var errStopReadingNetstatTable = errors.New("found private gateway")