From 080fc4cf87c4de796b2c5dc14eb9b94f6ec7a35a Mon Sep 17 00:00:00 2001 From: aimuz Date: Tue, 20 Feb 2024 02:58:00 +0000 Subject: [PATCH] net/netip: introduce parsePrefixError for better error handling Refactor ParsePrefix to return a parsePrefixError containing the input string and a detailed message on failure, improving error context and maintaining consistent error formatting within the netip package. Change-Id: I8d9fb2f833b0f96f43a14622e66e225b54440410 GitHub-Last-Rev: e17bec3afa4efd6c52463bb93e8f694b42c0c2b7 GitHub-Pull-Request: golang/go#65798 Reviewed-on: https://go-review.googlesource.com/c/go/+/565275 Auto-Submit: Michael Pratt Reviewed-by: Michael Pratt Reviewed-by: Damien Neil LUCI-TryBot-Result: Go LUCI --- src/net/netip/netip.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/net/netip/netip.go b/src/net/netip/netip.go index ce498a20fdf..7d816b3c645 100644 --- a/src/net/netip/netip.go +++ b/src/net/netip/netip.go @@ -1294,6 +1294,15 @@ func (p Prefix) compare(p2 Prefix) int { return p.Addr().Compare(p2.Addr()) } +type parsePrefixError struct { + in string // the string given to ParsePrefix + msg string // an explanation of the parse failure +} + +func (err parsePrefixError) Error() string { + return "netip.ParsePrefix(" + strconv.Quote(err.in) + "): " + err.msg +} + // ParsePrefix parses s as an IP address prefix. // The string can be in the form "192.168.1.0/24" or "2001:db8::/32", // the CIDR notation defined in RFC 4632 and RFC 4291. @@ -1304,34 +1313,34 @@ func (p Prefix) compare(p2 Prefix) int { func ParsePrefix(s string) (Prefix, error) { i := bytealg.LastIndexByteString(s, '/') if i < 0 { - return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): no '/'") + return Prefix{}, parsePrefixError{in: s, msg: "no '/'"} } ip, err := ParseAddr(s[:i]) if err != nil { - return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): " + err.Error()) + return Prefix{}, parsePrefixError{in: s, msg: err.Error()} } // IPv6 zones are not allowed: https://go.dev/issue/51899 if ip.Is6() && ip.z != z6noz { - return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): IPv6 zones cannot be present in a prefix") + return Prefix{}, parsePrefixError{in: s, msg: "IPv6 zones cannot be present in a prefix"} } bitsStr := s[i+1:] // strconv.Atoi accepts a leading sign and leading zeroes, but we don't want that. if len(bitsStr) > 1 && (bitsStr[0] < '1' || bitsStr[0] > '9') { - return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): bad bits after slash: " + strconv.Quote(bitsStr)) + return Prefix{}, parsePrefixError{in: s, msg: "bad bits after slash: " + strconv.Quote(bitsStr)} } bits, err := strconv.Atoi(bitsStr) if err != nil { - return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): bad bits after slash: " + strconv.Quote(bitsStr)) + return Prefix{}, parsePrefixError{in: s, msg: "bad bits after slash: " + strconv.Quote(bitsStr)} } maxBits := 32 if ip.Is6() { maxBits = 128 } if bits < 0 || bits > maxBits { - return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): prefix length out of range") + return Prefix{}, parsePrefixError{in: s, msg: "prefix length out of range"} } return PrefixFrom(ip, bits), nil }