chore: cleanup — untrack binaries, consolidate Go dirs, dedupe tools

- Untrack and delete compiled binaries (tarsum, gosoft.exe, rust uniq/uniq2);
  ignore build outputs (dist/, bin/, *.exe, *.test, .ruff_cache/)
- Merge tools/go/ and projects/go-tools/go/ into projects/go-tools/<name>/
- Fix goipgrep .gitignore: bare 'ipgrep' pattern was ignoring cmd/ipgrep/,
  so the main entrypoint was never tracked; now anchored to /ipgrep
- Archive duplicate implementations to archive/experimental/{rust,go}/
  (uniq, between, tarsum rewrites); canonical versions stay in tools/
- Update README tool catalog to match new layout

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
tobias
2026-06-10 13:42:45 +02:00
parent 401b3e1781
commit 1cbf8afb4a
39 changed files with 449 additions and 27 deletions
@@ -0,0 +1,27 @@
package normalize
import (
"fmt"
"net"
"strings"
)
// NormalizeIP validates an IP string and returns a canonical string form.
// If allowIPv6 is false, only IPv4 is accepted.
func NormalizeIP(s string, allowIPv6 bool) (string, bool) {
s = strings.TrimSpace(s)
if s == "" {
return "", false
}
ip := net.ParseIP(s)
if ip == nil {
return "", false
}
if v4 := ip.To4(); v4 != nil {
return fmt.Sprintf("%d.%d.%d.%d", v4[0], v4[1], v4[2], v4[3]), true
}
if !allowIPv6 {
return "", false
}
return ip.String(), true
}
@@ -0,0 +1,43 @@
package normalize
import (
"strings"
)
// NormalizeMAC converts supported MAC forms to canonical lower-case colon-separated form.
// Accepts: xx:xx:xx:xx:xx:xx, xx-xx-xx-xx-xx-xx, xxxx.xxxx.xxxx
func NormalizeMAC(s string) (string, bool) {
s = strings.TrimSpace(s)
if s == "" {
return "", false
}
s = strings.ToLower(s)
// remove common separators
s = strings.ReplaceAll(s, ":", "")
s = strings.ReplaceAll(s, "-", "")
s = strings.ReplaceAll(s, ".", "")
if len(s) != 12 {
return "", false
}
for i := 0; i < 12; i++ {
c := s[i]
if (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') {
continue
}
return "", false
}
// canonical form aa:bb:cc:dd:ee:ff
var b strings.Builder
b.Grow(17)
for i := 0; i < 12; i += 2 {
if i > 0 {
b.WriteByte(':')
}
b.WriteByte(s[i])
b.WriteByte(s[i+1])
}
return b.String(), true
}
@@ -0,0 +1,23 @@
package normalize
import "testing"
func TestNormalizeMAC(t *testing.T) {
cases := map[string]string{
"AA:BB:CC:DD:EE:FF": "aa:bb:cc:dd:ee:ff",
"aa-bb-cc-dd-ee-ff": "aa:bb:cc:dd:ee:ff",
"aabb.ccdd.eeff": "aa:bb:cc:dd:ee:ff",
}
for in, want := range cases {
got, ok := NormalizeMAC(in)
if !ok {
t.Fatalf("NormalizeMAC(%q) not ok", in)
}
if got != want {
t.Fatalf("NormalizeMAC(%q)=%q want %q", in, got, want)
}
}
if _, ok := NormalizeMAC("not-a-mac"); ok {
t.Fatalf("expected invalid mac")
}
}