From 96c59dfe8a61345434db066d5fd1d04a0d54465c Mon Sep 17 00:00:00 2001 From: Alejandro Mery Date: Mon, 3 Jun 2024 14:17:35 +0000 Subject: [PATCH] rings: introduce a generic DecodeAddress() for all four rings Signed-off-by: Alejandro Mery --- pkg/rings/decode.go | 74 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 pkg/rings/decode.go diff --git a/pkg/rings/decode.go b/pkg/rings/decode.go new file mode 100644 index 0000000..45c17cb --- /dev/null +++ b/pkg/rings/decode.go @@ -0,0 +1,74 @@ +package rings + +import ( + "net/netip" +) + +// DecodeAddress extracts ring address fields from a given 10.0.0.0/8 +// address. +// +// revive:disable:function-result-limit +func DecodeAddress[T ~uint | NodeID](addr netip.Addr) (RingID, RegionID, ZoneID, T) { + // revive:enable:function-result-limit + if addr.IsValid() { + if addr.Is4In6() { + addr = addr.Unmap() + } + + if addr.Is4() { + a4 := addr.As4() + return unsafeDecodeAddress[T](a4[0], a4[1], a4[2], a4[3]) + } + } + + return UnspecifiedRingID, 0, 0, 0 +} + +// revive:disable:function-result-limit +func unsafeDecodeAddress[T ~uint | NodeID](a, b, c, d byte) (RingID, RegionID, ZoneID, T) { + // revive:enable:function-result-limit + switch { + case a != 10: + return UnspecifiedRingID, 0, 0, 0 + case b == 0x00: + // 10.00.RZ.dd + k := RingZeroID + r := RegionID(c >> 4) + z := ZoneID(c & 0xf) + n := T(d) + + return k, r, z, n + case b&0xf0 != 0: + // 10.Rb.cc.dd + k := RingThreeID + r := RegionID(b >> 4) + + n2 := T(b & 0x0f) + n1 := T(c) + n0 := T(d) + n := n0 + n1<<8 + n2<<16 + + return k, r, 0, n + case c&0xf0 != 0: + // 10.0R.Zc.dd + k := RingOneID + r := RegionID(b) + z := ZoneID(c >> 4) + + n1 := T(c & 0x0f) + n0 := T(d) + n := n0 + n1<<8 + + return k, r, z, n + default: + // 10.0R.0c.dd + k := RingTwoID + r := RegionID(b) + + n1 := T(c & 0x0f) + n0 := T(d) + n := n0 + n1<<8 + + return k, r, 0, n + } +}